Commit 0d0f2a36 authored by David S. Miller's avatar David S. Miller

Merge branch 'mptcp-sdeq-fixes'

Mat Martineau says:

====================
mptcp: 32-bit sequence number improvements

MPTCP-level sequence numbers are 64 bits, but RFC 8684 allows use of
32-bit sequence numbers in the DSS option to save header space. Those
32-bit numbers are the least significant bits of the full 64-bit
sequence number, so the receiver must infer the correct upper 32 bits.

These two patches improve the logic for determining the full 64-bit
sequence numbers when the 32-bit truncated version has wrapped around.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d452d48b 5957a890
......@@ -896,19 +896,20 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk,
return false;
}
static u64 expand_ack(u64 old_ack, u64 cur_ack, bool use_64bit)
u64 __mptcp_expand_seq(u64 old_seq, u64 cur_seq)
{
u32 old_ack32, cur_ack32;
if (use_64bit)
return cur_ack;
old_ack32 = (u32)old_ack;
cur_ack32 = (u32)cur_ack;
cur_ack = (old_ack & GENMASK_ULL(63, 32)) + cur_ack32;
if (unlikely(before(cur_ack32, old_ack32)))
return cur_ack + (1LL << 32);
return cur_ack;
u32 old_seq32, cur_seq32;
old_seq32 = (u32)old_seq;
cur_seq32 = (u32)cur_seq;
cur_seq = (old_seq & GENMASK_ULL(63, 32)) + cur_seq32;
if (unlikely(cur_seq32 < old_seq32 && before(old_seq32, cur_seq32)))
return cur_seq + (1LL << 32);
/* reverse wrap could happen, too */
if (unlikely(cur_seq32 > old_seq32 && after(old_seq32, cur_seq32)))
return cur_seq - (1LL << 32);
return cur_seq;
}
static void ack_update_msk(struct mptcp_sock *msk,
......@@ -926,7 +927,7 @@ static void ack_update_msk(struct mptcp_sock *msk,
* more dangerous than missing an ack
*/
old_snd_una = msk->snd_una;
new_snd_una = expand_ack(old_snd_una, mp_opt->data_ack, mp_opt->ack64);
new_snd_una = mptcp_expand_seq(old_snd_una, mp_opt->data_ack, mp_opt->ack64);
/* ACK for data not even sent yet? Ignore. */
if (after64(new_snd_una, snd_nxt))
......@@ -963,7 +964,7 @@ bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq, bool us
return false;
WRITE_ONCE(msk->rcv_data_fin_seq,
expand_ack(READ_ONCE(msk->ack_seq), data_fin_seq, use_64bit));
mptcp_expand_seq(READ_ONCE(msk->ack_seq), data_fin_seq, use_64bit));
WRITE_ONCE(msk->rcv_data_fin, 1);
return true;
......
......@@ -593,6 +593,14 @@ int mptcp_setsockopt(struct sock *sk, int level, int optname,
int mptcp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *option);
u64 __mptcp_expand_seq(u64 old_seq, u64 cur_seq);
static inline u64 mptcp_expand_seq(u64 old_seq, u64 cur_seq, bool use_64bit)
{
if (use_64bit)
return cur_seq;
return __mptcp_expand_seq(old_seq, cur_seq);
}
void __mptcp_check_push(struct sock *sk, struct sock *ssk);
void __mptcp_data_acked(struct sock *sk);
void __mptcp_error_report(struct sock *sk);
......
......@@ -775,15 +775,6 @@ enum mapping_status {
MAPPING_DUMMY
};
static u64 expand_seq(u64 old_seq, u16 old_data_len, u64 seq)
{
if ((u32)seq == (u32)old_seq)
return old_seq;
/* Assume map covers data not mapped yet. */
return seq | ((old_seq + old_data_len + 1) & GENMASK_ULL(63, 32));
}
static void dbg_bad_map(struct mptcp_subflow_context *subflow, u32 ssn)
{
pr_debug("Bad mapping: ssn=%d map_seq=%d map_data_len=%d",
......@@ -907,13 +898,7 @@ static enum mapping_status get_mapping_status(struct sock *ssk,
data_len--;
}
if (!mpext->dsn64) {
map_seq = expand_seq(subflow->map_seq, subflow->map_data_len,
mpext->data_seq);
pr_debug("expanded seq=%llu", subflow->map_seq);
} else {
map_seq = mpext->data_seq;
}
map_seq = mptcp_expand_seq(READ_ONCE(msk->ack_seq), mpext->data_seq, mpext->dsn64);
WRITE_ONCE(mptcp_sk(subflow->conn)->use_64bit_ack, !!mpext->dsn64);
if (subflow->map_valid) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment