* [PATCH mptcp-next v4 1/8] mptcp: track and update contiguous data status
2021-09-18 7:22 [PATCH mptcp-next v4 0/8] The infinite mapping support Geliang Tang
@ 2021-09-18 7:22 ` Geliang Tang
2021-09-22 0:42 ` Mat Martineau
2021-09-18 7:22 ` [PATCH mptcp-next v4 2/8] mptcp: add last_fully_acked_dss_start_seq in the msk Geliang Tang
` (6 subsequent siblings)
7 siblings, 1 reply; 11+ messages in thread
From: Geliang Tang @ 2021-09-18 7:22 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
This patch added a new member last_retrans_seq in the msk to track the
last retransmitting sequence number.
Add a new helper named mptcp_is_data_contiguous() to check whether the
data is contiguous on a subflow.
When a bad checksum is detected and a single contiguous subflow is in
use, don't send RST + MP_FAIL, send data_ack + MP_FAIL instead.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
---
net/mptcp/protocol.c | 15 +++++++++++++--
net/mptcp/protocol.h | 6 ++++++
net/mptcp/subflow.c | 12 ++++++------
3 files changed, 25 insertions(+), 8 deletions(-)
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index ff574d62073f..b766b36e6c93 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1102,8 +1102,13 @@ static void __mptcp_clean_una(struct sock *sk)
msk->recovery = false;
out:
- if (cleaned && tcp_under_memory_pressure(sk))
- __mptcp_mem_reclaim_partial(sk);
+ if (cleaned) {
+ if (mptcp_is_data_contiguous(msk))
+ msk->last_retrans_seq = msk->snd_una - 1;
+
+ if (tcp_under_memory_pressure(sk))
+ __mptcp_mem_reclaim_partial(sk);
+ }
if (snd_una == READ_ONCE(msk->snd_nxt) &&
snd_una == READ_ONCE(msk->write_seq)) {
@@ -2419,6 +2424,7 @@ static void __mptcp_retrans(struct sock *sk)
struct mptcp_data_frag *dfrag;
size_t copied = 0;
struct sock *ssk;
+ u64 retrans_seq;
int ret;
mptcp_clean_una_wakeup(sk);
@@ -2464,6 +2470,9 @@ static void __mptcp_retrans(struct sock *sk)
dfrag->already_sent = max(dfrag->already_sent, info.sent);
tcp_push(ssk, 0, info.mss_now, tcp_sk(ssk)->nonagle,
info.size_goal);
+ retrans_seq = dfrag->data_seq + info.sent;
+ if (after64(retrans_seq, msk->last_retrans_seq))
+ msk->last_retrans_seq = retrans_seq;
}
release_sock(ssk);
@@ -2889,6 +2898,7 @@ struct sock *mptcp_sk_clone(const struct sock *sk,
msk->snd_una = msk->write_seq;
msk->wnd_end = msk->snd_nxt + req->rsk_rcv_wnd;
msk->setsockopt_seq = mptcp_sk(sk)->setsockopt_seq;
+ msk->last_retrans_seq = subflow_req->idsn - 1;
if (mp_opt->suboptions & OPTIONS_MPTCP_MPC) {
msk->can_ack = true;
@@ -3145,6 +3155,7 @@ void mptcp_finish_connect(struct sock *ssk)
WRITE_ONCE(msk->rcv_wnd_sent, ack_seq);
WRITE_ONCE(msk->can_ack, 1);
WRITE_ONCE(msk->snd_una, msk->write_seq);
+ WRITE_ONCE(msk->last_retrans_seq, subflow->idsn - 1);
mptcp_pm_new_connection(msk, ssk, 0);
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index d516fb6578cc..eb3473d128d4 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -227,6 +227,7 @@ struct mptcp_sock {
u64 ack_seq;
u64 rcv_wnd_sent;
u64 rcv_data_fin_seq;
+ u64 last_retrans_seq;
int wmem_reserved;
struct sock *last_snd;
int snd_burst;
@@ -625,6 +626,11 @@ static inline bool mptcp_has_another_subflow(struct sock *ssk)
return false;
}
+static inline bool mptcp_is_data_contiguous(struct mptcp_sock *msk)
+{
+ return before64(msk->last_retrans_seq, msk->snd_una);
+}
+
void __init mptcp_proto_init(void);
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
int __init mptcp_proto_v6_init(void);
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 1de7ce883c37..b07803ed3053 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -1166,15 +1166,15 @@ static bool subflow_check_data_avail(struct sock *ssk)
fallback:
/* RFC 8684 section 3.7. */
if (subflow->send_mp_fail) {
- if (mptcp_has_another_subflow(ssk)) {
+ if (mptcp_has_another_subflow(ssk) || !mptcp_is_data_contiguous(msk)) {
+ ssk->sk_err = EBADMSG;
+ tcp_set_state(ssk, TCP_CLOSE);
+ subflow->reset_transient = 0;
+ subflow->reset_reason = MPTCP_RST_EMIDDLEBOX;
+ tcp_send_active_reset(ssk, GFP_ATOMIC);
while ((skb = skb_peek(&ssk->sk_receive_queue)))
sk_eat_skb(ssk, skb);
}
- ssk->sk_err = EBADMSG;
- tcp_set_state(ssk, TCP_CLOSE);
- subflow->reset_transient = 0;
- subflow->reset_reason = MPTCP_RST_EMIDDLEBOX;
- tcp_send_active_reset(ssk, GFP_ATOMIC);
WRITE_ONCE(subflow->data_avail, 0);
return true;
}
--
2.31.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH mptcp-next v4 1/8] mptcp: track and update contiguous data status
2021-09-18 7:22 ` [PATCH mptcp-next v4 1/8] mptcp: track and update contiguous data status Geliang Tang
@ 2021-09-22 0:42 ` Mat Martineau
0 siblings, 0 replies; 11+ messages in thread
From: Mat Martineau @ 2021-09-22 0:42 UTC (permalink / raw)
To: Geliang Tang; +Cc: mptcp
On Sat, 18 Sep 2021, Geliang Tang wrote:
> This patch added a new member last_retrans_seq in the msk to track the
> last retransmitting sequence number.
>
> Add a new helper named mptcp_is_data_contiguous() to check whether the
> data is contiguous on a subflow.
>
> When a bad checksum is detected and a single contiguous subflow is in
> use, don't send RST + MP_FAIL, send data_ack + MP_FAIL instead.
>
> Signed-off-by: Geliang Tang <geliangtang@gmail.com>
> ---
> net/mptcp/protocol.c | 15 +++++++++++++--
> net/mptcp/protocol.h | 6 ++++++
> net/mptcp/subflow.c | 12 ++++++------
> 3 files changed, 25 insertions(+), 8 deletions(-)
>
> diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> index ff574d62073f..b766b36e6c93 100644
> --- a/net/mptcp/protocol.c
> +++ b/net/mptcp/protocol.c
> @@ -1102,8 +1102,13 @@ static void __mptcp_clean_una(struct sock *sk)
> msk->recovery = false;
>
> out:
> - if (cleaned && tcp_under_memory_pressure(sk))
> - __mptcp_mem_reclaim_partial(sk);
> + if (cleaned) {
> + if (mptcp_is_data_contiguous(msk))
> + msk->last_retrans_seq = msk->snd_una - 1;
> +
> + if (tcp_under_memory_pressure(sk))
> + __mptcp_mem_reclaim_partial(sk);
> + }
>
> if (snd_una == READ_ONCE(msk->snd_nxt) &&
> snd_una == READ_ONCE(msk->write_seq)) {
> @@ -2419,6 +2424,7 @@ static void __mptcp_retrans(struct sock *sk)
> struct mptcp_data_frag *dfrag;
> size_t copied = 0;
> struct sock *ssk;
> + u64 retrans_seq;
> int ret;
>
> mptcp_clean_una_wakeup(sk);
> @@ -2464,6 +2470,9 @@ static void __mptcp_retrans(struct sock *sk)
> dfrag->already_sent = max(dfrag->already_sent, info.sent);
> tcp_push(ssk, 0, info.mss_now, tcp_sk(ssk)->nonagle,
> info.size_goal);
> + retrans_seq = dfrag->data_seq + info.sent;
> + if (after64(retrans_seq, msk->last_retrans_seq))
> + msk->last_retrans_seq = retrans_seq;
> }
>
> release_sock(ssk);
> @@ -2889,6 +2898,7 @@ struct sock *mptcp_sk_clone(const struct sock *sk,
> msk->snd_una = msk->write_seq;
> msk->wnd_end = msk->snd_nxt + req->rsk_rcv_wnd;
> msk->setsockopt_seq = mptcp_sk(sk)->setsockopt_seq;
> + msk->last_retrans_seq = subflow_req->idsn - 1;
>
> if (mp_opt->suboptions & OPTIONS_MPTCP_MPC) {
> msk->can_ack = true;
> @@ -3145,6 +3155,7 @@ void mptcp_finish_connect(struct sock *ssk)
> WRITE_ONCE(msk->rcv_wnd_sent, ack_seq);
> WRITE_ONCE(msk->can_ack, 1);
> WRITE_ONCE(msk->snd_una, msk->write_seq);
> + WRITE_ONCE(msk->last_retrans_seq, subflow->idsn - 1);
>
> mptcp_pm_new_connection(msk, ssk, 0);
>
> diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
> index d516fb6578cc..eb3473d128d4 100644
> --- a/net/mptcp/protocol.h
> +++ b/net/mptcp/protocol.h
> @@ -227,6 +227,7 @@ struct mptcp_sock {
> u64 ack_seq;
> u64 rcv_wnd_sent;
> u64 rcv_data_fin_seq;
> + u64 last_retrans_seq;
> int wmem_reserved;
> struct sock *last_snd;
> int snd_burst;
> @@ -625,6 +626,11 @@ static inline bool mptcp_has_another_subflow(struct sock *ssk)
> return false;
> }
>
> +static inline bool mptcp_is_data_contiguous(struct mptcp_sock *msk)
> +{
> + return before64(msk->last_retrans_seq, msk->snd_una);
> +}
As I mentioned in
https://lore.kernel.org/mptcp/69c4ec57-94ed-4631-317a-617f994bc77@linux.intel.com/
I don't think this is enough to be sure the subflow stream is fully
contiguous (the one remaining subflow has flushed out all MPTCP-level
retransmissions).
MPTCP can do multiple retransmissions of the same MPTCP-level data, so it
seems necessary to track the last sequence number using the 32-bit TCP
sequence number on the subflow. For example, storing a copy of
tcp_sk(ssk)->snd_nxt after the tcp_push() call in __mptcp_retrans(). Then
in mptcp_data_ready() we can compare that retransmitted snd_nxt copy with
tcp_sk(ssk)->snd_una, very similar to the code added to
__mptcp_clean_una() above.
Anyone have a simpler idea?
- Mat
> +
> void __init mptcp_proto_init(void);
> #if IS_ENABLED(CONFIG_MPTCP_IPV6)
> int __init mptcp_proto_v6_init(void);
> diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
> index 1de7ce883c37..b07803ed3053 100644
> --- a/net/mptcp/subflow.c
> +++ b/net/mptcp/subflow.c
> @@ -1166,15 +1166,15 @@ static bool subflow_check_data_avail(struct sock *ssk)
> fallback:
> /* RFC 8684 section 3.7. */
> if (subflow->send_mp_fail) {
> - if (mptcp_has_another_subflow(ssk)) {
> + if (mptcp_has_another_subflow(ssk) || !mptcp_is_data_contiguous(msk)) {
> + ssk->sk_err = EBADMSG;
> + tcp_set_state(ssk, TCP_CLOSE);
> + subflow->reset_transient = 0;
> + subflow->reset_reason = MPTCP_RST_EMIDDLEBOX;
> + tcp_send_active_reset(ssk, GFP_ATOMIC);
> while ((skb = skb_peek(&ssk->sk_receive_queue)))
> sk_eat_skb(ssk, skb);
> }
> - ssk->sk_err = EBADMSG;
> - tcp_set_state(ssk, TCP_CLOSE);
> - subflow->reset_transient = 0;
> - subflow->reset_reason = MPTCP_RST_EMIDDLEBOX;
> - tcp_send_active_reset(ssk, GFP_ATOMIC);
> WRITE_ONCE(subflow->data_avail, 0);
> return true;
> }
> --
> 2.31.1
>
>
>
--
Mat Martineau
Intel
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH mptcp-next v4 2/8] mptcp: add last_fully_acked_dss_start_seq in the msk
2021-09-18 7:22 [PATCH mptcp-next v4 0/8] The infinite mapping support Geliang Tang
2021-09-18 7:22 ` [PATCH mptcp-next v4 1/8] mptcp: track and update contiguous data status Geliang Tang
@ 2021-09-18 7:22 ` Geliang Tang
2021-09-18 7:22 ` [PATCH mptcp-next v4 3/8] mptcp: infinite mapping sending Geliang Tang
` (5 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Geliang Tang @ 2021-09-18 7:22 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
This patch added a new member named last_fully_acked_dss_start_seq to the
msk to keep track of the beginning of the last fully-acked data segment.
This would be updated in __mptcp_clean_una.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
---
net/mptcp/protocol.c | 3 +++
net/mptcp/protocol.h | 1 +
2 files changed, 4 insertions(+)
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index b766b36e6c93..b056672541df 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1071,6 +1071,7 @@ static void __mptcp_clean_una(struct sock *sk)
WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
}
+ msk->last_fully_acked_dss_start_seq = dfrag->data_seq;
dfrag_clear(sk, dfrag);
cleaned = true;
}
@@ -2899,6 +2900,7 @@ struct sock *mptcp_sk_clone(const struct sock *sk,
msk->wnd_end = msk->snd_nxt + req->rsk_rcv_wnd;
msk->setsockopt_seq = mptcp_sk(sk)->setsockopt_seq;
msk->last_retrans_seq = subflow_req->idsn - 1;
+ msk->last_fully_acked_dss_start_seq = subflow_req->idsn - 1;
if (mp_opt->suboptions & OPTIONS_MPTCP_MPC) {
msk->can_ack = true;
@@ -3156,6 +3158,7 @@ void mptcp_finish_connect(struct sock *ssk)
WRITE_ONCE(msk->can_ack, 1);
WRITE_ONCE(msk->snd_una, msk->write_seq);
WRITE_ONCE(msk->last_retrans_seq, subflow->idsn - 1);
+ WRITE_ONCE(msk->last_fully_acked_dss_start_seq, subflow->idsn - 1);
mptcp_pm_new_connection(msk, ssk, 0);
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index eb3473d128d4..2f8a8589668c 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -224,6 +224,7 @@ struct mptcp_sock {
u64 remote_key;
u64 write_seq;
u64 snd_nxt;
+ u64 last_fully_acked_dss_start_seq;
u64 ack_seq;
u64 rcv_wnd_sent;
u64 rcv_data_fin_seq;
--
2.31.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH mptcp-next v4 3/8] mptcp: infinite mapping sending
2021-09-18 7:22 [PATCH mptcp-next v4 0/8] The infinite mapping support Geliang Tang
2021-09-18 7:22 ` [PATCH mptcp-next v4 1/8] mptcp: track and update contiguous data status Geliang Tang
2021-09-18 7:22 ` [PATCH mptcp-next v4 2/8] mptcp: add last_fully_acked_dss_start_seq in the msk Geliang Tang
@ 2021-09-18 7:22 ` Geliang Tang
2021-09-22 0:43 ` Mat Martineau
2021-09-18 7:22 ` [PATCH mptcp-next v4 4/8] mptcp: add the fallback check Geliang Tang
` (4 subsequent siblings)
7 siblings, 1 reply; 11+ messages in thread
From: Geliang Tang @ 2021-09-18 7:22 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
This patch added the infinite mapping sending logic.
Added a new flag send_infinite_map in struct mptcp_subflow_context. Set
it true when a single contiguous subflow is in use in
mptcp_pm_mp_fail_received.
In mptcp_sendmsg_frag, if this flag is true, call the new function
mptcp_update_infinite_map to set the infinite mapping.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
---
include/net/mptcp.h | 3 ++-
net/mptcp/options.c | 6 ++++--
net/mptcp/pm.c | 6 ++++++
net/mptcp/protocol.c | 19 +++++++++++++++++++
net/mptcp/protocol.h | 12 ++++++++++++
5 files changed, 43 insertions(+), 3 deletions(-)
diff --git a/include/net/mptcp.h b/include/net/mptcp.h
index f83fa48408b3..29e930540ea2 100644
--- a/include/net/mptcp.h
+++ b/include/net/mptcp.h
@@ -35,7 +35,8 @@ struct mptcp_ext {
frozen:1,
reset_transient:1;
u8 reset_reason:4,
- csum_reqd:1;
+ csum_reqd:1,
+ infinite_map:1;
};
#define MPTCP_RM_IDS_MAX 8
diff --git a/net/mptcp/options.c b/net/mptcp/options.c
index 422f4acfb3e6..9c175c298ff6 100644
--- a/net/mptcp/options.c
+++ b/net/mptcp/options.c
@@ -816,8 +816,10 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
opts->suboptions = 0;
- if (unlikely(__mptcp_check_fallback(msk)))
- return false;
+ if (unlikely(__mptcp_check_fallback(msk))) {
+ if (!mptcp_check_infinite_map(skb))
+ return false;
+ }
if (unlikely(skb && TCP_SKB_CB(skb)->tcp_flags & TCPHDR_RST)) {
if (mptcp_established_options_mp_fail(sk, &opt_size, remaining, opts)) {
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index 6ab386ff3294..4fad1fe8ba10 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -251,7 +251,13 @@ void mptcp_pm_mp_prio_received(struct sock *sk, u8 bkup)
void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq)
{
+ struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
+ struct mptcp_sock *msk = mptcp_sk(subflow->conn);
+
pr_debug("fail_seq=%llu", fail_seq);
+
+ if (!mptcp_has_another_subflow(sk) && mptcp_is_data_contiguous(msk))
+ subflow->send_infinite_map = 1;
}
/* path manager helpers */
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index b056672541df..ffef7e1f061b 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1279,6 +1279,23 @@ static void mptcp_update_data_checksum(struct sk_buff *skb, int added)
mpext->csum = csum_fold(csum_block_add(csum, skb_checksum(skb, offset, added, 0), offset));
}
+static void mptcp_update_infinite_map(struct mptcp_sock *msk, struct sock *ssk,
+ struct mptcp_ext *mpext)
+{
+ if (!mpext)
+ return;
+
+ mpext->infinite_map = 1;
+ mpext->data_seq = READ_ONCE(msk->last_fully_acked_dss_start_seq);
+ mpext->subflow_seq = 0;
+ mpext->data_len = 0;
+ mpext->csum = 0;
+
+ mptcp_subflow_ctx(ssk)->send_infinite_map = 0;
+ pr_fallback(msk);
+ __mptcp_do_fallback(msk);
+}
+
static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
struct mptcp_data_frag *dfrag,
struct mptcp_sendmsg_info *info)
@@ -1411,6 +1428,8 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
out:
if (READ_ONCE(msk->csum_enabled))
mptcp_update_data_checksum(skb, copy);
+ if (mptcp_subflow_ctx(ssk)->send_infinite_map)
+ mptcp_update_infinite_map(msk, ssk, mpext);
mptcp_subflow_ctx(ssk)->rel_write_seq += copy;
return copy;
}
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 2f8a8589668c..cb26183aec9b 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -433,6 +433,7 @@ struct mptcp_subflow_context {
backup : 1,
send_mp_prio : 1,
send_mp_fail : 1,
+ send_infinite_map : 1,
rx_eof : 1,
can_ack : 1, /* only after processing the remote a key */
disposable : 1, /* ctx can be free at ulp release time */
@@ -874,6 +875,17 @@ static inline void mptcp_do_fallback(struct sock *sk)
#define pr_fallback(a) pr_debug("%s:fallback to TCP (msk=%p)", __func__, a)
+static inline bool mptcp_check_infinite_map(struct sk_buff *skb)
+{
+ struct mptcp_ext *mpext;
+
+ mpext = skb ? mptcp_get_ext(skb) : NULL;
+ if (mpext && mpext->infinite_map)
+ return true;
+
+ return false;
+}
+
static inline bool subflow_simultaneous_connect(struct sock *sk)
{
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
--
2.31.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH mptcp-next v4 3/8] mptcp: infinite mapping sending
2021-09-18 7:22 ` [PATCH mptcp-next v4 3/8] mptcp: infinite mapping sending Geliang Tang
@ 2021-09-22 0:43 ` Mat Martineau
0 siblings, 0 replies; 11+ messages in thread
From: Mat Martineau @ 2021-09-22 0:43 UTC (permalink / raw)
To: Geliang Tang; +Cc: mptcp
On Sat, 18 Sep 2021, Geliang Tang wrote:
> This patch added the infinite mapping sending logic.
>
> Added a new flag send_infinite_map in struct mptcp_subflow_context. Set
> it true when a single contiguous subflow is in use in
> mptcp_pm_mp_fail_received.
>
> In mptcp_sendmsg_frag, if this flag is true, call the new function
> mptcp_update_infinite_map to set the infinite mapping.
>
> Signed-off-by: Geliang Tang <geliangtang@gmail.com>
> ---
> include/net/mptcp.h | 3 ++-
> net/mptcp/options.c | 6 ++++--
> net/mptcp/pm.c | 6 ++++++
> net/mptcp/protocol.c | 19 +++++++++++++++++++
> net/mptcp/protocol.h | 12 ++++++++++++
> 5 files changed, 43 insertions(+), 3 deletions(-)
>
> diff --git a/include/net/mptcp.h b/include/net/mptcp.h
> index f83fa48408b3..29e930540ea2 100644
> --- a/include/net/mptcp.h
> +++ b/include/net/mptcp.h
> @@ -35,7 +35,8 @@ struct mptcp_ext {
> frozen:1,
> reset_transient:1;
> u8 reset_reason:4,
> - csum_reqd:1;
> + csum_reqd:1,
> + infinite_map:1;
> };
>
> #define MPTCP_RM_IDS_MAX 8
> diff --git a/net/mptcp/options.c b/net/mptcp/options.c
> index 422f4acfb3e6..9c175c298ff6 100644
> --- a/net/mptcp/options.c
> +++ b/net/mptcp/options.c
> @@ -816,8 +816,10 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
>
> opts->suboptions = 0;
>
> - if (unlikely(__mptcp_check_fallback(msk)))
> - return false;
> + if (unlikely(__mptcp_check_fallback(msk))) {
> + if (!mptcp_check_infinite_map(skb))
> + return false;
> + }
This could be
if (unlikely(__mptcp_check_fallback(msk) && !mptcp_check_infinite_map(skb)))
...
(line-wrapped as needed)
rather than nesting the if's.
Mat
>
> if (unlikely(skb && TCP_SKB_CB(skb)->tcp_flags & TCPHDR_RST)) {
> if (mptcp_established_options_mp_fail(sk, &opt_size, remaining, opts)) {
> diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
> index 6ab386ff3294..4fad1fe8ba10 100644
> --- a/net/mptcp/pm.c
> +++ b/net/mptcp/pm.c
> @@ -251,7 +251,13 @@ void mptcp_pm_mp_prio_received(struct sock *sk, u8 bkup)
>
> void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq)
> {
> + struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
> + struct mptcp_sock *msk = mptcp_sk(subflow->conn);
> +
> pr_debug("fail_seq=%llu", fail_seq);
> +
> + if (!mptcp_has_another_subflow(sk) && mptcp_is_data_contiguous(msk))
> + subflow->send_infinite_map = 1;
> }
>
> /* path manager helpers */
> diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> index b056672541df..ffef7e1f061b 100644
> --- a/net/mptcp/protocol.c
> +++ b/net/mptcp/protocol.c
> @@ -1279,6 +1279,23 @@ static void mptcp_update_data_checksum(struct sk_buff *skb, int added)
> mpext->csum = csum_fold(csum_block_add(csum, skb_checksum(skb, offset, added, 0), offset));
> }
>
> +static void mptcp_update_infinite_map(struct mptcp_sock *msk, struct sock *ssk,
> + struct mptcp_ext *mpext)
> +{
> + if (!mpext)
> + return;
> +
> + mpext->infinite_map = 1;
> + mpext->data_seq = READ_ONCE(msk->last_fully_acked_dss_start_seq);
> + mpext->subflow_seq = 0;
> + mpext->data_len = 0;
> + mpext->csum = 0;
> +
> + mptcp_subflow_ctx(ssk)->send_infinite_map = 0;
> + pr_fallback(msk);
> + __mptcp_do_fallback(msk);
> +}
> +
> static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
> struct mptcp_data_frag *dfrag,
> struct mptcp_sendmsg_info *info)
> @@ -1411,6 +1428,8 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
> out:
> if (READ_ONCE(msk->csum_enabled))
> mptcp_update_data_checksum(skb, copy);
> + if (mptcp_subflow_ctx(ssk)->send_infinite_map)
> + mptcp_update_infinite_map(msk, ssk, mpext);
> mptcp_subflow_ctx(ssk)->rel_write_seq += copy;
> return copy;
> }
> diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
> index 2f8a8589668c..cb26183aec9b 100644
> --- a/net/mptcp/protocol.h
> +++ b/net/mptcp/protocol.h
> @@ -433,6 +433,7 @@ struct mptcp_subflow_context {
> backup : 1,
> send_mp_prio : 1,
> send_mp_fail : 1,
> + send_infinite_map : 1,
> rx_eof : 1,
> can_ack : 1, /* only after processing the remote a key */
> disposable : 1, /* ctx can be free at ulp release time */
> @@ -874,6 +875,17 @@ static inline void mptcp_do_fallback(struct sock *sk)
>
> #define pr_fallback(a) pr_debug("%s:fallback to TCP (msk=%p)", __func__, a)
>
> +static inline bool mptcp_check_infinite_map(struct sk_buff *skb)
> +{
> + struct mptcp_ext *mpext;
> +
> + mpext = skb ? mptcp_get_ext(skb) : NULL;
> + if (mpext && mpext->infinite_map)
> + return true;
> +
> + return false;
> +}
> +
> static inline bool subflow_simultaneous_connect(struct sock *sk)
> {
> struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
> --
> 2.31.1
>
>
>
--
Mat Martineau
Intel
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH mptcp-next v4 4/8] mptcp: add the fallback check
2021-09-18 7:22 [PATCH mptcp-next v4 0/8] The infinite mapping support Geliang Tang
` (2 preceding siblings ...)
2021-09-18 7:22 ` [PATCH mptcp-next v4 3/8] mptcp: infinite mapping sending Geliang Tang
@ 2021-09-18 7:22 ` Geliang Tang
2021-09-18 7:22 ` [PATCH mptcp-next v4 5/8] mptcp: infinite mapping receiving Geliang Tang
` (3 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Geliang Tang @ 2021-09-18 7:22 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
This patch added the fallback check in subflow_check_data_avail. Only do
the fallback when the msk isn't fallen back yet.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
---
net/mptcp/subflow.c | 46 +++++++++++++++++++++++----------------------
1 file changed, 24 insertions(+), 22 deletions(-)
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index b07803ed3053..89173f70707e 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -1164,35 +1164,37 @@ static bool subflow_check_data_avail(struct sock *ssk)
return false;
fallback:
- /* RFC 8684 section 3.7. */
- if (subflow->send_mp_fail) {
- if (mptcp_has_another_subflow(ssk) || !mptcp_is_data_contiguous(msk)) {
+ if (!__mptcp_check_fallback(msk)) {
+ /* RFC 8684 section 3.7. */
+ if (subflow->send_mp_fail) {
+ if (mptcp_has_another_subflow(ssk) || !mptcp_is_data_contiguous(msk)) {
+ ssk->sk_err = EBADMSG;
+ tcp_set_state(ssk, TCP_CLOSE);
+ subflow->reset_transient = 0;
+ subflow->reset_reason = MPTCP_RST_EMIDDLEBOX;
+ tcp_send_active_reset(ssk, GFP_ATOMIC);
+ while ((skb = skb_peek(&ssk->sk_receive_queue)))
+ sk_eat_skb(ssk, skb);
+ }
+ WRITE_ONCE(subflow->data_avail, 0);
+ return true;
+ }
+
+ if (subflow->mp_join || subflow->fully_established) {
+ /* fatal protocol error, close the socket.
+ * subflow_error_report() will introduce the appropriate barriers
+ */
ssk->sk_err = EBADMSG;
tcp_set_state(ssk, TCP_CLOSE);
subflow->reset_transient = 0;
- subflow->reset_reason = MPTCP_RST_EMIDDLEBOX;
+ subflow->reset_reason = MPTCP_RST_EMPTCP;
tcp_send_active_reset(ssk, GFP_ATOMIC);
- while ((skb = skb_peek(&ssk->sk_receive_queue)))
- sk_eat_skb(ssk, skb);
+ WRITE_ONCE(subflow->data_avail, 0);
+ return false;
}
- WRITE_ONCE(subflow->data_avail, 0);
- return true;
- }
- if (subflow->mp_join || subflow->fully_established) {
- /* fatal protocol error, close the socket.
- * subflow_error_report() will introduce the appropriate barriers
- */
- ssk->sk_err = EBADMSG;
- tcp_set_state(ssk, TCP_CLOSE);
- subflow->reset_transient = 0;
- subflow->reset_reason = MPTCP_RST_EMPTCP;
- tcp_send_active_reset(ssk, GFP_ATOMIC);
- WRITE_ONCE(subflow->data_avail, 0);
- return false;
+ __mptcp_do_fallback(msk);
}
-
- __mptcp_do_fallback(msk);
skb = skb_peek(&ssk->sk_receive_queue);
subflow->map_valid = 1;
subflow->map_seq = READ_ONCE(msk->ack_seq);
--
2.31.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH mptcp-next v4 5/8] mptcp: infinite mapping receiving
2021-09-18 7:22 [PATCH mptcp-next v4 0/8] The infinite mapping support Geliang Tang
` (3 preceding siblings ...)
2021-09-18 7:22 ` [PATCH mptcp-next v4 4/8] mptcp: add the fallback check Geliang Tang
@ 2021-09-18 7:22 ` Geliang Tang
2021-09-18 7:22 ` [PATCH mptcp-next v4 6/8] mptcp: add mib for infinite map sending Geliang Tang
` (2 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Geliang Tang @ 2021-09-18 7:22 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
This patch added the infinite mapping receiving logic. When the infinite
mapping is received, set the map_data_len of the subflow to 0.
In subflow_check_data_avail, only reset the subflow when the map_data_len
of the subflow is non-zero.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
---
net/mptcp/subflow.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 89173f70707e..fd44996a7b9a 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -968,6 +968,7 @@ static enum mapping_status get_mapping_status(struct sock *ssk,
data_len = mpext->data_len;
if (data_len == 0) {
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_INFINITEMAPRX);
+ subflow->map_data_len = 0;
return MAPPING_INVALID;
}
@@ -1180,7 +1181,7 @@ static bool subflow_check_data_avail(struct sock *ssk)
return true;
}
- if (subflow->mp_join || subflow->fully_established) {
+ if ((subflow->mp_join || subflow->fully_established) && subflow->map_data_len) {
/* fatal protocol error, close the socket.
* subflow_error_report() will introduce the appropriate barriers
*/
--
2.31.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH mptcp-next v4 6/8] mptcp: add mib for infinite map sending
2021-09-18 7:22 [PATCH mptcp-next v4 0/8] The infinite mapping support Geliang Tang
` (4 preceding siblings ...)
2021-09-18 7:22 ` [PATCH mptcp-next v4 5/8] mptcp: infinite mapping receiving Geliang Tang
@ 2021-09-18 7:22 ` Geliang Tang
2021-09-18 7:22 ` [PATCH mptcp-next v4 7/8] selftests: mptcp: add infinite map mibs check Geliang Tang
2021-09-18 7:22 ` [PATCH mptcp-next v4 8/8] DO-NOT-MERGE: mptcp: mp_fail test Geliang Tang
7 siblings, 0 replies; 11+ messages in thread
From: Geliang Tang @ 2021-09-18 7:22 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
This patch added a new mib named MPTCP_MIB_INFINITEMAPTX, increase it
when a infinite mapping has been sent out.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
---
net/mptcp/mib.c | 1 +
net/mptcp/mib.h | 1 +
net/mptcp/protocol.c | 1 +
3 files changed, 3 insertions(+)
diff --git a/net/mptcp/mib.c b/net/mptcp/mib.c
index b21ff9be04c6..ab55afdcae22 100644
--- a/net/mptcp/mib.c
+++ b/net/mptcp/mib.c
@@ -24,6 +24,7 @@ static const struct snmp_mib mptcp_snmp_list[] = {
SNMP_MIB_ITEM("MPJoinAckRx", MPTCP_MIB_JOINACKRX),
SNMP_MIB_ITEM("MPJoinAckHMacFailure", MPTCP_MIB_JOINACKMAC),
SNMP_MIB_ITEM("DSSNotMatching", MPTCP_MIB_DSSNOMATCH),
+ SNMP_MIB_ITEM("InfiniteMapTx", MPTCP_MIB_INFINITEMAPTX),
SNMP_MIB_ITEM("InfiniteMapRx", MPTCP_MIB_INFINITEMAPRX),
SNMP_MIB_ITEM("DSSNoMatchTCP", MPTCP_MIB_DSSTCPMISMATCH),
SNMP_MIB_ITEM("DataCsumErr", MPTCP_MIB_DATACSUMERR),
diff --git a/net/mptcp/mib.h b/net/mptcp/mib.h
index ecd3d8b117e0..7901f1338d15 100644
--- a/net/mptcp/mib.h
+++ b/net/mptcp/mib.h
@@ -17,6 +17,7 @@ enum linux_mptcp_mib_field {
MPTCP_MIB_JOINACKRX, /* Received an ACK + MP_JOIN */
MPTCP_MIB_JOINACKMAC, /* HMAC was wrong on ACK + MP_JOIN */
MPTCP_MIB_DSSNOMATCH, /* Received a new mapping that did not match the previous one */
+ MPTCP_MIB_INFINITEMAPTX, /* Sent an infinite mapping */
MPTCP_MIB_INFINITEMAPRX, /* Received an infinite mapping */
MPTCP_MIB_DSSTCPMISMATCH, /* DSS-mapping did not map with TCP's sequence numbers */
MPTCP_MIB_DATACSUMERR, /* The data checksum fail */
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index ffef7e1f061b..d035119b41cb 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1291,6 +1291,7 @@ static void mptcp_update_infinite_map(struct mptcp_sock *msk, struct sock *ssk,
mpext->data_len = 0;
mpext->csum = 0;
+ MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_INFINITEMAPTX);
mptcp_subflow_ctx(ssk)->send_infinite_map = 0;
pr_fallback(msk);
__mptcp_do_fallback(msk);
--
2.31.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH mptcp-next v4 7/8] selftests: mptcp: add infinite map mibs check
2021-09-18 7:22 [PATCH mptcp-next v4 0/8] The infinite mapping support Geliang Tang
` (5 preceding siblings ...)
2021-09-18 7:22 ` [PATCH mptcp-next v4 6/8] mptcp: add mib for infinite map sending Geliang Tang
@ 2021-09-18 7:22 ` Geliang Tang
2021-09-18 7:22 ` [PATCH mptcp-next v4 8/8] DO-NOT-MERGE: mptcp: mp_fail test Geliang Tang
7 siblings, 0 replies; 11+ messages in thread
From: Geliang Tang @ 2021-09-18 7:22 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
This patch added a function chk_infi_nr to check the mibs for the
infinite mapping.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
---
.../testing/selftests/net/mptcp/mptcp_join.sh | 38 +++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
index 255793c5ac4f..fe0c8f3164a7 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
@@ -615,6 +615,43 @@ chk_fail_nr()
fi
}
+chk_infi_nr()
+{
+ local mp_infi_nr_tx=$1
+ local mp_infi_nr_rx=$2
+ local count
+ local dump_stats
+
+ printf "%-39s %s" " " "itx"
+ count=`ip netns exec $ns1 nstat -as | grep InfiniteMapTx | awk '{print $2}'`
+ [ -z "$count" ] && count=0
+ if [ "$count" != "$mp_infi_nr_tx" ]; then
+ echo "[fail] got $count infinite map[s] TX expected $mp_infi_nr_tx"
+ ret=1
+ dump_stats=1
+ else
+ echo -n "[ ok ]"
+ fi
+
+ echo -n " - irx "
+ count=`ip netns exec $ns2 nstat -as | grep InfiniteMapRx | awk '{print $2}'`
+ [ -z "$count" ] && count=0
+ if [ "$count" != "$mp_infi_nr_rx" ]; then
+ echo "[fail] got $count infinite map[s] RX expected $mp_infi_nr_rx"
+ ret=1
+ dump_stats=1
+ else
+ echo "[ ok ]"
+ fi
+
+ if [ "${dump_stats}" = 1 ]; then
+ echo Server ns stats
+ ip netns exec $ns1 nstat -as | grep MPTcp
+ echo Client ns stats
+ ip netns exec $ns2 nstat -as | grep MPTcp
+ fi
+}
+
chk_join_nr()
{
local msg="$1"
@@ -665,6 +702,7 @@ chk_join_nr()
if [ $checksum -eq 1 ]; then
chk_csum_nr
chk_fail_nr 0 0
+ chk_infi_nr 0 0
fi
}
--
2.31.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH mptcp-next v4 8/8] DO-NOT-MERGE: mptcp: mp_fail test
2021-09-18 7:22 [PATCH mptcp-next v4 0/8] The infinite mapping support Geliang Tang
` (6 preceding siblings ...)
2021-09-18 7:22 ` [PATCH mptcp-next v4 7/8] selftests: mptcp: add infinite map mibs check Geliang Tang
@ 2021-09-18 7:22 ` Geliang Tang
7 siblings, 0 replies; 11+ messages in thread
From: Geliang Tang @ 2021-09-18 7:22 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
./mptcp_join.sh -Cf
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
---
net/mptcp/protocol.c | 9 +++++++++
.../testing/selftests/net/mptcp/mptcp_join.sh | 18 ++++++++++++++++++
2 files changed, 27 insertions(+)
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index d035119b41cb..5be8023f27ca 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1297,6 +1297,8 @@ static void mptcp_update_infinite_map(struct mptcp_sock *msk, struct sock *ssk,
__mptcp_do_fallback(msk);
}
+static int j;
+
static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
struct mptcp_data_frag *dfrag,
struct mptcp_sendmsg_info *info)
@@ -1431,6 +1433,13 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
mptcp_update_data_checksum(skb, copy);
if (mptcp_subflow_ctx(ssk)->send_infinite_map)
mptcp_update_infinite_map(msk, ssk, mpext);
+
+ pr_debug("%s j=%d", __func__, j++);
+ if (j == 20)
+ skb->data_len = 1;
+ if (j > 40)
+ j = 0;
+
mptcp_subflow_ctx(ssk)->rel_write_seq += copy;
return copy;
}
diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
index fe0c8f3164a7..38663f6373b8 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
@@ -977,6 +977,24 @@ chk_link_usage()
subflows_tests()
{
+ # 1 subflow
+ reset
+ ip netns exec $ns1 ./pm_nl_ctl limits 0 2
+ ip netns exec $ns2 ./pm_nl_ctl limits 0 2
+ run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
+ chk_join_nr "1 subflow" 0 0 0
+
+ exit
+
+ # multiple subflows
+ reset
+ ip netns exec $ns1 ./pm_nl_ctl limits 0 2
+ ip netns exec $ns2 ./pm_nl_ctl limits 0 2
+ ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
+ ip netns exec $ns2 ./pm_nl_ctl add 10.0.2.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
+ chk_join_nr "multiple subflows" 2 2 2
+
reset
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr "no JOIN" "0" "0" "0"
--
2.31.1
^ permalink raw reply related [flat|nested] 11+ messages in thread