OSDN Git Service

mptcp: Use 32-bit DATA_ACK when possible
authorChristoph Paasch <cpaasch@apple.com>
Thu, 14 May 2020 15:53:03 +0000 (08:53 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sat, 16 May 2020 20:51:10 +0000 (13:51 -0700)
RFC8684 allows to send 32-bit DATA_ACKs as long as the peer is not
sending 64-bit data-sequence numbers. The 64-bit DSN is only there for
extreme scenarios when a very high throughput subflow is combined with a
long-RTT subflow such that the high-throughput subflow wraps around the
32-bit sequence number space within an RTT of the high-RTT subflow.

It is thus a rare scenario and we should try to use the 32-bit DATA_ACK
instead as long as possible. It allows to reduce the TCP-option overhead
by 4 bytes, thus makes space for an additional SACK-block. It also makes
tcpdumps much easier to read when the DSN and DATA_ACK are both either
32 or 64-bit.

Signed-off-by: Christoph Paasch <cpaasch@apple.com>
Reviewed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/mptcp.h
net/mptcp/options.c
net/mptcp/protocol.h
net/mptcp/subflow.c

index c4a6ef4..46d0487 100644 (file)
@@ -16,7 +16,10 @@ struct seq_file;
 
 /* MPTCP sk_buff extension data */
 struct mptcp_ext {
-       u64             data_ack;
+       union {
+               u64     data_ack;
+               u32     data_ack32;
+       };
        u64             data_seq;
        u32             subflow_seq;
        u16             data_len;
index 45497af..ece6f92 100644 (file)
@@ -516,7 +516,16 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
                return ret;
        }
 
-       ack_size = TCPOLEN_MPTCP_DSS_ACK64;
+       if (subflow->use_64bit_ack) {
+               ack_size = TCPOLEN_MPTCP_DSS_ACK64;
+               opts->ext_copy.data_ack = msk->ack_seq;
+               opts->ext_copy.ack64 = 1;
+       } else {
+               ack_size = TCPOLEN_MPTCP_DSS_ACK32;
+               opts->ext_copy.data_ack32 = (uint32_t)(msk->ack_seq);
+               opts->ext_copy.ack64 = 0;
+       }
+       opts->ext_copy.use_ack = 1;
 
        /* Add kind/length/subtype/flag overhead if mapping is not populated */
        if (dss_size == 0)
@@ -524,10 +533,6 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
 
        dss_size += ack_size;
 
-       opts->ext_copy.data_ack = msk->ack_seq;
-       opts->ext_copy.ack64 = 1;
-       opts->ext_copy.use_ack = 1;
-
        *size = ALIGN(dss_size, 4);
        return true;
 }
@@ -986,8 +991,13 @@ mp_capable_done:
                u8 flags = 0;
 
                if (mpext->use_ack) {
-                       len += TCPOLEN_MPTCP_DSS_ACK64;
-                       flags = MPTCP_DSS_HAS_ACK | MPTCP_DSS_ACK64;
+                       flags = MPTCP_DSS_HAS_ACK;
+                       if (mpext->ack64) {
+                               len += TCPOLEN_MPTCP_DSS_ACK64;
+                               flags |= MPTCP_DSS_ACK64;
+                       } else {
+                               len += TCPOLEN_MPTCP_DSS_ACK32;
+                       }
                }
 
                if (mpext->use_map) {
@@ -1004,8 +1014,13 @@ mp_capable_done:
                *ptr++ = mptcp_option(MPTCPOPT_DSS, len, 0, flags);
 
                if (mpext->use_ack) {
-                       put_unaligned_be64(mpext->data_ack, ptr);
-                       ptr += 2;
+                       if (mpext->ack64) {
+                               put_unaligned_be64(mpext->data_ack, ptr);
+                               ptr += 2;
+                       } else {
+                               put_unaligned_be32(mpext->data_ack32, ptr);
+                               ptr += 1;
+                       }
                }
 
                if (mpext->use_map) {
index e4ca632..f5adca9 100644 (file)
@@ -290,6 +290,7 @@ struct mptcp_subflow_context {
                data_avail : 1,
                rx_eof : 1,
                data_fin_tx_enable : 1,
+               use_64bit_ack : 1, /* Set when we received a 64-bit DSN */
                can_ack : 1;        /* only after processing the remote a key */
        u64     data_fin_tx_seq;
        u32     remote_nonce;
index 53c75b0..0020d35 100644 (file)
@@ -667,9 +667,11 @@ static enum mapping_status get_mapping_status(struct sock *ssk)
        if (!mpext->dsn64) {
                map_seq = expand_seq(subflow->map_seq, subflow->map_data_len,
                                     mpext->data_seq);
+               subflow->use_64bit_ack = 0;
                pr_debug("expanded seq=%llu", subflow->map_seq);
        } else {
                map_seq = mpext->data_seq;
+               subflow->use_64bit_ack = 1;
        }
 
        if (subflow->map_valid) {