• Martin KaFai Lau's avatar
    inet: Add a 2nd listener hashtable (port+addr) · 61b7c691
    Martin KaFai Lau authored
    The current listener hashtable is hashed by port only.
    When a process is listening at many IP addresses with the same port (e.g.
    [IP1]:443, [IP2]:443... [IPN]:443), the inet[6]_lookup_listener()
    performance is degraded to a link list.  It is prone to syn attack.
    
    UDP had a similar issue and a second hashtable was added to resolve it.
    
    This patch adds a second hashtable for the listener's sockets.
    The second hashtable is hashed by port and address.
    
    It cannot reuse the existing skc_portaddr_node which is shared
    with skc_bind_node.  TCP listener needs to use skc_bind_node.
    Instead, this patch adds a hlist_node 'icsk_listen_portaddr_node' to
    the inet_connection_sock which the listener (like TCP) also belongs to.
    
    The new portaddr hashtable may need two lookup (First by IP:PORT.
    Second by INADDR_ANY:PORT if the IP:PORT is a not found).   Hence,
    it implements a similar cut off as UDP such that it will only consult the
    new portaddr hashtable if the current port-only hashtable has >10
    sk in the link-list.
    
    lhash2 and lhash2_mask are added to 'struct inet_hashinfo'.  I take
    this chance to plug a 4 bytes hole.  It is done by first moving
    the existing bind_bucket_cachep up and then add the new
    (int lhash2_mask, *lhash2) after the existing bhash_size.
    Signed-off-by: default avatarMartin KaFai Lau <kafai@fb.com>
    Reviewed-by: default avatarEric Dumazet <edumazet@google.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    61b7c691
inet_hashtables.c 21.7 KB