diff options
author | Eric Dumazet <edumazet@google.com> | 2014-06-02 16:26:03 +0400 |
---|---|---|
committer | Jiri Slaby <jslaby@suse.cz> | 2014-08-19 19:15:00 +0400 |
commit | 16cc7c2f0ce25aaa048b626477f594668203c44d (patch) | |
tree | 57fc6ac2ccf306697cff1a84827bca8fadb82b9b /net/ipv6/output_core.c | |
parent | 9ac1f1f2b7b385891a5a63d09337a2d66fd76673 (diff) | |
download | linux-16cc7c2f0ce25aaa048b626477f594668203c44d.tar.xz |
inetpeer: get rid of ip_id_count
[ Upstream commit 73f156a6e8c1074ac6327e0abd1169e95eb66463 ]
Ideally, we would need to generate IP ID using a per destination IP
generator.
linux kernels used inet_peer cache for this purpose, but this had a huge
cost on servers disabling MTU discovery.
1) each inet_peer struct consumes 192 bytes
2) inetpeer cache uses a binary tree of inet_peer structs,
with a nominal size of ~66000 elements under load.
3) lookups in this tree are hitting a lot of cache lines, as tree depth
is about 20.
4) If server deals with many tcp flows, we have a high probability of
not finding the inet_peer, allocating a fresh one, inserting it in
the tree with same initial ip_id_count, (cf secure_ip_id())
5) We garbage collect inet_peer aggressively.
IP ID generation do not have to be 'perfect'
Goal is trying to avoid duplicates in a short period of time,
so that reassembly units have a chance to complete reassembly of
fragments belonging to one message before receiving other fragments
with a recycled ID.
We simply use an array of generators, and a Jenkin hash using the dst IP
as a key.
ipv6_select_ident() is put back into net/ipv6/ip6_output.c where it
belongs (it is only used from this file)
secure_ip_id() and secure_ipv6_id() no longer are needed.
Rename ip_select_ident_more() to ip_select_ident_segs() to avoid
unnecessary decrement/increment of the number of segments.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Diffstat (limited to 'net/ipv6/output_core.c')
-rw-r--r-- | net/ipv6/output_core.c | 23 |
1 files changed, 0 insertions, 23 deletions
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c index b31a01263185..798eb0f79078 100644 --- a/net/ipv6/output_core.c +++ b/net/ipv6/output_core.c @@ -7,29 +7,6 @@ #include <net/ip6_fib.h> #include <net/addrconf.h> -void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) -{ - static atomic_t ipv6_fragmentation_id; - int ident; - -#if IS_ENABLED(CONFIG_IPV6) - if (rt && !(rt->dst.flags & DST_NOPEER)) { - struct inet_peer *peer; - struct net *net; - - net = dev_net(rt->dst.dev); - peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1); - if (peer) { - fhdr->identification = htonl(inet_getid(peer, 0)); - inet_putpeer(peer); - return; - } - } -#endif - ident = atomic_inc_return(&ipv6_fragmentation_id); - fhdr->identification = htonl(ident); -} -EXPORT_SYMBOL(ipv6_select_ident); int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) { |