selftests: mptcp: try to set mptcp ulp mode in different sk states
authorFlorian Westphal <fw@strlen.de>
Fri, 17 Dec 2021 23:37:01 +0000 (15:37 -0800)
committerJakub Kicinski <kuba@kernel.org>
Sat, 18 Dec 2021 03:27:04 +0000 (19:27 -0800)
The kernel will crash without
'mptcp: clear 'kern' flag from fallback sockets' change.

Since this doesn't slow down testing in a noticeable way,
run this unconditionally.

The explicit test did not catch this, because the check was done
for tcp socket returned by 'socket(.. IPPROTO_TCP) rather than a
tcp socket returned by accept() on a mptcp listen fd.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
tools/testing/selftests/net/mptcp/mptcp_connect.c
tools/testing/selftests/net/mptcp/mptcp_connect.sh

index 98de28a..a30e93c 100644 (file)
@@ -59,7 +59,6 @@ static enum cfg_peek cfg_peek = CFG_NONE_PEEK;
 static const char *cfg_host;
 static const char *cfg_port    = "12000";
 static int cfg_sock_proto      = IPPROTO_MPTCP;
-static bool tcpulp_audit;
 static int pf = AF_INET;
 static int cfg_sndbuf;
 static int cfg_rcvbuf;
@@ -103,7 +102,6 @@ static void die_usage(void)
        fprintf(stderr, "\t-s [MPTCP|TCP] -- use mptcp(default) or tcp sockets\n");
        fprintf(stderr, "\t-m [poll|mmap|sendfile] -- use poll(default)/mmap+write/sendfile\n");
        fprintf(stderr, "\t-M mark -- set socket packet mark\n");
-       fprintf(stderr, "\t-u -- check mptcp ulp\n");
        fprintf(stderr, "\t-w num -- wait num sec before closing the socket\n");
        fprintf(stderr, "\t-c cmsg -- test cmsg type <cmsg>\n");
        fprintf(stderr, "\t-o option -- test sockopt <option>\n");
@@ -215,6 +213,42 @@ static void set_transparent(int fd, int pf)
        }
 }
 
+static int do_ulp_so(int sock, const char *name)
+{
+       return setsockopt(sock, IPPROTO_TCP, TCP_ULP, name, strlen(name));
+}
+
+#define X(m)   xerror("%s:%u: %s: failed for proto %d at line %u", __FILE__, __LINE__, (m), proto, line)
+static void sock_test_tcpulp(int sock, int proto, unsigned int line)
+{
+       socklen_t buflen = 8;
+       char buf[8] = "";
+       int ret = getsockopt(sock, IPPROTO_TCP, TCP_ULP, buf, &buflen);
+
+       if (ret != 0)
+               X("getsockopt");
+
+       if (buflen > 0) {
+               if (strcmp(buf, "mptcp") != 0)
+                       xerror("unexpected ULP '%s' for proto %d at line %u", buf, proto, line);
+               ret = do_ulp_so(sock, "tls");
+               if (ret == 0)
+                       X("setsockopt");
+       } else if (proto == IPPROTO_MPTCP) {
+               ret = do_ulp_so(sock, "tls");
+               if (ret != -1)
+                       X("setsockopt");
+       }
+
+       ret = do_ulp_so(sock, "mptcp");
+       if (ret != -1)
+               X("setsockopt");
+
+#undef X
+}
+
+#define SOCK_TEST_TCPULP(s, p) sock_test_tcpulp((s), (p), __LINE__)
+
 static int sock_listen_mptcp(const char * const listenaddr,
                             const char * const port)
 {
@@ -238,6 +272,8 @@ static int sock_listen_mptcp(const char * const listenaddr,
                if (sock < 0)
                        continue;
 
+               SOCK_TEST_TCPULP(sock, cfg_sock_proto);
+
                if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one,
                                     sizeof(one)))
                        perror("setsockopt");
@@ -260,50 +296,17 @@ static int sock_listen_mptcp(const char * const listenaddr,
                return sock;
        }
 
+       SOCK_TEST_TCPULP(sock, cfg_sock_proto);
+
        if (listen(sock, 20)) {
                perror("listen");
                close(sock);
                return -1;
        }
 
-       return sock;
-}
+       SOCK_TEST_TCPULP(sock, cfg_sock_proto);
 
