* [RFC mptcp-next v2 1/6] mptcp: add MP_FAIL echo support
2022-02-17 11:23 [RFC mptcp-next v2 0/6] MP_FAIL echo and retrans Geliang Tang
@ 2022-02-17 11:23 ` Geliang Tang
2022-02-24 1:42 ` Mat Martineau
2022-02-17 11:23 ` [RFC mptcp-next v2 2/6] mptcp: add mibs for MP_FAIL echo Geliang Tang
` (4 subsequent siblings)
5 siblings, 1 reply; 10+ messages in thread
From: Geliang Tang @ 2022-02-17 11:23 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
Add MP_FAIL echo support.
Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
net/mptcp/pm.c | 10 ++++++++--
net/mptcp/protocol.h | 1 +
net/mptcp/subflow.c | 2 ++
3 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index d0d31d5c198a..dc0dffc1b6b5 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -279,8 +279,14 @@ void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq)
pr_debug("fail_seq=%llu", fail_seq);
- if (!mptcp_has_another_subflow(sk) && READ_ONCE(msk->allow_infinite_fallback))
- subflow->send_infinite_map = 1;
+ if (!mptcp_has_another_subflow(sk) && READ_ONCE(msk->allow_infinite_fallback)) {
+ if (!subflow->mp_fail_response_expect) {
+ subflow->send_mp_fail = 1;
+ subflow->send_infinite_map = 1;
+ } else {
+ subflow->mp_fail_response_expect = 0;
+ }
+ }
}
/* path manager helpers */
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 18ca0248c084..3c74b04fba6c 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -448,6 +448,7 @@ struct mptcp_subflow_context {
backup : 1,
send_mp_prio : 1,
send_mp_fail : 1,
+ mp_fail_response_expect : 1,
send_fastclose : 1,
send_infinite_map : 1,
rx_eof : 1,
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 8d086641bdc5..f06d93fce1bb 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -1172,6 +1172,8 @@ static bool subflow_check_data_avail(struct sock *ssk)
tcp_send_active_reset(ssk, GFP_ATOMIC);
while ((skb = skb_peek(&ssk->sk_receive_queue)))
sk_eat_skb(ssk, skb);
+ } else {
+ subflow->mp_fail_response_expect = 1;
}
WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA);
return true;
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [RFC mptcp-next v2 1/6] mptcp: add MP_FAIL echo support
2022-02-17 11:23 ` [RFC mptcp-next v2 1/6] mptcp: add MP_FAIL echo support Geliang Tang
@ 2022-02-24 1:42 ` Mat Martineau
0 siblings, 0 replies; 10+ messages in thread
From: Mat Martineau @ 2022-02-24 1:42 UTC (permalink / raw)
To: Geliang Tang; +Cc: mptcp
On Thu, 17 Feb 2022, Geliang Tang wrote:
> Add MP_FAIL echo support.
>
> Signed-off-by: Geliang Tang <geliang.tang@suse.com>
> ---
> net/mptcp/pm.c | 10 ++++++++--
> net/mptcp/protocol.h | 1 +
> net/mptcp/subflow.c | 2 ++
> 3 files changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
> index d0d31d5c198a..dc0dffc1b6b5 100644
> --- a/net/mptcp/pm.c
> +++ b/net/mptcp/pm.c
> @@ -279,8 +279,14 @@ void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq)
>
> pr_debug("fail_seq=%llu", fail_seq);
>
> - if (!mptcp_has_another_subflow(sk) && READ_ONCE(msk->allow_infinite_fallback))
> - subflow->send_infinite_map = 1;
> + if (!mptcp_has_another_subflow(sk) && READ_ONCE(msk->allow_infinite_fallback)) {
> + if (!subflow->mp_fail_response_expect) {
> + subflow->send_mp_fail = 1;
> + subflow->send_infinite_map = 1;
> + } else {
> + subflow->mp_fail_response_expect = 0;
I'm not sure this should be cleared. If the peer retransmits MP_FAIL, we
could receive MP_FAIL multiple times and we don't want to echo an MP_FAIL
back.
-Mat
> + }
> + }
> }
>
> /* path manager helpers */
> diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
> index 18ca0248c084..3c74b04fba6c 100644
> --- a/net/mptcp/protocol.h
> +++ b/net/mptcp/protocol.h
> @@ -448,6 +448,7 @@ struct mptcp_subflow_context {
> backup : 1,
> send_mp_prio : 1,
> send_mp_fail : 1,
> + mp_fail_response_expect : 1,
> send_fastclose : 1,
> send_infinite_map : 1,
> rx_eof : 1,
> diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
> index 8d086641bdc5..f06d93fce1bb 100644
> --- a/net/mptcp/subflow.c
> +++ b/net/mptcp/subflow.c
> @@ -1172,6 +1172,8 @@ static bool subflow_check_data_avail(struct sock *ssk)
> tcp_send_active_reset(ssk, GFP_ATOMIC);
> while ((skb = skb_peek(&ssk->sk_receive_queue)))
> sk_eat_skb(ssk, skb);
> + } else {
> + subflow->mp_fail_response_expect = 1;
> }
> WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA);
> return true;
> --
> 2.34.1
>
>
>
--
Mat Martineau
Intel
^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFC mptcp-next v2 2/6] mptcp: add mibs for MP_FAIL echo
2022-02-17 11:23 [RFC mptcp-next v2 0/6] MP_FAIL echo and retrans Geliang Tang
2022-02-17 11:23 ` [RFC mptcp-next v2 1/6] mptcp: add MP_FAIL echo support Geliang Tang
@ 2022-02-17 11:23 ` Geliang Tang
2022-02-17 11:23 ` [RFC mptcp-next v2 3/6] selftests: mptcp: add MP_FAIL echo mibs check Geliang Tang
` (3 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Geliang Tang @ 2022-02-17 11:23 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
Add MP_FAIL echo support.
Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
net/mptcp/mib.c | 2 ++
net/mptcp/mib.h | 2 ++
net/mptcp/pm.c | 2 ++
3 files changed, 6 insertions(+)
diff --git a/net/mptcp/mib.c b/net/mptcp/mib.c
index d93a8c9996fd..f3070daa013b 100644
--- a/net/mptcp/mib.c
+++ b/net/mptcp/mib.c
@@ -49,6 +49,8 @@ static const struct snmp_mib mptcp_snmp_list[] = {
SNMP_MIB_ITEM("MPPrioRx", MPTCP_MIB_MPPRIORX),
SNMP_MIB_ITEM("MPFailTx", MPTCP_MIB_MPFAILTX),
SNMP_MIB_ITEM("MPFailRx", MPTCP_MIB_MPFAILRX),
+ SNMP_MIB_ITEM("MPFailEchoTx", MPTCP_MIB_MPFAILECHOTX),
+ SNMP_MIB_ITEM("MPFailEchoRx", MPTCP_MIB_MPFAILECHORX),
SNMP_MIB_ITEM("MPFastcloseTx", MPTCP_MIB_MPFASTCLOSETX),
SNMP_MIB_ITEM("MPFastcloseRx", MPTCP_MIB_MPFASTCLOSERX),
SNMP_MIB_ITEM("MPRstTx", MPTCP_MIB_MPRSTTX),
diff --git a/net/mptcp/mib.h b/net/mptcp/mib.h
index 529d07af9e14..83219721d337 100644
--- a/net/mptcp/mib.h
+++ b/net/mptcp/mib.h
@@ -42,6 +42,8 @@ enum linux_mptcp_mib_field {
MPTCP_MIB_MPPRIORX, /* Received a MP_PRIO */
MPTCP_MIB_MPFAILTX, /* Transmit a MP_FAIL */
MPTCP_MIB_MPFAILRX, /* Received a MP_FAIL */
+ MPTCP_MIB_MPFAILECHOTX, /* Transmit a MP_FAIL echo */
+ MPTCP_MIB_MPFAILECHORX, /* Received a MP_FAIL echo */
MPTCP_MIB_MPFASTCLOSETX, /* Transmit a MP_FASTCLOSE */
MPTCP_MIB_MPFASTCLOSERX, /* Received a MP_FASTCLOSE */
MPTCP_MIB_MPRSTTX, /* Transmit a MP_RST */
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index dc0dffc1b6b5..314e110588d7 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -283,8 +283,10 @@ void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq)
if (!subflow->mp_fail_response_expect) {
subflow->send_mp_fail = 1;
subflow->send_infinite_map = 1;
+ MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFAILECHOTX);
} else {
subflow->mp_fail_response_expect = 0;
+ MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFAILECHORX);
}
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* [RFC mptcp-next v2 3/6] selftests: mptcp: add MP_FAIL echo mibs check
2022-02-17 11:23 [RFC mptcp-next v2 0/6] MP_FAIL echo and retrans Geliang Tang
2022-02-17 11:23 ` [RFC mptcp-next v2 1/6] mptcp: add MP_FAIL echo support Geliang Tang
2022-02-17 11:23 ` [RFC mptcp-next v2 2/6] mptcp: add mibs for MP_FAIL echo Geliang Tang
@ 2022-02-17 11:23 ` Geliang Tang
2022-02-17 11:23 ` [RFC mptcp-next v2 4/6] mptcp: add a new sysctl mp_fail_timeout Geliang Tang
` (2 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Geliang Tang @ 2022-02-17 11:23 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
This patch added the MP_FAIL echo mibs check.
Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
.../testing/selftests/net/mptcp/mptcp_join.sh | 24 +++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
index 8708be740334..9a1d8a1d3447 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
@@ -947,6 +947,8 @@ chk_infi_nr()
{
local infi_tx=$1
local infi_rx=$2
+ local echo_tx=${3:-$infi_tx}
+ local echo_rx=${4:-$infi_rx}
local count
local dump_stats
@@ -972,6 +974,28 @@ chk_infi_nr()
echo "[ ok ]"
fi
+ printf "%-${nr_blank}s %s" " " "etx"
+ count=`ip netns exec $ns2 nstat -as | grep MPTcpExtMPFailEchoTx | awk '{print $2}'`
+ [ -z "$count" ] && count=0
+ if [ "$count" != "$echo_tx" ]; then
+ echo "[fail] got $count MP_FAIL echo[s] RX expected $echo_tx"
+ ret=1
+ dump_stats=1
+ else
+ echo -n "[ ok ]"
+ fi
+
+ echo -n " - echorx"
+ count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPFailEchoRx | awk '{print $2}'`
+ [ -z "$count" ] && count=0
+ if [ "$count" != "$echo_rx" ]; then
+ echo "[fail] got $count MP_FAIL echo[s] RX expected $echo_rx"
+ ret=1
+ dump_stats=1
+ else
+ echo "[ ok ]"
+ fi
+
[ "${dump_stats}" = 1 ] && dump_stats
}
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* [RFC mptcp-next v2 4/6] mptcp: add a new sysctl mp_fail_timeout
2022-02-17 11:23 [RFC mptcp-next v2 0/6] MP_FAIL echo and retrans Geliang Tang
` (2 preceding siblings ...)
2022-02-17 11:23 ` [RFC mptcp-next v2 3/6] selftests: mptcp: add MP_FAIL echo mibs check Geliang Tang
@ 2022-02-17 11:23 ` Geliang Tang
2022-02-24 1:44 ` Mat Martineau
2022-02-17 11:23 ` [RFC mptcp-next v2 5/6] mptcp: add MP_FAIL retrans support Geliang Tang
2022-02-17 11:23 ` [RFC mptcp-next v2 6/6] selftests: mptcp: MP_FAIL timeout testcases TODO Geliang Tang
5 siblings, 1 reply; 10+ messages in thread
From: Geliang Tang @ 2022-02-17 11:23 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
This patch added a new sysctl, named mp_fail_timeout, to control the
timeout value (in seconds) of the MP_FAIL retransmission.
Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
Documentation/networking/mptcp-sysctl.rst | 10 ++++++++++
net/mptcp/ctrl.c | 14 ++++++++++++++
net/mptcp/protocol.h | 1 +
3 files changed, 25 insertions(+)
diff --git a/Documentation/networking/mptcp-sysctl.rst b/Documentation/networking/mptcp-sysctl.rst
index e263dfcc4b40..3ad19e04ecce 100644
--- a/Documentation/networking/mptcp-sysctl.rst
+++ b/Documentation/networking/mptcp-sysctl.rst
@@ -75,3 +75,13 @@ stale_loss_cnt - INTEGER
This is a per-namespace sysctl.
Default: 4
+
+mp_fail_timeout - INTEGER (seconds)
+ Set the timeout after which a MP_FAIL control message will be
+ resent to an MPTCP peer that has not acknowledged a previous
+ MP_FAIL message.
+
+ The default value matches TCP_RTO_MAX. This is a per-namespace
+ sysctl.
+
+ Default: 120
diff --git a/net/mptcp/ctrl.c b/net/mptcp/ctrl.c
index ae20b7d92e28..a211af9b19e8 100644
--- a/net/mptcp/ctrl.c
+++ b/net/mptcp/ctrl.c
@@ -32,6 +32,7 @@ struct mptcp_pernet {
u8 checksum_enabled;
u8 allow_join_initial_addr_port;
u8 pm_type;
+ unsigned int mp_fail_timeout;
};
static struct mptcp_pernet *mptcp_get_pernet(const struct net *net)
@@ -69,6 +70,11 @@ int mptcp_get_pm_type(const struct net *net)
return mptcp_get_pernet(net)->pm_type;
}
+unsigned int mptcp_get_mp_fail_timeout(const struct net *net)
+{
+ return mptcp_get_pernet(net)->mp_fail_timeout;
+}
+
static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
{
pernet->mptcp_enabled = 1;
@@ -77,6 +83,7 @@ static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
pernet->allow_join_initial_addr_port = 1;
pernet->stale_loss_cnt = 4;
pernet->pm_type = MPTCP_PM_TYPE_KERNEL;
+ pernet->mp_fail_timeout = TCP_RTO_MAX;
}
#ifdef CONFIG_SYSCTL
@@ -128,6 +135,12 @@ static struct ctl_table mptcp_sysctl_table[] = {
.extra1 = SYSCTL_ZERO,
.extra2 = &mptcp_pm_type_max
},
+ {
+ .procname = "mp_fail_timeout",
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_jiffies,
+ },
{}
};
@@ -149,6 +162,7 @@ static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)
table[3].data = &pernet->allow_join_initial_addr_port;
table[4].data = &pernet->stale_loss_cnt;
table[5].data = &pernet->pm_type;
+ table[6].data = &pernet->mp_fail_timeout;
hdr = register_net_sysctl(net, MPTCP_SYSCTL_PATH, table);
if (!hdr)
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 3c74b04fba6c..c28842ab0dcc 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -583,6 +583,7 @@ int mptcp_is_checksum_enabled(const struct net *net);
int mptcp_allow_join_id0(const struct net *net);
unsigned int mptcp_stale_loss_cnt(const struct net *net);
int mptcp_get_pm_type(const struct net *net);
+unsigned int mptcp_get_mp_fail_timeout(const struct net *net);
void mptcp_subflow_fully_established(struct mptcp_subflow_context *subflow,
struct mptcp_options_received *mp_opt);
bool __mptcp_retransmit_pending_data(struct sock *sk);
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [RFC mptcp-next v2 4/6] mptcp: add a new sysctl mp_fail_timeout
2022-02-17 11:23 ` [RFC mptcp-next v2 4/6] mptcp: add a new sysctl mp_fail_timeout Geliang Tang
@ 2022-02-24 1:44 ` Mat Martineau
0 siblings, 0 replies; 10+ messages in thread
From: Mat Martineau @ 2022-02-24 1:44 UTC (permalink / raw)
To: Geliang Tang; +Cc: mptcp
On Thu, 17 Feb 2022, Geliang Tang wrote:
> This patch added a new sysctl, named mp_fail_timeout, to control the
> timeout value (in seconds) of the MP_FAIL retransmission.
>
I'm reluctant to add a sysctl for this - is there a use case other than
making the selftest run faster? :)
-Mat
> Signed-off-by: Geliang Tang <geliang.tang@suse.com>
> ---
> Documentation/networking/mptcp-sysctl.rst | 10 ++++++++++
> net/mptcp/ctrl.c | 14 ++++++++++++++
> net/mptcp/protocol.h | 1 +
> 3 files changed, 25 insertions(+)
>
> diff --git a/Documentation/networking/mptcp-sysctl.rst b/Documentation/networking/mptcp-sysctl.rst
> index e263dfcc4b40..3ad19e04ecce 100644
> --- a/Documentation/networking/mptcp-sysctl.rst
> +++ b/Documentation/networking/mptcp-sysctl.rst
> @@ -75,3 +75,13 @@ stale_loss_cnt - INTEGER
> This is a per-namespace sysctl.
>
> Default: 4
> +
> +mp_fail_timeout - INTEGER (seconds)
> + Set the timeout after which a MP_FAIL control message will be
> + resent to an MPTCP peer that has not acknowledged a previous
> + MP_FAIL message.
> +
> + The default value matches TCP_RTO_MAX. This is a per-namespace
> + sysctl.
> +
> + Default: 120
> diff --git a/net/mptcp/ctrl.c b/net/mptcp/ctrl.c
> index ae20b7d92e28..a211af9b19e8 100644
> --- a/net/mptcp/ctrl.c
> +++ b/net/mptcp/ctrl.c
> @@ -32,6 +32,7 @@ struct mptcp_pernet {
> u8 checksum_enabled;
> u8 allow_join_initial_addr_port;
> u8 pm_type;
> + unsigned int mp_fail_timeout;
> };
>
> static struct mptcp_pernet *mptcp_get_pernet(const struct net *net)
> @@ -69,6 +70,11 @@ int mptcp_get_pm_type(const struct net *net)
> return mptcp_get_pernet(net)->pm_type;
> }
>
> +unsigned int mptcp_get_mp_fail_timeout(const struct net *net)
> +{
> + return mptcp_get_pernet(net)->mp_fail_timeout;
> +}
> +
> static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
> {
> pernet->mptcp_enabled = 1;
> @@ -77,6 +83,7 @@ static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
> pernet->allow_join_initial_addr_port = 1;
> pernet->stale_loss_cnt = 4;
> pernet->pm_type = MPTCP_PM_TYPE_KERNEL;
> + pernet->mp_fail_timeout = TCP_RTO_MAX;
> }
>
> #ifdef CONFIG_SYSCTL
> @@ -128,6 +135,12 @@ static struct ctl_table mptcp_sysctl_table[] = {
> .extra1 = SYSCTL_ZERO,
> .extra2 = &mptcp_pm_type_max
> },
> + {
> + .procname = "mp_fail_timeout",
> + .maxlen = sizeof(unsigned int),
> + .mode = 0644,
> + .proc_handler = proc_dointvec_jiffies,
> + },
> {}
> };
>
> @@ -149,6 +162,7 @@ static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)
> table[3].data = &pernet->allow_join_initial_addr_port;
> table[4].data = &pernet->stale_loss_cnt;
> table[5].data = &pernet->pm_type;
> + table[6].data = &pernet->mp_fail_timeout;
>
> hdr = register_net_sysctl(net, MPTCP_SYSCTL_PATH, table);
> if (!hdr)
> diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
> index 3c74b04fba6c..c28842ab0dcc 100644
> --- a/net/mptcp/protocol.h
> +++ b/net/mptcp/protocol.h
> @@ -583,6 +583,7 @@ int mptcp_is_checksum_enabled(const struct net *net);
> int mptcp_allow_join_id0(const struct net *net);
> unsigned int mptcp_stale_loss_cnt(const struct net *net);
> int mptcp_get_pm_type(const struct net *net);
> +unsigned int mptcp_get_mp_fail_timeout(const struct net *net);
> void mptcp_subflow_fully_established(struct mptcp_subflow_context *subflow,
> struct mptcp_options_received *mp_opt);
> bool __mptcp_retransmit_pending_data(struct sock *sk);
> --
> 2.34.1
>
>
>
--
Mat Martineau
Intel
^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFC mptcp-next v2 5/6] mptcp: add MP_FAIL retrans support
2022-02-17 11:23 [RFC mptcp-next v2 0/6] MP_FAIL echo and retrans Geliang Tang
` (3 preceding siblings ...)
2022-02-17 11:23 ` [RFC mptcp-next v2 4/6] mptcp: add a new sysctl mp_fail_timeout Geliang Tang
@ 2022-02-17 11:23 ` Geliang Tang
2022-02-24 1:54 ` Mat Martineau
2022-02-17 11:23 ` [RFC mptcp-next v2 6/6] selftests: mptcp: MP_FAIL timeout testcases TODO Geliang Tang
5 siblings, 1 reply; 10+ messages in thread
From: Geliang Tang @ 2022-02-17 11:23 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
Add MP_FAIL retrans support.
Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
net/mptcp/pm.c | 1 +
net/mptcp/protocol.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
net/mptcp/protocol.h | 2 ++
net/mptcp/subflow.c | 1 +
4 files changed, 47 insertions(+), 1 deletion(-)
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index 314e110588d7..ccb29b2d2075 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -285,6 +285,7 @@ void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq)
subflow->send_infinite_map = 1;
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFAILECHOTX);
} else {
+ sk_stop_timer((struct sock *)msk, &msk->sk.icsk_retransmit_timer);
subflow->mp_fail_response_expect = 0;
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFAILECHORX);
}
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 4599bde215b2..461fd30c6b9d 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -50,6 +50,8 @@ enum {
MPTCP_CMSG_INQ = BIT(1),
};
+#define MP_FAIL_RETRANS_MAX 3
+
static struct percpu_counter mptcp_sockets_allocated ____cacheline_aligned_in_smp;
static void __mptcp_destroy_sock(struct sock *sk);
@@ -860,6 +862,46 @@ static void mptcp_reset_timer(struct sock *sk)
sk_reset_timer(sk, &icsk->icsk_retransmit_timer, jiffies + tout);
}
+static void mptcp_mp_fail_timer(struct timer_list *t)
+{
+ struct inet_connection_sock *icsk = from_timer(icsk, t,
+ icsk_retransmit_timer);
+ struct sock *sk = &icsk->icsk_inet.sk;
+ struct mptcp_sock *msk = mptcp_sk(sk);
+ struct mptcp_subflow_context *subflow;
+
+ if (!msk)
+ return;
+ if (inet_sk_state_load(sk) == TCP_CLOSE)
+ return;
+
+ bh_lock_sock(sk);
+
+ subflow = mptcp_subflow_ctx(msk->first);
+ subflow->send_mp_fail = 1;
+ MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFAILTX);
+ pr_debug("retransmit MP_FAIL %u", subflow->retrans_times++);
+
+ if (subflow->retrans_times < MP_FAIL_RETRANS_MAX) {
+ __mptcp_set_timeout(sk, mptcp_get_mp_fail_timeout(sock_net(sk)));
+ mptcp_reset_timer(sk);
+ }
+
+ bh_unlock_sock(sk);
+ sock_put(sk);
+}
+
+void mptcp_setup_mp_fail_timer(struct mptcp_sock *msk)
+{
+ struct sock *sk = (struct sock *)msk;
+
+ /* re-use the csk retrans timer for MP_FAIL retrans */
+ sk_stop_timer(sk, &msk->sk.icsk_retransmit_timer);
+ timer_setup(&msk->sk.icsk_retransmit_timer, mptcp_mp_fail_timer, 0);
+ __mptcp_set_timeout(sk, mptcp_get_mp_fail_timeout(sock_net(sk)));
+ mptcp_reset_timer(sk);
+}
+
bool mptcp_schedule_work(struct sock *sk)
{
if (inet_sk_state_load(sk) != TCP_CLOSE &&
@@ -1598,7 +1640,7 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
out:
/* ensure the rtx timer is running */
- if (!mptcp_timer_pending(sk))
+ if (!mptcp_timer_pending(sk) && !__mptcp_check_fallback(msk))
mptcp_reset_timer(sk);
if (copied)
__mptcp_check_send_data_fin(sk);
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index c28842ab0dcc..40954f2389e8 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -467,6 +467,7 @@ struct mptcp_subflow_context {
u8 reset_transient:1;
u8 reset_reason:4;
u8 stale_count;
+ u8 retrans_times;
long delegated_status;
@@ -669,6 +670,7 @@ void mptcp_rcv_space_init(struct mptcp_sock *msk, const struct sock *ssk);
void mptcp_data_ready(struct sock *sk, struct sock *ssk);
bool mptcp_finish_join(struct sock *sk);
bool mptcp_schedule_work(struct sock *sk);
+void mptcp_setup_mp_fail_timer(struct mptcp_sock *msk);
int mptcp_setsockopt(struct sock *sk, int level, int optname,
sockptr_t optval, unsigned int optlen);
int mptcp_getsockopt(struct sock *sk, int level, int optname,
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index f06d93fce1bb..a30867f926fd 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -1174,6 +1174,7 @@ static bool subflow_check_data_avail(struct sock *ssk)
sk_eat_skb(ssk, skb);
} else {
subflow->mp_fail_response_expect = 1;
+ mptcp_setup_mp_fail_timer(msk);
}
WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA);
return true;
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [RFC mptcp-next v2 5/6] mptcp: add MP_FAIL retrans support
2022-02-17 11:23 ` [RFC mptcp-next v2 5/6] mptcp: add MP_FAIL retrans support Geliang Tang
@ 2022-02-24 1:54 ` Mat Martineau
0 siblings, 0 replies; 10+ messages in thread
From: Mat Martineau @ 2022-02-24 1:54 UTC (permalink / raw)
To: Geliang Tang; +Cc: mptcp
On Thu, 17 Feb 2022, Geliang Tang wrote:
> Add MP_FAIL retrans support.
>
I'm still trying to figure out if retransmitting MP_FAIL is the action to
take if the MP_FAIL echo is not received. Could also just send RST, as in
the other checksum error cases. As Christoph said, this is a "best effort"
thing and I'm not sure the rare case justifies very much complexity. There
are other scenarios that arise: for example, the MP_FAIL echo from the
peer is lost, but the infinite mapping from the peer is delivered. That
implies that the peer did get the MP_FAIL, but the RFC doesn't have the
details on what to do.
What do you think about resetting the subflow if the fallback process
doesn't follow the expected steps?
- Mat
> Signed-off-by: Geliang Tang <geliang.tang@suse.com>
> ---
> net/mptcp/pm.c | 1 +
> net/mptcp/protocol.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
> net/mptcp/protocol.h | 2 ++
> net/mptcp/subflow.c | 1 +
> 4 files changed, 47 insertions(+), 1 deletion(-)
>
> diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
> index 314e110588d7..ccb29b2d2075 100644
> --- a/net/mptcp/pm.c
> +++ b/net/mptcp/pm.c
> @@ -285,6 +285,7 @@ void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq)
> subflow->send_infinite_map = 1;
> MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFAILECHOTX);
> } else {
> + sk_stop_timer((struct sock *)msk, &msk->sk.icsk_retransmit_timer);
> subflow->mp_fail_response_expect = 0;
> MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFAILECHORX);
> }
> diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> index 4599bde215b2..461fd30c6b9d 100644
> --- a/net/mptcp/protocol.c
> +++ b/net/mptcp/protocol.c
> @@ -50,6 +50,8 @@ enum {
> MPTCP_CMSG_INQ = BIT(1),
> };
>
> +#define MP_FAIL_RETRANS_MAX 3
> +
> static struct percpu_counter mptcp_sockets_allocated ____cacheline_aligned_in_smp;
>
> static void __mptcp_destroy_sock(struct sock *sk);
> @@ -860,6 +862,46 @@ static void mptcp_reset_timer(struct sock *sk)
> sk_reset_timer(sk, &icsk->icsk_retransmit_timer, jiffies + tout);
> }
>
> +static void mptcp_mp_fail_timer(struct timer_list *t)
> +{
> + struct inet_connection_sock *icsk = from_timer(icsk, t,
> + icsk_retransmit_timer);
> + struct sock *sk = &icsk->icsk_inet.sk;
> + struct mptcp_sock *msk = mptcp_sk(sk);
> + struct mptcp_subflow_context *subflow;
> +
> + if (!msk)
> + return;
> + if (inet_sk_state_load(sk) == TCP_CLOSE)
> + return;
> +
> + bh_lock_sock(sk);
> +
> + subflow = mptcp_subflow_ctx(msk->first);
> + subflow->send_mp_fail = 1;
> + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFAILTX);
> + pr_debug("retransmit MP_FAIL %u", subflow->retrans_times++);
> +
> + if (subflow->retrans_times < MP_FAIL_RETRANS_MAX) {
> + __mptcp_set_timeout(sk, mptcp_get_mp_fail_timeout(sock_net(sk)));
> + mptcp_reset_timer(sk);
> + }
> +
> + bh_unlock_sock(sk);
> + sock_put(sk);
> +}
> +
> +void mptcp_setup_mp_fail_timer(struct mptcp_sock *msk)
> +{
> + struct sock *sk = (struct sock *)msk;
> +
> + /* re-use the csk retrans timer for MP_FAIL retrans */
> + sk_stop_timer(sk, &msk->sk.icsk_retransmit_timer);
> + timer_setup(&msk->sk.icsk_retransmit_timer, mptcp_mp_fail_timer, 0);
> + __mptcp_set_timeout(sk, mptcp_get_mp_fail_timeout(sock_net(sk)));
> + mptcp_reset_timer(sk);
> +}
> +
> bool mptcp_schedule_work(struct sock *sk)
> {
> if (inet_sk_state_load(sk) != TCP_CLOSE &&
> @@ -1598,7 +1640,7 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
>
> out:
> /* ensure the rtx timer is running */
> - if (!mptcp_timer_pending(sk))
> + if (!mptcp_timer_pending(sk) && !__mptcp_check_fallback(msk))
> mptcp_reset_timer(sk);
> if (copied)
> __mptcp_check_send_data_fin(sk);
> diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
> index c28842ab0dcc..40954f2389e8 100644
> --- a/net/mptcp/protocol.h
> +++ b/net/mptcp/protocol.h
> @@ -467,6 +467,7 @@ struct mptcp_subflow_context {
> u8 reset_transient:1;
> u8 reset_reason:4;
> u8 stale_count;
> + u8 retrans_times;
>
> long delegated_status;
>
> @@ -669,6 +670,7 @@ void mptcp_rcv_space_init(struct mptcp_sock *msk, const struct sock *ssk);
> void mptcp_data_ready(struct sock *sk, struct sock *ssk);
> bool mptcp_finish_join(struct sock *sk);
> bool mptcp_schedule_work(struct sock *sk);
> +void mptcp_setup_mp_fail_timer(struct mptcp_sock *msk);
> int mptcp_setsockopt(struct sock *sk, int level, int optname,
> sockptr_t optval, unsigned int optlen);
> int mptcp_getsockopt(struct sock *sk, int level, int optname,
> diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
> index f06d93fce1bb..a30867f926fd 100644
> --- a/net/mptcp/subflow.c
> +++ b/net/mptcp/subflow.c
> @@ -1174,6 +1174,7 @@ static bool subflow_check_data_avail(struct sock *ssk)
> sk_eat_skb(ssk, skb);
> } else {
> subflow->mp_fail_response_expect = 1;
> + mptcp_setup_mp_fail_timer(msk);
> }
> WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA);
> return true;
> --
> 2.34.1
>
>
>
--
Mat Martineau
Intel
^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFC mptcp-next v2 6/6] selftests: mptcp: MP_FAIL timeout testcases TODO
2022-02-17 11:23 [RFC mptcp-next v2 0/6] MP_FAIL echo and retrans Geliang Tang
` (4 preceding siblings ...)
2022-02-17 11:23 ` [RFC mptcp-next v2 5/6] mptcp: add MP_FAIL retrans support Geliang Tang
@ 2022-02-17 11:23 ` Geliang Tang
5 siblings, 0 replies; 10+ messages in thread
From: Geliang Tang @ 2022-02-17 11:23 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
This patch added the MP_FAIL timeout testcases.
Doesn't work yet.
Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
.../testing/selftests/net/mptcp/mptcp_join.sh | 48 +++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
index 9a1d8a1d3447..f28faf901a24 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
@@ -41,6 +41,24 @@ CBPF_MPTCP_SUBOPTION_ADD_ADDR="14,
6 0 0 65535,
6 0 0 0"
+# generated using "nfbpf_compile '(ip && (ip[54] & 0xf0) == 0x60) ||
+# (ip6 && (ip6[74] & 0xf0) == 0x60)'"
+CBPF_MPTCP_SUBOPTION_MP_FAIL="14,
+ 48 0 0 0,
+ 84 0 0 240,
+ 21 0 3 64,
+ 48 0 0 54,
+ 84 0 0 240,
+ 21 6 7 96,
+ 48 0 0 0,
+ 84 0 0 240,
+ 21 0 4 96,
+ 48 0 0 74,
+ 84 0 0 240,
+ 21 0 1 96,
+ 6 0 0 65535,
+ 6 0 0 0"
+
init_partial()
{
capout=$(mktemp)
@@ -261,6 +279,27 @@ reset_with_fail()
index 100 || exit 1
}
+reset_with_fail_timeout()
+{
+ local i="$1"
+ local ip="${2:-4}"
+ local tables
+
+ tables="iptables"
+ if [ $ip -eq 6 ]; then
+ tables="ip6tables"
+ fi
+
+ reset_with_fail $i $ip
+
+ ip netns exec $ns1 sysctl -q net.mptcp.mp_fail_timeout=1
+ ip netns exec $ns2 $tables -A OUTPUT -p tcp \
+ -m tcp --tcp-option 30 \
+ -m bpf --bytecode \
+ "$CBPF_MPTCP_SUBOPTION_MP_FAIL" \
+ -j DROP
+}
+
print_file_err()
{
ls -l "$1" 1>&2
@@ -2455,6 +2494,15 @@ fail_tests()
1 \
0 \
1
+
+ # single subflow
+ reset_with_fail_timeout 1
+ run_tests $ns1 $ns2 10.0.1.1 128
+ chk_join_nr "MP_FAIL timeout 1: $(pedit_action_pkts) corrupted pkts" 0 0 0 \
+ +1 +0 \
+ 1 \
+ 0 \
+ 1
}
all_tests()
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread