+++ /dev/null
-From b1cdd1c781f9b8335f6b5c708bd99b180896c5bb Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sat, 12 Jun 2021 21:32:15 +0900
-Subject: tcp: Add num_closed_socks to struct sock_reuseport.
-
-From: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
-
-[ Upstream commit 5c040eaf5d1753aafe12989ca712175df0b9c436 ]
-
-As noted in the following commit, a closed listener has to hold the
-reference to the reuseport group for socket migration. This patch adds a
-field (num_closed_socks) to struct sock_reuseport to manage closed sockets
-within the same reuseport group. Moreover, this and the following commits
-introduce some helper functions to split socks[] into two sections and keep
-TCP_LISTEN and TCP_CLOSE sockets in each section. Like a double-ended
-queue, we will place TCP_LISTEN sockets from the front and TCP_CLOSE
-sockets from the end.
-
- TCP_LISTEN----------> <-------TCP_CLOSE
- +---+---+ --- +---+ --- +---+ --- +---+
- | 0 | 1 | ... | i | ... | j | ... | k |
- +---+---+ --- +---+ --- +---+ --- +---+
-
- i = num_socks - 1
- j = max_socks - num_closed_socks
- k = max_socks - 1
-
-This patch also extends reuseport_add_sock() and reuseport_grow() to
-support num_closed_socks.
-
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
-Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-Reviewed-by: Eric Dumazet <edumazet@google.com>
-Acked-by: Martin KaFai Lau <kafai@fb.com>
-Link: https://lore.kernel.org/bpf/20210612123224.12525-3-kuniyu@amazon.co.jp
-Stable-dep-of: 69421bf98482 ("udp: Update reuse->has_conns under reuseport_lock.")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- include/net/sock_reuseport.h | 5 ++-
- net/core/sock_reuseport.c | 75 +++++++++++++++++++++++++++---------
- 2 files changed, 60 insertions(+), 20 deletions(-)
-
-diff --git a/include/net/sock_reuseport.h b/include/net/sock_reuseport.h
-index 505f1e18e9bf..0e558ca7afbf 100644
---- a/include/net/sock_reuseport.h
-+++ b/include/net/sock_reuseport.h
-@@ -13,8 +13,9 @@ extern spinlock_t reuseport_lock;
- struct sock_reuseport {
- struct rcu_head rcu;
-
-- u16 max_socks; /* length of socks */
-- u16 num_socks; /* elements in socks */
-+ u16 max_socks; /* length of socks */
-+ u16 num_socks; /* elements in socks */
-+ u16 num_closed_socks; /* closed elements in socks */
- /* The last synq overflow event timestamp of this
- * reuse->socks[] group.
- */
-diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c
-index b065f0a103ed..f478c65a281b 100644
---- a/net/core/sock_reuseport.c
-+++ b/net/core/sock_reuseport.c
-@@ -18,6 +18,49 @@ DEFINE_SPINLOCK(reuseport_lock);
-
- static DEFINE_IDA(reuseport_ida);
-
-+static int reuseport_sock_index(struct sock *sk,
-+ const struct sock_reuseport *reuse,
-+ bool closed)
-+{
-+ int left, right;
-+
-+ if (!closed) {
-+ left = 0;
-+ right = reuse->num_socks;
-+ } else {
-+ left = reuse->max_socks - reuse->num_closed_socks;
-+ right = reuse->max_socks;
-+ }
-+
-+ for (; left < right; left++)
-+ if (reuse->socks[left] == sk)
-+ return left;
-+ return -1;
-+}
-+
-+static void __reuseport_add_sock(struct sock *sk,
-+ struct sock_reuseport *reuse)
-+{
-+ reuse->socks[reuse->num_socks] = sk;
-+ /* paired with smp_rmb() in reuseport_select_sock() */
-+ smp_wmb();
-+ reuse->num_socks++;
-+}
-+
-+static bool __reuseport_detach_sock(struct sock *sk,
-+ struct sock_reuseport *reuse)
-+{
-+ int i = reuseport_sock_index(sk, reuse, false);
-+
-+ if (i == -1)
-+ return false;
-+
-+ reuse->socks[i] = reuse->socks[reuse->num_socks - 1];
-+ reuse->num_socks--;
-+
-+ return true;
-+}
-+
- static struct sock_reuseport *__reuseport_alloc(unsigned int max_socks)
- {
- unsigned int size = sizeof(struct sock_reuseport) +
-@@ -72,9 +115,9 @@ int reuseport_alloc(struct sock *sk, bool bind_inany)
- }
-
- reuse->reuseport_id = id;
-+ reuse->bind_inany = bind_inany;
- reuse->socks[0] = sk;
- reuse->num_socks = 1;
-- reuse->bind_inany = bind_inany;
- rcu_assign_pointer(sk->sk_reuseport_cb, reuse);
-
- out:
-@@ -98,6 +141,7 @@ static struct sock_reuseport *reuseport_grow(struct sock_reuseport *reuse)
- return NULL;
-
- more_reuse->num_socks = reuse->num_socks;
-+ more_reuse->num_closed_socks = reuse->num_closed_socks;
- more_reuse->prog = reuse->prog;
- more_reuse->reuseport_id = reuse->reuseport_id;
- more_reuse->bind_inany = reuse->bind_inany;
-@@ -105,9 +149,13 @@ static struct sock_reuseport *reuseport_grow(struct sock_reuseport *reuse)
-
- memcpy(more_reuse->socks, reuse->socks,
- reuse->num_socks * sizeof(struct sock *));
-+ memcpy(more_reuse->socks +
-+ (more_reuse->max_socks - more_reuse->num_closed_socks),
-+ reuse->socks + (reuse->max_socks - reuse->num_closed_socks),
-+ reuse->num_closed_socks * sizeof(struct sock *));
- more_reuse->synq_overflow_ts = READ_ONCE(reuse->synq_overflow_ts);
-
-- for (i = 0; i < reuse->num_socks; ++i)
-+ for (i = 0; i < reuse->max_socks; ++i)
- rcu_assign_pointer(reuse->socks[i]->sk_reuseport_cb,
- more_reuse);
-
-@@ -158,7 +206,7 @@ int reuseport_add_sock(struct sock *sk, struct sock *sk2, bool bind_inany)
- return -EBUSY;
- }
-
-- if (reuse->num_socks == reuse->max_socks) {
-+ if (reuse->num_socks + reuse->num_closed_socks == reuse->max_socks) {
- reuse = reuseport_grow(reuse);
- if (!reuse) {
- spin_unlock_bh(&reuseport_lock);
-@@ -166,10 +214,7 @@ int reuseport_add_sock(struct sock *sk, struct sock *sk2, bool bind_inany)
- }
- }
-
-- reuse->socks[reuse->num_socks] = sk;
-- /* paired with smp_rmb() in reuseport_select_sock() */
-- smp_wmb();
-- reuse->num_socks++;
-+ __reuseport_add_sock(sk, reuse);
- rcu_assign_pointer(sk->sk_reuseport_cb, reuse);
-
- spin_unlock_bh(&reuseport_lock);
-@@ -183,7 +228,6 @@ EXPORT_SYMBOL(reuseport_add_sock);
- void reuseport_detach_sock(struct sock *sk)
- {
- struct sock_reuseport *reuse;
-- int i;
-
- spin_lock_bh(&reuseport_lock);
- reuse = rcu_dereference_protected(sk->sk_reuseport_cb,
-@@ -200,16 +244,11 @@ void reuseport_detach_sock(struct sock *sk)
- bpf_sk_reuseport_detach(sk);
-
- rcu_assign_pointer(sk->sk_reuseport_cb, NULL);
-+ __reuseport_detach_sock(sk, reuse);
-+
-+ if (reuse->num_socks + reuse->num_closed_socks == 0)
-+ call_rcu(&reuse->rcu, reuseport_free_rcu);
-
-- for (i = 0; i < reuse->num_socks; i++) {
-- if (reuse->socks[i] == sk) {
-- reuse->socks[i] = reuse->socks[reuse->num_socks - 1];
-- reuse->num_socks--;
-- if (reuse->num_socks == 0)
-- call_rcu(&reuse->rcu, reuseport_free_rcu);
-- break;
-- }
-- }
- spin_unlock_bh(&reuseport_lock);
- }
- EXPORT_SYMBOL(reuseport_detach_sock);
-@@ -274,7 +313,7 @@ struct sock *reuseport_select_sock(struct sock *sk,
- prog = rcu_dereference(reuse->prog);
- socks = READ_ONCE(reuse->num_socks);
- if (likely(socks)) {
-- /* paired with smp_wmb() in reuseport_add_sock() */
-+ /* paired with smp_wmb() in __reuseport_add_sock() */
- smp_rmb();
-
- if (!prog || !skb)
---
-2.35.1
-
-From 4b84c215237ebacc8ee55b1ab4c829614b619842 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
+From 69421bf98482d089e50799f45e48b25ce4a8d154 Mon Sep 17 00:00:00 2001
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
Date: Fri, 14 Oct 2022 11:26:25 -0700
Subject: udp: Update reuse->has_conns under reuseport_lock.
From: Kuniyuki Iwashima <kuniyu@amazon.com>
-[ Upstream commit 69421bf98482d089e50799f45e48b25ce4a8d154 ]
+commit 69421bf98482d089e50799f45e48b25ce4a8d154 upstream.
When we call connect() for a UDP socket in a reuseport group, we have
to update sk->sk_reuseport_cb->has_conns to 1. Otherwise, the kernel
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Link: https://lore.kernel.org/r/20221014182625.89913-1-kuniyu@amazon.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
- include/net/sock_reuseport.h | 11 +++++------
- net/core/sock_reuseport.c | 16 ++++++++++++++++
- net/ipv4/datagram.c | 2 +-
- net/ipv4/udp.c | 2 +-
- net/ipv6/datagram.c | 2 +-
- net/ipv6/udp.c | 2 +-
+ include/net/sock_reuseport.h | 11 +++++------
+ net/core/sock_reuseport.c | 16 ++++++++++++++++
+ net/ipv4/datagram.c | 2 +-
+ net/ipv4/udp.c | 2 +-
+ net/ipv6/datagram.c | 2 +-
+ net/ipv6/udp.c | 2 +-
6 files changed, 25 insertions(+), 10 deletions(-)
-diff --git a/include/net/sock_reuseport.h b/include/net/sock_reuseport.h
-index 0e558ca7afbf..6348c6f26903 100644
--- a/include/net/sock_reuseport.h
+++ b/include/net/sock_reuseport.h
-@@ -39,21 +39,20 @@ extern struct sock *reuseport_select_sock(struct sock *sk,
+@@ -38,21 +38,20 @@ extern struct sock *reuseport_select_soc
extern int reuseport_attach_prog(struct sock *sk, struct bpf_prog *prog);
extern int reuseport_detach_prog(struct sock *sk);
+void reuseport_has_conns_set(struct sock *sk);
+
#endif /* _SOCK_REUSEPORT_H */
-diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c
-index f478c65a281b..364cf6c6912b 100644
--- a/net/core/sock_reuseport.c
+++ b/net/core/sock_reuseport.c
@@ -18,6 +18,22 @@ DEFINE_SPINLOCK(reuseport_lock);
+}
+EXPORT_SYMBOL(reuseport_has_conns_set);
+
- static int reuseport_sock_index(struct sock *sk,
- const struct sock_reuseport *reuse,
- bool closed)
-diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c
-index 4a8550c49202..112c6e892d30 100644
+ static struct sock_reuseport *__reuseport_alloc(unsigned int max_socks)
+ {
+ unsigned int size = sizeof(struct sock_reuseport) +
--- a/net/ipv4/datagram.c
+++ b/net/ipv4/datagram.c
-@@ -70,7 +70,7 @@ int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
+@@ -70,7 +70,7 @@ int __ip4_datagram_connect(struct sock *
}
inet->inet_daddr = fl4->daddr;
inet->inet_dport = usin->sin_port;
sk->sk_state = TCP_ESTABLISHED;
sk_set_txhash(sk);
inet->inet_id = prandom_u32();
-diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
-index 4446aa8237ff..b093daaa3deb 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
-@@ -446,7 +446,7 @@ static struct sock *udp4_lib_lookup2(struct net *net,
+@@ -446,7 +446,7 @@ static struct sock *udp4_lib_lookup2(str
result = lookup_reuseport(net, sk, skb,
saddr, sport, daddr, hnum);
/* Fall back to scoring if group has connections */
return result;
result = result ? : sk;
-diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
-index 206f66310a88..f4559e5bc84b 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
-@@ -256,7 +256,7 @@ int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr,
+@@ -256,7 +256,7 @@ ipv4_connected:
goto out;
}
sk->sk_state = TCP_ESTABLISHED;
sk_set_txhash(sk);
out:
-diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
-index 9b504bf49214..514e6a55959f 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
-@@ -179,7 +179,7 @@ static struct sock *udp6_lib_lookup2(struct net *net,
+@@ -179,7 +179,7 @@ static struct sock *udp6_lib_lookup2(str
result = lookup_reuseport(net, sk, skb,
saddr, sport, daddr, hnum);
/* Fall back to scoring if group has connections */
return result;
result = result ? : sk;
---
-2.35.1
-