[PATCH net v3 2/2] selftests/net: test TCP reuseport socket selection

Menglong Dong posted 2 patches 2 months ago
[PATCH net v3 2/2] selftests/net: test TCP reuseport socket selection
Posted by Menglong Dong 2 months ago
The test script is provided by Kuniyuki in [1], which is used to test the
selection of the TCP reuseport socket problem.

Link: https://lore.kernel.org/netdev/20250801040757.1599996-1-kuniyu@google.com/ [1]
Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
---
 tools/testing/selftests/net/Makefile         |  1 +
 tools/testing/selftests/net/tcp_reuseport.py | 36 ++++++++++++++++++++
 2 files changed, 37 insertions(+)
 create mode 100755 tools/testing/selftests/net/tcp_reuseport.py

diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index b31a71f2b372..0f4c3eea9709 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -117,6 +117,7 @@ TEST_GEN_FILES += tfo
 TEST_PROGS += tfo_passive.sh
 TEST_PROGS += broadcast_pmtu.sh
 TEST_PROGS += ipv6_force_forwarding.sh
+TEST_PROGS += tcp_reuseport.py
 
 # YNL files, must be before "include ..lib.mk"
 YNL_GEN_FILES := busy_poller netlink-dumps
diff --git a/tools/testing/selftests/net/tcp_reuseport.py b/tools/testing/selftests/net/tcp_reuseport.py
new file mode 100755
index 000000000000..eaeb7096382e
--- /dev/null
+++ b/tools/testing/selftests/net/tcp_reuseport.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+
+import os
+
+from lib.py import ksft_run, ksft_exit
+from socket import *
+
+def test_reuseport_select() -> None:
+    s1 = socket()
+    s1.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
+    s1.setsockopt(SOL_SOCKET, SO_BINDTODEVICE, b'lo')
+    s1.listen()
+    s1.setblocking(False)
+
+    s2 = socket()
+    s2.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
+    s2.bind(s1.getsockname())
+    s2.listen()
+    s2.setblocking(False)
+
+    for i in range(3):
+        c = socket()
+        c.connect(s1.getsockname())
+        try:
+            print("SUCCESS: assigned properly:", s1.accept())
+        except:
+            print("FAIL: wrong assignment")
+            os.sys.exit(1)
+
+def main() -> None:
+    ksft_run([test_reuseport_select])
+    ksft_exit()
+
+if __name__ == "__main__":
+    main()
-- 
2.50.1
Re: [PATCH net v3 2/2] selftests/net: test TCP reuseport socket selection
Posted by Kuniyuki Iwashima 2 months ago
On Sat, Aug 2, 2025 at 2:24 AM Menglong Dong <menglong8.dong@gmail.com> wrote:
>
> The test script is provided by Kuniyuki in [1], which is used to test the
> selection of the TCP reuseport socket problem.
>
> Link: https://lore.kernel.org/netdev/20250801040757.1599996-1-kuniyu@google.com/ [1]
> Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
> ---
>  tools/testing/selftests/net/Makefile         |  1 +
>  tools/testing/selftests/net/tcp_reuseport.py | 36 ++++++++++++++++++++
>  2 files changed, 37 insertions(+)
>  create mode 100755 tools/testing/selftests/net/tcp_reuseport.py
>
> diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
> index b31a71f2b372..0f4c3eea9709 100644
> --- a/tools/testing/selftests/net/Makefile
> +++ b/tools/testing/selftests/net/Makefile
> @@ -117,6 +117,7 @@ TEST_GEN_FILES += tfo
>  TEST_PROGS += tfo_passive.sh
>  TEST_PROGS += broadcast_pmtu.sh
>  TEST_PROGS += ipv6_force_forwarding.sh
> +TEST_PROGS += tcp_reuseport.py
>
>  # YNL files, must be before "include ..lib.mk"
>  YNL_GEN_FILES := busy_poller netlink-dumps
> diff --git a/tools/testing/selftests/net/tcp_reuseport.py b/tools/testing/selftests/net/tcp_reuseport.py
> new file mode 100755
> index 000000000000..eaeb7096382e
> --- /dev/null
> +++ b/tools/testing/selftests/net/tcp_reuseport.py
> @@ -0,0 +1,36 @@
> +#!/usr/bin/env python3
> +# SPDX-License-Identifier: GPL-2.0
> +
> +import os
> +
> +from lib.py import ksft_run, ksft_exit
> +from socket import *
> +
> +def test_reuseport_select() -> None:
> +    s1 = socket()
> +    s1.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
> +    s1.setsockopt(SOL_SOCKET, SO_BINDTODEVICE, b'lo')
> +    s1.listen()
> +    s1.setblocking(False)
> +
> +    s2 = socket()
> +    s2.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
> +    s2.bind(s1.getsockname())
> +    s2.listen()
> +    s2.setblocking(False)
> +
> +    for i in range(3):
> +        c = socket()
> +        c.connect(s1.getsockname())
> +        try:
> +            print("SUCCESS: assigned properly:", s1.accept())
> +        except:
> +            print("FAIL: wrong assignment")
> +            os.sys.exit(1)

