Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'mptcp-various-small-improvements'

Matthieu Baerts says:

====================
mptcp: various small improvements

The following patches are not related to each other.

- Patch 1: Avoid sending advertisements on stale subflows, reducing
risks on loosing them.

- Patch 2: Annotate data-races around subflow->fully_established, using
READ/WRITE_ONCE().

- Patch 3: A small clean-up on the PM side, avoiding a bit of duplicated
code.

- Patch 4: Use "Middlebox interference" MP_TCPRST code in reaction to a
packet received without MPTCP options in the middle of a connection.
====================

Link: https://patch.msgid.link/20241021-net-next-mptcp-misc-6-13-v1-0-1ef02746504a@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+33 -20
+1 -1
net/mptcp/diag.c
··· 47 47 flags |= MPTCP_SUBFLOW_FLAG_BKUP_REM; 48 48 if (sf->request_bkup) 49 49 flags |= MPTCP_SUBFLOW_FLAG_BKUP_LOC; 50 - if (sf->fully_established) 50 + if (READ_ONCE(sf->fully_established)) 51 51 flags |= MPTCP_SUBFLOW_FLAG_FULLY_ESTABLISHED; 52 52 if (sf->conn_finished) 53 53 flags |= MPTCP_SUBFLOW_FLAG_CONNECTED;
+2 -2
net/mptcp/options.c
··· 461 461 return false; 462 462 463 463 /* MPC/MPJ needed only on 3rd ack packet, DATA_FIN and TCP shutdown take precedence */ 464 - if (subflow->fully_established || snd_data_fin_enable || 464 + if (READ_ONCE(subflow->fully_established) || snd_data_fin_enable || 465 465 subflow->snd_isn != TCP_SKB_CB(skb)->seq || 466 466 sk->sk_state != TCP_ESTABLISHED) 467 467 return false; ··· 930 930 /* here we can process OoO, in-window pkts, only in-sequence 4th ack 931 931 * will make the subflow fully established 932 932 */ 933 - if (likely(subflow->fully_established)) { 933 + if (likely(READ_ONCE(subflow->fully_established))) { 934 934 /* on passive sockets, check for 3rd ack retransmission 935 935 * note that msk is always set by subflow_syn_recv_sock() 936 936 * for mp_join subflows
+3
net/mptcp/pm.c
··· 154 154 void mptcp_pm_connection_closed(struct mptcp_sock *msk) 155 155 { 156 156 pr_debug("msk=%p\n", msk); 157 + 158 + if (msk->token) 159 + mptcp_event(MPTCP_EVENT_CLOSED, msk, NULL, GFP_KERNEL); 157 160 } 158 161 159 162 void mptcp_pm_subflow_established(struct mptcp_sock *msk)
+11 -3
net/mptcp/pm_netlink.c
··· 781 781 782 782 void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk) 783 783 { 784 - struct mptcp_subflow_context *subflow; 784 + struct mptcp_subflow_context *subflow, *alt = NULL; 785 785 786 786 msk_owned_by_me(msk); 787 787 lockdep_assert_held(&msk->pm.lock); ··· 792 792 793 793 mptcp_for_each_subflow(msk, subflow) { 794 794 if (__mptcp_subflow_active(subflow)) { 795 - mptcp_pm_send_ack(msk, subflow, false, false); 796 - break; 795 + if (!subflow->stale) { 796 + mptcp_pm_send_ack(msk, subflow, false, false); 797 + return; 798 + } 799 + 800 + if (!alt) 801 + alt = subflow; 797 802 } 798 803 } 804 + 805 + if (alt) 806 + mptcp_pm_send_ack(msk, alt, false, false); 799 807 } 800 808 801 809 int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
+3 -5
net/mptcp/protocol.c
··· 3139 3139 3140 3140 sock_hold(sk); 3141 3141 pr_debug("msk=%p state=%d\n", sk, sk->sk_state); 3142 - if (msk->token) 3143 - mptcp_event(MPTCP_EVENT_CLOSED, msk, NULL, GFP_KERNEL); 3142 + mptcp_pm_connection_closed(msk); 3144 3143 3145 3144 if (sk->sk_state == TCP_CLOSE) { 3146 3145 __mptcp_destroy_sock(sk); ··· 3205 3206 mptcp_stop_rtx_timer(sk); 3206 3207 mptcp_stop_tout_timer(sk); 3207 3208 3208 - if (msk->token) 3209 - mptcp_event(MPTCP_EVENT_CLOSED, msk, NULL, GFP_KERNEL); 3209 + mptcp_pm_connection_closed(msk); 3210 3210 3211 3211 /* msk->subflow is still intact, the following will not free the first 3212 3212 * subflow ··· 3509 3511 struct tcp_sock *tp = tcp_sk(ssk); 3510 3512 unsigned long timeout; 3511 3513 3512 - if (mptcp_subflow_ctx(ssk)->fully_established) 3514 + if (READ_ONCE(mptcp_subflow_ctx(ssk)->fully_established)) 3513 3515 return; 3514 3516 3515 3517 /* reschedule with a timeout above RTT, as we must look only for drop */
+3 -3
net/mptcp/protocol.h
··· 513 513 request_bkup : 1, 514 514 mp_capable : 1, /* remote is MPTCP capable */ 515 515 mp_join : 1, /* remote is JOINing */ 516 - fully_established : 1, /* path validated */ 517 516 pm_notified : 1, /* PM hook called for established status */ 518 517 conn_finished : 1, 519 518 map_valid : 1, ··· 531 532 is_mptfo : 1, /* subflow is doing TFO */ 532 533 close_event_done : 1, /* has done the post-closed part */ 533 534 mpc_drop : 1, /* the MPC option has been dropped in a rtx */ 534 - __unused : 8; 535 + __unused : 9; 535 536 bool data_avail; 536 537 bool scheduled; 537 538 bool pm_listener; /* a listener managed by the kernel PM? */ 539 + bool fully_established; /* path validated */ 538 540 u32 remote_nonce; 539 541 u64 thmac; 540 542 u32 local_nonce; ··· 780 780 static inline bool __mptcp_subflow_active(struct mptcp_subflow_context *subflow) 781 781 { 782 782 /* can't send if JOIN hasn't completed yet (i.e. is usable for mptcp) */ 783 - if (subflow->request_join && !subflow->fully_established) 783 + if (subflow->request_join && !READ_ONCE(subflow->fully_established)) 784 784 return false; 785 785 786 786 return __tcp_can_send(mptcp_subflow_tcp_sock(subflow));
+10 -6
net/mptcp/subflow.c
··· 800 800 const struct mptcp_options_received *mp_opt) 801 801 { 802 802 subflow_set_remote_key(msk, subflow, mp_opt); 803 - subflow->fully_established = 1; 803 + WRITE_ONCE(subflow->fully_established, true); 804 804 WRITE_ONCE(msk->fully_established, true); 805 805 806 806 if (subflow->is_mptfo) ··· 971 971 MAPPING_EMPTY, 972 972 MAPPING_DATA_FIN, 973 973 MAPPING_DUMMY, 974 - MAPPING_BAD_CSUM 974 + MAPPING_BAD_CSUM, 975 + MAPPING_NODSS 975 976 }; 976 977 977 978 static void dbg_bad_map(struct mptcp_subflow_context *subflow, u32 ssn) ··· 1129 1128 return MAPPING_EMPTY; 1130 1129 } 1131 1130 1131 + /* If the required DSS has likely been dropped by a middlebox */ 1132 1132 if (!subflow->map_valid) 1133 - return MAPPING_INVALID; 1133 + return MAPPING_NODSS; 1134 1134 1135 1135 goto validate_seq; 1136 1136 } ··· 1345 1343 status = get_mapping_status(ssk, msk); 1346 1344 trace_subflow_check_data_avail(status, skb_peek(&ssk->sk_receive_queue)); 1347 1345 if (unlikely(status == MAPPING_INVALID || status == MAPPING_DUMMY || 1348 - status == MAPPING_BAD_CSUM)) 1346 + status == MAPPING_BAD_CSUM || status == MAPPING_NODSS)) 1349 1347 goto fallback; 1350 1348 1351 1349 if (status != MAPPING_OK) ··· 1398 1396 * subflow_error_report() will introduce the appropriate barriers 1399 1397 */ 1400 1398 subflow->reset_transient = 0; 1401 - subflow->reset_reason = MPTCP_RST_EMPTCP; 1399 + subflow->reset_reason = status == MAPPING_NODSS ? 1400 + MPTCP_RST_EMIDDLEBOX : 1401 + MPTCP_RST_EMPTCP; 1402 1402 1403 1403 reset: 1404 1404 WRITE_ONCE(ssk->sk_err, EBADMSG); ··· 2066 2062 } else if (subflow_req->mp_join) { 2067 2063 new_ctx->ssn_offset = subflow_req->ssn_offset; 2068 2064 new_ctx->mp_join = 1; 2069 - new_ctx->fully_established = 1; 2065 + WRITE_ONCE(new_ctx->fully_established, true); 2070 2066 new_ctx->remote_key_valid = 1; 2071 2067 new_ctx->backup = subflow_req->backup; 2072 2068 new_ctx->request_bkup = subflow_req->request_bkup;