-static bool sock_test_tcpulp(const char * const remoteaddr,
-                            const char * const port)
-{
-       struct addrinfo hints = {
-               .ai_protocol = IPPROTO_TCP,
-               .ai_socktype = SOCK_STREAM,
-       };
-       struct addrinfo *a, *addr;
-       int sock = -1, ret = 0;
-       bool test_pass = false;
-
-       hints.ai_family = AF_INET;
-
-       xgetaddrinfo(remoteaddr, port, &hints, &addr);
-       for (a = addr; a; a = a->ai_next) {
-               sock = socket(a->ai_family, a->ai_socktype, IPPROTO_TCP);
-               if (sock < 0) {
-                       perror("socket");
-                       continue;
-               }
-               ret = setsockopt(sock, IPPROTO_TCP, TCP_ULP, "mptcp",
-                                sizeof("mptcp"));
-               if (ret == -1 && errno == EOPNOTSUPP)
-                       test_pass = true;
-               close(sock);
-
-               if (test_pass)
-                       break;
-               if (!ret)
-                       fprintf(stderr,
-                               "setsockopt(TCP_ULP) returned 0\n");
-               else
-                       perror("setsockopt(TCP_ULP)");
-       }
-       return test_pass;
+       return sock;
 }
 
 static int sock_connect_mptcp(const char * const remoteaddr,
@@ -326,6 +329,8 @@ static int sock_connect_mptcp(const char * const remoteaddr,
                        continue;
                }
 
+               SOCK_TEST_TCPULP(sock, proto);
+
                if (cfg_mark)
                        set_mark(sock, cfg_mark);
 
@@ -338,6 +343,8 @@ static int sock_connect_mptcp(const char * const remoteaddr,
        }
 
        freeaddrinfo(addr);
+       if (sock != -1)
+               SOCK_TEST_TCPULP(sock, proto);
        return sock;
 }
 
@@ -954,6 +961,8 @@ int main_loop_s(int listensock)
                check_sockaddr(pf, &ss, salen);
                check_getpeername(remotesock, &ss, salen);
 
+               SOCK_TEST_TCPULP(remotesock, 0);
+
                return copyfd_io(0, remotesock, 1);
        }
 
@@ -1059,6 +1068,8 @@ int main_loop(void)
 
        check_getpeername_connect(fd);
 
+       SOCK_TEST_TCPULP(fd, cfg_sock_proto);
+
        if (cfg_rcvbuf)
                set_rcvbuf(fd, cfg_rcvbuf);
        if (cfg_sndbuf)
@@ -1151,7 +1162,7 @@ static void parse_opts(int argc, char **argv)
 {
        int c;
 
-       while ((c = getopt(argc, argv, "6jr:lp:s:hut:T:m:S:R:w:M:P:c:o:")) != -1) {
+       while ((c = getopt(argc, argv, "6jr:lp:s:ht:T:m:S:R:w:M:P:c:o:")) != -1) {
                switch (c) {
                case 'j':
                        cfg_join = true;
@@ -1177,9 +1188,6 @@ static void parse_opts(int argc, char **argv)
                case 'h':
                        die_usage();
                        break;
-               case 'u':
-                       tcpulp_audit = true;
-                       break;
                case '6':
                        pf = AF_INET6;
                        break;
@@ -1233,9 +1241,6 @@ int main(int argc, char *argv[])
        signal(SIGUSR1, handle_signal);
        parse_opts(argc, argv);
 
-       if (tcpulp_audit)
-               return sock_test_tcpulp(cfg_host, cfg_port) ? 0 : 1;
-
        if (listen_mode) {
                int fd = sock_listen_mptcp(cfg_host, cfg_port);
 
index a4226b6..ee28f82 100755 (executable)
@@ -296,24 +296,6 @@ check_mptcp_disabled()
        return 0
 }
 
-check_mptcp_ulp_setsockopt()
-{
-       local t retval
-       t="ns_ulp-$sech-$(mktemp -u XXXXXX)"
-
-       ip netns add ${t} || exit $ksft_skip
-       if ! ip netns exec ${t} ./mptcp_connect -u -p 10000 -s TCP 127.0.0.1 2>&1; then
-               printf "setsockopt(..., TCP_ULP, \"mptcp\", ...) allowed\t[ FAIL ]\n"
-               retval=1
-               ret=$retval
-       else
-               printf "setsockopt(..., TCP_ULP, \"mptcp\", ...) blocked\t[ OK ]\n"
-               retval=0
-       fi
-       ip netns del ${t}
-       return $retval
-}
-
 # $1: IP address
 is_v6()
 {
@@ -780,8 +762,6 @@ make_file "$sin" "server"
 
 check_mptcp_disabled
 
-check_mptcp_ulp_setsockopt
-
 stop_if_error "The kernel configuration is not valid for MPTCP"
 
 echo "INFO: validating network environment with pings"