Merge tag 'usb-serial-5.15-rc1-2' of https://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / net / mptcp / pm.c
index 639271e..6ab386f 100644 (file)
@@ -10,6 +10,8 @@
 #include <net/mptcp.h>
 #include "protocol.h"
 
+#include "mib.h"
+
 /* path manager command handlers */
 
 int mptcp_pm_announce_addr(struct mptcp_sock *msk,
@@ -18,23 +20,23 @@ int mptcp_pm_announce_addr(struct mptcp_sock *msk,
 {
        u8 add_addr = READ_ONCE(msk->pm.addr_signal);
 
-       pr_debug("msk=%p, local_id=%d", msk, addr->id);
+       pr_debug("msk=%p, local_id=%d, echo=%d", msk, addr->id, echo);
 
        lockdep_assert_held(&msk->pm.lock);
 
-       if (add_addr) {
-               pr_warn("addr_signal error, add_addr=%d", add_addr);
+       if (add_addr &
+           (echo ? BIT(MPTCP_ADD_ADDR_ECHO) : BIT(MPTCP_ADD_ADDR_SIGNAL))) {
+               pr_warn("addr_signal error, add_addr=%d, echo=%d", add_addr, echo);
                return -EINVAL;
        }
 
-       msk->pm.local = *addr;
-       add_addr |= BIT(MPTCP_ADD_ADDR_SIGNAL);
-       if (echo)
+       if (echo) {
+               msk->pm.remote = *addr;
                add_addr |= BIT(MPTCP_ADD_ADDR_ECHO);
-       if (addr->family == AF_INET6)
-               add_addr |= BIT(MPTCP_ADD_ADDR_IPV6);
-       if (addr->port)
-               add_addr |= BIT(MPTCP_ADD_ADDR_PORT);
+       } else {
+               msk->pm.local = *addr;
+               add_addr |= BIT(MPTCP_ADD_ADDR_SIGNAL);
+       }
        WRITE_ONCE(msk->pm.addr_signal, add_addr);
        return 0;
 }
@@ -247,12 +249,21 @@ void mptcp_pm_mp_prio_received(struct sock *sk, u8 bkup)
        mptcp_event(MPTCP_EVENT_SUB_PRIORITY, mptcp_sk(subflow->conn), sk, GFP_ATOMIC);
 }
 
+void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq)
+{
+       pr_debug("fail_seq=%llu", fail_seq);
+}
+
 /* path manager helpers */
 
-bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
-                             struct mptcp_addr_info *saddr, bool *echo, bool *port)
+bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, struct sk_buff *skb,
+                             unsigned int opt_size, unsigned int remaining,
+                             struct mptcp_addr_info *addr, bool *echo,
+                             bool *port, bool *drop_other_suboptions)
 {
        int ret = false;
+       u8 add_addr;
+       u8 family;
 
        spin_lock_bh(&msk->pm.lock);
 
@@ -260,14 +271,30 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
        if (!mptcp_pm_should_add_signal(msk))
                goto out_unlock;
 
+       /* always drop every other options for pure ack ADD_ADDR; this is a
+        * plain dup-ack from TCP perspective. The other MPTCP-relevant info,
+        * if any, will be carried by the 'original' TCP ack
+        */
+       if (skb && skb_is_tcp_pure_ack(skb)) {
+               remaining += opt_size;
+               *drop_other_suboptions = true;
+       }
+
        *echo = mptcp_pm_should_add_signal_echo(msk);
-       *port = mptcp_pm_should_add_signal_port(msk);
+       *port = !!(*echo ? msk->pm.remote.port : msk->pm.local.port);
 
-       if (remaining < mptcp_add_addr_len(msk->pm.local.family, *echo, *port))
+       family = *echo ? msk->pm.remote.family : msk->pm.local.family;
+       if (remaining < mptcp_add_addr_len(family, *echo, *port))
                goto out_unlock;
 
-       *saddr = msk->pm.local;
-       WRITE_ONCE(msk->pm.addr_signal, 0);
+       if (*echo) {
+               *addr = msk->pm.remote;
+               add_addr = msk->pm.addr_signal & ~BIT(MPTCP_ADD_ADDR_ECHO);
+       } else {
+               *addr = msk->pm.local;
+               add_addr = msk->pm.addr_signal & ~BIT(MPTCP_ADD_ADDR_SIGNAL);
+       }
+       WRITE_ONCE(msk->pm.addr_signal, add_addr);
        ret = true;
 
 out_unlock:
@@ -279,6 +306,7 @@ bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
                             struct mptcp_rm_list *rm_list)
 {
        int ret = false, len;
+       u8 rm_addr;
 
        spin_lock_bh(&msk->pm.lock);
 
@@ -286,16 +314,17 @@ bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
        if (!mptcp_pm_should_rm_signal(msk))
                goto out_unlock;
 
+       rm_addr = msk->pm.addr_signal & ~BIT(MPTCP_RM_ADDR_SIGNAL);
        len = mptcp_rm_addr_len(&msk->pm.rm_list_tx);
        if (len < 0) {
-               WRITE_ONCE(msk->pm.addr_signal, 0);
+               WRITE_ONCE(msk->pm.addr_signal, rm_addr);
                goto out_unlock;
        }
        if (remaining < len)
                goto out_unlock;
 
        *rm_list = msk->pm.rm_list_tx;
-       WRITE_ONCE(msk->pm.addr_signal, 0);
+       WRITE_ONCE(msk->pm.addr_signal, rm_addr);
        ret = true;
 
 out_unlock:
@@ -308,6 +337,25 @@ int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
        return mptcp_pm_nl_get_local_id(msk, skc);
 }
 
+void mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk)
+{
+       struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
+       u32 rcv_tstamp = READ_ONCE(tcp_sk(ssk)->rcv_tstamp);
+
+       /* keep track of rtx periods with no progress */
+       if (!subflow->stale_count) {
+               subflow->stale_rcv_tstamp = rcv_tstamp;
+               subflow->stale_count++;
+       } else if (subflow->stale_rcv_tstamp == rcv_tstamp) {
+               if (subflow->stale_count < U8_MAX)
+                       subflow->stale_count++;
+               mptcp_pm_nl_subflow_chk_stale(msk, ssk);
+       } else {
+               subflow->stale_count = 0;
+               mptcp_subflow_set_active(subflow);
+       }
+}
+
 void mptcp_pm_data_init(struct mptcp_sock *msk)
 {
        msk->pm.add_addr_signaled = 0;