--- /dev/null
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+rndh=$(printf %x $sec)-$(mktemp -u XXXXXX)
+ns="ns1-$rndh"
+ksft_skip=4
+test_cnt=1
+ret=0
+pids=()
+
+flush_pids()
+{
+       # mptcp_connect in join mode will sleep a bit before completing,
+       # give it some time
+       sleep 1.1
+
+       for pid in ${pids[@]}; do
+               [ -d /proc/$pid ] && kill -SIGUSR1 $pid >/dev/null 2>&1
+       done
+       pids=()
+}
+
+cleanup()
+{
+       ip netns del $ns
+       for pid in ${pids[@]}; do
+               [ -d /proc/$pid ] && kill -9 $pid >/dev/null 2>&1
+       done
+}
+
+ip -Version > /dev/null 2>&1
+if [ $? -ne 0 ];then
+       echo "SKIP: Could not run test without ip tool"
+       exit $ksft_skip
+fi
+ss -h | grep -q MPTCP
+if [ $? -ne 0 ];then
+       echo "SKIP: ss tool does not support MPTCP"
+       exit $ksft_skip
+fi
+
+__chk_nr()
+{
+       local condition="$1"
+       local expected=$2
+       local msg nr
+
+       shift 2
+       msg=$*
+       nr=$(ss -inmHMN $ns | $condition)
+
+       printf "%-50s" "$msg"
+       if [ $nr != $expected ]; then
+               echo "[ fail ] expected $expected found $nr"
+               ret=$test_cnt
+       else
+               echo "[  ok  ]"
+       fi
+       test_cnt=$((test_cnt+1))
+}
+
+chk_msk_nr()
+{
+       __chk_nr "grep -c token:" $*
+}
+
+chk_msk_fallback_nr()
+{
+               __chk_nr "grep -c fallback" $*
+}
+
+chk_msk_remote_key_nr()
+{
+               __chk_nr "grep -c remote_key" $*
+}
+
+
+trap cleanup EXIT
+ip netns add $ns
+ip -n $ns link set dev lo up
+
+echo "a" | ip netns exec $ns ./mptcp_connect -p 10000 -l 0.0.0.0 -t 100 >/dev/null &
+sleep 0.1
+pids[0]=$!
+chk_msk_nr 0 "no msk on netns creation"
+
+echo "b" | ip netns exec $ns ./mptcp_connect -p 10000 127.0.0.1 -j -t 100 >/dev/null &
+sleep 0.1
+pids[1]=$!
+chk_msk_nr 2 "after MPC handshake "
+chk_msk_remote_key_nr 2 "....chk remote_key"
+chk_msk_fallback_nr 0 "....chk no fallback"
+flush_pids
+
+
+echo "a" | ip netns exec $ns ./mptcp_connect -p 10001 -s TCP -l 0.0.0.0 -t 100 >/dev/null &
+pids[0]=$!
+sleep 0.1
+echo "b" | ip netns exec $ns ./mptcp_connect -p 10001 127.0.0.1 -j -t 100 >/dev/null &
+pids[1]=$!
+sleep 0.1
+chk_msk_fallback_nr 1 "check fallback"
+flush_pids
+
+NR_CLIENTS=100
+for I in `seq 1 $NR_CLIENTS`; do
+       echo "a" | ip netns exec $ns ./mptcp_connect -p $((I+10001)) -l 0.0.0.0 -t 100 -w 10 >/dev/null  &
+       pids[$((I*2))]=$!
+done
+sleep 0.1
+
+for I in `seq 1 $NR_CLIENTS`; do
+       echo "b" | ip netns exec $ns ./mptcp_connect -p $((I+10001)) 127.0.0.1 -t 100 -w 10 >/dev/null &
+       pids[$((I*2 + 1))]=$!
+done
+sleep 1.5
+
+chk_msk_nr $((NR_CLIENTS*2)) "many msk socket present"
+flush_pids
+
+exit $ret
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <strings.h>
+#include <signal.h>
 #include <unistd.h>
 
 #include <sys/poll.h>
 
 static int  poll_timeout = 10 * 1000;
 static bool listen_mode;
+static bool quit;
 
 enum cfg_mode {
        CFG_MODE_POLL,
 static int cfg_sndbuf;
 static int cfg_rcvbuf;
 static bool cfg_join;
+static int cfg_wait;
 
 static void die_usage(void)
 {
        fprintf(stderr, "Usage: mptcp_connect [-6] [-u] [-s MPTCP|TCP] [-p port] [-m mode]"
-               "[-l] connect_address\n");
+               "[-l] [-w sec] connect_address\n");
        fprintf(stderr, "\t-6 use ipv6\n");
        fprintf(stderr, "\t-t num -- set poll timeout to num\n");
        fprintf(stderr, "\t-S num -- set SO_SNDBUF to num\n");
        fprintf(stderr, "\t-m [MPTCP|TCP] -- use tcp or mptcp sockets\n");
        fprintf(stderr, "\t-s [mmap|poll] -- use poll (default) or mmap\n");
        fprintf(stderr, "\t-u -- check mptcp ulp\n");
+       fprintf(stderr, "\t-w num -- wait num sec before closing the socket\n");
        exit(1);
 }
 
+static void handle_signal(int nr)
+{
+       quit = true;
+}
+
 static const char *getxinfo_strerr(int err)
 {
        if (err == EAI_SYSTEM)
        }
 
        /* leave some time for late join/announce */
-       if (cfg_join)
-               usleep(400000);
+       if (cfg_wait)
+               usleep(cfg_wait);
 
        close(peerfd);
        return 0;
 {
        int c;
 
-       while ((c = getopt(argc, argv, "6jlp:s:hut:m:S:R:")) != -1) {
+       while ((c = getopt(argc, argv, "6jlp:s:hut:m:S:R:w:")) != -1) {
                switch (c) {
                case 'j':
                        cfg_join = true;
                        cfg_mode = CFG_MODE_POLL;
+                       cfg_wait = 400000;
                        break;
                case 'l':
                        listen_mode = true;
                case 'R':
                        cfg_rcvbuf = parse_int(optarg);
                        break;
+               case 'w':
+                       cfg_wait = atoi(optarg)*1000000;
+                       break;
                }
        }
 
 {
        init_rng();
 
+       signal(SIGUSR1, handle_signal);
        parse_opts(argc, argv);
 
        if (tcpulp_audit)