aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Frederic Sowa <hannes@stressinduktion.org>2015-03-25 12:07:44 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-25 14:07:04 -0400
commitb6a7719aedd7e5c0f2df7641aa47386111682df4 (patch)
treef0374d5535a6670c1cb453cc6c0e15237e108376
parent8fa38a38ac37a0ca5366cd62ba4339c2bab49db9 (diff)
ipv4: hash net ptr into fragmentation bucket selection
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>
-rw-r--r--drivers/net/ppp/pptp.c2
-rw-r--r--include/net/ip.h12
-rw-r--r--net/ipv4/igmp.c4
-rw-r--r--net/ipv4/ip_output.c7
-rw-r--r--net/ipv4/ip_tunnel_core.c2
-rw-r--r--net/ipv4/ipmr.c7
-rw-r--r--net/ipv4/raw.c2
-rw-r--r--net/ipv4/route.c4
-rw-r--r--net/ipv4/xfrm4_mode_tunnel.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_xmit.c5
10 files changed, 26 insertions, 21 deletions
diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c
index 1dc628ffce2b..e3bfbd4d0136 100644
--- a/drivers/net/ppp/pptp.c
+++ b/drivers/net/ppp/pptp.c
@@ -281,7 +281,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
281 nf_reset(skb); 281 nf_reset(skb);
282 282
283 skb->ip_summed = CHECKSUM_NONE; 283 skb->ip_summed = CHECKSUM_NONE;
284 ip_select_ident(skb, NULL); 284 ip_select_ident(sock_net(sk), skb, NULL);
285 ip_send_check(iph); 285 ip_send_check(iph);
286 286
287 ip_local_out(skb); 287 ip_local_out(skb);
diff --git a/include/net/ip.h b/include/net/ip.h
index 025c61c0dffb..d0808a323763 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -318,9 +318,10 @@ static inline unsigned int ip_skb_dst_mtu(const struct sk_buff *skb)
318} 318}
319 319
320u32 ip_idents_reserve(u32 hash, int segs); 320u32 ip_idents_reserve(u32 hash, int segs);
321void __ip_select_ident(struct iphdr *iph, int segs); 321void __ip_select_ident(struct net *net, struct iphdr *iph, int segs);
322 322
323static inline void ip_select_ident_segs(struct sk_buff *skb, struct sock *sk, int segs) 323static inline void ip_select_ident_segs(struct net *net, struct sk_buff *skb,
324 struct sock *sk, int segs)
324{ 325{
325 struct iphdr *iph = ip_hdr(skb); 326 struct iphdr *iph = ip_hdr(skb);
326 327
@@ -337,13 +338,14 @@ static inline void ip_select_ident_segs(struct sk_buff *skb, struct sock *sk, in
337 iph->id = 0; 338 iph->id = 0;
338 } 339 }
339 } else { 340 } else {
340 __ip_select_ident(iph, segs); 341 __ip_select_ident(net, iph, segs);
341 } 342 }
342} 343}
343 344
344static inline void ip_select_ident(struct sk_buff *skb, struct sock *sk) 345static inline void ip_select_ident(struct net *net, struct sk_buff *skb,
346 struct sock *sk)
345{ 347{
346 ip_select_ident_segs(skb, sk, 1); 348 ip_select_ident_segs(net, skb, sk, 1);
347} 349}
348 350
349static inline __wsum inet_compute_pseudo(struct sk_buff *skb, int proto) 351static inline __wsum inet_compute_pseudo(struct sk_buff *skb, int proto)
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index ad3f866085de..ad09213ac5b2 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -370,7 +370,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, unsigned int mtu)
370 pip->saddr = fl4.saddr; 370 pip->saddr = fl4.saddr;
371 pip->protocol = IPPROTO_IGMP; 371 pip->protocol = IPPROTO_IGMP;
372 pip->tot_len = 0; /* filled in later */ 372 pip->tot_len = 0; /* filled in later */
373 ip_select_ident(skb, NULL); 373 ip_select_ident(net, skb, NULL);
374 ((u8 *)&pip[1])[0] = IPOPT_RA; 374 ((u8 *)&pip[1])[0] = IPOPT_RA;
375 ((u8 *)&pip[1])[1] = 4; 375 ((u8 *)&pip[1])[1] = 4;
376 ((u8 *)&pip[1])[2] = 0; 376 ((u8 *)&pip[1])[2] = 0;
@@ -714,7 +714,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
714 iph->daddr = dst; 714 iph->daddr = dst;
715 iph->saddr = fl4.saddr; 715 iph->saddr = fl4.saddr;
716 iph->protocol = IPPROTO_IGMP; 716 iph->protocol = IPPROTO_IGMP;
717 ip_select_ident(skb, NULL); 717 ip_select_ident(net, skb, NULL);
718 ((u8 *)&iph[1])[0] = IPOPT_RA; 718 ((u8 *)&iph[1])[0] = IPOPT_RA;
719 ((u8 *)&iph[1])[1] = 4; 719 ((u8 *)&iph[1])[1] = 4;
720 ((u8 *)&iph[1])[2] = 0; 720 ((u8 *)&iph[1])[2] = 0;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 90b49e88e84a..8259e777b249 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -148,7 +148,7 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
148 iph->daddr = (opt && opt->opt.srr ? opt->opt.faddr : daddr); 148 iph->daddr = (opt && opt->opt.srr ? opt->opt.faddr : daddr);
149 iph->saddr = saddr; 149 iph->saddr = saddr;
150 iph->protocol = sk->sk_protocol; 150 iph->protocol = sk->sk_protocol;
151 ip_select_ident(skb, sk); 151 ip_select_ident(sock_net(sk), skb, sk);
152 152
153 if (opt && opt->opt.optlen) { 153 if (opt && opt->opt.optlen) {
154 iph->ihl += opt->opt.optlen>>2; 154 iph->ihl += opt->opt.optlen>>2;
@@ -430,7 +430,8 @@ packet_routed:
430 ip_options_build(skb, &inet_opt->opt, inet->inet_daddr, rt, 0); 430 ip_options_build(skb, &inet_opt->opt, inet->inet_daddr, rt, 0);
431 } 431 }
432 432
433 ip_select_ident_segs(skb, sk, skb_shinfo(skb)->gso_segs ?: 1); 433 ip_select_ident_segs(sock_net(sk), skb, sk,
434 skb_shinfo(skb)->gso_segs ?: 1);
434 435
435 /* TODO : should we use skb->sk here instead of sk ? */ 436 /* TODO : should we use skb->sk here instead of sk ? */
436 skb->priority = sk->sk_priority; 437 skb->priority = sk->sk_priority;
@@ -1379,7 +1380,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
1379 iph->ttl = ttl; 1380 iph->ttl = ttl;
1380 iph->protocol = sk->sk_protocol; 1381 iph->protocol = sk->sk_protocol;
1381 ip_copy_addrs(iph, fl4); 1382 ip_copy_addrs(iph, fl4);
1382 ip_select_ident(skb, sk); 1383 ip_select_ident(net, skb, sk);
1383 1384
1384 if (opt) { 1385 if (opt) {
1385 iph->ihl += opt->optlen>>2; 1386 iph->ihl += opt->optlen>>2;
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
index 88c386cf7d85..8c4dcc46acd2 100644
--- a/net/ipv4/ip_tunnel_core.c
+++ b/net/ipv4/ip_tunnel_core.c
@@ -74,7 +74,7 @@ int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
74 iph->daddr = dst; 74 iph->daddr = dst;
75 iph->saddr = src; 75 iph->saddr = src;
76 iph->ttl = ttl; 76 iph->ttl = ttl;
77 __ip_select_ident(iph, skb_shinfo(skb)->gso_segs ?: 1); 77 __ip_select_ident(sock_net(sk), iph, skb_shinfo(skb)->gso_segs ?: 1);
78 78
79 err = ip_local_out_sk(sk, skb); 79 err = ip_local_out_sk(sk, skb);
80 if (unlikely(net_xmit_eval(err))) 80 if (unlikely(net_xmit_eval(err)))
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 5b188832800f..c688cd1b2110 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1642,7 +1642,8 @@ static struct notifier_block ip_mr_notifier = {
1642 * important for multicast video. 1642 * important for multicast video.
1643 */ 1643 */
1644 1644
1645static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr) 1645static void ip_encap(struct net *net, struct sk_buff *skb,
1646 __be32 saddr, __be32 daddr)
1646{ 1647{
1647 struct iphdr *iph; 1648 struct iphdr *iph;
1648 const struct iphdr *old_iph = ip_hdr(skb); 1649 const struct iphdr *old_iph = ip_hdr(skb);
@@ -1661,7 +1662,7 @@ static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr)
1661 iph->protocol = IPPROTO_IPIP; 1662 iph->protocol = IPPROTO_IPIP;
1662 iph->ihl = 5; 1663 iph->ihl = 5;
1663 iph->tot_len = htons(skb->len); 1664 iph->tot_len = htons(skb->len);
1664 ip_select_ident(skb, NULL); 1665 ip_select_ident(net, skb, NULL);
1665 ip_send_check(iph); 1666 ip_send_check(iph);
1666 1667
1667 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); 1668 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,
1758 * What do we do with netfilter? -- RR 1759 * What do we do with netfilter? -- RR
1759 */ 1760 */
1760 if (vif->flags & VIFF_TUNNEL) { 1761 if (vif->flags & VIFF_TUNNEL) {
1761 ip_encap(skb, vif->local, vif->remote); 1762 ip_encap(net, skb, vif->local, vif->remote);
1762 /* FIXME: extra output firewall step used to be here. --RR */ 1763 /* FIXME: extra output firewall step used to be here. --RR */
1763 vif->dev->stats.tx_packets++; 1764 vif->dev->stats.tx_packets++;
1764 vif->dev->stats.tx_bytes += skb->len; 1765 vif->dev->stats.tx_bytes += skb->len;
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 923cf538fce1..56946f47d446 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -404,7 +404,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
404 iph->check = 0; 404 iph->check = 0;
405 iph->tot_len = htons(length); 405 iph->tot_len = htons(length);
406 if (!iph->id) 406 if (!iph->id)
407 ip_select_ident(skb, NULL); 407 ip_select_ident(net, skb, NULL);
408 408
409 iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); 409 iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
410 } 410 }
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 649c8a3f0189..be8703d02ef0 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -482,7 +482,7 @@ u32 ip_idents_reserve(u32 hash, int segs)
482} 482}
483EXPORT_SYMBOL(ip_idents_reserve); 483EXPORT_SYMBOL(ip_idents_reserve);
484 484
485void __ip_select_ident(struct iphdr *iph, int segs) 485void __ip_select_ident(struct net *net, struct iphdr *iph, int segs)
486{ 486{
487 static u32 ip_idents_hashrnd __read_mostly; 487 static u32 ip_idents_hashrnd __read_mostly;
488 u32 hash, id; 488 u32 hash, id;
@@ -491,7 +491,7 @@ void __ip_select_ident(struct iphdr *iph, int segs)
491 491
492 hash = jhash_3words((__force u32)iph->daddr, 492 hash = jhash_3words((__force u32)iph->daddr,
493 (__force u32)iph->saddr, 493 (__force u32)iph->saddr,
494 iph->protocol, 494 iph->protocol ^ net_hash_mix(net),
495 ip_idents_hashrnd); 495 ip_idents_hashrnd);
496 id = ip_idents_reserve(hash, segs); 496 id = ip_idents_reserve(hash, segs);
497 iph->id = htons(id); 497 iph->id = htons(id);
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index 91771a7c802f..35feda676464 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -63,7 +63,7 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
63 63
64 top_iph->saddr = x->props.saddr.a4; 64 top_iph->saddr = x->props.saddr.a4;
65 top_iph->daddr = x->id.daddr.a4; 65 top_iph->daddr = x->id.daddr.a4;
66 ip_select_ident(skb, NULL); 66 ip_select_ident(dev_net(dst->dev), skb, NULL);
67 67
68 return 0; 68 return 0;
69} 69}
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index f35c15b0de6b..bf02932b7188 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -924,7 +924,8 @@ int
924ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, 924ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
925 struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh) 925 struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
926{ 926{
927 struct netns_ipvs *ipvs = net_ipvs(skb_net(skb)); 927 struct net *net = skb_net(skb);
928 struct netns_ipvs *ipvs = net_ipvs(net);
928 struct rtable *rt; /* Route to the other host */ 929 struct rtable *rt; /* Route to the other host */
929 __be32 saddr; /* Source for tunnel */ 930 __be32 saddr; /* Source for tunnel */
930 struct net_device *tdev; /* Device to other host */ 931 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,
991 iph->daddr = cp->daddr.ip; 992 iph->daddr = cp->daddr.ip;
992 iph->saddr = saddr; 993 iph->saddr = saddr;
993 iph->ttl = ttl; 994 iph->ttl = ttl;
994 ip_select_ident(skb, NULL); 995 ip_select_ident(net, skb, NULL);
995 996
996 /* Another hack: avoid icmp_send in ip_fragment */ 997 /* Another hack: avoid icmp_send in ip_fragment */
997 skb->ignore_df = 1; 998 skb->ignore_df = 1;