diff mbox series

[net-next,1/4] selftests: drv-net: try to check if port is in use

Message ID 20240620232902.1343834-2-kuba@kernel.org (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series selftests: drv-net: rss_ctx: add tests for RSS contexts | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 8 this patch: 8
netdev/build_tools success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers warning 2 maintainers not CCed: shuah@kernel.org linux-kselftest@vger.kernel.org
netdev/build_clang success Errors and warnings before: 8 this patch: 8
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 8 this patch: 8
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 25 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Jakub Kicinski June 20, 2024, 11:28 p.m. UTC
We use random ports for communication. As Willem predicted
this leads to occasional failures. Try to check if port is
already in use by opening a socket and binding to that port.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
 tools/testing/selftests/net/lib/py/utils.py | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

Comments

David Wei June 21, 2024, 1:52 a.m. UTC | #1
On 2024-06-20 16:28, Jakub Kicinski wrote:
> We use random ports for communication. As Willem predicted
> this leads to occasional failures. Try to check if port is
> already in use by opening a socket and binding to that port.
> 
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> ---
>  tools/testing/selftests/net/lib/py/utils.py | 13 ++++++++++++-
>  1 file changed, 12 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/selftests/net/lib/py/utils.py
> index 0540ea24921d..9fa9ec720c89 100644
> --- a/tools/testing/selftests/net/lib/py/utils.py
> +++ b/tools/testing/selftests/net/lib/py/utils.py
> @@ -3,6 +3,7 @@
>  import json as _json
>  import random
>  import re
> +import socket
>  import subprocess
>  import time
>  
> @@ -81,7 +82,17 @@ import time
>      """
>      Get unprivileged port, for now just random, one day we may decide to check if used.

That day is today ;)

>      """
> -    return random.randint(10000, 65535)
> +    while True:
> +        port = random.randint(10000, 65535)
> +        try:
> +            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
> +                s.bind(("", port))
> +            with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
> +                s.bind(("", port))
> +            return port
> +        except OSError as e:
> +            if e.errno != 98:  # already in use
> +                raise
>  
>  
>  def wait_port_listen(port, proto="tcp", ns=None, host=None, sleep=0.005, deadline=5):
Willem de Bruijn June 23, 2024, 7:34 a.m. UTC | #2
Jakub Kicinski wrote:
> We use random ports for communication. As Willem predicted
> this leads to occasional failures. Try to check if port is
> already in use by opening a socket and binding to that port.
> 
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> ---
>  tools/testing/selftests/net/lib/py/utils.py | 13 ++++++++++++-
>  1 file changed, 12 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/selftests/net/lib/py/utils.py
> index 0540ea24921d..9fa9ec720c89 100644
> --- a/tools/testing/selftests/net/lib/py/utils.py
> +++ b/tools/testing/selftests/net/lib/py/utils.py
> @@ -3,6 +3,7 @@
>  import json as _json
>  import random
>  import re
> +import socket
>  import subprocess
>  import time
>  
> @@ -81,7 +82,17 @@ import time
>      """
>      Get unprivileged port, for now just random, one day we may decide to check if used.
>      """
> -    return random.randint(10000, 65535)
> +    while True:
> +        port = random.randint(10000, 65535)
> +        try:
> +            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
> +                s.bind(("", port))
> +            with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
> +                s.bind(("", port))

Is the separate AF_INET needed? As AF_INET6 is not IPV6_V6ONLY.

The following correctly fails in the second bind

    with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s6:
      s6.bind(("", 8000))
      with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s4:
          s4.bind(("", 8000))


> +            return port
> +        except OSError as e:
> +            if e.errno != 98:  # already in use
> +                raise
>  
>  
>  def wait_port_listen(port, proto="tcp", ns=None, host=None, sleep=0.005, deadline=5):
> -- 
> 2.45.2
>
Przemek Kitszel June 24, 2024, 1:59 p.m. UTC | #3
On 6/21/24 01:28, Jakub Kicinski wrote:
> We use random ports for communication. As Willem predicted
> this leads to occasional failures. Try to check if port is
> already in use by opening a socket and binding to that port.
> 
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> ---
>   tools/testing/selftests/net/lib/py/utils.py | 13 ++++++++++++-
>   1 file changed, 12 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/selftests/net/lib/py/utils.py
> index 0540ea24921d..9fa9ec720c89 100644
> --- a/tools/testing/selftests/net/lib/py/utils.py
> +++ b/tools/testing/selftests/net/lib/py/utils.py
> @@ -3,6 +3,7 @@
>   import json as _json
>   import random
>   import re
> +import socket
>   import subprocess
>   import time
>   
> @@ -81,7 +82,17 @@ import time
>       """
>       Get unprivileged port, for now just random, one day we may decide to check if used.
>       """

nit: this comment could be now updated

> -    return random.randint(10000, 65535)
> +    while True:

nit: perhaps you could limit the loop to some finite number of steps
for the case that all ports are in use :P

> +        port = random.randint(10000, 65535)
> +        try:
> +            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
> +                s.bind(("", port))
> +            with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
> +                s.bind(("", port))
> +            return port
> +        except OSError as e:
> +            if e.errno != 98:  # already in use
> +                raise
>   
>   
>   def wait_port_listen(port, proto="tcp", ns=None, host=None, sleep=0.005, deadline=5):
diff mbox series

Patch

diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/selftests/net/lib/py/utils.py
index 0540ea24921d..9fa9ec720c89 100644
--- a/tools/testing/selftests/net/lib/py/utils.py
+++ b/tools/testing/selftests/net/lib/py/utils.py
@@ -3,6 +3,7 @@ 
 import json as _json
 import random
 import re
+import socket
 import subprocess
 import time
 
@@ -81,7 +82,17 @@  import time
     """
     Get unprivileged port, for now just random, one day we may decide to check if used.
     """
-    return random.randint(10000, 65535)
+    while True:
+        port = random.randint(10000, 65535)
+        try:
+            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
+                s.bind(("", port))
+            with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
+                s.bind(("", port))
+            return port
+        except OSError as e:
+            if e.errno != 98:  # already in use
+                raise
 
 
 def wait_port_listen(port, proto="tcp", ns=None, host=None, sleep=0.005, deadline=5):