OSDN Git Service

Merge branch '10GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next
authorDavid S. Miller <davem@davemloft.net>
Wed, 9 Mar 2022 10:39:29 +0000 (10:39 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 9 Mar 2022 10:39:29 +0000 (10:39 +0000)
-queue

Tony Nguyen says:

====================
10GbE Intel Wired LAN Driver Updates 2022-03-08

This series contains updates to ixgbe and ixgbevf drivers.

Slawomir adds an implementation for ndo_set_vf_link_state() to allow
for disabling of VF link state as well a mailbox implementation so
the VF can query the state. Additionally, for 82599, the option to
disable a VF after receiving several malicious driver detection (MDD)
events are encountered is added. For ixgbevf, the corresponding
implementation to query and report a disabled state is added.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/prestera/prestera_acl.c
drivers/ptp/ptp_ocp.c
include/trace/events/mptcp.h
include/uapi/linux/mptcp.h
net/core/sock.c
net/mptcp/pm_netlink.c
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/subflow.c
tools/testing/selftests/net/mptcp/mptcp_join.sh
tools/testing/selftests/net/mptcp/pm_nl_ctl.c

index e4af8a5..47c899c 100644 (file)
@@ -91,7 +91,7 @@ static const struct rhashtable_params __prestera_acl_rule_entry_ht_params = {
 
 int prestera_acl_chain_to_client(u32 chain_index, u32 *client)
 {
-       u32 client_map[] = {
+       static const u32 client_map[] = {
                PRESTERA_HW_COUNTER_CLIENT_LOOKUP_0,
                PRESTERA_HW_COUNTER_CLIENT_LOOKUP_1,
                PRESTERA_HW_COUNTER_CLIENT_LOOKUP_2
index 334435e..d2d663e 100644 (file)
@@ -2608,7 +2608,7 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        err = pci_enable_device(pdev);
        if (err) {
                dev_err(&pdev->dev, "pci_enable_device\n");
-               goto out_unregister;
+               goto out_free;
        }
 
        bp = devlink_priv(devlink);
@@ -2654,7 +2654,7 @@ out:
        pci_set_drvdata(pdev, NULL);
 out_disable:
        pci_disable_device(pdev);
-out_unregister:
+out_free:
        devlink_free(devlink);
        return err;
 }
index 6bf4317..f8e28e6 100644 (file)
@@ -115,6 +115,10 @@ DECLARE_EVENT_CLASS(mptcp_dump_mpext,
                  __entry->csum_reqd)
 );
 
+DEFINE_EVENT(mptcp_dump_mpext, mptcp_sendmsg_frag,
+       TP_PROTO(struct mptcp_ext *mpext),
+       TP_ARGS(mpext));
+
 DEFINE_EVENT(mptcp_dump_mpext, get_mapping_status,
        TP_PROTO(struct mptcp_ext *mpext),
        TP_ARGS(mpext));
index f106a39..9690efe 100644 (file)
@@ -81,6 +81,7 @@ enum {
 #define MPTCP_PM_ADDR_FLAG_SUBFLOW                     (1 << 1)
 #define MPTCP_PM_ADDR_FLAG_BACKUP                      (1 << 2)
 #define MPTCP_PM_ADDR_FLAG_FULLMESH                    (1 << 3)
+#define MPTCP_PM_ADDR_FLAG_IMPLICIT                    (1 << 4)
 
 enum {
        MPTCP_PM_CMD_UNSPEC,
index 784c92e..1180a0c 100644 (file)
@@ -1377,9 +1377,9 @@ set_sndbuf:
                        if (!(sk_is_tcp(sk) ||
                              (sk->sk_type == SOCK_DGRAM &&
                               sk->sk_protocol == IPPROTO_UDP)))
-                               ret = -ENOTSUPP;
+                               ret = -EOPNOTSUPP;
                } else if (sk->sk_family != PF_RDS) {
-                       ret = -ENOTSUPP;
+                       ret = -EOPNOTSUPP;
                }
                if (!ret) {
                        if (val < 0 || val > 1)
index 75a0a27..800515f 100644 (file)
@@ -83,16 +83,6 @@ static bool addresses_equal(const struct mptcp_addr_info *a,
        return a->port == b->port;
 }
 
-static bool address_zero(const struct mptcp_addr_info *addr)
-{
-       struct mptcp_addr_info zero;
-
-       memset(&zero, 0, sizeof(zero));
-       zero.family = addr->family;
-
-       return addresses_equal(addr, &zero, true);
-}
-
 static void local_address(const struct sock_common *skc,
                          struct mptcp_addr_info *addr)
 {
@@ -877,10 +867,18 @@ static bool address_use_port(struct mptcp_pm_addr_entry *entry)
                MPTCP_PM_ADDR_FLAG_SIGNAL;
 }
 
+/* caller must ensure the RCU grace period is already elapsed */
+static void __mptcp_pm_release_addr_entry(struct mptcp_pm_addr_entry *entry)
+{
+       if (entry->lsk)
+               sock_release(entry->lsk);
+       kfree(entry);
+}
+
 static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
                                             struct mptcp_pm_addr_entry *entry)
 {
-       struct mptcp_pm_addr_entry *cur;
+       struct mptcp_pm_addr_entry *cur, *del_entry = NULL;
        unsigned int addr_max;
        int ret = -EINVAL;
 
@@ -901,8 +899,22 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
        list_for_each_entry(cur, &pernet->local_addr_list, list) {
                if (addresses_equal(&cur->addr, &entry->addr,
                                    address_use_port(entry) &&
-                                   address_use_port(cur)))
-                       goto out;
+                                   address_use_port(cur))) {
+                       /* allow replacing the exiting endpoint only if such
+                        * endpoint is an implicit one and the user-space
+                        * did not provide an endpoint id
+                        */
+                       if (!(cur->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT))
+                               goto out;
+                       if (entry->addr.id)
+                               goto out;
+
+                       pernet->addrs--;
+                       entry->addr.id = cur->addr.id;
+                       list_del_rcu(&cur->list);
+                       del_entry = cur;
+                       break;
+               }
        }
 
        if (!entry->addr.id) {
@@ -938,6 +950,12 @@ find_next:
 
 out:
        spin_unlock_bh(&pernet->lock);
+
+       /* just replaced an existing entry, free it */
+       if (del_entry) {
+               synchronize_rcu();
+               __mptcp_pm_release_addr_entry(del_entry);
+       }
        return ret;
 }
 
@@ -1011,9 +1029,6 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
        if (addresses_equal(&msk_local, &skc_local, false))
                return 0;
 
-       if (address_zero(&skc_local))
-               return 0;
-
        pernet = net_generic(sock_net((struct sock *)msk), pm_nl_pernet_id);
 
        rcu_read_lock();
@@ -1036,7 +1051,7 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
        entry->addr.id = 0;
        entry->addr.port = 0;
        entry->ifindex = 0;
-       entry->flags = 0;
+       entry->flags = MPTCP_PM_ADDR_FLAG_IMPLICIT;
        entry->lsk = NULL;
        ret = mptcp_pm_nl_append_new_local_addr(pernet, entry);
        if (ret < 0)
@@ -1249,6 +1264,17 @@ static int mptcp_nl_cmd_add_addr(struct sk_buff *skb, struct genl_info *info)
                return -EINVAL;
        }
 
+       if (addr.flags & MPTCP_PM_ADDR_FLAG_SIGNAL &&
+           addr.flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
+               GENL_SET_ERR_MSG(info, "flags mustn't have both signal and fullmesh");
+               return -EINVAL;
+       }
+
+       if (addr.flags & MPTCP_PM_ADDR_FLAG_IMPLICIT) {
+               GENL_SET_ERR_MSG(info, "can't create IMPLICIT endpoint");
+               return -EINVAL;
+       }
+
        entry = kmalloc(sizeof(*entry), GFP_KERNEL);
        if (!entry) {
                GENL_SET_ERR_MSG(info, "can't allocate addr");
@@ -1333,11 +1359,12 @@ static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk,
 }
 
 static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
-                                                  struct mptcp_addr_info *addr)
+                                                  const struct mptcp_pm_addr_entry *entry)
 {
-       struct mptcp_sock *msk;
-       long s_slot = 0, s_num = 0;
+       const struct mptcp_addr_info *addr = &entry->addr;
        struct mptcp_rm_list list = { .nr = 0 };
+       long s_slot = 0, s_num = 0;
+       struct mptcp_sock *msk;
 
        pr_debug("remove_id=%d", addr->id);
 
@@ -1354,7 +1381,8 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
 
                lock_sock(sk);
                remove_subflow = lookup_subflow_by_saddr(&msk->conn_list, addr);
-               mptcp_pm_remove_anno_addr(msk, addr, remove_subflow);
+               mptcp_pm_remove_anno_addr(msk, addr, remove_subflow &&
+                                         !(entry->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT));
                if (remove_subflow)
                        mptcp_pm_remove_subflow(msk, &list);
                release_sock(sk);
@@ -1367,14 +1395,6 @@ next:
        return 0;
 }
 
