ipv4: hash net ptr into fragmentation bucket selection
authorHannes Frederic Sowa <hannes@stressinduktion.org>
Wed, 25 Mar 2015 16:07:44 +0000 (17:07 +0100)
committerDavid S. Miller <davem@davemloft.net>
Wed, 25 Mar 2015 18:07:04 +0000 (14:07 -0400)
As namespaces are sometimes used with overlapping ip address ranges,
we should also use the namespace as input to the hash to select the ip
fragmentation counter bucket.

Cc: Eric Dumazet <edumazet@google.com>
Cc: Flavio Leitner <fbl@redhat.com>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ppp/pptp.c
include/net/ip.h
net/ipv4/igmp.c
net/ipv4/ip_output.c
net/ipv4/ip_tunnel_core.c
net/ipv4/ipmr.c
net/ipv4/raw.c
net/ipv4/route.c
net/ipv4/xfrm4_mode_tunnel.c
net/netfilter/ipvs/ip_vs_xmit.c

index 1dc628ffce2b52a565354f060dca84467d67e4b9..e3bfbd4d01367fc32b063d3305b635006d3f9b03 100644 (file)
@@ -281,7 +281,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
        nf_reset(skb);
 
        skb->ip_summed = CHECKSUM_NONE;
-       ip_select_ident(skb, NULL);
+       ip_select_ident(sock_net(sk), skb, NULL);
        ip_send_check(iph);
 
        ip_local_out(skb);
index 025c61c0dffbfe9ddfcc2cd6f9eb38b2af504d3f..d0808a3237630d7d94fd27d9dddff05f4b330408 100644 (file)
@@ -318,9 +318,10 @@ static inline unsigned int ip_skb_dst_mtu(const struct sk_buff *skb)
 }
 
 u32 ip_idents_reserve(u32 hash, int segs);
-void __ip_select_ident(struct iphdr *iph, int segs);
+void __ip_select_ident(struct net *net, struct iphdr *iph, int segs);
 
-static inline void ip_select_ident_segs(struct sk_buff *skb, struct sock *sk, int segs)
+static inline void ip_select_ident_segs(struct net *net, struct sk_buff *skb,
+                                       struct sock *sk, int segs)
 {
        struct iphdr *iph = ip_hdr(skb);
 
@@ -337,13 +338,14 @@ static inline void ip_select_ident_segs(struct sk_buff *skb, struct sock *sk, in
                        iph->id = 0;
                }
        } else {
-               __ip_select_ident(iph, segs);
+               __ip_select_ident(net, iph, segs);
        }
 }
 
-static inline void ip_select_ident(struct sk_buff *skb, struct sock *sk)
+static inline void ip_select_ident(struct net *net, struct sk_buff *skb,
+                                  struct sock *sk)
 {
-       ip_select_ident_segs(skb, sk, 1);
+       ip_select_ident_segs(net, skb, sk, 1);
 }
 
 static inline __wsum inet_compute_pseudo(struct sk_buff *skb, int proto)
index ad3f866085def009d62a32d058bdd711ad1fcb0c..ad09213ac5b2fbe3af068334953807f8e4157df1 100644 (file)
@@ -370,7 +370,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, unsigned int mtu)
        pip->saddr    = fl4.saddr;
        pip->protocol = IPPROTO_IGMP;
        pip->tot_len  = 0;      /* filled in later */
-       ip_select_ident(skb, NULL);
+       ip_select_ident(net, skb, NULL);
        ((u8 *)&pip[1])[0] = IPOPT_RA;
        ((u8 *)&pip[1])[1] = 4;
        ((u8 *)&pip[1])[2] = 0;
@@ -714,7 +714,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
        iph->daddr    = dst;
        iph->saddr    = fl4.saddr;
        iph->protocol = IPPROTO_IGMP;
-       ip_select_ident(skb, NULL);
+       ip_select_ident(net, skb, NULL);
        ((u8 *)&iph[1])[0] = IPOPT_RA;
        ((u8 *)&iph[1])[1] = 4;
        ((u8 *)&iph[1])[2] = 0;
index 90b49e88e84a63d0b46fc01c2ded1e3dddd61fcb..8259e777b2492b3c75363712255f126bf8d6d15c 100644 (file)
@@ -148,7 +148,7 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
        iph->daddr    = (opt && opt->opt.srr ? opt->opt.faddr : daddr);
        iph->saddr    = saddr;
        iph->protocol = sk->sk_protocol;
-       ip_select_ident(skb, sk);
+       ip_select_ident(sock_net(sk), skb, sk);
 
        if (opt && opt->opt.optlen) {
                iph->ihl += opt->opt.optlen>>2;
@@ -430,7 +430,8 @@ packet_routed:
                ip_options_build(skb, &inet_opt->opt, inet->inet_daddr, rt, 0);
        }
 
-       ip_select_ident_segs(skb, sk, skb_shinfo(skb)->gso_segs ?: 1);
+       ip_select_ident_segs(sock_net(sk), skb, sk,
+                            skb_shinfo(skb)->gso_segs ?: 1);
 
        /* TODO : should we use skb->sk here instead of sk ? */
        skb->priority = sk->sk_priority;
