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

Merge branch 'mptcp-track-more-fallback-cases'

Matthieu Baerts says:

====================
mptcp: track more fallback cases

This series has two patches linked to fallback to TCP:

- Patch 1: additional MIB counters for remaining error code paths around
fallback

- Patch 2: remove dedicated pr_debug() linked to fallback now that
everything should be covered by dedicated MIB counters.
====================

Link: https://patch.msgid.link/20250723-net-next-mptcp-track-fallbacks-v1-0-a83cce08f2d5@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+62 -54
+2 -2
net/mptcp/ctrl.c
··· 533 533 to_max = mptcp_get_pernet(net)->syn_retrans_before_tcp_fallback; 534 534 535 535 if (timeouts == to_max || (timeouts < to_max && expired)) { 536 - MPTCP_INC_STATS(net, MPTCP_MIB_MPCAPABLEACTIVEDROP); 537 536 subflow->mpc_drop = 1; 538 - mptcp_subflow_early_fallback(mptcp_sk(subflow->conn), subflow); 537 + mptcp_early_fallback(mptcp_sk(subflow->conn), subflow, 538 + MPTCP_MIB_MPCAPABLEACTIVEDROP); 539 539 } 540 540 } 541 541
+5
net/mptcp/mib.c
··· 80 80 SNMP_MIB_ITEM("RcvWndConflict", MPTCP_MIB_RCVWNDCONFLICT), 81 81 SNMP_MIB_ITEM("MPCurrEstab", MPTCP_MIB_CURRESTAB), 82 82 SNMP_MIB_ITEM("Blackhole", MPTCP_MIB_BLACKHOLE), 83 + SNMP_MIB_ITEM("MPCapableDataFallback", MPTCP_MIB_MPCAPABLEDATAFALLBACK), 84 + SNMP_MIB_ITEM("MD5SigFallback", MPTCP_MIB_MD5SIGFALLBACK), 85 + SNMP_MIB_ITEM("DssFallback", MPTCP_MIB_DSSFALLBACK), 86 + SNMP_MIB_ITEM("SimultConnectFallback", MPTCP_MIB_SIMULTCONNFALLBACK), 87 + SNMP_MIB_ITEM("FallbackFailed", MPTCP_MIB_FALLBACKFAILED), 83 88 SNMP_MIB_SENTINEL 84 89 }; 85 90
+7
net/mptcp/mib.h
··· 81 81 MPTCP_MIB_RCVWNDCONFLICT, /* Conflict with while updating msk rcv wnd */ 82 82 MPTCP_MIB_CURRESTAB, /* Current established MPTCP connections */ 83 83 MPTCP_MIB_BLACKHOLE, /* A blackhole has been detected */ 84 + MPTCP_MIB_MPCAPABLEDATAFALLBACK, /* Missing DSS/MPC+data on first 85 + * established packet 86 + */ 87 + MPTCP_MIB_MD5SIGFALLBACK, /* Conflicting TCP option enabled */ 88 + MPTCP_MIB_DSSFALLBACK, /* Bad or missing DSS */ 89 + MPTCP_MIB_SIMULTCONNFALLBACK, /* Simultaneous connect */ 90 + MPTCP_MIB_FALLBACKFAILED, /* Can't fallback due to msk status */ 84 91 __MPTCP_MIB_MAX 85 92 }; 86 93
+3 -2
net/mptcp/options.c
··· 978 978 if (subflow->mp_join) 979 979 goto reset; 980 980 subflow->mp_capable = 0; 981 - if (!mptcp_try_fallback(ssk)) 981 + if (!mptcp_try_fallback(ssk, MPTCP_MIB_MPCAPABLEDATAFALLBACK)) { 982 + MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_FALLBACKFAILED); 982 983 goto reset; 983 - pr_fallback(msk); 984 + } 984 985 return false; 985 986 } 986 987
+30 -15
net/mptcp/protocol.c
··· 68 68 return &inet_stream_ops; 69 69 } 70 70 71 + bool __mptcp_try_fallback(struct mptcp_sock *msk, int fb_mib) 72 + { 73 + struct net *net = sock_net((struct sock *)msk); 74 + 75 + if (__mptcp_check_fallback(msk)) 76 + return true; 77 + 78 + spin_lock_bh(&msk->fallback_lock); 79 + if (!msk->allow_infinite_fallback) { 80 + spin_unlock_bh(&msk->fallback_lock); 81 + return false; 82 + } 83 + 84 + msk->allow_subflows = false; 85 + set_bit(MPTCP_FALLBACK_DONE, &msk->flags); 86 + __MPTCP_INC_STATS(net, fb_mib); 87 + spin_unlock_bh(&msk->fallback_lock); 88 + return true; 89 + } 90 + 71 91 static int __mptcp_socket_create(struct mptcp_sock *msk) 72 92 { 73 93 struct mptcp_subflow_context *subflow; ··· 581 561 582 562 static void mptcp_dss_corruption(struct mptcp_sock *msk, struct sock *ssk) 583 563 { 584 - if (mptcp_try_fallback(ssk)) { 585 - MPTCP_INC_STATS(sock_net(ssk), 586 - MPTCP_MIB_DSSCORRUPTIONFALLBACK); 587 - } else { 564 + if (!mptcp_try_fallback(ssk, MPTCP_MIB_DSSCORRUPTIONFALLBACK)) { 588 565 MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DSSCORRUPTIONRESET); 589 566 mptcp_subflow_reset(ssk); 590 567 } ··· 1160 1143 mpext->infinite_map = 1; 1161 1144 mpext->data_len = 0; 1162 1145 1163 - if (!mptcp_try_fallback(ssk)) { 1146 + if (!mptcp_try_fallback(ssk, MPTCP_MIB_INFINITEMAPTX)) { 1147 + MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_FALLBACKFAILED); 1164 1148 mptcp_subflow_reset(ssk); 1165 1149 return; 1166 1150 } 1167 1151 1168 - MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_INFINITEMAPTX); 1169 1152 mptcp_subflow_ctx(ssk)->send_infinite_map = 0; 1170 - pr_fallback(msk); 1171 1153 } 1172 1154 1173 1155 #define MPTCP_MAX_GSO_SIZE (GSO_LEGACY_MAX_SIZE - (MAX_TCP_HEADER + 1)) ··· 3705 3689 * TCP option space. 3706 3690 */ 3707 3691 if (rcu_access_pointer(tcp_sk(ssk)->md5sig_info)) 3708 - mptcp_subflow_early_fallback(msk, subflow); 3692 + mptcp_early_fallback(msk, subflow, MPTCP_MIB_MD5SIGFALLBACK); 3709 3693 #endif 3710 3694 if (subflow->request_mptcp) { 3711 - if (mptcp_active_should_disable(sk)) { 3712 - MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_MPCAPABLEACTIVEDISABLED); 3713 - mptcp_subflow_early_fallback(msk, subflow); 3714 - } else if (mptcp_token_new_connect(ssk) < 0) { 3715 - MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_TOKENFALLBACKINIT); 3716 - mptcp_subflow_early_fallback(msk, subflow); 3717 - } 3695 + if (mptcp_active_should_disable(sk)) 3696 + mptcp_early_fallback(msk, subflow, 3697 + MPTCP_MIB_MPCAPABLEACTIVEDISABLED); 3698 + else if (mptcp_token_new_connect(ssk) < 0) 3699 + mptcp_early_fallback(msk, subflow, 3700 + MPTCP_MIB_TOKENFALLBACKINIT); 3718 3701 } 3719 3702 3720 3703 WRITE_ONCE(msk->write_seq, subflow->idsn);
+8 -26
net/mptcp/protocol.h
··· 1223 1223 return __mptcp_check_fallback(msk); 1224 1224 } 1225 1225 1226 - static inline bool __mptcp_try_fallback(struct mptcp_sock *msk) 1227 - { 1228 - if (__mptcp_check_fallback(msk)) { 1229 - pr_debug("TCP fallback already done (msk=%p)\n", msk); 1230 - return true; 1231 - } 1232 - spin_lock_bh(&msk->fallback_lock); 1233 - if (!msk->allow_infinite_fallback) { 1234 - spin_unlock_bh(&msk->fallback_lock); 1235 - return false; 1236 - } 1237 - 1238 - msk->allow_subflows = false; 1239 - set_bit(MPTCP_FALLBACK_DONE, &msk->flags); 1240 - spin_unlock_bh(&msk->fallback_lock); 1241 - return true; 1242 - } 1243 - 1244 1226 static inline bool __mptcp_has_initial_subflow(const struct mptcp_sock *msk) 1245 1227 { 1246 1228 struct sock *ssk = READ_ONCE(msk->first); ··· 1232 1250 TCPF_SYN_RECV | TCPF_LISTEN)); 1233 1251 } 1234 1252 1235 - static inline bool mptcp_try_fallback(struct sock *ssk) 1253 + bool __mptcp_try_fallback(struct mptcp_sock *msk, int fb_mib); 1254 + 1255 + static inline bool mptcp_try_fallback(struct sock *ssk, int fb_mib) 1236 1256 { 1237 1257 struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); 1238 1258 struct sock *sk = subflow->conn; 1239 1259 struct mptcp_sock *msk; 1240 1260 1241 1261 msk = mptcp_sk(sk); 1242 - if (!__mptcp_try_fallback(msk)) 1262 + if (!__mptcp_try_fallback(msk, fb_mib)) 1243 1263 return false; 1244 1264 if (READ_ONCE(msk->snd_data_fin_enable) && !(ssk->sk_shutdown & SEND_SHUTDOWN)) { 1245 1265 gfp_t saved_allocation = ssk->sk_allocation; ··· 1257 1273 return true; 1258 1274 } 1259 1275 1260 - #define pr_fallback(a) pr_debug("%s:fallback to TCP (msk=%p)\n", __func__, a) 1261 - 1262 - static inline void mptcp_subflow_early_fallback(struct mptcp_sock *msk, 1263 - struct mptcp_subflow_context *subflow) 1276 + static inline void mptcp_early_fallback(struct mptcp_sock *msk, 1277 + struct mptcp_subflow_context *subflow, 1278 + int fb_mib) 1264 1279 { 1265 - pr_fallback(msk); 1266 1280 subflow->request_mptcp = 0; 1267 - WARN_ON_ONCE(!__mptcp_try_fallback(msk)); 1281 + WARN_ON_ONCE(!__mptcp_try_fallback(msk, fb_mib)); 1268 1282 } 1269 1283 1270 1284 static inline bool mptcp_check_infinite_map(struct sk_buff *skb)
+7 -9
net/mptcp/subflow.c
··· 544 544 mptcp_get_options(skb, &mp_opt); 545 545 if (subflow->request_mptcp) { 546 546 if (!(mp_opt.suboptions & OPTION_MPTCP_MPC_SYNACK)) { 547 - if (!mptcp_try_fallback(sk)) 547 + if (!mptcp_try_fallback(sk, 548 + MPTCP_MIB_MPCAPABLEACTIVEFALLBACK)) { 549 + MPTCP_INC_STATS(sock_net(sk), 550 + MPTCP_MIB_FALLBACKFAILED); 548 551 goto do_reset; 552 + } 549 553 550 - MPTCP_INC_STATS(sock_net(sk), 551 - MPTCP_MIB_MPCAPABLEACTIVEFALLBACK); 552 - pr_fallback(msk); 553 554 goto fallback; 554 555 } 555 556 ··· 1407 1406 return true; 1408 1407 } 1409 1408 1410 - if (!mptcp_try_fallback(ssk)) { 1409 + if (!mptcp_try_fallback(ssk, MPTCP_MIB_DSSFALLBACK)) { 1411 1410 /* fatal protocol error, close the socket. 1412 1411 * subflow_error_report() will introduce the appropriate barriers 1413 1412 */ ··· 1854 1853 { 1855 1854 struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); 1856 1855 struct sock *parent = subflow->conn; 1857 - struct mptcp_sock *msk; 1858 1856 1859 1857 __subflow_state_change(sk); 1860 1858 1861 - msk = mptcp_sk(parent); 1862 1859 if (subflow_simultaneous_connect(sk)) { 1863 - WARN_ON_ONCE(!mptcp_try_fallback(sk)); 1864 - pr_fallback(msk); 1860 + WARN_ON_ONCE(!mptcp_try_fallback(sk, MPTCP_MIB_SIMULTCONNFALLBACK)); 1865 1861 subflow->conn_finished = 1; 1866 1862 mptcp_propagate_state(parent, sk, subflow, NULL); 1867 1863 }