-/* caller must ensure the RCU grace period is already elapsed */
-static void __mptcp_pm_release_addr_entry(struct mptcp_pm_addr_entry *entry)
-{
-       if (entry->lsk)
-               sock_release(entry->lsk);
-       kfree(entry);
-}
-
 static int mptcp_nl_remove_id_zero_address(struct net *net,
                                           struct mptcp_addr_info *addr)
 {
@@ -1451,7 +1471,7 @@ static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
        __clear_bit(entry->addr.id, pernet->id_bitmap);
        spin_unlock_bh(&pernet->lock);
 
-       mptcp_nl_remove_subflow_and_signal_addr(sock_net(skb->sk), &entry->addr);
+       mptcp_nl_remove_subflow_and_signal_addr(sock_net(skb->sk), entry);
        synchronize_rcu();
        __mptcp_pm_release_addr_entry(entry);
 
@@ -1466,14 +1486,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 1c72f25..101aeeb 100644 (file)
@@ -117,6 +117,9 @@ static int __mptcp_socket_create(struct mptcp_sock *msk)
        list_add(&subflow->node, &msk->conn_list);
        sock_hold(ssock->sk);
        subflow->request_mptcp = 1;
+
+       /* This is the first subflow, always with id 0 */
+       subflow->local_id_valid = 1;
        mptcp_sock_graft(msk->first, sk->sk_socket);
 
        return 0;
@@ -1356,6 +1359,7 @@ alloc_skb:
 out:
        if (READ_ONCE(msk->csum_enabled))
                mptcp_update_data_checksum(skb, copy);
+       trace_mptcp_sendmsg_frag(mpext);
        mptcp_subflow_ctx(ssk)->rel_write_seq += copy;
        return copy;
 }
