Skip to content

Commit

Permalink
mptcp: Handle incoming 32-bit DATA_FIN values
Browse files Browse the repository at this point in the history
The peer may send a DATA_FIN mapping with either a 32-bit or 64-bit
sequence number. When a 32-bit sequence number is received for the
DATA_FIN, it must be expanded to 64 bits before comparing it to the
last acked sequence number. This expansion was missing.

Closes: #93
Fixes: 3721b9b (mptcp: Track received DATA_FIN sequence number and add related helpers)
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
  • Loading branch information
mjmartineau authored and jenkins-tessares committed Oct 2, 2020
1 parent 747532c commit dc5e891
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 7 deletions.
7 changes: 4 additions & 3 deletions net/mptcp/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,7 @@ static void update_una(struct mptcp_sock *msk,
}
}

bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq)
bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq, bool use_64bit)
{
/* Skip if DATA_FIN was already received.
* If updating simultaneously with the recvmsg loop, values
Expand All @@ -827,7 +827,8 @@ bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq)
if (READ_ONCE(msk->rcv_data_fin) || !READ_ONCE(msk->first))
return false;

WRITE_ONCE(msk->rcv_data_fin_seq, data_fin_seq);
WRITE_ONCE(msk->rcv_data_fin_seq,
expand_ack(READ_ONCE(msk->ack_seq), data_fin_seq, use_64bit));
WRITE_ONCE(msk->rcv_data_fin, 1);

return true;
Expand Down Expand Up @@ -919,7 +920,7 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
*/
if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) {
if (mp_opt.data_fin && mp_opt.data_len == 1 &&
mptcp_update_rcv_data_fin(msk, mp_opt.data_seq) &&
mptcp_update_rcv_data_fin(msk, mp_opt.data_seq, mp_opt.dsn64) &&
schedule_work(&msk->work))
sock_hold(subflow->conn);

Expand Down
2 changes: 1 addition & 1 deletion net/mptcp/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ void mptcp_data_ready(struct sock *sk, struct sock *ssk);
bool mptcp_finish_join(struct sock *sk);
void mptcp_data_acked(struct sock *sk);
void mptcp_subflow_eof(struct sock *sk);
bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq);
bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq, bool use_64bit);
void mptcp_destroy_common(struct mptcp_sock *msk);

void __init mptcp_token_init(void);
Expand Down
16 changes: 13 additions & 3 deletions net/mptcp/subflow.c
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,8 @@ static enum mapping_status get_mapping_status(struct sock *ssk,

if (mpext->data_fin == 1) {
if (data_len == 1) {
bool updated = mptcp_update_rcv_data_fin(msk, mpext->data_seq);
bool updated = mptcp_update_rcv_data_fin(msk, mpext->data_seq,
mpext->dsn64);
pr_debug("DATA_FIN with no payload seq=%llu", mpext->data_seq);
if (subflow->map_valid) {
/* A DATA_FIN might arrive in a DSS
Expand All @@ -749,8 +750,17 @@ static enum mapping_status get_mapping_status(struct sock *ssk,
return MAPPING_DATA_FIN;
}
} else {
mptcp_update_rcv_data_fin(msk, mpext->data_seq + data_len);
pr_debug("DATA_FIN with mapping seq=%llu", mpext->data_seq + data_len);
u64 data_fin_seq = mpext->data_seq + data_len;

/* If mpext->data_seq is a 32-bit value, data_fin_seq
* must also be limited to 32 bits.
*/
if (!mpext->dsn64)
data_fin_seq &= GENMASK_ULL(31, 0);

mptcp_update_rcv_data_fin(msk, data_fin_seq, mpext->dsn64);
pr_debug("DATA_FIN with mapping seq=%llu dsn64=%d",
data_fin_seq, mpext->dsn64);
}

/* Adjust for DATA_FIN using 1 byte of sequence space */
Expand Down

0 comments on commit dc5e891

Please sign in to comment.