Merge 5.17-rc6 into char-misc-next
[linux-2.6-microblaze.git] / net / mptcp / pm_netlink.c
index 356f596..4b5d795 100644 (file)
@@ -546,6 +546,16 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
        if (msk->pm.add_addr_signaled < add_addr_signal_max) {
                local = select_signal_address(pernet, msk);
 
+               /* due to racing events on both ends we can reach here while
+                * previous add address is still running: if we invoke now
+                * mptcp_pm_announce_addr(), that will fail and the
+                * corresponding id will be marked as used.
+                * Instead let the PM machinery reschedule us when the
+                * current address announce will be completed.
+                */
+               if (msk->pm.addr_signal & BIT(MPTCP_ADD_ADDR_SIGNAL))
+                       return;
+
                if (local) {
                        if (mptcp_pm_alloc_anno_list(msk, local)) {
                                __clear_bit(local->addr.id, msk->pm.id_avail_bitmap);
@@ -650,6 +660,7 @@ static void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk)
        unsigned int add_addr_accept_max;
        struct mptcp_addr_info remote;
        unsigned int subflows_max;
+       bool reset_port = false;
        int i, nr;
 
        add_addr_accept_max = mptcp_pm_get_add_addr_accept_max(msk);
@@ -659,15 +670,19 @@ static void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk)
                 msk->pm.add_addr_accepted, add_addr_accept_max,
                 msk->pm.remote.family);
 
-       if (lookup_subflow_by_daddr(&msk->conn_list, &msk->pm.remote))
+       remote = msk->pm.remote;
+       if (lookup_subflow_by_daddr(&msk->conn_list, &remote))
                goto add_addr_echo;
 
+       /* pick id 0 port, if none is provided the remote address */
+       if (!remote.port) {
+               reset_port = true;
+               remote.port = sk->sk_dport;
+       }
+
        /* connect to the specified remote address, using whatever
         * local address the routing configuration will pick.
         */
-       remote = msk->pm.remote;
-       if (!remote.port)
-               remote.port = sk->sk_dport;
        nr = fill_local_addresses_vec(msk, addrs);
 
        msk->pm.add_addr_accepted++;
@@ -680,8 +695,12 @@ static void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk)
                __mptcp_subflow_connect(sk, &addrs[i], &remote);
        spin_lock_bh(&msk->pm.lock);
 
+       /* be sure to echo exactly the received address */
+       if (reset_port)
+               remote.port = 0;
+
 add_addr_echo:
-       mptcp_pm_announce_addr(msk, &msk->pm.remote, true);
+       mptcp_pm_announce_addr(msk, &remote, true);
        mptcp_pm_nl_addr_send_ack(msk);
 }