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

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
Loading
Loading
Loading
Loading
+15 −14
Original line number Diff line number Diff line
@@ -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;
	u32 old_seq32, cur_seq32;

	if (use_64bit)
		return cur_ack;
	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);

	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;
	/* 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;
+8 −0
Original line number Diff line number Diff line
@@ -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);
+1 −16
Original line number Diff line number Diff line
@@ -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) {