mirror of https://gitee.com/openkylin/linux.git
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: Christoph Paasch <cpaasch@apple.com> Reviewed-by: Matthieu Baerts <matthieu.baerts@tessares.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
9efd6a3cec
commit
a0c1d0eafd
|
@ -16,7 +16,10 @@ struct seq_file;
|
||||||
|
|
||||||
/* MPTCP sk_buff extension data */
|
/* MPTCP sk_buff extension data */
|
||||||
struct mptcp_ext {
|
struct mptcp_ext {
|
||||||
|
union {
|
||||||
u64 data_ack;
|
u64 data_ack;
|
||||||
|
u32 data_ack32;
|
||||||
|
};
|
||||||
u64 data_seq;
|
u64 data_seq;
|
||||||
u32 subflow_seq;
|
u32 subflow_seq;
|
||||||
u16 data_len;
|
u16 data_len;
|
||||||
|
|
|
@ -516,7 +516,16 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (subflow->use_64bit_ack) {
|
||||||
ack_size = TCPOLEN_MPTCP_DSS_ACK64;
|
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 */
|
/* Add kind/length/subtype/flag overhead if mapping is not populated */
|
||||||
if (dss_size == 0)
|
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;
|
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);
|
*size = ALIGN(dss_size, 4);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -986,8 +991,13 @@ void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts)
|
||||||
u8 flags = 0;
|
u8 flags = 0;
|
||||||
|
|
||||||
if (mpext->use_ack) {
|
if (mpext->use_ack) {
|
||||||
|
flags = MPTCP_DSS_HAS_ACK;
|
||||||
|
if (mpext->ack64) {
|
||||||
len += TCPOLEN_MPTCP_DSS_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) {
|
if (mpext->use_map) {
|
||||||
|
@ -1004,8 +1014,13 @@ void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts)
|
||||||
*ptr++ = mptcp_option(MPTCPOPT_DSS, len, 0, flags);
|
*ptr++ = mptcp_option(MPTCPOPT_DSS, len, 0, flags);
|
||||||
|
|
||||||
if (mpext->use_ack) {
|
if (mpext->use_ack) {
|
||||||
|
if (mpext->ack64) {
|
||||||
put_unaligned_be64(mpext->data_ack, ptr);
|
put_unaligned_be64(mpext->data_ack, ptr);
|
||||||
ptr += 2;
|
ptr += 2;
|
||||||
|
} else {
|
||||||
|
put_unaligned_be32(mpext->data_ack32, ptr);
|
||||||
|
ptr += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mpext->use_map) {
|
if (mpext->use_map) {
|
||||||
|
|
|
@ -290,6 +290,7 @@ struct mptcp_subflow_context {
|
||||||
data_avail : 1,
|
data_avail : 1,
|
||||||
rx_eof : 1,
|
rx_eof : 1,
|
||||||
data_fin_tx_enable : 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 */
|
can_ack : 1; /* only after processing the remote a key */
|
||||||
u64 data_fin_tx_seq;
|
u64 data_fin_tx_seq;
|
||||||
u32 remote_nonce;
|
u32 remote_nonce;
|
||||||
|
|
|
@ -667,9 +667,11 @@ static enum mapping_status get_mapping_status(struct sock *ssk)
|
||||||
if (!mpext->dsn64) {
|
if (!mpext->dsn64) {
|
||||||
map_seq = expand_seq(subflow->map_seq, subflow->map_data_len,
|
map_seq = expand_seq(subflow->map_seq, subflow->map_data_len,
|
||||||
mpext->data_seq);
|
mpext->data_seq);
|
||||||
|
subflow->use_64bit_ack = 0;
|
||||||
pr_debug("expanded seq=%llu", subflow->map_seq);
|
pr_debug("expanded seq=%llu", subflow->map_seq);
|
||||||
} else {
|
} else {
|
||||||
map_seq = mpext->data_seq;
|
map_seq = mpext->data_seq;
|
||||||
|
subflow->use_64bit_ack = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subflow->map_valid) {
|
if (subflow->map_valid) {
|
||||||
|
|
Loading…
Reference in New Issue