mptcp: more careful RM_ADDR generation
authorPaolo Abeni <pabeni@redhat.com>
Mon, 7 Mar 2022 20:44:35 +0000 (12:44 -0800)
committerJakub Kicinski <kuba@kernel.org>
Wed, 9 Mar 2022 06:06:11 +0000 (22:06 -0800)
The in-kernel MPTCP path manager, when processing the MPTCP_PM_CMD_FLUSH_ADDR
command, generates RM_ADDR events for each known local address. While that
is allowed by the RFC, it makes unpredictable the exact number of RM_ADDR
generated when both ends flush the PM addresses.

This change restricts the RM_ADDR generation to previously explicitly
announced addresses, and adjust the expected results in a bunch of related
self-tests.

Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/mptcp/pm_netlink.c
tools/testing/selftests/net/mptcp/mptcp_join.sh

index 75a0a27..91b77d1 100644 (file)
@@ -1466,14 +1466,12 @@ static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk,
 
        list_for_each_entry(entry, rm_list, list) {
                if (lookup_subflow_by_saddr(&msk->conn_list, &entry->addr) &&
-                   alist.nr < MPTCP_RM_IDS_MAX &&
-                   slist.nr < MPTCP_RM_IDS_MAX) {
-                       alist.ids[alist.nr++] = entry->addr.id;
+                   slist.nr < MPTCP_RM_IDS_MAX)
                        slist.ids[slist.nr++] = entry->addr.id;
-               } else if (remove_anno_list_by_saddr(msk, &entry->addr) &&
-                        alist.nr < MPTCP_RM_IDS_MAX) {
+
+               if (remove_anno_list_by_saddr(msk, &entry->addr) &&
+                   alist.nr < MPTCP_RM_IDS_MAX)
                        alist.ids[alist.nr++] = entry->addr.id;
-               }
        }
 
        if (alist.nr) {
index d4769bc..02bab8a 100755 (executable)
@@ -1149,14 +1149,25 @@ chk_rm_nr()
 {
        local rm_addr_nr=$1
        local rm_subflow_nr=$2
-       local invert=${3:-""}
+       local invert
+       local simult
        local count
        local dump_stats
        local addr_ns=$ns1
        local subflow_ns=$ns2
        local extra_msg=""
 
-       if [[ $invert = "invert" ]]; then
+       shift 2
+       while [ -n "$1" ]; do
+               [ "$1" = "invert" ] && invert=true
+               [ "$1" = "simult" ] && simult=true
+               shift
+       done
+
+       if [ -z $invert ]; then
+               addr_ns=$ns1
+               subflow_ns=$ns2
+       elif [ $invert = "true" ]; then
                addr_ns=$ns2
                subflow_ns=$ns1
                extra_msg="   invert"
@@ -1176,6 +1187,25 @@ chk_rm_nr()
        echo -n " - rmsf  "
        count=`ip netns exec $subflow_ns nstat -as | grep MPTcpExtRmSubflow | awk '{print $2}'`
        [ -z "$count" ] && count=0
+       if [ -n "$simult" ]; then
+               local cnt=$(ip netns exec $addr_ns nstat -as | grep MPTcpExtRmSubflow | awk '{print $2}')
+               local suffix
+
+               # in case of simult flush, the subflow removal count on each side is
+               # unreliable
+               [ -z "$cnt" ] && cnt=0
+               count=$((count + cnt))
+               [ "$count" != "$rm_subflow_nr" ] && suffix="$count in [$rm_subflow_nr:$((rm_subflow_nr*2))]"
+               if [ $count -ge "$rm_subflow_nr" ] && \
+                  [ "$count" -le "$((rm_subflow_nr *2 ))" ]; then
+                       echo "[ ok ] $suffix"
+               else
+                       echo "[fail] got $count RM_SUBFLOW[s] expected in range [$rm_subflow_nr:$((rm_subflow_nr*2))]"
+                       ret=1
+                       dump_stats=1
+               fi
+               return
+       fi
        if [ "$count" != "$rm_subflow_nr" ]; then
                echo "[fail] got $count RM_SUBFLOW[s] expected $rm_subflow_nr"
                ret=1
@@ -1666,7 +1696,7 @@ remove_tests()
        run_tests $ns1 $ns2 10.0.1.1 0 -8 -8 slow
        chk_join_nr "flush subflows and signal" 3 3 3
        chk_add_nr 1 1
-       chk_rm_nr 2 2
+       chk_rm_nr 1 3 invert simult
 
        # subflows flush
        reset
@@ -1677,7 +1707,7 @@ remove_tests()
        pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
        run_tests $ns1 $ns2 10.0.1.1 0 -8 -8 slow
        chk_join_nr "flush subflows" 3 3 3
-       chk_rm_nr 3 3
+       chk_rm_nr 0 3 simult
 
        # addresses flush
        reset
@@ -1689,7 +1719,7 @@ remove_tests()
        run_tests $ns1 $ns2 10.0.1.1 0 -8 -8 slow
        chk_join_nr "flush addresses" 3 3 3
        chk_add_nr 3 3
-       chk_rm_nr 3 3 invert
+       chk_rm_nr 3 3 invert simult
 
        # invalid addresses flush
        reset
@@ -1973,7 +2003,7 @@ add_addr_ports_tests()
        run_tests $ns1 $ns2 10.0.1.1 0 -8 -2 slow
        chk_join_nr "flush subflows and signal with port" 3 3 3
        chk_add_nr 1 1
-       chk_rm_nr 2 2
+       chk_rm_nr 1 3 invert simult
 
        # multiple addresses with port
        reset