index 9d0ee6c..3c1a303 100644 (file)
@@ -442,7 +442,8 @@ struct mptcp_subflow_context {
                rx_eof : 1,
                can_ack : 1,        /* only after processing the remote a key */
                disposable : 1,     /* ctx can be free at ulp release time */
-               stale : 1;          /* unable to snd/rcv data, do not use for xmit */
+               stale : 1,          /* unable to snd/rcv data, do not use for xmit */
+               local_id_valid : 1; /* local_id is correctly initialized */
        enum mptcp_data_avail data_avail;
        u32     remote_nonce;
        u64     thmac;
index 45c004f..aba260f 100644 (file)
@@ -481,6 +481,51 @@ do_reset:
        mptcp_subflow_reset(sk);
 }
 
+static void subflow_set_local_id(struct mptcp_subflow_context *subflow, int local_id)
+{
+       subflow->local_id = local_id;
+       subflow->local_id_valid = 1;
+}
+
+static int subflow_chk_local_id(struct sock *sk)
+{
+       struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
+       struct mptcp_sock *msk = mptcp_sk(subflow->conn);
+       int err;
+
+       if (likely(subflow->local_id_valid))
+               return 0;
+
+       err = mptcp_pm_get_local_id(msk, (struct sock_common *)sk);
+       if (err < 0)
+               return err;
+
+       subflow_set_local_id(subflow, err);
+       return 0;
+}
+
+static int subflow_rebuild_header(struct sock *sk)
+{
+       int err = subflow_chk_local_id(sk);
+
+       if (unlikely(err < 0))
+               return err;
+
+       return inet_sk_rebuild_header(sk);
+}
+
+#if IS_ENABLED(CONFIG_MPTCP_IPV6)
+static int subflow_v6_rebuild_header(struct sock *sk)
+{
+       int err = subflow_chk_local_id(sk);
+
+       if (unlikely(err < 0))
+               return err;
+
+       return inet6_sk_rebuild_header(sk);
+}
+#endif
+
 struct request_sock_ops mptcp_subflow_request_sock_ops;
 static struct tcp_request_sock_ops subflow_request_sock_ipv4_ops __ro_after_init;
 
