|
16 | 16 | #include <net/inet_hashtables.h>
|
17 | 17 | #include <net/protocol.h>
|
18 | 18 | #include <net/tcp.h>
|
| 19 | +#include <net/tcp_states.h> |
19 | 20 | #if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
20 | 21 | #include <net/transp_v6.h>
|
21 | 22 | #endif
|
@@ -163,6 +164,101 @@ static bool mptcp_subflow_dsn_valid(const struct mptcp_sock *msk,
|
163 | 164 | return mptcp_subflow_data_available(ssk);
|
164 | 165 | }
|
165 | 166 |
|
| 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 | + |
166 | 262 | static bool __mptcp_move_skbs_from_subflow(struct mptcp_sock *msk,
|
167 | 263 | struct sock *ssk,
|
168 | 264 | unsigned int *bytes)
|
@@ -303,16 +399,6 @@ static void __mptcp_flush_join_list(struct mptcp_sock *msk)
|
303 | 399 | spin_unlock_bh(&msk->join_list_lock);
|
304 | 400 | }
|
305 | 401 |
|
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 |
| - |
316 | 402 | static bool mptcp_timer_pending(struct sock *sk)
|
317 | 403 | {
|
318 | 404 | return timer_pending(&inet_csk(sk)->icsk_retransmit_timer);
|
|
0 commit comments