aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorHannes Frederic Sowa <hannes@stressinduktion.org>2015-03-25 12:07:45 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-25 14:07:04 -0400
commit5a352dd0a3aac03b443c94828dfd7144261c8636 (patch)
treea6d7355e995fb8c16766fde2cd8ce5ed56b3626a /net/ipv6
parentb6a7719aedd7e5c0f2df7641aa47386111682df4 (diff)
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>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/ip6_output.c6
-rw-r--r--net/ipv6/output_core.c14
-rw-r--r--net/ipv6/udp_offload.c4
3 files changed, 13 insertions, 11 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 7e80b61b51ff..b06ad00048d5 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -628,7 +628,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
628 skb_reset_network_header(skb); 628 skb_reset_network_header(skb);
629 memcpy(skb_network_header(skb), tmp_hdr, hlen); 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 fh->nexthdr = nexthdr; 632 fh->nexthdr = nexthdr;
633 fh->reserved = 0; 633 fh->reserved = 0;
634 fh->frag_off = htons(IP6_MF); 634 fh->frag_off = htons(IP6_MF);
@@ -775,7 +775,7 @@ slow_path:
775 fh->nexthdr = nexthdr; 775 fh->nexthdr = nexthdr;
776 fh->reserved = 0; 776 fh->reserved = 0;
777 if (!frag_id) { 777 if (!frag_id) {
778 ipv6_select_ident(fh, rt); 778 ipv6_select_ident(net, fh, rt);
779 frag_id = fh->identification; 779 frag_id = fh->identification;
780 } else 780 } else
781 fh->identification = frag_id; 781 fh->identification = frag_id;
@@ -1079,7 +1079,7 @@ static inline int ip6_ufo_append_data(struct sock *sk,
1079 skb_shinfo(skb)->gso_size = (mtu - fragheaderlen - 1079 skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
1080 sizeof(struct frag_hdr)) & ~7; 1080 sizeof(struct frag_hdr)) & ~7;
1081 skb_shinfo(skb)->gso_type = SKB_GSO_UDP; 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 skb_shinfo(skb)->ip6_frag_id = fhdr.identification; 1083 skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
1084 1084
1085append: 1085append:
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
index 74581f706c4d..4016a6ef9d61 100644
--- a/net/ipv6/output_core.c
+++ b/net/ipv6/output_core.c
@@ -9,13 +9,14 @@
9#include <net/addrconf.h> 9#include <net/addrconf.h>
10#include <net/secure_seq.h> 10#include <net/secure_seq.h>
11 11
12static u32 __ipv6_select_ident(u32 hashrnd, struct in6_addr *dst, 12static u32 __ipv6_select_ident(struct net *net, u32 hashrnd,
13 struct in6_addr *src) 13 struct in6_addr *dst, struct in6_addr *src)
14{ 14{
15 u32 hash, id; 15 u32 hash, id;
16 16
17 hash = __ipv6_addr_jhash(dst, hashrnd); 17 hash = __ipv6_addr_jhash(dst, hashrnd);
18 hash = __ipv6_addr_jhash(src, hash); 18 hash = __ipv6_addr_jhash(src, hash);
19 hash ^= net_hash_mix(net);
19 20
20 /* Treat id of 0 as unset and if we get 0 back from ip_idents_reserve, 21 /* Treat id of 0 as unset and if we get 0 back from ip_idents_reserve,
21 * set the hight order instead thus minimizing possible future 22 * set the hight order instead thus minimizing possible future
@@ -36,7 +37,7 @@ static u32 __ipv6_select_ident(u32 hashrnd, struct in6_addr *dst,
36 * 37 *
37 * The network header must be set before calling this. 38 * The network header must be set before calling this.
38 */ 39 */
39void ipv6_proxy_select_ident(struct sk_buff *skb) 40void ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb)
40{ 41{
41 static u32 ip6_proxy_idents_hashrnd __read_mostly; 42 static u32 ip6_proxy_idents_hashrnd __read_mostly;
42 struct in6_addr buf[2]; 43 struct in6_addr buf[2];
@@ -53,20 +54,21 @@ void ipv6_proxy_select_ident(struct sk_buff *skb)
53 net_get_random_once(&ip6_proxy_idents_hashrnd, 54 net_get_random_once(&ip6_proxy_idents_hashrnd,
54 sizeof(ip6_proxy_idents_hashrnd)); 55 sizeof(ip6_proxy_idents_hashrnd));
55 56
56 id = __ipv6_select_ident(ip6_proxy_idents_hashrnd, 57 id = __ipv6_select_ident(net, ip6_proxy_idents_hashrnd,
57 &addrs[1], &addrs[0]); 58 &addrs[1], &addrs[0]);
58 skb_shinfo(skb)->ip6_frag_id = htonl(id); 59 skb_shinfo(skb)->ip6_frag_id = htonl(id);
59} 60}
60EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident); 61EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident);
61 62
62void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) 63void ipv6_select_ident(struct net *net, struct frag_hdr *fhdr,
64 struct rt6_info *rt)
63{ 65{
64 static u32 ip6_idents_hashrnd __read_mostly; 66 static u32 ip6_idents_hashrnd __read_mostly;
65 u32 id; 67 u32 id;
66 68
67 net_get_random_once(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd)); 69 net_get_random_once(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd));
68 70
69 id = __ipv6_select_ident(ip6_idents_hashrnd, &rt->rt6i_dst.addr, 71 id = __ipv6_select_ident(net, ip6_idents_hashrnd, &rt->rt6i_dst.addr,
70 &rt->rt6i_src.addr); 72 &rt->rt6i_src.addr);
71 fhdr->identification = htonl(id); 73 fhdr->identification = htonl(id);
72} 74}
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
index be2c0ba82c85..7441e1e63893 100644
--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -54,7 +54,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
54 54
55 /* Set the IPv6 fragment id if not set yet */ 55 /* Set the IPv6 fragment id if not set yet */
56 if (!skb_shinfo(skb)->ip6_frag_id) 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 segs = NULL; 59 segs = NULL;
60 goto out; 60 goto out;
@@ -113,7 +113,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
113 fptr->nexthdr = nexthdr; 113 fptr->nexthdr = nexthdr;
114 fptr->reserved = 0; 114 fptr->reserved = 0;
115 if (!skb_shinfo(skb)->ip6_frag_id) 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 fptr->identification = skb_shinfo(skb)->ip6_frag_id; 117 fptr->identification = skb_shinfo(skb)->ip6_frag_id;
118 118
119 /* Fragment the skb. ipv6 header and the remaining fields of the 119 /* Fragment the skb. ipv6 header and the remaining fields of the