@@ -1104,7 +1149,7 @@ static bool subflow_check_data_avail(struct sock *ssk)
        struct sk_buff *skb;
 
        if (!skb_peek(&ssk->sk_receive_queue))
-               WRITE_ONCE(subflow->data_avail, 0);
+               WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA);
        if (subflow->data_avail)
                return true;
 
@@ -1169,7 +1214,7 @@ fallback:
                subflow->reset_transient = 0;
                subflow->reset_reason = MPTCP_RST_EMIDDLEBOX;
                tcp_send_active_reset(ssk, GFP_ATOMIC);
-               WRITE_ONCE(subflow->data_avail, 0);
+               WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA);
                return true;
        }
 
@@ -1182,7 +1227,7 @@ fallback:
                subflow->reset_transient = 0;
                subflow->reset_reason = MPTCP_RST_EMPTCP;
                tcp_send_active_reset(ssk, GFP_ATOMIC);
-               WRITE_ONCE(subflow->data_avail, 0);
+               WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA);
                return false;
        }
 
@@ -1204,7 +1249,7 @@ bool mptcp_subflow_data_available(struct sock *sk)
        if (subflow->map_valid &&
            mptcp_subflow_get_map_offset(subflow) >= subflow->map_data_len) {
                subflow->map_valid = 0;
-               WRITE_ONCE(subflow->data_avail, 0);
+               WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA);
 
                pr_debug("Done with mapping: seq=%u data_len=%u",
                         subflow->map_subflow_seq,
@@ -1398,13 +1443,8 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
                get_random_bytes(&subflow->local_nonce, sizeof(u32));
        } while (!subflow->local_nonce);
 
-       if (!local_id) {
-               err = mptcp_pm_get_local_id(msk, (struct sock_common *)ssk);
-               if (err < 0)
-                       goto failed;
-
-               local_id = err;
-       }
+       if (local_id)
+               subflow_set_local_id(subflow, local_id);
 
        mptcp_pm_get_flags_and_ifindex_by_id(sock_net(sk), local_id,
                                             &flags, &ifindex);
@@ -1429,7 +1469,6 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
        pr_debug("msk=%p remote_token=%u local_id=%d remote_id=%d", msk,
                 remote_token, local_id, remote_id);
        subflow->remote_token = remote_token;
-       subflow->local_id = local_id;
        subflow->remote_id = remote_id;
        subflow->request_join = 1;
        subflow->request_bkup = !!(flags & MPTCP_PM_ADDR_FLAG_BACKUP);
@@ -1728,15 +1767,22 @@ static void subflow_ulp_clone(const struct request_sock *req,
                new_ctx->token = subflow_req->token;
                new_ctx->ssn_offset = subflow_req->ssn_offset;
                new_ctx->idsn = subflow_req->idsn;
+
+               /* this is the first subflow, id is always 0 */
+               new_ctx->local_id_valid = 1;
        } else if (subflow_req->mp_join) {
                new_ctx->ssn_offset = subflow_req->ssn_offset;
                new_ctx->mp_join = 1;
                new_ctx->fully_established = 1;
                new_ctx->backup = subflow_req->backup;
-               new_ctx->local_id = subflow_req->local_id;
                new_ctx->remote_id = subflow_req->remote_id;
                new_ctx->token = subflow_req->token;
                new_ctx->thmac = subflow_req->thmac;
+
+               /* the subflow req id is valid, fetched via subflow_check_req()
+                * and subflow_token_join_request()
+                */
+               subflow_set_local_id(new_ctx, subflow_req->local_id);
        }
 }
 
