Commit a0c1d0ea authored by Christoph Paasch's avatar Christoph Paasch Committed by David S. Miller
Browse files

mptcp: Use 32-bit DATA_ACK when possible



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: default avatarChristoph Paasch <cpaasch@apple.com>
Reviewed-by: default avatarMatthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9efd6a3c
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -16,7 +16,10 @@ struct seq_file;

/* MPTCP sk_buff extension data */
struct mptcp_ext {
	union {
		u64	data_ack;
		u32	data_ack32;
	};
	u64		data_seq;
	u32		subflow_seq;
	u16		data_len;
+24 −9
Original line number Diff line number Diff line
@@ -516,7 +516,16 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
		return ret;
	}

	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) {
			flags = MPTCP_DSS_HAS_ACK;
			if (mpext->ack64) {
				len += TCPOLEN_MPTCP_DSS_ACK64;
			flags = MPTCP_DSS_HAS_ACK | 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) {
			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) {
+1 −0
Original line number Diff line number Diff line
@@ -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;
+2 −0
Original line number Diff line number Diff line
@@ -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) {