| From foo@baz Mon 17 Aug 2020 11:30:21 AM CEST |
| From: Tim Froidcoeur <tim.froidcoeur@tessares.net> |
| Date: Tue, 11 Aug 2020 20:33:23 +0200 |
| Subject: net: refactor bind_bucket fastreuse into helper |
| |
| From: Tim Froidcoeur <tim.froidcoeur@tessares.net> |
| |
| [ Upstream commit 62ffc589abb176821662efc4525ee4ac0b9c3894 ] |
| |
| Refactor the fastreuse update code in inet_csk_get_port into a small |
| helper function that can be called from other places. |
| |
| Acked-by: Matthieu Baerts <matthieu.baerts@tessares.net> |
| Signed-off-by: Tim Froidcoeur <tim.froidcoeur@tessares.net> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| include/net/inet_connection_sock.h | 4 + |
| net/ipv4/inet_connection_sock.c | 97 ++++++++++++++++++++----------------- |
| 2 files changed, 57 insertions(+), 44 deletions(-) |
| |
| --- a/include/net/inet_connection_sock.h |
| +++ b/include/net/inet_connection_sock.h |
| @@ -309,6 +309,10 @@ int inet_csk_compat_getsockopt(struct so |
| int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname, |
| char __user *optval, unsigned int optlen); |
| |
| +/* update the fast reuse flag when adding a socket */ |
| +void inet_csk_update_fastreuse(struct inet_bind_bucket *tb, |
| + struct sock *sk); |
| + |
| struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu); |
| |
| #define TCP_PINGPONG_THRESH 3 |
| --- a/net/ipv4/inet_connection_sock.c |
| +++ b/net/ipv4/inet_connection_sock.c |
| @@ -296,6 +296,57 @@ static inline int sk_reuseport_match(str |
| ipv6_only_sock(sk), true, false); |
| } |
| |
| +void inet_csk_update_fastreuse(struct inet_bind_bucket *tb, |
| + struct sock *sk) |
| +{ |
| + kuid_t uid = sock_i_uid(sk); |
| + bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN; |
| + |
| + if (hlist_empty(&tb->owners)) { |
| + tb->fastreuse = reuse; |
| + if (sk->sk_reuseport) { |
| + tb->fastreuseport = FASTREUSEPORT_ANY; |
| + tb->fastuid = uid; |
| + tb->fast_rcv_saddr = sk->sk_rcv_saddr; |
| + tb->fast_ipv6_only = ipv6_only_sock(sk); |
| + tb->fast_sk_family = sk->sk_family; |
| +#if IS_ENABLED(CONFIG_IPV6) |
| + tb->fast_v6_rcv_saddr = sk->sk_v6_rcv_saddr; |
| +#endif |
| + } else { |
| + tb->fastreuseport = 0; |
| + } |
| + } else { |
| + if (!reuse) |
| + tb->fastreuse = 0; |
| + if (sk->sk_reuseport) { |
| + /* We didn't match or we don't have fastreuseport set on |
| + * the tb, but we have sk_reuseport set on this socket |
| + * and we know that there are no bind conflicts with |
| + * this socket in this tb, so reset our tb's reuseport |
| + * settings so that any subsequent sockets that match |
| + * our current socket will be put on the fast path. |
| + * |
| + * If we reset we need to set FASTREUSEPORT_STRICT so we |
| + * do extra checking for all subsequent sk_reuseport |
| + * socks. |
| + */ |
| + if (!sk_reuseport_match(tb, sk)) { |
| + tb->fastreuseport = FASTREUSEPORT_STRICT; |
| + tb->fastuid = uid; |
| + tb->fast_rcv_saddr = sk->sk_rcv_saddr; |
| + tb->fast_ipv6_only = ipv6_only_sock(sk); |
| + tb->fast_sk_family = sk->sk_family; |
| +#if IS_ENABLED(CONFIG_IPV6) |
| + tb->fast_v6_rcv_saddr = sk->sk_v6_rcv_saddr; |
| +#endif |
| + } |
| + } else { |
| + tb->fastreuseport = 0; |
| + } |
| + } |
| +} |
| + |
| /* Obtain a reference to a local port for the given sock, |
| * if snum is zero it means select any available local port. |
| * We try to allocate an odd port (and leave even ports for connect()) |
| @@ -308,7 +359,6 @@ int inet_csk_get_port(struct sock *sk, u |
| struct inet_bind_hashbucket *head; |
| struct net *net = sock_net(sk); |
| struct inet_bind_bucket *tb = NULL; |
| - kuid_t uid = sock_i_uid(sk); |
| int l3mdev; |
| |
| l3mdev = inet_sk_bound_l3mdev(sk); |
| @@ -345,49 +395,8 @@ tb_found: |
| goto fail_unlock; |
| } |
| success: |
| - if (hlist_empty(&tb->owners)) { |
| - tb->fastreuse = reuse; |
| - if (sk->sk_reuseport) { |
| - tb->fastreuseport = FASTREUSEPORT_ANY; |
| - tb->fastuid = uid; |
| - tb->fast_rcv_saddr = sk->sk_rcv_saddr; |
| - tb->fast_ipv6_only = ipv6_only_sock(sk); |
| - tb->fast_sk_family = sk->sk_family; |
| -#if IS_ENABLED(CONFIG_IPV6) |
| - tb->fast_v6_rcv_saddr = sk->sk_v6_rcv_saddr; |
| -#endif |
| - } else { |
| - tb->fastreuseport = 0; |
| - } |
| - } else { |
| - if (!reuse) |
| - tb->fastreuse = 0; |
| - if (sk->sk_reuseport) { |
| - /* We didn't match or we don't have fastreuseport set on |
| - * the tb, but we have sk_reuseport set on this socket |
| - * and we know that there are no bind conflicts with |
| - * this socket in this tb, so reset our tb's reuseport |
| - * settings so that any subsequent sockets that match |
| - * our current socket will be put on the fast path. |
| - * |
| - * If we reset we need to set FASTREUSEPORT_STRICT so we |
| - * do extra checking for all subsequent sk_reuseport |
| - * socks. |
| - */ |
| - if (!sk_reuseport_match(tb, sk)) { |
| - tb->fastreuseport = FASTREUSEPORT_STRICT; |
| - tb->fastuid = uid; |
| - tb->fast_rcv_saddr = sk->sk_rcv_saddr; |
| - tb->fast_ipv6_only = ipv6_only_sock(sk); |
| - tb->fast_sk_family = sk->sk_family; |
| -#if IS_ENABLED(CONFIG_IPV6) |
| - tb->fast_v6_rcv_saddr = sk->sk_v6_rcv_saddr; |
| -#endif |
| - } |
| - } else { |
| - tb->fastreuseport = 0; |
| - } |
| - } |
| + inet_csk_update_fastreuse(tb, sk); |
| + |
| if (!inet_csk(sk)->icsk_bind_hash) |
| inet_bind_hash(sk, tb, port); |
| WARN_ON(inet_csk(sk)->icsk_bind_hash != tb); |