@@ -1789,6 +1835,7 @@ void __init mptcp_subflow_init(void)
        subflow_specific.conn_request = subflow_v4_conn_request;
        subflow_specific.syn_recv_sock = subflow_syn_recv_sock;
        subflow_specific.sk_rx_dst_set = subflow_finish_connect;
+       subflow_specific.rebuild_header = subflow_rebuild_header;
 
        tcp_prot_override = tcp_prot;
        tcp_prot_override.release_cb = tcp_release_cb_override;
@@ -1801,6 +1848,7 @@ void __init mptcp_subflow_init(void)
        subflow_v6_specific.conn_request = subflow_v6_conn_request;
        subflow_v6_specific.syn_recv_sock = subflow_syn_recv_sock;
        subflow_v6_specific.sk_rx_dst_set = subflow_finish_connect;
+       subflow_v6_specific.rebuild_header = subflow_v6_rebuild_header;
 
        subflow_v6m_specific = subflow_v6_specific;
        subflow_v6m_specific.queue_xmit = ipv4_specific.queue_xmit;
@@ -1808,6 +1856,7 @@ void __init mptcp_subflow_init(void)
        subflow_v6m_specific.net_header_len = ipv4_specific.net_header_len;
        subflow_v6m_specific.mtu_reduced = ipv4_specific.mtu_reduced;
        subflow_v6m_specific.net_frag_header_len = 0;
+       subflow_v6m_specific.rebuild_header = subflow_rebuild_header;
 
        tcpv6_prot_override = tcpv6_prot;
        tcpv6_prot_override.release_cb = tcp_release_cb_override;
index 45c6e5f..ee43594 100755 (executable)
@@ -16,7 +16,6 @@ capture=0
 checksum=0
 ip_mptcp=0
 check_invert=0
-do_all_tests=1
 init=0
 
 TEST_COUNT=0
@@ -311,6 +310,21 @@ wait_rm_addr()
        done
 }
 
+wait_mpj()
+{
+       local ns="${1}"
+       local cnt old_cnt
+
+       old_cnt=$(ip netns exec ${ns} nstat -as | grep MPJoinAckRx | awk '{print $2}')
+
+       local i
+       for i in $(seq 10); do
+               cnt=$(ip netns exec ${ns} nstat -as | grep MPJoinAckRx | awk '{print $2}')
+               [ "$cnt" = "${old_cnt}" ] || break
+               sleep 0.1
+       done
+}
+
 pm_nl_set_limits()
 {
        local ns=$1
@@ -411,6 +425,80 @@ pm_nl_change_endpoint()
        fi
 }
 
