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>
This commit is contained in:
+2
-2
@@ -533,9 +533,9 @@ void mptcp_active_detect_blackhole(struct sock *ssk, bool expired)
|
||||
to_max = mptcp_get_pernet(net)->syn_retrans_before_tcp_fallback;
|
||||
|
||||
if (timeouts == to_max || (timeouts < to_max && expired)) {
|
||||
MPTCP_INC_STATS(net, MPTCP_MIB_MPCAPABLEACTIVEDROP);
|
||||
subflow->mpc_drop = 1;
|
||||
mptcp_subflow_early_fallback(mptcp_sk(subflow->conn), subflow);
|
||||
mptcp_early_fallback(mptcp_sk(subflow->conn), subflow,
|
||||
MPTCP_MIB_MPCAPABLEACTIVEDROP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,11 @@ static const struct snmp_mib mptcp_snmp_list[] = {
|
||||
SNMP_MIB_ITEM("RcvWndConflict", MPTCP_MIB_RCVWNDCONFLICT),
|
||||
SNMP_MIB_ITEM("MPCurrEstab", MPTCP_MIB_CURRESTAB),
|
||||
SNMP_MIB_ITEM("Blackhole", MPTCP_MIB_BLACKHOLE),
|
||||
SNMP_MIB_ITEM("MPCapableDataFallback", MPTCP_MIB_MPCAPABLEDATAFALLBACK),
|
||||
SNMP_MIB_ITEM("MD5SigFallback", MPTCP_MIB_MD5SIGFALLBACK),
|
||||
SNMP_MIB_ITEM("DssFallback", MPTCP_MIB_DSSFALLBACK),
|
||||
SNMP_MIB_ITEM("SimultConnectFallback", MPTCP_MIB_SIMULTCONNFALLBACK),
|
||||
SNMP_MIB_ITEM("FallbackFailed", MPTCP_MIB_FALLBACKFAILED),
|
||||
SNMP_MIB_SENTINEL
|
||||
};
|
||||
|
||||
|
||||
@@ -81,6 +81,13 @@ enum linux_mptcp_mib_field {
|
||||
MPTCP_MIB_RCVWNDCONFLICT, /* Conflict with while updating msk rcv wnd */
|
||||
MPTCP_MIB_CURRESTAB, /* Current established MPTCP connections */
|
||||
MPTCP_MIB_BLACKHOLE, /* A blackhole has been detected */
|
||||
MPTCP_MIB_MPCAPABLEDATAFALLBACK, /* Missing DSS/MPC+data on first
|
||||
* established packet
|
||||
*/
|
||||
MPTCP_MIB_MD5SIGFALLBACK, /* Conflicting TCP option enabled */
|
||||
MPTCP_MIB_DSSFALLBACK, /* Bad or missing DSS */
|
||||
MPTCP_MIB_SIMULTCONNFALLBACK, /* Simultaneous connect */
|
||||
MPTCP_MIB_FALLBACKFAILED, /* Can't fallback due to msk status */
|
||||
__MPTCP_MIB_MAX
|
||||
};
|
||||
|
||||
|
||||
+3
-2
@@ -978,9 +978,10 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk,
|
||||
if (subflow->mp_join)
|
||||
goto reset;
|
||||
subflow->mp_capable = 0;
|
||||
if (!mptcp_try_fallback(ssk))
|
||||
if (!mptcp_try_fallback(ssk, MPTCP_MIB_MPCAPABLEDATAFALLBACK)) {
|
||||
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_FALLBACKFAILED);
|
||||
goto reset;
|
||||
pr_fallback(msk);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+30
-15
@@ -68,6 +68,26 @@ static const struct proto_ops *mptcp_fallback_tcp_ops(const struct sock *sk)
|
||||
return &inet_stream_ops;
|
||||
}
|
||||
|
||||
bool __mptcp_try_fallback(struct mptcp_sock *msk, int fb_mib)
|
||||
{
|
||||
struct net *net = sock_net((struct sock *)msk);
|
||||
|
||||
if (__mptcp_check_fallback(msk))
|
||||
return true;
|
||||
|
||||
spin_lock_bh(&msk->fallback_lock);
|
||||
if (!msk->allow_infinite_fallback) {
|
||||
spin_unlock_bh(&msk->fallback_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
msk->allow_subflows = false;
|
||||
set_bit(MPTCP_FALLBACK_DONE, &msk->flags);
|
||||
__MPTCP_INC_STATS(net, fb_mib);
|
||||
spin_unlock_bh(&msk->fallback_lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int __mptcp_socket_create(struct mptcp_sock *msk)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow;
|
||||
@@ -561,10 +581,7 @@ static bool mptcp_check_data_fin(struct sock *sk)
|
||||
|
||||
static void mptcp_dss_corruption(struct mptcp_sock *msk, struct sock *ssk)
|
||||
{
|
||||
if (mptcp_try_fallback(ssk)) {
|
||||
MPTCP_INC_STATS(sock_net(ssk),
|
||||
MPTCP_MIB_DSSCORRUPTIONFALLBACK);
|
||||
} else {
|
||||
if (!mptcp_try_fallback(ssk, MPTCP_MIB_DSSCORRUPTIONFALLBACK)) {
|
||||
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DSSCORRUPTIONRESET);
|
||||
mptcp_subflow_reset(ssk);
|
||||
}
|
||||
@@ -1143,14 +1160,13 @@ static void mptcp_update_infinite_map(struct mptcp_sock *msk,
|
||||
mpext->infinite_map = 1;
|
||||
mpext->data_len = 0;
|
||||
|
||||
if (!mptcp_try_fallback(ssk)) {
|
||||
if (!mptcp_try_fallback(ssk, MPTCP_MIB_INFINITEMAPTX)) {
|
||||
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_FALLBACKFAILED);
|
||||
mptcp_subflow_reset(ssk);
|
||||
return;
|
||||
}
|
||||
|
||||
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_INFINITEMAPTX);
|
||||
mptcp_subflow_ctx(ssk)->send_infinite_map = 0;
|
||||
pr_fallback(msk);
|
||||
}
|
||||
|
||||
#define MPTCP_MAX_GSO_SIZE (GSO_LEGACY_MAX_SIZE - (MAX_TCP_HEADER + 1))
|
||||
@@ -3689,16 +3705,15 @@ static int mptcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
||||
* TCP option space.
|
||||
*/
|
||||
if (rcu_access_pointer(tcp_sk(ssk)->md5sig_info))
|
||||
mptcp_subflow_early_fallback(msk, subflow);
|
||||
mptcp_early_fallback(msk, subflow, MPTCP_MIB_MD5SIGFALLBACK);
|
||||
#endif
|
||||
if (subflow->request_mptcp) {
|
||||
if (mptcp_active_should_disable(sk)) {
|
||||
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_MPCAPABLEACTIVEDISABLED);
|
||||
mptcp_subflow_early_fallback(msk, subflow);
|
||||
} else if (mptcp_token_new_connect(ssk) < 0) {
|
||||
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_TOKENFALLBACKINIT);
|
||||
mptcp_subflow_early_fallback(msk, subflow);
|
||||
}
|
||||
if (mptcp_active_should_disable(sk))
|
||||
mptcp_early_fallback(msk, subflow,
|
||||
MPTCP_MIB_MPCAPABLEACTIVEDISABLED);
|
||||
else if (mptcp_token_new_connect(ssk) < 0)
|
||||
mptcp_early_fallback(msk, subflow,
|
||||
MPTCP_MIB_TOKENFALLBACKINIT);
|
||||
}
|
||||
|
||||
WRITE_ONCE(msk->write_seq, subflow->idsn);
|
||||
|
||||
+8
-26
@@ -1223,24 +1223,6 @@ static inline bool mptcp_check_fallback(const struct sock *sk)
|
||||
return __mptcp_check_fallback(msk);
|
||||
}
|
||||
|
||||
static inline bool __mptcp_try_fallback(struct mptcp_sock *msk)
|
||||
{
|
||||
if (__mptcp_check_fallback(msk)) {
|
||||
pr_debug("TCP fallback already done (msk=%p)\n", msk);
|
||||
return true;
|
||||
}
|
||||
spin_lock_bh(&msk->fallback_lock);
|
||||
if (!msk->allow_infinite_fallback) {
|
||||
spin_unlock_bh(&msk->fallback_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
msk->allow_subflows = false;
|
||||
set_bit(MPTCP_FALLBACK_DONE, &msk->flags);
|
||||
spin_unlock_bh(&msk->fallback_lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool __mptcp_has_initial_subflow(const struct mptcp_sock *msk)
|
||||
{
|
||||
struct sock *ssk = READ_ONCE(msk->first);
|
||||
@@ -1250,14 +1232,16 @@ static inline bool __mptcp_has_initial_subflow(const struct mptcp_sock *msk)
|
||||
TCPF_SYN_RECV | TCPF_LISTEN));
|
||||
}
|
||||
|
||||
static inline bool mptcp_try_fallback(struct sock *ssk)
|
||||
bool __mptcp_try_fallback(struct mptcp_sock *msk, int fb_mib);
|
||||
|
||||
static inline bool mptcp_try_fallback(struct sock *ssk, int fb_mib)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
|
||||
struct sock *sk = subflow->conn;
|
||||
struct mptcp_sock *msk;
|
||||
|
||||
msk = mptcp_sk(sk);
|
||||
if (!__mptcp_try_fallback(msk))
|
||||
if (!__mptcp_try_fallback(msk, fb_mib))
|
||||
return false;
|
||||
if (READ_ONCE(msk->snd_data_fin_enable) && !(ssk->sk_shutdown & SEND_SHUTDOWN)) {
|
||||
gfp_t saved_allocation = ssk->sk_allocation;
|
||||
@@ -1273,14 +1257,12 @@ static inline bool mptcp_try_fallback(struct sock *ssk)
|
||||
return true;
|
||||
}
|
||||
|
||||
#define pr_fallback(a) pr_debug("%s:fallback to TCP (msk=%p)\n", __func__, a)
|
||||
|
||||
static inline void mptcp_subflow_early_fallback(struct mptcp_sock *msk,
|
||||
struct mptcp_subflow_context *subflow)
|
||||
static inline void mptcp_early_fallback(struct mptcp_sock *msk,
|
||||
struct mptcp_subflow_context *subflow,
|
||||
int fb_mib)
|
||||
{
|
||||
pr_fallback(msk);
|
||||
subflow->request_mptcp = 0;
|
||||
WARN_ON_ONCE(!__mptcp_try_fallback(msk));
|
||||
WARN_ON_ONCE(!__mptcp_try_fallback(msk, fb_mib));
|
||||
}
|
||||
|
||||
static inline bool mptcp_check_infinite_map(struct sk_buff *skb)
|
||||
|
||||
+7
-9
@@ -544,12 +544,13 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
|
||||
mptcp_get_options(skb, &mp_opt);
|
||||
if (subflow->request_mptcp) {
|
||||
if (!(mp_opt.suboptions & OPTION_MPTCP_MPC_SYNACK)) {
|
||||
if (!mptcp_try_fallback(sk))
|
||||
if (!mptcp_try_fallback(sk,
|
||||
MPTCP_MIB_MPCAPABLEACTIVEFALLBACK)) {
|
||||
MPTCP_INC_STATS(sock_net(sk),
|
||||
MPTCP_MIB_FALLBACKFAILED);
|
||||
goto do_reset;
|
||||
}
|
||||
|
||||
MPTCP_INC_STATS(sock_net(sk),
|
||||
MPTCP_MIB_MPCAPABLEACTIVEFALLBACK);
|
||||
pr_fallback(msk);
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
@@ -1406,7 +1407,7 @@ fallback:
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!mptcp_try_fallback(ssk)) {
|
||||
if (!mptcp_try_fallback(ssk, MPTCP_MIB_DSSFALLBACK)) {
|
||||
/* fatal protocol error, close the socket.
|
||||
* subflow_error_report() will introduce the appropriate barriers
|
||||
*/
|
||||
@@ -1853,14 +1854,11 @@ static void subflow_state_change(struct sock *sk)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
||||
struct sock *parent = subflow->conn;
|
||||
struct mptcp_sock *msk;
|
||||
|
||||
__subflow_state_change(sk);
|
||||
|
||||
msk = mptcp_sk(parent);
|
||||
if (subflow_simultaneous_connect(sk)) {
|
||||
WARN_ON_ONCE(!mptcp_try_fallback(sk));
|
||||
pr_fallback(msk);
|
||||
WARN_ON_ONCE(!mptcp_try_fallback(sk, MPTCP_MIB_SIMULTCONNFALLBACK));
|
||||
subflow->conn_finished = 1;
|
||||
mptcp_propagate_state(parent, sk, subflow, NULL);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user