android_kernel_xiaomi_sm8350/net/ipv6
Eric Dumazet 81c3d5470e [INET]: speedup inet (tcp/dccp) lookups
Arnaldo and I agreed it could be applied now, because I have other
pending patches depending on this one (Thank you Arnaldo)

(The other important patch moves skc_refcnt in a separate cache line,
so that the SMP/NUMA performance doesnt suffer from cache line ping pongs)

1) First some performance data :
--------------------------------

tcp_v4_rcv() wastes a *lot* of time in __inet_lookup_established()

The most time critical code is :

sk_for_each(sk, node, &head->chain) {
     if (INET_MATCH(sk, acookie, saddr, daddr, ports, dif))
         goto hit; /* You sunk my battleship! */
}

The sk_for_each() does use prefetch() hints but only the begining of
"struct sock" is prefetched.

As INET_MATCH first comparison uses inet_sk(__sk)->daddr, wich is far
away from the begining of "struct sock", it has to bring into CPU
cache cold cache line. Each iteration has to use at least 2 cache
lines.

This can be problematic if some chains are very long.

2) The goal
-----------

The idea I had is to change things so that INET_MATCH() may return
FALSE in 99% of cases only using the data already in the CPU cache,
using one cache line per iteration.

3) Description of the patch
---------------------------

Adds a new 'unsigned int skc_hash' field in 'struct sock_common',
filling a 32 bits hole on 64 bits platform.

struct sock_common {
	unsigned short		skc_family;
	volatile unsigned char	skc_state;
	unsigned char		skc_reuse;
	int			skc_bound_dev_if;
	struct hlist_node	skc_node;
	struct hlist_node	skc_bind_node;
	atomic_t		skc_refcnt;
+	unsigned int		skc_hash;
	struct proto		*skc_prot;
};

Store in this 32 bits field the full hash, not masked by (ehash_size -
1) Using this full hash as the first comparison done in INET_MATCH
permits us immediatly skip the element without touching a second cache
line in case of a miss.

Suppress the sk_hashent/tw_hashent fields since skc_hash (aliased to
sk_hash and tw_hash) already contains the slot number if we mask with
(ehash_size - 1)

File include/net/inet_hashtables.h

64 bits platforms :
#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
     (((__sk)->sk_hash == (__hash))
     ((*((__u64 *)&(inet_sk(__sk)->daddr)))== (__cookie))   &&  \
     ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports))   &&  \
     (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))

32bits platforms:
#define TCP_IPV4_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
     (((__sk)->sk_hash == (__hash))                 &&  \
     (inet_sk(__sk)->daddr          == (__saddr))   &&  \
     (inet_sk(__sk)->rcv_saddr      == (__daddr))   &&  \
     (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))


- Adds a prefetch(head->chain.first) in 
__inet_lookup_established()/__tcp_v4_check_established() and 
__inet6_lookup_established()/__tcp_v6_check_established() and 
__dccp_v4_check_established() to bring into cache the first element of the 
list, before the {read|write}_lock(&head->lock);

Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>
Acked-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
2005-10-03 14:13:38 -07:00
..
netfilter [NET]: Fix packet timestamping. 2005-10-03 13:57:23 -07:00
addrconf.c [IPV6]: Fix [Bug 5306] Oops on IPv6 route lookup 2005-09-26 15:10:16 -07:00
af_inet6.c [NET]: Fix sparse warnings 2005-08-29 16:01:32 -07:00
ah6.c [CRYPTO]: crypto_free_tfm() callers no longer need to check for NULL 2005-09-01 17:44:29 -07:00
anycast.c
datagram.c [XFRM]: Always release dst_entry on error in xfrm_lookup 2005-09-08 15:11:55 -07:00
esp6.c [CRYPTO]: crypto_free_tfm() callers no longer need to check for NULL 2005-09-01 17:44:29 -07:00
exthdrs_core.c
exthdrs.c [IPV6]: Bring Type 0 routing header in-line with rfc3542. 2005-09-10 00:15:06 -07:00
icmp.c [XFRM]: Always release dst_entry on error in xfrm_lookup 2005-09-08 15:11:55 -07:00
inet6_hashtables.c [INET6_HASHTABLES]: Move inet6_lookup functions to net/ipv6/inet6_hashtables.c 2005-08-29 15:57:29 -07:00
ip6_fib.c [PATCH] timer initialization cleanup: DEFINE_TIMER 2005-09-09 14:03:48 -07:00
ip6_flowlabel.c [PATCH] timer initialization cleanup: DEFINE_TIMER 2005-09-09 14:03:48 -07:00
ip6_input.c [IPV4/6]: Check if packet was actually delivered to a raw socket to decide whether to send an ICMP unreachable 2005-08-29 15:37:22 -07:00
ip6_output.c [IPV6]: Support IPV6_{RECV,}TCLASS socket options / ancillary data. 2005-09-08 10:19:03 +09:00
ip6_tunnel.c [IPV6]: Don't redo xfrm_lookup for cached dst entries 2005-09-08 14:27:47 -07:00
ipcomp6.c [CRYPTO]: crypto_free_tfm() callers no longer need to check for NULL 2005-09-01 17:44:29 -07:00
ipv6_sockglue.c [IPV6]: Support IPV6_{RECV,}TCLASS socket options / ancillary data. 2005-09-08 10:19:03 +09:00
ipv6_syms.c
Kconfig
Makefile [INET6_HASHTABLES]: Move inet6_lookup functions to net/ipv6/inet6_hashtables.c 2005-08-29 15:57:29 -07:00
mcast.c [MCAST]: Fix MCAST_EXCLUDE line dupes 2005-09-14 20:53:42 -07:00
ndisc.c [XFRM]: Always release dst_entry on error in xfrm_lookup 2005-09-08 15:11:55 -07:00
netfilter.c [NET]: Make NETDEBUG pure printk wrappers 2005-08-29 15:56:08 -07:00
proc.c
protocol.c
raw.c [PATCH] raw_sendmsg DoS on 2.6 2005-09-19 18:45:42 -07:00
reassembly.c [IPV6]: Need to use pskb_trim_rcsum(). 2005-09-08 12:57:43 -07:00
route.c [NET]: Fix sparse warnings 2005-08-29 16:01:32 -07:00
sit.c [NET]: Fix sparse warnings 2005-08-29 16:01:32 -07:00
sysctl_net_ipv6.c [NET]: Fix sparse warnings 2005-08-29 16:01:32 -07:00
tcp_ipv6.c [INET]: speedup inet (tcp/dccp) lookups 2005-10-03 14:13:38 -07:00
udp.c [IPV6]: Check connect(2) status for IPv6 UDP socket (Re: xfrm_lookup) 2005-09-18 00:30:08 -07:00
xfrm6_input.c
xfrm6_output.c
xfrm6_policy.c
xfrm6_state.c
xfrm6_tunnel.c [NET]: use __read_mostly on kmem_cache_t , DEFINE_SNMP_STAT pointers 2005-08-29 16:11:18 -07:00