+pm_nl_check_endpoint()
+{
+       local line expected_line
+       local title="$1"
+       local msg="$2"
+       local ns=$3
+       local addr=$4
+       local _flags=""
+       local flags
+       local _port
+       local port
+       local dev
+       local _id
+       local id
+
+       if [ -n "${title}" ]; then
+               printf "%03u %-36s %s" "${TEST_COUNT}" "${title}" "${msg}"
+       else
+               printf "%-${nr_blank}s %s" " " "${msg}"
+       fi
+
+       shift 4
+       while [ -n "$1" ]; do
+               if [ $1 = "flags" ]; then
+                       _flags=$2
+                       [ ! -z $_flags ]; flags="flags $_flags"
+                       shift
+               elif [ $1 = "dev" ]; then
+                       [ ! -z $2 ]; dev="dev $1"
+                       shift
+               elif [ $1 = "id" ]; then
+                       _id=$2
+                       [ ! -z $_id ]; id="id $_id"
+                       shift
+               elif [ $1 = "port" ]; then
+                       _port=$2
+                       [ ! -z $_port ]; port=" port $_port"
+                       shift
+               fi
+
+               shift
+       done
+
+       if [ -z "$id" ]; then
+               echo "[skip] bad test - missing endpoint id"
+               return
+       fi
+
+       if [ $ip_mptcp -eq 1 ]; then
+               line=$(ip -n $ns mptcp endpoint show $id)
+               # the dump order is: address id flags port dev
+               expected_line="$addr"
+               [ -n "$addr" ] && expected_line="$expected_line $addr"
+               expected_line="$expected_line $id"
+               [ -n "$_flags" ] && expected_line="$expected_line ${_flags//","/" "}"
+               [ -n "$dev" ] && expected_line="$expected_line $dev"
+               [ -n "$port" ] && expected_line="$expected_line $port"
+       else
+               line=$(ip netns exec $ns ./pm_nl_ctl get $_id)
+               # the dump order is: id flags dev address port
+               expected_line="$id"
+               [ -n "$flags" ] && expected_line="$expected_line $flags"
+               [ -n "$dev" ] && expected_line="$expected_line $dev"
+               [ -n "$addr" ] && expected_line="$expected_line $addr"
+               [ -n "$_port" ] && expected_line="$expected_line $_port"
+       fi
+       if [ "$line" = "$expected_line" ]; then
+               echo "[ ok ]"
+       else
+               echo "[fail] expected '$expected_line' found '$line'"
+               ret=1
+       fi
+}
+
 do_transfer()
 {
        listener_ns="$1"
@@ -1150,14 +1238,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"
@@ -1177,6 +1276,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
@@ -1243,7 +1361,7 @@ chk_link_usage()
        fi
 }
 
-wait_for_tw()
+wait_attempt_fail()
 {
        local timeout_ms=$((timeout_poll * 1000))
        local time=0
@@ -1362,7 +1480,7 @@ subflows_error_tests()
        TEST_COUNT=$((TEST_COUNT+1))
 
        # mpj subflow will be in TW after the reset
-       wait_for_tw $ns2
+       wait_attempt_fail $ns2
        pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
        wait
 
@@ -1667,7 +1785,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
@@ -1678,7 +1796,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
@@ -1690,7 +1808,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
@@ -1909,7 +2027,7 @@ backup_tests()
        run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow backup
        chk_join_nr "single address, backup" 1 1 1
        chk_add_nr 1 1
-       chk_prio_nr 1 0
+       chk_prio_nr 1 1
 
        # single address with port, backup
        reset
@@ -1919,7 +2037,7 @@ backup_tests()
        run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow backup
        chk_join_nr "single address with port, backup" 1 1 1
        chk_add_nr 1 1
-       chk_prio_nr 1 0
+       chk_prio_nr 1 1
 }
 
 add_addr_ports_tests()
@@ -1974,7 +2092,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
@@ -2240,6 +2358,30 @@ fastclose_tests()
        chk_rst_nr 1 1 invert
 }
 
+implicit_tests()
+{
+       # userspace pm type prevents add_addr
+       reset
+       pm_nl_set_limits $ns1 2 2
+       pm_nl_set_limits $ns2 2 2
+       pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+       run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow &
+
+       wait_mpj $ns1
+       TEST_COUNT=$((TEST_COUNT + 1))
+       pm_nl_check_endpoint "implicit EP" "creation" \
+               $ns2 10.0.2.2 id 1 flags implicit
+
+       pm_nl_add_endpoint $ns2 10.0.2.2 id 33
+       pm_nl_check_endpoint "" "ID change is prevented" \
+               $ns2 10.0.2.2 id 1 flags implicit
+
+       pm_nl_add_endpoint $ns2 10.0.2.2 flags signal
+       pm_nl_check_endpoint "" "modif is allowed" \
+               $ns2 10.0.2.2 id 1 flags signal
+       wait
+}
+
 all_tests()
 {
        subflows_tests
@@ -2258,6 +2400,7 @@ all_tests()
        deny_join_id0_tests
        fullmesh_tests
        fastclose_tests
+       implicit_tests
 }
 
 # [$1: error message]
@@ -2285,6 +2428,7 @@ usage()
        echo "  -d deny_join_id0_tests"
        echo "  -m fullmesh_tests"
        echo "  -z fastclose_tests"
