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

ipv6: 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
5a352dd0 b6a7719a

+16 -13
+3 -2
include/net/ipv6.h
··· 671 671 return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr)); 672 672 } 673 673 674 - void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt); 675 - void ipv6_proxy_select_ident(struct sk_buff *skb); 674 + void ipv6_select_ident(struct net *net, struct frag_hdr *fhdr, 675 + struct rt6_info *rt); 676 + void ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb); 676 677 677 678 int ip6_dst_hoplimit(struct dst_entry *dst); 678 679
+3 -3
net/ipv6/ip6_output.c
··· 628 628 skb_reset_network_header(skb); 629 629 memcpy(skb_network_header(skb), tmp_hdr, hlen); 630 630 631 - ipv6_select_ident(fh, rt); 631 + ipv6_select_ident(net, fh, rt); 632 632 fh->nexthdr = nexthdr; 633 633 fh->reserved = 0; 634 634 fh->frag_off = htons(IP6_MF); ··· 775 775 fh->nexthdr = nexthdr; 776 776 fh->reserved = 0; 777 777 if (!frag_id) { 778 - ipv6_select_ident(fh, rt); 778 + ipv6_select_ident(net, fh, rt); 779 779 frag_id = fh->identification; 780 780 } else 781 781 fh->identification = frag_id; ··· 1079 1079 skb_shinfo(skb)->gso_size = (mtu - fragheaderlen - 1080 1080 sizeof(struct frag_hdr)) & ~7; 1081 1081 skb_shinfo(skb)->gso_type = SKB_GSO_UDP; 1082 - ipv6_select_ident(&fhdr, rt); 1082 + ipv6_select_ident(sock_net(sk), &fhdr, rt); 1083 1083 skb_shinfo(skb)->ip6_frag_id = fhdr.identification; 1084 1084 1085 1085 append:
+8 -6
net/ipv6/output_core.c
··· 9 9 #include <net/addrconf.h> 10 10 #include <net/secure_seq.h> 11 11 12 - static u32 __ipv6_select_ident(u32 hashrnd, struct in6_addr *dst, 13 - struct in6_addr *src) 12 + static u32 __ipv6_select_ident(struct net *net, u32 hashrnd, 13 + struct in6_addr *dst, struct in6_addr *src) 14 14 { 15 15 u32 hash, id; 16 16 17 17 hash = __ipv6_addr_jhash(dst, hashrnd); 18 18 hash = __ipv6_addr_jhash(src, hash); 19 + hash ^= net_hash_mix(net); 19 20 20 21 /* Treat id of 0 as unset and if we get 0 back from ip_idents_reserve, 21 22 * set the hight order instead thus minimizing possible future ··· 37 36 * 38 37 * The network header must be set before calling this. 39 38 */ 40 - void ipv6_proxy_select_ident(struct sk_buff *skb) 39 + void ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb) 41 40 { 42 41 static u32 ip6_proxy_idents_hashrnd __read_mostly; 43 42 struct in6_addr buf[2]; ··· 54 53 net_get_random_once(&ip6_proxy_idents_hashrnd, 55 54 sizeof(ip6_proxy_idents_hashrnd)); 56 55 57 - id = __ipv6_select_ident(ip6_proxy_idents_hashrnd, 56 + id = __ipv6_select_ident(net, ip6_proxy_idents_hashrnd, 58 57 &addrs[1], &addrs[0]); 59 58 skb_shinfo(skb)->ip6_frag_id = htonl(id); 60 59 } 61 60 EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident); 62 61 63 - void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) 62 + void ipv6_select_ident(struct net *net, struct frag_hdr *fhdr, 63 + struct rt6_info *rt) 64 64 { 65 65 static u32 ip6_idents_hashrnd __read_mostly; 66 66 u32 id; 67 67 68 68 net_get_random_once(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd)); 69 69 70 - id = __ipv6_select_ident(ip6_idents_hashrnd, &rt->rt6i_dst.addr, 70 + id = __ipv6_select_ident(net, ip6_idents_hashrnd, &rt->rt6i_dst.addr, 71 71 &rt->rt6i_src.addr); 72 72 fhdr->identification = htonl(id); 73 73 }
+2 -2
net/ipv6/udp_offload.c
··· 54 54 55 55 /* Set the IPv6 fragment id if not set yet */ 56 56 if (!skb_shinfo(skb)->ip6_frag_id) 57 - ipv6_proxy_select_ident(skb); 57 + ipv6_proxy_select_ident(dev_net(skb->dev), skb); 58 58 59 59 segs = NULL; 60 60 goto out; ··· 113 113 fptr->nexthdr = nexthdr; 114 114 fptr->reserved = 0; 115 115 if (!skb_shinfo(skb)->ip6_frag_id) 116 - ipv6_proxy_select_ident(skb); 116 + ipv6_proxy_select_ident(dev_net(skb->dev), skb); 117 117 fptr->identification = skb_shinfo(skb)->ip6_frag_id; 118 118 119 119 /* Fragment the skb. ipv6 header and the remaining fields of the