Skip to content

Commit 5a352dd

Browse files
strssndktndavem330
authored andcommitted
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>
1 parent b6a7719 commit 5a352dd

File tree

4 files changed

+16
-13
lines changed

4 files changed

+16
-13
lines changed

include/net/ipv6.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -671,8 +671,9 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add
671671
return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr));
672672
}
673673

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);
676677

677678
int ip6_dst_hoplimit(struct dst_entry *dst);
678679

net/ipv6/ip6_output.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
628628
skb_reset_network_header(skb);
629629
memcpy(skb_network_header(skb), tmp_hdr, hlen);
630630

631-
ipv6_select_ident(fh, rt);
631+
ipv6_select_ident(net, fh, rt);
632632
fh->nexthdr = nexthdr;
633633
fh->reserved = 0;
634634
fh->frag_off = htons(IP6_MF);
@@ -775,7 +775,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
775775
fh->nexthdr = nexthdr;
776776
fh->reserved = 0;
777777
if (!frag_id) {
778-
ipv6_select_ident(fh, rt);
778+
ipv6_select_ident(net, fh, rt);
779779
frag_id = fh->identification;
780780
} else
781781
fh->identification = frag_id;
@@ -1079,7 +1079,7 @@ static inline int ip6_ufo_append_data(struct sock *sk,
10791079
skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
10801080
sizeof(struct frag_hdr)) & ~7;
10811081
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
1082-
ipv6_select_ident(&fhdr, rt);
1082+
ipv6_select_ident(sock_net(sk), &fhdr, rt);
10831083
skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
10841084

10851085
append:

net/ipv6/output_core.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@
99
#include <net/addrconf.h>
1010
#include <net/secure_seq.h>
1111

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)
1414
{
1515
u32 hash, id;
1616

1717
hash = __ipv6_addr_jhash(dst, hashrnd);
1818
hash = __ipv6_addr_jhash(src, hash);
19+
hash ^= net_hash_mix(net);
1920

2021
/* Treat id of 0 as unset and if we get 0 back from ip_idents_reserve,
2122
* set the hight order instead thus minimizing possible future
@@ -36,7 +37,7 @@ static u32 __ipv6_select_ident(u32 hashrnd, struct in6_addr *dst,
3637
*
3738
* The network header must be set before calling this.
3839
*/
39-
void ipv6_proxy_select_ident(struct sk_buff *skb)
40+
void ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb)
4041
{
4142
static u32 ip6_proxy_idents_hashrnd __read_mostly;
4243
struct in6_addr buf[2];
@@ -53,20 +54,21 @@ void ipv6_proxy_select_ident(struct sk_buff *skb)
5354
net_get_random_once(&ip6_proxy_idents_hashrnd,
5455
sizeof(ip6_proxy_idents_hashrnd));
5556

56-
id = __ipv6_select_ident(ip6_proxy_idents_hashrnd,
57+
id = __ipv6_select_ident(net, ip6_proxy_idents_hashrnd,
5758
&addrs[1], &addrs[0]);
5859
skb_shinfo(skb)->ip6_frag_id = htonl(id);
5960
}
6061
EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident);
6162

62-
void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
63+
void ipv6_select_ident(struct net *net, struct frag_hdr *fhdr,
64+
struct rt6_info *rt)
6365
{
6466
static u32 ip6_idents_hashrnd __read_mostly;
6567
u32 id;
6668

6769
net_get_random_once(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd));
6870

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,
7072
&rt->rt6i_src.addr);
7173
fhdr->identification = htonl(id);
7274
}

net/ipv6/udp_offload.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
5454

5555
/* Set the IPv6 fragment id if not set yet */
5656
if (!skb_shinfo(skb)->ip6_frag_id)
57-
ipv6_proxy_select_ident(skb);
57+
ipv6_proxy_select_ident(dev_net(skb->dev), skb);
5858

5959
segs = NULL;
6060
goto out;
@@ -113,7 +113,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
113113
fptr->nexthdr = nexthdr;
114114
fptr->reserved = 0;
115115
if (!skb_shinfo(skb)->ip6_frag_id)
116-
ipv6_proxy_select_ident(skb);
116+
ipv6_proxy_select_ident(dev_net(skb->dev), skb);
117117
fptr->identification = skb_shinfo(skb)->ip6_frag_id;
118118

119119
/* Fragment the skb. ipv6 header and the remaining fields of the

0 commit comments

Comments
 (0)