It seems you don't need to handle an exception with ksft.
You can see os.sys.exit(1) triggers another exception when
you run it without patch 1.

TAP version 13
1..1
# timeout set to 3600
# selftests: net: tcp_reuseport.py
# TAP version 13
# 1..1
# FAIL: wrong assignment
# # Exception| Traceback (most recent call last):
# # Exception|   File
"/root/linux/tools/testing/selftests/net/./tcp_reuseport.py", line 26,
in test_reuseport_select
# # Exception|     print("SUCCESS: assigned properly:", s1.accept())
# # Exception|                                          ~~~~~~~~~^^
# # Exception|   File "/usr/lib64/python3.13/socket.py", line 295, in accept
# # Exception|     fd, addr = self._accept()
# # Exception|                ~~~~~~~~~~~~^^
# # Exception| BlockingIOError: [Errno 11] Resource temporarily unavailable
# # Exception|
# # Exception| During handling of the above exception, another
exception occurred:
# # Exception|
# # Exception| Traceback (most recent call last):
# # Exception|   File
"/root/linux/tools/testing/selftests/net/lib/py/ksft.py", line 244, in
ksft_run
# # Exception|     case(*args)
# # Exception|     ~~~~^^^^^^^
# # Exception|   File
"/root/linux/tools/testing/selftests/net/./tcp_reuseport.py", line 29,
in test_reuseport_select
# # Exception|     os.sys.exit(1)
# # Exception|     ~~~~~~~~~~~^^^
# # Exception| SystemExit: 1
# not ok 1 tcp_reuseport.test_reuseport_select
# # Totals: pass:0 fail:1 xfail:0 xpass:0 skip:0 error:0
not ok 1 selftests: net: tcp_reuseport.py # exit=1


btw, I'd write an official uAPI selftest in plain C for socket as
python sometimes does a tricky thing and I don't trust it.

For example, this is...

from socket import *

s = socket()
s.listen(-1)

internally translated to:

socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 3
listen(3, 0)                            = 0
Re: [PATCH net v3 2/2] selftests/net: test TCP reuseport socket selection
Posted by Menglong Dong 1 month, 3 weeks ago
On Wed, Aug 6, 2025 at 3:01 AM Kuniyuki Iwashima <kuniyu@google.com> wrote:
>
> On Sat, Aug 2, 2025 at 2:24 AM Menglong Dong <menglong8.dong@gmail.com> wrote:
> >
> > The test script is provided by Kuniyuki in [1], which is used to test the
> > selection of the TCP reuseport socket problem.
> >
> > Link: https://lore.kernel.org/netdev/20250801040757.1599996-1-kuniyu@google.com/ [1]
> > Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
> > ---
> >  tools/testing/selftests/net/Makefile         |  1 +
> >  tools/testing/selftests/net/tcp_reuseport.py | 36 ++++++++++++++++++++
> >  2 files changed, 37 insertions(+)
> >  create mode 100755 tools/testing/selftests/net/tcp_reuseport.py
> >
> > diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
> > index b31a71f2b372..0f4c3eea9709 100644
> > --- a/tools/testing/selftests/net/Makefile
> > +++ b/tools/testing/selftests/net/Makefile
> > @@ -117,6 +117,7 @@ TEST_GEN_FILES += tfo
> >  TEST_PROGS += tfo_passive.sh
> >  TEST_PROGS += broadcast_pmtu.sh
> >  TEST_PROGS += ipv6_force_forwarding.sh
> > +TEST_PROGS += tcp_reuseport.py
> >
> >  # YNL files, must be before "include ..lib.mk"
> >  YNL_GEN_FILES := busy_poller netlink-dumps
> > diff --git a/tools/testing/selftests/net/tcp_reuseport.py b/tools/testing/selftests/net/tcp_reuseport.py
> > new file mode 100755
> > index 000000000000..eaeb7096382e
> > --- /dev/null
> > +++ b/tools/testing/selftests/net/tcp_reuseport.py
> > @@ -0,0 +1,36 @@
> > +#!/usr/bin/env python3
> > +# SPDX-License-Identifier: GPL-2.0
> > +
> > +import os
> > +
> > +from lib.py import ksft_run, ksft_exit
> > +from socket import *
> > +
> > +def test_reuseport_select() -> None:
> > +    s1 = socket()
> > +    s1.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
> > +    s1.setsockopt(SOL_SOCKET, SO_BINDTODEVICE, b'lo')
> > +    s1.listen()
> > +    s1.setblocking(False)
> > +
> > +    s2 = socket()
> > +    s2.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
> > +    s2.bind(s1.getsockname())
> > +    s2.listen()
> > +    s2.setblocking(False)
> > +
> > +    for i in range(3):
> > +        c = socket()
> > +        c.connect(s1.getsockname())
> > +        try:
> > +            print("SUCCESS: assigned properly:", s1.accept())
> > +        except:
> > +            print("FAIL: wrong assignment")
> > +            os.sys.exit(1)
>
> It seems you don't need to handle an exception with ksft.
> You can see os.sys.exit(1) triggers another exception when
> you run it without patch 1.
>
> TAP version 13
> 1..1
> # timeout set to 3600
> # selftests: net: tcp_reuseport.py
> # TAP version 13
> # 1..1
> # FAIL: wrong assignment
> # # Exception| Traceback (most recent call last):
> # # Exception|   File
> "/root/linux/tools/testing/selftests/net/./tcp_reuseport.py", line 26,
> in test_reuseport_select
> # # Exception|     print("SUCCESS: assigned properly:", s1.accept())
> # # Exception|                                          ~~~~~~~~~^^
> # # Exception|   File "/usr/lib64/python3.13/socket.py", line 295, in accept
> # # Exception|     fd, addr = self._accept()
> # # Exception|                ~~~~~~~~~~~~^^
> # # Exception| BlockingIOError: [Errno 11] Resource temporarily unavailable
> # # Exception|
> # # Exception| During handling of the above exception, another
> exception occurred:
> # # Exception|
> # # Exception| Traceback (most recent call last):
> # # Exception|   File
> "/root/linux/tools/testing/selftests/net/lib/py/ksft.py", line 244, in
> ksft_run
> # # Exception|     case(*args)
> # # Exception|     ~~~~^^^^^^^
> # # Exception|   File
> "/root/linux/tools/testing/selftests/net/./tcp_reuseport.py", line 29,
> in test_reuseport_select
> # # Exception|     os.sys.exit(1)
> # # Exception|     ~~~~~~~~~~~^^^
> # # Exception| SystemExit: 1
> # not ok 1 tcp_reuseport.test_reuseport_select
> # # Totals: pass:0 fail:1 xfail:0 xpass:0 skip:0 error:0
> not ok 1 selftests: net: tcp_reuseport.py # exit=1
>
>
> btw, I'd write an official uAPI selftest in plain C for socket as
> python sometimes does a tricky thing and I don't trust it.

Yeah, sounds nice, and C has better compatibility and
reliability for the testing.

>
> For example, this is...
>
> from socket import *
>
> s = socket()
> s.listen(-1)
>
> internally translated to:
>
> socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 3
> listen(3, 0)                            = 0