@@ -1379,7 +1380,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
        iph->ttl = ttl;
        iph->protocol = sk->sk_protocol;
        ip_copy_addrs(iph, fl4);
-       ip_select_ident(skb, sk);
+       ip_select_ident(net, skb, sk);
 
        if (opt) {
                iph->ihl += opt->optlen>>2;
index 88c386cf7d85a985b9bd0aca11d3528347aea152..8c4dcc46acd2932e062faf546331c938b160b0d1 100644 (file)
@@ -74,7 +74,7 @@ int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
        iph->daddr      =       dst;
        iph->saddr      =       src;
        iph->ttl        =       ttl;
-       __ip_select_ident(iph, skb_shinfo(skb)->gso_segs ?: 1);
+       __ip_select_ident(sock_net(sk), iph, skb_shinfo(skb)->gso_segs ?: 1);
 
        err = ip_local_out_sk(sk, skb);
        if (unlikely(net_xmit_eval(err)))
index 5b188832800f1a63243729bf581642c7241a3a2a..c688cd1b2110f06e56d6b119bca2a87f02decd56 100644 (file)
@@ -1642,7 +1642,8 @@ static struct notifier_block ip_mr_notifier = {
  *     important for multicast video.
  */
 
-static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr)
+static void ip_encap(struct net *net, struct sk_buff *skb,
+                    __be32 saddr, __be32 daddr)
 {
        struct iphdr *iph;
        const struct iphdr *old_iph = ip_hdr(skb);
@@ -1661,7 +1662,7 @@ static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr)
        iph->protocol   =       IPPROTO_IPIP;
        iph->ihl        =       5;
        iph->tot_len    =       htons(skb->len);
-       ip_select_ident(skb, NULL);
+       ip_select_ident(net, skb, NULL);
        ip_send_check(iph);
 
        memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
@@ -1758,7 +1759,7 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt,
         * What do we do with netfilter? -- RR
         */
        if (vif->flags & VIFF_TUNNEL) {
-               ip_encap(skb, vif->local, vif->remote);
+               ip_encap(net, skb, vif->local, vif->remote);
                /* FIXME: extra output firewall step used to be here. --RR */
                vif->dev->stats.tx_packets++;
                vif->dev->stats.tx_bytes += skb->len;
index 923cf538fce1444d10bf6c7e2e1dcc44058586fb..56946f47d44673c9f93ab4d5d04b0811b8491c8a 100644 (file)
@@ -404,7 +404,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
                iph->check   = 0;
                iph->tot_len = htons(length);
                if (!iph->id)
-                       ip_select_ident(skb, NULL);
+                       ip_select_ident(net, skb, NULL);
 
                iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
        }
index 649c8a3f01894e3d33cb23fda71a2a49aafe5051..be8703d02ef052d6b3872063a7b057b298ac7b13 100644 (file)
@@ -482,7 +482,7 @@ u32 ip_idents_reserve(u32 hash, int segs)
 }
 EXPORT_SYMBOL(ip_idents_reserve);
 
-void __ip_select_ident(struct iphdr *iph, int segs)
+void __ip_select_ident(struct net *net, struct iphdr *iph, int segs)
 {
        static u32 ip_idents_hashrnd __read_mostly;
        u32 hash, id;
@@ -491,7 +491,7 @@ void __ip_select_ident(struct iphdr *iph, int segs)
 
        hash = jhash_3words((__force u32)iph->daddr,
                            (__force u32)iph->saddr,
-                           iph->protocol,
+                           iph->protocol ^ net_hash_mix(net),
                            ip_idents_hashrnd);
        id = ip_idents_reserve(hash, segs);
        iph->id = htons(id);
index 91771a7c802f828c33429413674c5f78ca393b6f..35feda67646494c92263cf30109432fb395fa1df 100644 (file)
@@ -63,7 +63,7 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
 
        top_iph->saddr = x->props.saddr.a4;
        top_iph->daddr = x->id.daddr.a4;
-       ip_select_ident(skb, NULL);
+       ip_select_ident(dev_net(dst->dev), skb, NULL);
 
        return 0;
 }
index f35c15b0de6b64375b06f634dfb141b88888c3d2..bf02932b7188d71ea0c0f1ea438c1b33766b7979 100644 (file)
@@ -924,7 +924,8 @@ int
 ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
                  struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
 {
-       struct netns_ipvs *ipvs = net_ipvs(skb_net(skb));
+       struct net *net = skb_net(skb);
+       struct netns_ipvs *ipvs = net_ipvs(net);
        struct rtable *rt;                      /* Route to the other host */
        __be32 saddr;                           /* Source for tunnel */
        struct net_device *tdev;                /* Device to other host */
@@ -991,7 +992,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
        iph->daddr              =       cp->daddr.ip;
        iph->saddr              =       saddr;
        iph->ttl                =       ttl;
-       ip_select_ident(skb, NULL);
+       ip_select_ident(net, skb, NULL);
 
        /* Another hack: avoid icmp_send in ip_fragment */
        skb->ignore_df = 1;