Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Hannes Frederic Sowa and committed by
David S. Miller
b6a7719a 8fa38a38

+26 -21
+1 -1
drivers/net/ppp/pptp.c
··· 281 281 nf_reset(skb); 282 282 283 283 skb->ip_summed = CHECKSUM_NONE; 284 - ip_select_ident(skb, NULL); 284 + ip_select_ident(sock_net(sk), skb, NULL); 285 285 ip_send_check(iph); 286 286 287 287 ip_local_out(skb);
+7 -5
include/net/ip.h
··· 318 318 } 319 319 320 320 u32 ip_idents_reserve(u32 hash, int segs); 321 - void __ip_select_ident(struct iphdr *iph, int segs); 321 + void __ip_select_ident(struct net *net, struct iphdr *iph, int segs); 322 322 323 - static inline void ip_select_ident_segs(struct sk_buff *skb, struct sock *sk, int segs) 323 + static inline void ip_select_ident_segs(struct net *net, struct sk_buff *skb, 324 + struct sock *sk, int segs) 324 325 { 325 326 struct iphdr *iph = ip_hdr(skb); 326 327 ··· 338 337 iph->id = 0; 339 338 } 340 339 } else { 341 - __ip_select_ident(iph, segs); 340 + __ip_select_ident(net, iph, segs); 342 341 } 343 342 } 344 343 345 - static inline void ip_select_ident(struct sk_buff *skb, struct sock *sk) 344 + static inline void ip_select_ident(struct net *net, struct sk_buff *skb, 345 + struct sock *sk) 346 346 { 347 - ip_select_ident_segs(skb, sk, 1); 347 + ip_select_ident_segs(net, skb, sk, 1); 348 348 } 349 349 350 350 static inline __wsum inet_compute_pseudo(struct sk_buff *skb, int proto)
+2 -2
net/ipv4/igmp.c
··· 370 370 pip->saddr = fl4.saddr; 371 371 pip->protocol = IPPROTO_IGMP; 372 372 pip->tot_len = 0; /* filled in later */ 373 - ip_select_ident(skb, NULL); 373 + ip_select_ident(net, skb, NULL); 374 374 ((u8 *)&pip[1])[0] = IPOPT_RA; 375 375 ((u8 *)&pip[1])[1] = 4; 376 376 ((u8 *)&pip[1])[2] = 0; ··· 714 714 iph->daddr = dst; 715 715 iph->saddr = fl4.saddr; 716 716 iph->protocol = IPPROTO_IGMP; 717 - ip_select_ident(skb, NULL); 717 + ip_select_ident(net, skb, NULL); 718 718 ((u8 *)&iph[1])[0] = IPOPT_RA; 719 719 ((u8 *)&iph[1])[1] = 4; 720 720 ((u8 *)&iph[1])[2] = 0;
+4 -3
net/ipv4/ip_output.c
··· 148 148 iph->daddr = (opt && opt->opt.srr ? opt->opt.faddr : daddr); 149 149 iph->saddr = saddr; 150 150 iph->protocol = sk->sk_protocol; 151 - ip_select_ident(skb, sk); 151 + ip_select_ident(sock_net(sk), skb, sk); 152 152 153 153 if (opt && opt->opt.optlen) { 154 154 iph->ihl += opt->opt.optlen>>2; ··· 430 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 436 /* TODO : should we use skb->sk here instead of sk ? */ 436 437 skb->priority = sk->sk_priority; ··· 1380 1379 iph->ttl = ttl; 1381 1380 iph->protocol = sk->sk_protocol; 1382 1381 ip_copy_addrs(iph, fl4); 1383 - ip_select_ident(skb, sk); 1382 + ip_select_ident(net, skb, sk); 1384 1383 1385 1384 if (opt) { 1386 1385 iph->ihl += opt->optlen>>2;
+1 -1
net/ipv4/ip_tunnel_core.c
··· 74 74 iph->daddr = dst; 75 75 iph->saddr = src; 76 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 79 err = ip_local_out_sk(sk, skb); 80 80 if (unlikely(net_xmit_eval(err)))
+4 -3
net/ipv4/ipmr.c
··· 1642 1642 * important for multicast video. 1643 1643 */ 1644 1644 1645 - static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr) 1645 + static void ip_encap(struct net *net, struct sk_buff *skb, 1646 + __be32 saddr, __be32 daddr) 1646 1647 { 1647 1648 struct iphdr *iph; 1648 1649 const struct iphdr *old_iph = ip_hdr(skb); ··· 1662 1661 iph->protocol = IPPROTO_IPIP; 1663 1662 iph->ihl = 5; 1664 1663 iph->tot_len = htons(skb->len); 1665 - ip_select_ident(skb, NULL); 1664 + ip_select_ident(net, skb, NULL); 1666 1665 ip_send_check(iph); 1667 1666 1668 1667 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); ··· 1759 1758 * What do we do with netfilter? -- RR 1760 1759 */ 1761 1760 if (vif->flags & VIFF_TUNNEL) { 1762 - ip_encap(skb, vif->local, vif->remote); 1761 + ip_encap(net, skb, vif->local, vif->remote); 1763 1762 /* FIXME: extra output firewall step used to be here. --RR */ 1764 1763 vif->dev->stats.tx_packets++; 1765 1764 vif->dev->stats.tx_bytes += skb->len;
+1 -1
net/ipv4/raw.c
··· 404 404 iph->check = 0; 405 405 iph->tot_len = htons(length); 406 406 if (!iph->id) 407 - ip_select_ident(skb, NULL); 407 + ip_select_ident(net, skb, NULL); 408 408 409 409 iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); 410 410 }
+2 -2
net/ipv4/route.c
··· 482 482 } 483 483 EXPORT_SYMBOL(ip_idents_reserve); 484 484 485 - void __ip_select_ident(struct iphdr *iph, int segs) 485 + void __ip_select_ident(struct net *net, struct iphdr *iph, int segs) 486 486 { 487 487 static u32 ip_idents_hashrnd __read_mostly; 488 488 u32 hash, id; ··· 491 491 492 492 hash = jhash_3words((__force u32)iph->daddr, 493 493 (__force u32)iph->saddr, 494 - iph->protocol, 494 + iph->protocol ^ net_hash_mix(net), 495 495 ip_idents_hashrnd); 496 496 id = ip_idents_reserve(hash, segs); 497 497 iph->id = htons(id);
+1 -1
net/ipv4/xfrm4_mode_tunnel.c
··· 63 63 64 64 top_iph->saddr = x->props.saddr.a4; 65 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 68 return 0; 69 69 }
+3 -2
net/netfilter/ipvs/ip_vs_xmit.c
··· 924 924 ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, 925 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 929 struct rtable *rt; /* Route to the other host */ 929 930 __be32 saddr; /* Source for tunnel */ 930 931 struct net_device *tdev; /* Device to other host */ ··· 992 991 iph->daddr = cp->daddr.ip; 993 992 iph->saddr = saddr; 994 993 iph->ttl = ttl; 995 - ip_select_ident(skb, NULL); 994 + ip_select_ident(net, skb, NULL); 996 995 997 996 /* Another hack: avoid icmp_send in ip_fragment */ 998 997 skb->ignore_df = 1;