Skip to content

Commit 3721b9b

Browse files
mjmartineaudavem330
authored andcommitted
mptcp: Track received DATA_FIN sequence number and add related helpers
Incoming DATA_FIN headers need to propagate the presence of the DATA_FIN bit and the associated sequence number to the MPTCP layer, even when arriving on a bare ACK that does not get added to the receive queue. Add structure members to store the DATA_FIN information and helpers to set and check those values. Signed-off-by: Mat Martineau <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7279da6 commit 3721b9b

File tree

3 files changed

+115
-10
lines changed

3 files changed

+115
-10
lines changed

net/mptcp/options.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,22 @@ static void update_una(struct mptcp_sock *msk,
782782
}
783783
}
784784

785+
bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq)
786+
{
787+
/* Skip if DATA_FIN was already received.
788+
* If updating simultaneously with the recvmsg loop, values
789+
* should match. If they mismatch, the peer is misbehaving and
790+
* we will prefer the most recent information.
791+
*/
792+
if (READ_ONCE(msk->rcv_data_fin) || !READ_ONCE(msk->first))
793+
return false;
794+
795+
WRITE_ONCE(msk->rcv_data_fin_seq, data_fin_seq);
796+
WRITE_ONCE(msk->rcv_data_fin, 1);
797+
798+
return true;
799+
}
800+
785801
static bool add_addr_hmac_valid(struct mptcp_sock *msk,
786802
struct mptcp_options_received *mp_opt)
787803
{

net/mptcp/protocol.c

Lines changed: 96 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <net/inet_hashtables.h>
1717
#include <net/protocol.h>
1818
#include <net/tcp.h>
19+
#include <net/tcp_states.h>
1920
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
2021
#include <net/transp_v6.h>
2122
#endif
@@ -163,6 +164,101 @@ static bool mptcp_subflow_dsn_valid(const struct mptcp_sock *msk,
163164
return mptcp_subflow_data_available(ssk);
164165
}
165166

167+
static bool mptcp_pending_data_fin(struct sock *sk, u64 *seq)
168+
{
169+
struct mptcp_sock *msk = mptcp_sk(sk);
170+
171+
if (READ_ONCE(msk->rcv_data_fin) &&
172+
((1 << sk->sk_state) &
173+
(TCPF_ESTABLISHED | TCPF_FIN_WAIT1 | TCPF_FIN_WAIT2))) {
174+
u64 rcv_data_fin_seq = READ_ONCE(msk->rcv_data_fin_seq);
175+
176+
if (msk->ack_seq == rcv_data_fin_seq) {
177+
if (seq)
178+
*seq = rcv_data_fin_seq;
179+
180+
return true;
181+
}
182+
}
183+
184+
return false;
185+
}
186+
187+
static void mptcp_set_timeout(const struct sock *sk, const struct sock *ssk)
188+
{
189+
long tout = ssk && inet_csk(ssk)->icsk_pending ?
190+
inet_csk(ssk)->icsk_timeout - jiffies : 0;
191+
192+
if (tout <= 0)
193+
tout = mptcp_sk(sk)->timer_ival;
194+
mptcp_sk(sk)->timer_ival = tout > 0 ? tout : TCP_RTO_MIN;
195+
}
196+
197+
static void mptcp_check_data_fin(struct sock *sk)
198+
{
199+
struct mptcp_sock *msk = mptcp_sk(sk);
200+
u64 rcv_data_fin_seq;
201+
202+
if (__mptcp_check_fallback(msk) || !msk->first)
203+
return;
204+
205+
/* Need to ack a DATA_FIN received from a peer while this side
206+
* of the connection is in ESTABLISHED, FIN_WAIT1, or FIN_WAIT2.
207+
* msk->rcv_data_fin was set when parsing the incoming options
208+
* at the subflow level and the msk lock was not held, so this
209+
* is the first opportunity to act on the DATA_FIN and change
210+
* the msk state.
211+
*
212+
* If we are caught up to the sequence number of the incoming
213+
* DATA_FIN, send the DATA_ACK now and do state transition. If
214+
* not caught up, do nothing and let the recv code send DATA_ACK
215+
* when catching up.
216+
*/
217+
218+
if (mptcp_pending_data_fin(sk, &rcv_data_fin_seq)) {
219+
struct mptcp_subflow_context *subflow;
220+
221+
msk->ack_seq++;
222+
WRITE_ONCE(msk->rcv_data_fin, 0);
223+
224+
sk->sk_shutdown |= RCV_SHUTDOWN;
225+
226+
switch (sk->sk_state) {
227+
case TCP_ESTABLISHED:
228+
inet_sk_state_store(sk, TCP_CLOSE_WAIT);
229+
break;
230+
case TCP_FIN_WAIT1:
231+
inet_sk_state_store(sk, TCP_CLOSING);
232+
break;
233+
case TCP_FIN_WAIT2:
234+
inet_sk_state_store(sk, TCP_CLOSE);
235+
// @@ Close subflows now?
236+
break;
237+
default:
238+
/* Other states not expected */
239+
WARN_ON_ONCE(1);
240+
break;
241+
}
242+
243+
mptcp_set_timeout(sk, NULL);
244+
mptcp_for_each_subflow(msk, subflow) {
245+
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
246+
247+
lock_sock(ssk);
248+
tcp_send_ack(ssk);
249+
release_sock(ssk);
250+
}
251+
252+
sk->sk_state_change(sk);
253+
254+
if (sk->sk_shutdown == SHUTDOWN_MASK ||
255+
sk->sk_state == TCP_CLOSE)
256+
sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_HUP);
257+
else
258+
sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
259+
}
260+
}
261+
166262
static bool __mptcp_move_skbs_from_subflow(struct mptcp_sock *msk,
167263
struct sock *ssk,
168264
unsigned int *bytes)
@@ -303,16 +399,6 @@ static void __mptcp_flush_join_list(struct mptcp_sock *msk)
303399
spin_unlock_bh(&msk->join_list_lock);
304400
}
305401

306-
static void mptcp_set_timeout(const struct sock *sk, const struct sock *ssk)
307-
{
308-
long tout = ssk && inet_csk(ssk)->icsk_pending ?
309-
inet_csk(ssk)->icsk_timeout - jiffies : 0;
310-
311-
if (tout <= 0)
312-
tout = mptcp_sk(sk)->timer_ival;
313-
mptcp_sk(sk)->timer_ival = tout > 0 ? tout : TCP_RTO_MIN;
314-
}
315-
316402
static bool mptcp_timer_pending(struct sock *sk)
317403
{
318404
return timer_pending(&inet_csk(sk)->icsk_retransmit_timer);

net/mptcp/protocol.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,12 +193,14 @@ struct mptcp_sock {
193193
u64 remote_key;
194194
u64 write_seq;
195195
u64 ack_seq;
196+
u64 rcv_data_fin_seq;
196197
atomic64_t snd_una;
197198
unsigned long timer_ival;
198199
u32 token;
199200
unsigned long flags;
200201
bool can_ack;
201202
bool fully_established;
203+
bool rcv_data_fin;
202204
bool snd_data_fin_enable;
203205
spinlock_t join_list_lock;
204206
struct work_struct work;
@@ -385,6 +387,7 @@ void mptcp_data_ready(struct sock *sk, struct sock *ssk);
385387
bool mptcp_finish_join(struct sock *sk);
386388
void mptcp_data_acked(struct sock *sk);
387389
void mptcp_subflow_eof(struct sock *sk);
390+
bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq);
388391

389392
void __init mptcp_token_init(void);
390393
static inline void mptcp_token_init_request(struct request_sock *req)

0 commit comments

Comments
 (0)