+       echo "  -I implicit_tests"
        echo "  -c capture pcap files"
        echo "  -C enable data checksum"
        echo "  -i use ip mptcp"
@@ -2293,84 +2437,69 @@ usage()
        exit ${ret}
 }
 
-for arg in "$@"; do
-       # check for "capture/checksum" args before launching tests
-       if [[ "${arg}" =~ ^"-"[0-9a-zA-Z]*"c"[0-9a-zA-Z]*$ ]]; then
-               capture=1
-       fi
-       if [[ "${arg}" =~ ^"-"[0-9a-zA-Z]*"C"[0-9a-zA-Z]*$ ]]; then
-               checksum=1
-       fi
-       if [[ "${arg}" =~ ^"-"[0-9a-zA-Z]*"i"[0-9a-zA-Z]*$ ]]; then
-               ip_mptcp=1
-       fi
-
-       # exception for the capture/checksum/ip_mptcp options, the rest means: a part of the tests
-       if [ "${arg}" != "-c" ] && [ "${arg}" != "-C" ] && [ "${arg}" != "-i" ]; then
-               do_all_tests=0
-       fi
-done
-
-if [ $do_all_tests -eq 1 ]; then
-       all_tests
-       exit $ret
-fi
 
-while getopts 'fesltra64bpkdmchzCSi' opt; do
+tests=()
+while getopts 'fesltra64bpkdmchzICSi' opt; do
        case $opt in
                f)
-                       subflows_tests
+                       tests+=(subflows_tests)
                        ;;
                e)
-                       subflows_error_tests
+                       tests+=(subflows_error_tests)
                        ;;
                s)
-                       signal_address_tests
+                       tests+=(signal_address_tests)
                        ;;
                l)
-                       link_failure_tests
+                       tests+=(link_failure_tests)
                        ;;
                t)
-                       add_addr_timeout_tests
+                       tests+=(add_addr_timeout_tests)
                        ;;
                r)
-                       remove_tests
+                       tests+=(remove_tests)
                        ;;
                a)
-                       add_tests
+                       tests+=(add_tests)
                        ;;
                6)
-                       ipv6_tests
+                       tests+=(ipv6_tests)
                        ;;
                4)
-                       v4mapped_tests
+                       tests+=(v4mapped_tests)
                        ;;
                b)
-                       backup_tests
+                       tests+=(backup_tests)
                        ;;
                p)
-                       add_addr_ports_tests
+                       tests+=(add_addr_ports_tests)
                        ;;
                k)
-                       syncookies_tests
+                       tests+=(syncookies_tests)
                        ;;
                S)
-                       checksum_tests
+                       tests+=(checksum_tests)
                        ;;
                d)
-                       deny_join_id0_tests
+                       tests+=(deny_join_id0_tests)
                        ;;
                m)
-                       fullmesh_tests
+                       tests+=(fullmesh_tests)
                        ;;
                z)
-                       fastclose_tests
+                       tests+=(fastclose_tests)
+                       ;;
+               I)
+                       tests+=(implicit_tests)
                        ;;
                c)
+                       capture=1
                        ;;
                C)
+                       checksum=1
                        ;;
                i)
+                       ip_mptcp=1
                        ;;
                h)
                        usage
@@ -2381,4 +2510,12 @@ while getopts 'fesltra64bpkdmchzCSi' opt; do
        esac
 done
 
+if [ ${#tests[@]} -eq 0 ]; then
+       all_tests
+else
+       for subtests in "${tests[@]}"; do
+               "${subtests}"
+       done
+fi
+
 exit $ret
index 22a5ec1..a75a68a 100644 (file)
@@ -436,6 +436,13 @@ static void print_addr(struct rtattr *attrs, int len)
                                        printf(",");
                        }
 
+                       if (flags & MPTCP_PM_ADDR_FLAG_IMPLICIT) {
+                               printf("implicit");
+                               flags &= ~MPTCP_PM_ADDR_FLAG_IMPLICIT;
+                               if (flags)
+                                       printf(",");
+                       }
+
                        /* bump unknown flags, if any */
                        if (flags)
                                printf("0x%x", flags);