mptcp.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH mptcp-next v5 01/10] mptcp: Fast Open Mechanism
@ 2022-09-14 11:31 Dmytro Shytyi
  2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 02/10] Initiator: MSG_FASTOPEN in sendto triggers the mptcp_sendsmg_fastopen. It requests a MPTFO cookie. Suggestion @palbeni(JAN 17): 'split the patch in several small one, clearly documenting in the individual commit message what each patch is doing and why' Dmytro Shytyi
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Dmytro Shytyi @ 2022-09-14 11:31 UTC (permalink / raw)
  To: mptcp; +Cc: Dmytro Shytyi

This set of patches will bring "Fast Open" Option support to MPTCP.
The aim of Fast Open Mechanism is to eliminate one round trip
time from a TCP conversation by allowing data to be included as
part of the SYN segment that initiates the connection.

IETF RFC 8684: Appendix B. TCP Fast Open and MPTCP.

[PATCH v5] includes "client-server" partial support for :
1. MPTCP cookie request from client (seems OK).
2. MPTCP cookie offering from server (seems OK).
3. MPTCP SYN+DATA+COOKIE from client (seems OK).
4. subsequent write + read on the opened socket (seems OK).

===Changes between v4 and v5:
- All data sent by the initiator received by listener in userspace.
- No more infinite re-transmissions of the same packet in the
end of the second connection.
- ”WARNING in sk stream kill queues”, when skb is added to
msk queue - is fixed.
- Fix the second (discarded) packet that is re-transmitted in the
end of 2nd session.
- We have (in the v4 it is not present) the FIN in the end of the
2nd (TFO data+cookie+syn) session.
===Tradeoffs of v5:
-Minimal impact on existing TCP code in linux kernel.
-Icreased size of the patch. Some functions are inspired from
existing code in fastopen.c and others.
===Future work:
-Address the appearence of ”MPTCP FIN” as ducplicated acks.

Add separate *.c file. Function prototypes are coming to protocol.h
(Suggestion of @palbeni (JUN 17))

Signed-off-by: Dmytro Shytyi <dmytro@shytyi.net>
---
 net/mptcp/Makefile   | 2 +-
 net/mptcp/fastopen.c | 5 +++++
 2 files changed, 6 insertions(+), 1 deletion(-)
 create mode 100644 net/mptcp/fastopen.c

diff --git a/net/mptcp/Makefile b/net/mptcp/Makefile
index 8a7f68efa35f..c42ad8609876 100644
--- a/net/mptcp/Makefile
+++ b/net/mptcp/Makefile
@@ -2,7 +2,7 @@
 obj-$(CONFIG_MPTCP) += mptcp.o
 
 mptcp-y := protocol.o subflow.o options.o token.o crypto.o ctrl.o pm.o diag.o \
-	   mib.o pm_netlink.o sockopt.o pm_userspace.o sched.o
+	   mib.o pm_netlink.o sockopt.o pm_userspace.o sched.o fastopen.o
 
 obj-$(CONFIG_SYN_COOKIES) += syncookies.o
 obj-$(CONFIG_INET_MPTCP_DIAG) += mptcp_diag.o
diff --git a/net/mptcp/fastopen.c b/net/mptcp/fastopen.c
new file mode 100644
index 000000000000..0c9ef6f5d528
--- /dev/null
+++ b/net/mptcp/fastopen.c
@@ -0,0 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0
+ * MPTCP Fast Open Mechanism. Copyright (c) 2021-2022, Dmytro SHYTYI
+ */
+
+#include "protocol.h"
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH mptcp-next v5 02/10] Initiator: MSG_FASTOPEN in sendto triggers the mptcp_sendsmg_fastopen. It requests a MPTFO cookie. Suggestion @palbeni(JAN 17): 'split the patch in several small one, clearly documenting in the individual commit message what each patch is doing and why'
  2022-09-14 11:31 [RFC PATCH mptcp-next v5 01/10] mptcp: Fast Open Mechanism Dmytro Shytyi
@ 2022-09-14 11:31 ` Dmytro Shytyi
  2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 03/10] Initiator: mptcp_sendmsg_fastopen. Usage of lock_sock() / release_sock() leads to hangup' Dmytro Shytyi
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Dmytro Shytyi @ 2022-09-14 11:31 UTC (permalink / raw)
  To: mptcp; +Cc: Dmytro Shytyi

Initiator: MSG_FASTOPEN in sendto triggers the mptcp_sendsmg_fastopen.
It requests a MPTFO cookie. Suggestion @palbeni(JAN 17): 'split the patch 
in several small one, clearly documenting in the individual commit message 
what each patch is doing and why'

Signed-off-by: Dmytro Shytyi <dmytro@shytyi.net>
---
 net/mptcp/fastopen.c | 50 ++++++++++++++++++++++++++++++++++++++++++++
 net/mptcp/protocol.c |  4 ++--
 net/mptcp/protocol.h |  6 ++++++
 3 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/net/mptcp/fastopen.c b/net/mptcp/fastopen.c
index 0c9ef6f5d528..9974508e0f4c 100644
--- a/net/mptcp/fastopen.c
+++ b/net/mptcp/fastopen.c
@@ -3,3 +3,53 @@
  */
 
 #include "protocol.h"
+
+int mptcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
+			   size_t len, struct mptcp_sock *msk,
+			   size_t *copied)
+{
+	const struct iphdr *iph;
+	struct ubuf_info *uarg;
+	struct sockaddr *uaddr;
+	struct sk_buff *skb;
+	struct tcp_sock *tp;
+	struct socket *ssk;
+	int ret;
+
+	ssk = __mptcp_nmpc_socket(msk);
+	if (unlikely(!ssk))
+		goto out_EFAULT;
+	skb = tcp_stream_alloc_skb(ssk->sk, 0, ssk->sk->sk_allocation, true);
+	if (unlikely(!skb))
+		goto out_EFAULT;
+	iph = ip_hdr(skb);
+	if (unlikely(!iph))
+		goto out_EFAULT;
+	uarg = msg_zerocopy_realloc(sk, len, skb_zcopy(skb));
+	if (unlikely(!uarg))
+		goto out_EFAULT;
+	uaddr = msg->msg_name;
+
+	tp = tcp_sk(ssk->sk);
+	if (unlikely(!tp))
+		goto out_EFAULT;
+	if (!tp->fastopen_req)
+		tp->fastopen_req = kzalloc(sizeof(*tp->fastopen_req),
+					   ssk->sk->sk_allocation);
+
+	if (unlikely(!tp->fastopen_req))
+		goto out_EFAULT;
+	tp->fastopen_req->data = msg;
+	tp->fastopen_req->size = len;
+	tp->fastopen_req->uarg = uarg;
+
+	/* requests a cookie */
+	ret = mptcp_stream_connect(sk->sk_socket, uaddr,
+				   msg->msg_namelen, msg->msg_flags);
+	if (!ret)
+		*copied = len;
+	return ret;
+out_EFAULT:
+	ret = -EFAULT;
+	return ret;
+}
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 55442df8fb97..6bbf1b86465d 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1672,9 +1672,9 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 	int ret = 0;
 	long timeo;
 
-	/* we don't support FASTOPEN yet */
+	/* we don't fully support FASTOPEN yet */
 	if (msg->msg_flags & MSG_FASTOPEN)
-		return -EOPNOTSUPP;
+		ret = mptcp_sendmsg_fastopen(sk, msg, len, msk, &copied);
 
 	/* silently ignore everything else */
 	msg->msg_flags &= MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL;
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 1bc9f6e77ddd..ad51910f1cc9 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -836,6 +836,12 @@ void mptcp_event_addr_announced(const struct sock *ssk, const struct mptcp_addr_
 void mptcp_event_addr_removed(const struct mptcp_sock *msk, u8 id);
 bool mptcp_userspace_pm_active(const struct mptcp_sock *msk);
 
+// Fast Open Mechanism functions begin
+int mptcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
+			   size_t len, struct mptcp_sock *msk,
+			   size_t *copied);
+// Fast Open Mechanism functions end
+
 static inline bool mptcp_pm_should_add_signal(struct mptcp_sock *msk)
 {
 	return READ_ONCE(msk->pm.addr_signal) &
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH mptcp-next v5 03/10] Initiator: mptcp_sendmsg_fastopen. Usage of lock_sock() / release_sock() leads to hangup'
  2022-09-14 11:31 [RFC PATCH mptcp-next v5 01/10] mptcp: Fast Open Mechanism Dmytro Shytyi
  2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 02/10] Initiator: MSG_FASTOPEN in sendto triggers the mptcp_sendsmg_fastopen. It requests a MPTFO cookie. Suggestion @palbeni(JAN 17): 'split the patch in several small one, clearly documenting in the individual commit message what each patch is doing and why' Dmytro Shytyi
@ 2022-09-14 11:31 ` Dmytro Shytyi
  2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 04/10] Treat a socket option TCP_FASTOPEN on Lister side. Suggestion @mmartineau(MAY 22): 'Need to use ssk instead of sk in these several lines' (1 AUG): 'Since fastopen is only relevant for the initial subflow (and never with MP_JOIN). __mptcp_nmpc_socket() should give the initial subflow' Dmytro Shytyi
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Dmytro Shytyi @ 2022-09-14 11:31 UTC (permalink / raw)
  To: mptcp; +Cc: Dmytro Shytyi

Initiator: mptcp_sendmsg_fastopen. Usage of 
lock_sock() / release_sock() leads to hangup'

Signed-off-by: Dmytro Shytyi <dmytro@shytyi.net>
---
 net/mptcp/fastopen.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/mptcp/fastopen.c b/net/mptcp/fastopen.c
index 9974508e0f4c..0e071c988894 100644
--- a/net/mptcp/fastopen.c
+++ b/net/mptcp/fastopen.c
@@ -49,6 +49,7 @@ int mptcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
 	if (!ret)
 		*copied = len;
 	return ret;
+
 out_EFAULT:
 	ret = -EFAULT;
 	return ret;
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH mptcp-next v5 04/10] Treat a socket option TCP_FASTOPEN on Lister side. Suggestion @mmartineau(MAY 22): 'Need to use ssk instead of sk in these several lines' (1 AUG): 'Since fastopen is only relevant for the initial subflow (and never with MP_JOIN). __mptcp_nmpc_socket() should give the initial subflow'
  2022-09-14 11:31 [RFC PATCH mptcp-next v5 01/10] mptcp: Fast Open Mechanism Dmytro Shytyi
  2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 02/10] Initiator: MSG_FASTOPEN in sendto triggers the mptcp_sendsmg_fastopen. It requests a MPTFO cookie. Suggestion @palbeni(JAN 17): 'split the patch in several small one, clearly documenting in the individual commit message what each patch is doing and why' Dmytro Shytyi
  2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 03/10] Initiator: mptcp_sendmsg_fastopen. Usage of lock_sock() / release_sock() leads to hangup' Dmytro Shytyi
@ 2022-09-14 11:31 ` Dmytro Shytyi
  2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 05/10] This fixes the unexpected value of subflow->map_seq for the second packet that leads to packet discard and further retransmit Dmytro Shytyi
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Dmytro Shytyi @ 2022-09-14 11:31 UTC (permalink / raw)
  To: mptcp; +Cc: Dmytro Shytyi

Treat a socket option TCP_FASTOPEN on
Lister side. Suggestion @mmartineau(MAY 22): 'Need to use ssk instead of sk
in these several lines' (1 AUG): 'Since fastopen is only relevant for the
initial subflow (and never with MP_JOIN). __mptcp_nmpc_socket() should give
the initial subflow'

Signed-off-by: Dmytro Shytyi <dmytro@shytyi.net>
---
 net/mptcp/fastopen.c | 31 +++++++++++++++++++++++++++++++
 net/mptcp/protocol.c |  4 ++--
 net/mptcp/protocol.h |  3 +++
 net/mptcp/sockopt.c  |  3 +++
 4 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/net/mptcp/fastopen.c b/net/mptcp/fastopen.c
index 0e071c988894..2633d5148dcb 100644
--- a/net/mptcp/fastopen.c
+++ b/net/mptcp/fastopen.c
@@ -54,3 +54,34 @@ int mptcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
 	ret = -EFAULT;
 	return ret;
 }
+
+int mptcp_setsockopt_sol_tcp_fastopen(struct mptcp_sock *msk, sockptr_t optval,
+				      unsigned int optlen)
+{
+	struct sock *ssk = __mptcp_nmpc_socket(msk)->sk;
+	struct sock *sk = (struct sock *)msk;
+	struct net *net = sock_net(sk);
+	int val;
+	int ret;
+
+	ret = 0;
+
+	if (copy_from_sockptr(&val, optval, sizeof(val)))
+		return -EFAULT;
+
+	lock_sock(sk);
+	lock_sock(ssk);
+
+	if (val >= 0 && ((1 << ssk->sk_state) & (TCPF_CLOSE |
+	    TCPF_LISTEN))) {
+		tcp_fastopen_init_key_once(net);
+		fastopen_queue_tune(ssk, val);
+	} else {
+		ret = -EINVAL;
+	}
+
+	release_sock(ssk);
+	release_sock(sk);
+
+	return ret;
+}
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 6bbf1b86465d..af99a03021c9 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -3474,8 +3474,8 @@ static void mptcp_subflow_early_fallback(struct mptcp_sock *msk,
 	__mptcp_do_fallback(msk);
 }
 
-static int mptcp_stream_connect(struct socket *sock, struct sockaddr *uaddr,
-				int addr_len, int flags)
+int mptcp_stream_connect(struct socket *sock, struct sockaddr *uaddr,
+			 int addr_len, int flags)
 {
 	struct mptcp_sock *msk = mptcp_sk(sock->sk);
 	struct mptcp_subflow_context *subflow;
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index ad51910f1cc9..ef8330d5a9b5 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -835,11 +835,14 @@ void mptcp_event(enum mptcp_event_type type, const struct mptcp_sock *msk,
 void mptcp_event_addr_announced(const struct sock *ssk, const struct mptcp_addr_info *info);
 void mptcp_event_addr_removed(const struct mptcp_sock *msk, u8 id);
 bool mptcp_userspace_pm_active(const struct mptcp_sock *msk);
+int mptcp_stream_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags);
 
 // Fast Open Mechanism functions begin
 int mptcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
 			   size_t len, struct mptcp_sock *msk,
 			   size_t *copied);
+int mptcp_setsockopt_sol_tcp_fastopen(struct mptcp_sock *msk, sockptr_t optval,
+				      unsigned int optlen);
 // Fast Open Mechanism functions end
 
 static inline bool mptcp_pm_should_add_signal(struct mptcp_sock *msk)
diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
index 423d3826ca1e..f62f0d63b8e6 100644
--- a/net/mptcp/sockopt.c
+++ b/net/mptcp/sockopt.c
@@ -559,6 +559,7 @@ static bool mptcp_supported_sockopt(int level, int optname)
 		case TCP_NOTSENT_LOWAT:
 		case TCP_TX_DELAY:
 		case TCP_INQ:
+		case TCP_FASTOPEN:
 			return true;
 		}
 
@@ -796,6 +797,8 @@ static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
 		return mptcp_setsockopt_sol_tcp_nodelay(msk, optval, optlen);
 	case TCP_DEFER_ACCEPT:
 		return mptcp_setsockopt_sol_tcp_defer(msk, optval, optlen);
+	case TCP_FASTOPEN:
+		return mptcp_setsockopt_sol_tcp_fastopen(msk, optval, optlen);
 	}
 
 	return -EOPNOTSUPP;
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH mptcp-next v5 05/10] This fixes the unexpected value of subflow->map_seq for the second packet that leads to packet discard and further retransmit
  2022-09-14 11:31 [RFC PATCH mptcp-next v5 01/10] mptcp: Fast Open Mechanism Dmytro Shytyi
                   ` (2 preceding siblings ...)
  2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 04/10] Treat a socket option TCP_FASTOPEN on Lister side. Suggestion @mmartineau(MAY 22): 'Need to use ssk instead of sk in these several lines' (1 AUG): 'Since fastopen is only relevant for the initial subflow (and never with MP_JOIN). __mptcp_nmpc_socket() should give the initial subflow' Dmytro Shytyi
@ 2022-09-14 11:31 ` Dmytro Shytyi
  2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 06/10] This commit introduces mptfo variables for msk and options. Also fixes the infinite retransmissions in the end of second session. Suggestion @palbeni (SEP 1) during the meting to 'look at data_ack' Dmytro Shytyi
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Dmytro Shytyi @ 2022-09-14 11:31 UTC (permalink / raw)
  To: mptcp; +Cc: Dmytro Shytyi

This fixes the unexpected value of
subflow->map_seq for the second packet that leads to packet discard and
further retransmit.

Signed-off-by: Dmytro Shytyi <dmytro@shytyi.net>
---
 net/mptcp/subflow.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index c7d49fb6e7bd..075c61d1d37f 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -1077,8 +1077,10 @@ static enum mapping_status get_mapping_status(struct sock *ssk,
 		/* will validate the next map after consuming the current one */
 		goto validate_csum;
 	}
-
-	subflow->map_seq = map_seq;
+	if (msk->is_mptfo)
+		subflow->map_seq = READ_ONCE(msk->ack_seq);
+	else
+		subflow->map_seq = map_seq;
 	subflow->map_subflow_seq = mpext->subflow_seq;
 	subflow->map_data_len = data_len;
 	subflow->map_valid = 1;
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH mptcp-next v5 06/10] This commit introduces mptfo variables for msk and options. Also fixes the infinite retransmissions in the end of second session. Suggestion @palbeni (SEP 1) during the meting to 'look at data_ack'
  2022-09-14 11:31 [RFC PATCH mptcp-next v5 01/10] mptcp: Fast Open Mechanism Dmytro Shytyi
                   ` (3 preceding siblings ...)
  2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 05/10] This fixes the unexpected value of subflow->map_seq for the second packet that leads to packet discard and further retransmit Dmytro Shytyi
@ 2022-09-14 11:31 ` Dmytro Shytyi
  2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 07/10] Add the received skb on the listener side to msk and set flag mptfo to 1 to treat some parts only in MPTFO case. This function is called from the functions presented in the next patch Dmytro Shytyi
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Dmytro Shytyi @ 2022-09-14 11:31 UTC (permalink / raw)
  To: mptcp; +Cc: Dmytro Shytyi

This commit introduces mptfo
variables for msk and options. Also fixes the infinite retransmissions in the
end of second session. Suggestion @palbeni (SEP 1) during the meting to 'look
at data_ack'

Signed-off-by: Dmytro Shytyi <dmytro@shytyi.net>
---
 net/mptcp/fastopen.c | 16 ++++++++++++++++
 net/mptcp/options.c  |  3 +++
 net/mptcp/protocol.h |  6 +++++-
 3 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/net/mptcp/fastopen.c b/net/mptcp/fastopen.c
index 2633d5148dcb..ea46a4b405db 100644
--- a/net/mptcp/fastopen.c
+++ b/net/mptcp/fastopen.c
@@ -85,3 +85,19 @@ int mptcp_setsockopt_sol_tcp_fastopen(struct mptcp_sock *msk, sockptr_t optval,
 
 	return ret;
 }
+
+void mptcp_treat_3d_ack_fastopen(struct mptcp_sock *msk, struct mptcp_subflow_context *subflow,
+				 struct mptcp_options_received mp_opt)
+{
+	u64 ack_seq;
+
+	if (mp_opt.suboptions & OPTIONS_MPTCP_MPC && mp_opt.is_mptfo && msk->is_mptfo) {
+		msk->can_ack = true;
+		msk->remote_key = mp_opt.sndr_key;
+		mptcp_crypto_key_sha(msk->remote_key, NULL, &ack_seq);
+		ack_seq++;
+		WRITE_ONCE(msk->ack_seq, ack_seq);
+		pr_debug("ack_seq=%llu sndr_key=%llu", msk->ack_seq, mp_opt.sndr_key);
+		atomic64_set(&msk->rcv_wnd_sent, ack_seq);
+	}
+}
diff --git a/net/mptcp/options.c b/net/mptcp/options.c
index 30d289044e71..267a346eb0bb 100644
--- a/net/mptcp/options.c
+++ b/net/mptcp/options.c
@@ -91,6 +91,7 @@ static void mptcp_parse_option(const struct sk_buff *skb,
 			ptr += 8;
 		}
 		if (opsize >= TCPOLEN_MPTCP_MPC_ACK) {
+			mp_opt->is_mptfo = 1;
 			mp_opt->rcvr_key = get_unaligned_be64(ptr);
 			ptr += 8;
 		}
@@ -1124,6 +1125,8 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
 		return sk->sk_state != TCP_CLOSE;
 
 	if (unlikely(mp_opt.suboptions != OPTION_MPTCP_DSS)) {
+		mptcp_treat_3d_ack_fastopen(msk, subflow, mp_opt);
+
 		if ((mp_opt.suboptions & OPTION_MPTCP_FASTCLOSE) &&
 		    msk->local_key == mp_opt.rcvr_key) {
 			WRITE_ONCE(msk->rcv_fastclose, true);
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index ef8330d5a9b5..a23f4529827e 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -155,7 +155,8 @@ struct mptcp_options_received {
 		echo:1,
 		backup:1,
 		deny_join_id0:1,
-		__unused:2;
+		is_mptfo:1,
+		__unused:1;
 	u8	join_id;
 	u64	thmac;
 	u8	hmac[MPTCPOPT_HMAC_LEN];
@@ -282,6 +283,7 @@ struct mptcp_sock {
 	bool		use_64bit_ack; /* Set when we received a 64-bit DSN */
 	bool		csum_enabled;
 	bool		allow_infinite_fallback;
+	bool		is_mptfo;
 	u8		mpc_endpoint_id;
 	u8		recvmsg_inq:1,
 			cork:1,
@@ -843,6 +845,8 @@ int mptcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
 			   size_t *copied);
 int mptcp_setsockopt_sol_tcp_fastopen(struct mptcp_sock *msk, sockptr_t optval,
 				      unsigned int optlen);
+void mptcp_treat_3d_ack_fastopen(struct mptcp_sock *msk, struct mptcp_subflow_context *subflow,
+				 struct mptcp_options_received mp_opt);
 // Fast Open Mechanism functions end
 
 static inline bool mptcp_pm_should_add_signal(struct mptcp_sock *msk)
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH mptcp-next v5 07/10] Add the received skb on the listener side to msk and set flag mptfo to 1 to treat some parts only in MPTFO case. This function is called from the functions presented in the next patch
  2022-09-14 11:31 [RFC PATCH mptcp-next v5 01/10] mptcp: Fast Open Mechanism Dmytro Shytyi
                   ` (4 preceding siblings ...)
  2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 06/10] This commit introduces mptfo variables for msk and options. Also fixes the infinite retransmissions in the end of second session. Suggestion @palbeni (SEP 1) during the meting to 'look at data_ack' Dmytro Shytyi
@ 2022-09-14 11:31 ` Dmytro Shytyi
  2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 08/10] This is temporary modification and will be adressed in the new version of the patch: Remove OPTIONS_TS from the options. See disscusion in the mailing list (JAN 18) [PATCH v2] fastopen with @palbeni Dmytro Shytyi
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Dmytro Shytyi @ 2022-09-14 11:31 UTC (permalink / raw)
  To: mptcp; +Cc: Dmytro Shytyi

Add the received skb on the listener
side to msk and set flag mptfo to 1 to treat some parts only in MPTFO case.
This function is called from the functions presented in the next patch

Signed-off-by: Dmytro Shytyi <dmytro@shytyi.net>
---
 net/mptcp/fastopen.c | 444 +++++++++++++++++++++++++++++++++++++++++++
 net/mptcp/protocol.h |  41 ++++
 net/mptcp/subflow.c  |   2 +-
 3 files changed, 486 insertions(+), 1 deletion(-)

diff --git a/net/mptcp/fastopen.c b/net/mptcp/fastopen.c
index ea46a4b405db..fd0e4b7c8f68 100644
--- a/net/mptcp/fastopen.c
+++ b/net/mptcp/fastopen.c
@@ -101,3 +101,447 @@ void mptcp_treat_3d_ack_fastopen(struct mptcp_sock *msk, struct mptcp_subflow_co
 		atomic64_set(&msk->rcv_wnd_sent, ack_seq);
 	}
 }
+
+void mptcp_fastopen_add_skb(struct sock *sk, struct sk_buff *skb, struct request_sock *req)
+{
+	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
+	struct tcp_request_sock *tcp_r_sock = tcp_rsk(req);
+	struct sock *socket = mptcp_subflow_ctx(sk)->conn;
+	struct mptcp_sock *msk = mptcp_sk(socket);
+	struct tcp_sock *tp = tcp_sk(sk);
+
+	if (TCP_SKB_CB(skb)->end_seq == tp->rcv_nxt)
+		return;
+
+	skb = skb_clone(skb, GFP_ATOMIC);
+	if (!skb)
+		return;
+
+	skb_dst_drop(skb);
+
+	tp->segs_in = 0;
+	tcp_segs_in(tp, skb);
+	__skb_pull(skb, tcp_hdrlen(skb));
+	sk_forced_mem_schedule(sk, skb->truesize);
+
+	TCP_SKB_CB(skb)->seq++;
+	TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_SYN;
+
+	tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+
+	msk->is_mptfo = 1;
+
+	//Solves: WARNING: at 704 _mptcp_move_skbs_from_subflow+0x5d0/0x651
+	tp->copied_seq += tp->rcv_nxt - tcp_r_sock->rcv_isn - 1;
+
+	TCP_SKB_CB(skb)->seq += tp->rcv_nxt - tcp_r_sock->rcv_isn - 1;
+	TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq;
+
+	TCP_SKB_CB(skb)->seq += tp->rcv_nxt - tcp_r_sock->rcv_isn - 1;
+	TCP_SKB_CB(skb)->end_seq =  TCP_SKB_CB(skb)->seq;
+
+	subflow->map_seq = mptcp_subflow_get_mapped_dsn(subflow);
+
+	//Solves: BAD mapping: ssn=0 map_seq=1 map_data_len=3
+	subflow->ssn_offset = tp->copied_seq - 1;
+
+	skb_ext_reset(skb);
+
+	//mptcp_set_owner_r begin
+	skb_orphan(skb);
+	skb->sk = socket;
+	skb->destructor = mptcp_rfree;
+	atomic_add(skb->truesize, &socket->sk_rmem_alloc);
+	msk->rmem_fwd_alloc -= skb->truesize;
+	//mptcp_set owner_r end
+
+	__skb_queue_tail(&msk->receive_queue, skb);
+
+	atomic64_set(&msk->rcv_wnd_sent, mptcp_subflow_get_mapped_dsn(subflow));
+
+	tp->syn_data_acked = 1;
+
+	tp->bytes_received = skb->len;
+
+	if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
+		tcp_fin(sk);
+}
+
+struct sock *mptcp_fastopen_create_child(struct sock *sk,
+					 struct sk_buff *skb,
+					 struct request_sock *req)
+{
+	struct request_sock_queue *r_sock_queue = &inet_csk(sk)->icsk_accept_queue;
+	struct tcp_sock *tp;
+	struct sock *child_sock;
+	bool own_req;
+
+	child_sock = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL,
+							      NULL, &own_req);
+	if (!child_sock)
+		return NULL;
+
+	spin_lock(&r_sock_queue->fastopenq.lock);
+	r_sock_queue->fastopenq.qlen++;
+	spin_unlock(&r_sock_queue->fastopenq.lock);
+
+	tp = tcp_sk(child_sock);
+
+	rcu_assign_pointer(tp->fastopen_rsk, req);
+	tcp_rsk(req)->tfo_listener = true;
+
+	tp->snd_wnd = ntohs(tcp_hdr(skb)->window);
+	tp->max_window = tp->snd_wnd;
+
+	inet_csk_reset_xmit_timer(child_sock, ICSK_TIME_RETRANS,
+				  TCP_TIMEOUT_INIT, TCP_RTO_MAX);
+
+	refcount_set(&req->rsk_refcnt, 2);
+
+	tcp_init_transfer(child_sock, BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB, skb);
+
+	tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1;
+
+	mptcp_fastopen_add_skb(child_sock, skb, req);
+
+	tcp_rsk(req)->rcv_nxt = tp->rcv_nxt;
+	tp->rcv_wup = tp->rcv_nxt;
+
+	return child_sock;
+}
+
+bool mptcp_fastopen_queue_check(struct sock *sk)
+{
+	struct fastopen_queue *fo_queue;
+	struct request_sock *req_sock;
+
+	fo_queue = &inet_csk(sk)->icsk_accept_queue.fastopenq;
+	if (fo_queue->max_qlen == 0)
+		return false;
+
+	if (fo_queue->qlen >= fo_queue->max_qlen) {
+		spin_lock(&fo_queue->lock);
+		req_sock = fo_queue->rskq_rst_head;
+		if (!req_sock || time_after(req_sock->rsk_timer.expires, jiffies)) {
+			spin_unlock(&fo_queue->lock);
+			return false;
+		}
+		fo_queue->rskq_rst_head = req_sock->dl_next;
+		fo_queue->qlen--;
+		spin_unlock(&fo_queue->lock);
+		reqsk_put(req_sock);
+	}
+	return true;
+}
+
+bool mptcp_fastopen_cookie_gen_cipher(struct request_sock *req,
+				      struct sk_buff *syn,
+				      const siphash_key_t *key,
+				      struct tcp_fastopen_cookie *foc)
+{
+	if (req->rsk_ops->family == AF_INET) {
+		const struct iphdr *iph = ip_hdr(syn);
+
+		foc->val[0] = cpu_to_le64(siphash(&iph->saddr,
+					  sizeof(iph->saddr) +
+					  sizeof(iph->daddr),
+					  key));
+		foc->len = TCP_FASTOPEN_COOKIE_SIZE;
+		return true;
+	}
+
+	return false;
+}
+
+void mptcp_fastopen_cookie_gen(struct sock *sk,
+			       struct request_sock *req,
+			       struct sk_buff *syn,
+			       struct tcp_fastopen_cookie *foc)
+{
+	struct tcp_fastopen_context *ctx;
+
+	rcu_read_lock();
+	ctx = tcp_fastopen_get_ctx(sk);
+	if (ctx)
+		mptcp_fastopen_cookie_gen_cipher(req, syn, &ctx->key[0], foc);
+	rcu_read_unlock();
+}
+
+int mptcp_fastopen_cookie_gen_check(struct sock *sk,
+				    struct request_sock *req,
+				    struct sk_buff *syn,
+				    struct tcp_fastopen_cookie *orig,
+				    struct tcp_fastopen_cookie *valid_foc)
+{
+	struct tcp_fastopen_cookie mptcp_search_foc = { .len = -1 };
+	struct tcp_fastopen_cookie *mptcp_foc = valid_foc;
+	struct tcp_fastopen_context *mptcp_fo_ctx;
+	int i, ret = 0;
+
+	rcu_read_lock();
+	mptcp_fo_ctx = tcp_fastopen_get_ctx(sk);
+	if (!mptcp_fo_ctx)
+		goto out;
+	for (i = 0; i < tcp_fastopen_context_len(mptcp_fo_ctx); i++) {
+		mptcp_fastopen_cookie_gen_cipher(req, syn, &mptcp_fo_ctx->key[i], mptcp_foc);
+		if (tcp_fastopen_cookie_match(mptcp_foc, orig)) {
+			ret = i + 1;
+			goto out;
+		}
+		mptcp_foc = &mptcp_search_foc;
+	}
+out:
+	rcu_read_unlock();
+	return ret;
+}
+
+bool mptcp_fastopen_no_cookie(const struct sock *sk,
+			      const struct dst_entry *dst,
+			      int flag)
+{
+	return (sock_net(sk)->ipv4.sysctl_tcp_fastopen & flag) ||
+	       tcp_sk(sk)->fastopen_no_cookie ||
+	       (dst && dst_metric(dst, RTAX_FASTOPEN_NO_COOKIE));
+}
+
+struct sock *mptcp_try_fastopen(struct sock *sk, struct sk_buff *skb,
+				struct request_sock *req,
+				struct tcp_fastopen_cookie *foc,
+				const struct dst_entry *dst)
+{
+	bool syn_data_status = TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq + 1;
+	struct tcp_fastopen_cookie valid_mptcp_foc = { .len = -1 };
+	struct sock *child_sock;
+	int ret = 0;
+
+	if ((syn_data_status || foc->len >= 0) &&
+	    mptcp_fastopen_queue_check(sk)) {
+		foc->len = -1;
+		return NULL;
+	}
+
+	if (mptcp_fastopen_no_cookie(sk, dst, TFO_SERVER_COOKIE_NOT_REQD))
+		goto fastopen;
+
+	if (foc->len == 0) {
+		mptcp_fastopen_cookie_gen(sk, req, skb, &valid_mptcp_foc);
+	} else if (foc->len > 0) {
+		ret = mptcp_fastopen_cookie_gen_check(sk, req, skb, foc,
+						      &valid_mptcp_foc);
+		if (ret) {
+fastopen:
+			child_sock = mptcp_fastopen_create_child(sk, skb, req);
+			if (child_sock) {
+				if (ret == 2) {
+					valid_mptcp_foc.exp = foc->exp;
+					*foc = valid_mptcp_foc;
+				} else {
+					foc->len = -1;
+				}
+				return child_sock;
+			}
+		}
+	}
+	valid_mptcp_foc.exp = foc->exp;
+	*foc = valid_mptcp_foc;
+	return NULL;
+}
+
+int mptcp_conn_request(struct request_sock_ops *rsk_ops,
+		       const struct tcp_request_sock_ops *af_ops,
+		       struct sock *sk, struct sk_buff *skb)
+{
+	struct tcp_fastopen_cookie mptcp_foc = { .len = -1 };
+	struct tcp_options_received tmp_opt_rcvd;
+	__u32 isn = TCP_SKB_CB(skb)->tcp_tw_isn;
+	struct tcp_sock *tp_sock = tcp_sk(sk);
+	struct sock *mptcp_fo_sk = NULL;
+	struct net *net = sock_net(sk);
+	struct request_sock *req_sock;
+	bool want_cookie = false;
+	struct dst_entry *dst;
+	struct flowi fl;
+
+	if (sk_acceptq_is_full(sk))
+		goto drop;
+
+	req_sock = inet_reqsk_alloc(rsk_ops, sk, !want_cookie);
+	if (!req_sock)
+		goto drop;
+
+	req_sock->syncookie = want_cookie;
+	tcp_rsk(req_sock)->af_specific = af_ops;
+	tcp_rsk(req_sock)->ts_off = 0;
+	tcp_rsk(req_sock)->is_mptcp = 1;
+
+	tcp_clear_options(&tmp_opt_rcvd);
+	tmp_opt_rcvd.mss_clamp = af_ops->mss_clamp;
+	tmp_opt_rcvd.user_mss  = tp_sock->rx_opt.user_mss;
+	tcp_parse_options(sock_net(sk), skb, &tmp_opt_rcvd, 0,
+			  want_cookie ? NULL : &mptcp_foc);
+
+	if (want_cookie && !tmp_opt_rcvd.saw_tstamp)
+		tcp_clear_options(&tmp_opt_rcvd);
+
+	if (IS_ENABLED(CONFIG_SMC) && want_cookie)
+		tmp_opt_rcvd.smc_ok = 0;
+
+	tmp_opt_rcvd.tstamp_ok = tmp_opt_rcvd.saw_tstamp;
+	mptcp_openreq_init(req_sock, &tmp_opt_rcvd, skb, sk);
+	inet_rsk(req_sock)->no_srccheck = inet_sk(sk)->transparent;
+
+	inet_rsk(req_sock)->ir_iif = inet_request_bound_dev_if(sk, skb);
+
+	dst = af_ops->route_req(sk, skb, &fl, req_sock);
+	if (!dst)
+		goto drop_and_free;
+
+	if (tmp_opt_rcvd.tstamp_ok)
+		tcp_rsk(req_sock)->ts_off = af_ops->init_ts_off(net, skb);
+
+	if (!want_cookie && !isn) {
+		if (!net->ipv4.sysctl_tcp_syncookies &&
+		    (net->ipv4.sysctl_max_syn_backlog - inet_csk_reqsk_queue_len(sk) <
+		     (net->ipv4.sysctl_max_syn_backlog >> 2)) &&
+		    !tcp_peer_is_proven(req_sock, dst)) {
+			goto drop_and_release;
+		}
+
+		isn = af_ops->init_seq(skb);
+	}
+
+	mptcp_ecn_create_request(req_sock, skb, sk, dst);
+
+	if (want_cookie) {
+		isn = cookie_init_sequence(af_ops, sk, skb, &req_sock->mss);
+		if (!tmp_opt_rcvd.tstamp_ok)
+			inet_rsk(req_sock)->ecn_ok = 0;
+	}
+
+	tcp_rsk(req_sock)->snt_isn = isn;
+	tcp_rsk(req_sock)->txhash = net_tx_rndhash();
+	tcp_rsk(req_sock)->syn_tos = TCP_SKB_CB(skb)->ip_dsfield;
+
+	tcp_openreq_init_rwin(req_sock, sk, dst);
+	sk_rx_queue_set(req_to_sk(req_sock), skb);
+	if (!want_cookie) {
+		mptcp_reqsk_record_syn(sk, req_sock, skb);
+		mptcp_fo_sk = mptcp_try_fastopen(sk, skb, req_sock, &mptcp_foc, dst);
+	}
+	if (mptcp_fo_sk) {
+		af_ops->send_synack(mptcp_fo_sk, dst, &fl, req_sock,
+				    &mptcp_foc, TCP_SYNACK_FASTOPEN, skb);
+		if (!inet_csk_reqsk_queue_add(sk, req_sock, mptcp_fo_sk)) {
+			reqsk_fastopen_remove(mptcp_fo_sk, req_sock, false);
+			bh_unlock_sock(mptcp_fo_sk);
+			sock_put(mptcp_fo_sk);
+			goto drop_and_free;
+		}
+		sk->sk_data_ready(sk);
+		bh_unlock_sock(mptcp_fo_sk);
+		sock_put(mptcp_fo_sk);
+	} else {
+		tcp_rsk(req_sock)->tfo_listener = false;
+		if (!want_cookie) {
+			req_sock->timeout = tcp_timeout_init((struct sock *)req_sock);
+			inet_csk_reqsk_queue_hash_add(sk, req_sock, req_sock->timeout);
+		}
+		af_ops->send_synack(sk, dst, &fl, req_sock, &mptcp_foc,
+				    !want_cookie ? TCP_SYNACK_NORMAL :
+						   TCP_SYNACK_COOKIE,
+				    skb);
+		if (want_cookie) {
+			reqsk_free(req_sock);
+			return 0;
+		}
+	}
+	reqsk_put(req_sock);
+	return 0;
+
+drop_and_release:
+	dst_release(dst);
+drop_and_free:
+	__reqsk_free(req_sock);
+drop:
+	tcp_listendrop(sk);
+	return 0;
+}
+
+void mptcp_reqsk_record_syn(const struct sock *sk,
+			    struct request_sock *req,
+			    const struct sk_buff *skb)
+{
+	if (tcp_sk(sk)->save_syn) {
+		u32 length = skb_network_header_len(skb) + tcp_hdrlen(skb);
+		struct saved_syn *svd_syn;
+		u32 mac_headerlen;
+		void *base;
+
+		if (tcp_sk(sk)->save_syn == 2) {
+			base = skb_mac_header(skb);
+			mac_headerlen = skb_mac_header_len(skb);
+			length += mac_headerlen;
+		} else {
+			base = skb_network_header(skb);
+			mac_headerlen = 0;
+		}
+
+		svd_syn = kmalloc(struct_size(svd_syn, data, length),
+				  GFP_ATOMIC);
+		if (svd_syn) {
+			svd_syn->mac_hdrlen = mac_headerlen;
+			svd_syn->network_hdrlen = skb_network_header_len(skb);
+			svd_syn->tcp_hdrlen = tcp_hdrlen(skb);
+			memcpy(svd_syn->data, base, length);
+			req->saved_syn = svd_syn;
+		}
+	}
+}
+
+void mptcp_ecn_create_request(struct request_sock *req,
+			      const struct sk_buff *skb,
+			      const struct sock *listen_sk,
+			      const struct dst_entry *dst)
+{
+	const struct tcphdr *thdr = tcp_hdr(skb);
+	const struct net *net = sock_net(listen_sk);
+	bool thdr_ecn = thdr->ece && thdr->cwr;
+	bool ect_stat, ecn_okay;
+	u32 ecn_okay_dst;
+
+	if (!thdr_ecn)
+		return;
+
+	ect_stat = !INET_ECN_is_not_ect(TCP_SKB_CB(skb)->ip_dsfield);
+	ecn_okay_dst = dst_feature(dst, DST_FEATURE_ECN_MASK);
+	ecn_okay = net->ipv4.sysctl_tcp_ecn || ecn_okay_dst;
+
+	if (((!ect_stat || thdr->res1) && ecn_okay) || tcp_ca_needs_ecn(listen_sk) ||
+	    (ecn_okay_dst & DST_FEATURE_ECN_CA) ||
+	    tcp_bpf_ca_needs_ecn((struct sock *)req))
+		inet_rsk(req)->ecn_ok = 1;
+}
+
+void mptcp_openreq_init(struct request_sock *req,
+			const struct tcp_options_received *rx_opt,
+			struct sk_buff *skb, const struct sock *sk)
+{
+	struct inet_request_sock *ireq = inet_rsk(req);
+
+	req->rsk_rcv_wnd = 0;
+	tcp_rsk(req)->rcv_isn = TCP_SKB_CB(skb)->seq;
+	tcp_rsk(req)->rcv_nxt = TCP_SKB_CB(skb)->seq + 1;
+	tcp_rsk(req)->snt_synack = 0;
+	tcp_rsk(req)->last_oow_ack_time = 0;
+	req->mss = rx_opt->mss_clamp;
+	req->ts_recent = rx_opt->saw_tstamp ? rx_opt->rcv_tsval : 0;
+	ireq->tstamp_ok = rx_opt->tstamp_ok;
+	ireq->sack_ok = rx_opt->sack_ok;
+	ireq->snd_wscale = rx_opt->snd_wscale;
+	ireq->wscale_ok = rx_opt->wscale_ok;
+	ireq->acked = 0;
+	ireq->ecn_ok = 0;
+	ireq->ir_rmt_port = tcp_hdr(skb)->source;
+	ireq->ir_num = ntohs(tcp_hdr(skb)->dest);
+	ireq->ir_mark = inet_request_mark(sk, skb);
+}
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index a23f4529827e..aea413f8d9cc 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -847,6 +847,47 @@ int mptcp_setsockopt_sol_tcp_fastopen(struct mptcp_sock *msk, sockptr_t optval,
 				      unsigned int optlen);
 void mptcp_treat_3d_ack_fastopen(struct mptcp_sock *msk, struct mptcp_subflow_context *subflow,
 				 struct mptcp_options_received mp_opt);
+void mptcp_treat_3d_ack_fastopen(struct mptcp_sock *msk, struct mptcp_subflow_context *subflow,
+				 struct mptcp_options_received mp_opt);
+void mptcp_fastopen_add_skb(struct sock *sk, struct sk_buff *skb,
+			    struct request_sock *req);
+void mptcp_reqsk_record_syn(const struct sock *sk,
+			    struct request_sock *req,
+			    const struct sk_buff *skb);
+void mptcp_ecn_create_request(struct request_sock *req,
+			      const struct sk_buff *skb,
+			      const struct sock *listen_sk,
+			      const struct dst_entry *dst);
+void mptcp_openreq_init(struct request_sock *req,
+			const struct tcp_options_received *rx_opt,
+			struct sk_buff *skb, const struct sock *sk);
+struct sock *mptcp_fastopen_create_child(struct sock *sk,
+					 struct sk_buff *skb,
+					 struct request_sock *req);
+bool mptcp_fastopen_queue_check(struct sock *sk);
+bool mptcp_fastopen_cookie_gen_cipher(struct request_sock *req,
+				      struct sk_buff *syn,
+				      const siphash_key_t *key,
+				      struct tcp_fastopen_cookie *foc);
+void mptcp_fastopen_cookie_gen(struct sock *sk,
+			       struct request_sock *req,
+			       struct sk_buff *syn,
+			       struct tcp_fastopen_cookie *foc);
+int mptcp_fastopen_cookie_gen_check(struct sock *sk,
+				    struct request_sock *req,
+				    struct sk_buff *syn,
+				    struct tcp_fastopen_cookie *orig,
+				    struct tcp_fastopen_cookie *valid_foc);
+bool mptcp_fastopen_no_cookie(const struct sock *sk,
+			      const struct dst_entry *dst,
+			      int flag);
+struct sock *mptcp_try_fastopen(struct sock *sk, struct sk_buff *skb,
+				struct request_sock *req,
+				struct tcp_fastopen_cookie *foc,
+				const struct dst_entry *dst);
+int mptcp_conn_request(struct request_sock_ops *rsk_ops,
+		       const struct tcp_request_sock_ops *af_ops,
+		       struct sock *sk, struct sk_buff *skb);
 // Fast Open Mechanism functions end
 
 static inline bool mptcp_pm_should_add_signal(struct mptcp_sock *msk)
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 075c61d1d37f..ff5fe4ff3d21 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -542,7 +542,7 @@ static int subflow_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 	if (skb_rtable(skb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
 		goto drop;
 
-	return tcp_conn_request(&mptcp_subflow_request_sock_ops,
+	return mptcp_conn_request(&mptcp_subflow_request_sock_ops,
 				&subflow_request_sock_ipv4_ops,
 				sk, skb);
 drop:
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH mptcp-next v5 08/10] This is temporary modification and will be adressed in the new version of the patch: Remove OPTIONS_TS from the options. See disscusion in the mailing list (JAN 18) [PATCH v2] fastopen with @palbeni
  2022-09-14 11:31 [RFC PATCH mptcp-next v5 01/10] mptcp: Fast Open Mechanism Dmytro Shytyi
                   ` (5 preceding siblings ...)
  2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 07/10] Add the received skb on the listener side to msk and set flag mptfo to 1 to treat some parts only in MPTFO case. This function is called from the functions presented in the next patch Dmytro Shytyi
@ 2022-09-14 11:31 ` Dmytro Shytyi
  2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 09/10] These 2 functions are from protocol.c. Cannot import as not in protocol.h. Should I leave them like this? Or add prototypes in protocol.h and reuse? Dmytro Shytyi
  2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 10/10] MPTFO tests: these are examples that probably are going to be integrated to the mptcp_connect.* selftests Dmytro Shytyi
  8 siblings, 0 replies; 10+ messages in thread
From: Dmytro Shytyi @ 2022-09-14 11:31 UTC (permalink / raw)
  To: mptcp; +Cc: Dmytro Shytyi

This is temporary modification and
will be adressed in the new version of the patch: Remove OPTIONS_TS from the
options. See disscusion in the mailing list (JAN 18) [PATCH v2] fastopen with
@palbeni

Signed-off-by: Dmytro Shytyi <dmytro@shytyi.net>
---
 include/net/mptcp.h   | 2 +-
 net/ipv4/tcp_output.c | 2 +-
 net/mptcp/options.c   | 8 ++++++--
 3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/include/net/mptcp.h b/include/net/mptcp.h
index c25939b2af68..7881b18aecb4 100644
--- a/include/net/mptcp.h
+++ b/include/net/mptcp.h
@@ -140,7 +140,7 @@ void mptcp_space(const struct sock *ssk, int *space, int *full_space);
 bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb,
 		       unsigned int *size, struct mptcp_out_options *opts);
 bool mptcp_synack_options(const struct request_sock *req, unsigned int *size,
-			  struct mptcp_out_options *opts);
+			  struct mptcp_out_options *opts, u16 *tcp_options);
 bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
 			       unsigned int *size, unsigned int remaining,
 			       struct mptcp_out_options *opts);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 290019de766d..3900fc57325d 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -744,7 +744,7 @@ static void mptcp_set_option_cond(const struct request_sock *req,
 	if (rsk_is_mptcp(req)) {
 		unsigned int size;
 
-		if (mptcp_synack_options(req, &size, &opts->mptcp)) {
+		if (mptcp_synack_options(req, &size, &opts->mptcp, &opts->options)) {
 			if (*remaining >= size) {
 				opts->options |= OPTION_MPTCP;
 				*remaining -= size;
diff --git a/net/mptcp/options.c b/net/mptcp/options.c
index 267a346eb0bb..e7c3a362bd27 100644
--- a/net/mptcp/options.c
+++ b/net/mptcp/options.c
@@ -889,16 +889,20 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
 }
 
 bool mptcp_synack_options(const struct request_sock *req, unsigned int *size,
-			  struct mptcp_out_options *opts)
+			  struct mptcp_out_options *opts, u16 *tcp_options)
 {
 	struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
 
+#define OPTION_TS               BIT(1)
+
+	*tcp_options ^= OPTION_TS;
 	if (subflow_req->mp_capable) {
 		opts->suboptions = OPTION_MPTCP_MPC_SYNACK;
 		opts->sndr_key = subflow_req->local_key;
 		opts->csum_reqd = subflow_req->csum_reqd;
 		opts->allow_join_id0 = subflow_req->allow_join_id0;
-		*size = TCPOLEN_MPTCP_MPC_SYNACK;
+		//*size = TCPOLEN_MPTCP_MPC_SYNACK;
+		*size = TCPOLEN_MPTCP_MPC_SYNACK - TCPOLEN_TSTAMP_ALIGNED + TCPOLEN_SACKPERM_ALIGNED;
 		pr_debug("subflow_req=%p, local_key=%llu",
 			 subflow_req, subflow_req->local_key);
 		return true;
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH mptcp-next v5 09/10] These 2 functions are from protocol.c. Cannot import as not in protocol.h. Should I leave them like this? Or add prototypes in protocol.h and reuse?
  2022-09-14 11:31 [RFC PATCH mptcp-next v5 01/10] mptcp: Fast Open Mechanism Dmytro Shytyi
                   ` (6 preceding siblings ...)
  2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 08/10] This is temporary modification and will be adressed in the new version of the patch: Remove OPTIONS_TS from the options. See disscusion in the mailing list (JAN 18) [PATCH v2] fastopen with @palbeni Dmytro Shytyi
@ 2022-09-14 11:31 ` Dmytro Shytyi
  2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 10/10] MPTFO tests: these are examples that probably are going to be integrated to the mptcp_connect.* selftests Dmytro Shytyi
  8 siblings, 0 replies; 10+ messages in thread
From: Dmytro Shytyi @ 2022-09-14 11:31 UTC (permalink / raw)
  To: mptcp; +Cc: Dmytro Shytyi

These 2 functions are from
protocol.c. Cannot import as not in protocol.h. Should I leave them like
this? Or add prototypes in protocol.h and reuse?

Signed-off-by: Dmytro Shytyi <dmytro@shytyi.net>
---
 net/mptcp/fastopen.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/net/mptcp/fastopen.c b/net/mptcp/fastopen.c
index fd0e4b7c8f68..6a4cb7a28871 100644
--- a/net/mptcp/fastopen.c
+++ b/net/mptcp/fastopen.c
@@ -102,6 +102,25 @@ void mptcp_treat_3d_ack_fastopen(struct mptcp_sock *msk, struct mptcp_subflow_co
 	}
 }
 
+static void mptcp_rmem_uncharge(struct sock *sk, int size)
+{
+	struct mptcp_sock *msk = mptcp_sk(sk);
+	int reclaimable;
+
+	msk->rmem_fwd_alloc += size;
+	reclaimable = msk->rmem_fwd_alloc - sk_unused_reserved_mem(sk);
+
+}
+
+static void mptcp_rfree(struct sk_buff *skb)
+{
+	unsigned int len = skb->truesize;
+	struct sock *sk = skb->sk;
+
+	atomic_sub(len, &sk->sk_rmem_alloc);
+	mptcp_rmem_uncharge(sk, len);
+}
+
 void mptcp_fastopen_add_skb(struct sock *sk, struct sk_buff *skb, struct request_sock *req)
 {
 	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH mptcp-next v5 10/10] MPTFO tests: these are examples that probably are going to be integrated to the mptcp_connect.* selftests
  2022-09-14 11:31 [RFC PATCH mptcp-next v5 01/10] mptcp: Fast Open Mechanism Dmytro Shytyi
                   ` (7 preceding siblings ...)
  2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 09/10] These 2 functions are from protocol.c. Cannot import as not in protocol.h. Should I leave them like this? Or add prototypes in protocol.h and reuse? Dmytro Shytyi
@ 2022-09-14 11:31 ` Dmytro Shytyi
  8 siblings, 0 replies; 10+ messages in thread
From: Dmytro Shytyi @ 2022-09-14 11:31 UTC (permalink / raw)
  To: mptcp; +Cc: Dmytro Shytyi

MPTFO tests: these are examples that
probably are going to be integrated to the mptcp_connect.* selftests

Signed-off-by: Dmytro Shytyi <dmytro@shytyi.net>
---
 tools/testing/selftests/net/mptcp/mptfo.sh    | 13 +++
 .../selftests/net/mptcp/mptfo_initiator.c     | 41 ++++++++
 .../selftests/net/mptcp/mptfo_listener.c      | 98 +++++++++++++++++++
 3 files changed, 152 insertions(+)
 create mode 100644 tools/testing/selftests/net/mptcp/mptfo.sh
 create mode 100644 tools/testing/selftests/net/mptcp/mptfo_initiator.c
 create mode 100644 tools/testing/selftests/net/mptcp/mptfo_listener.c

diff --git a/tools/testing/selftests/net/mptcp/mptfo.sh b/tools/testing/selftests/net/mptcp/mptfo.sh
new file mode 100644
index 000000000000..9ed0cb281094
--- /dev/null
+++ b/tools/testing/selftests/net/mptcp/mptfo.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+#This is an example of environmen that was used to generate wireshark
+sudo ip netns add server
+sudo ip netns add client
+sudo ip link add veth0 type veth peer name veth1
+sudo ip link set veth1 netns server
+sudo ip link set veth0 netns client
+sudo ip netns exec client ip a a 10.10.0.1/24 dev veth0
+sudo ip netns exec server ip a a 10.10.0.2/24 dev veth1
+sudo ip netns exec client ip link set dev  veth0 up
+sudo ip netns exec server ip link set dev  veth1 up
+sudo ip netns exec server bash -c "echo 2 > /proc/sys/net/ipv4/tcp_fastopen"
+sudo ip netns exec client bash -c "echo 1 > /proc/sys/net/ipv4/tcp_fastopen"
diff --git a/tools/testing/selftests/net/mptcp/mptfo_initiator.c b/tools/testing/selftests/net/mptcp/mptfo_initiator.c
new file mode 100644
index 000000000000..e23b88693fb0
--- /dev/null
+++ b/tools/testing/selftests/net/mptcp/mptfo_initiator.c
@@ -0,0 +1,41 @@
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <netinet/tcp.h>
+#include <string.h>
+#include <signal.h>
+
+#define SERVER_PORT 7003
+
+int main(int argc, char *argv[])
+{
+	unsigned char valsyn[3] = "abc";
+	struct sockaddr_in daddr;
+	char *valend = "fff";
+	char *val1 = "zz1";
+	char *val2 = "zz2";
+	char *val3 = "zz3";
+	int sock_fd = -1;
+	int ret;
+
+	memset(&daddr, 0, sizeof(daddr));
+	inet_pton(AF_INET, "10.10.0.2", &daddr.sin_addr);
+	daddr.sin_family = AF_INET;
+	daddr.sin_port = htons(SERVER_PORT);
+
+	sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_MPTCP);
+
+	ret = sendto(sock_fd, valsyn, 3, MSG_FASTOPEN, (struct sockaddr *) &daddr, sizeof(daddr));
+	ret = write(sock_fd, val1, 3);
+	ret = write(sock_fd, val2, 3);
+	ret = write(sock_fd, val2, 3);
+	ret = write(sock_fd, val2, 3);
+	ret = write(sock_fd, val3, 3);
+	ret = write(sock_fd, valend, 3);
+
+	close(sock_fd);
+	return EXIT_SUCCESS;
+}
diff --git a/tools/testing/selftests/net/mptcp/mptfo_listener.c b/tools/testing/selftests/net/mptcp/mptfo_listener.c
new file mode 100644
index 000000000000..7e3de8d1d08c
--- /dev/null
+++ b/tools/testing/selftests/net/mptcp/mptfo_listener.c
@@ -0,0 +1,98 @@
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <linux/in.h>
+#include <netinet/tcp.h>
+
+#define CLIENT_QUEUE_LEN 10
+#define SERVER_PORT 7003
+
+int main(void)
+{
+	int listen_sock_fd = -1, client_sock_fd = -1;
+	char str_addr[INET6_ADDRSTRLEN];
+	struct sockaddr_in server_addr;
+	int ret, flag;
+	int qlen = 5;
+	char ch;
+
+	server_addr.sin_family = AF_INET;
+	inet_pton(AF_INET, "10.10.0.2", &server_addr.sin_addr);
+	server_addr.sin_port = htons(SERVER_PORT);
+
+	/* Create socket for listening (client requests) */
+	listen_sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_MPTCP);
+	if (listen_sock_fd == -1) {
+		perror("socket()server");
+		return EXIT_FAILURE;
+	}
+
+	/* Set socket to reuse address */
+	flag = 1;
+	ret = setsockopt(listen_sock_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
+	if (ret == -1) {
+		perror("setsockopt()");
+		return EXIT_FAILURE;
+	}
+
+	ret = setsockopt(listen_sock_fd, SOL_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen));
+	if (ret == -1) {
+		perror("setsockopt()TCP_FASTOPEN");
+		return EXIT_FAILURE;
+	}
+
+	/* Bind address and socket together */
+	ret = bind(listen_sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
+	if (ret == -1) {
+		perror("bind()");
+		close(listen_sock_fd);
+		return EXIT_FAILURE;
+	}
+
+	/* Create listening queue (client requests) */
+	ret = listen(listen_sock_fd, CLIENT_QUEUE_LEN);
+	if (ret == -1) {
+		perror("listen()");
+		close(listen_sock_fd);
+		return EXIT_FAILURE;
+	}
+	perror("Server listening");
+	while (1) {
+		/* Do TCP handshake with client */
+		client_sock_fd = accept(listen_sock_fd,
+				NULL,
+				0);
+		if (client_sock_fd == -1) {
+			perror("accept()");
+			close(listen_sock_fd);
+			return EXIT_FAILURE;
+		} else {
+			perror("ACCEPT_SUCCESS");
+		}
+
+		char rb[1024];
+
+		while (1) {
+			ret = read(client_sock_fd, rb, 3);
+
+			if (ret == -1) {
+				perror("SERVVERread()");
+				close(client_sock_fd);
+				break;
+			} else {
+				fprintf(stderr, "received %c%c%c from client", rb[0], rb[1], rb[2]);
+			}
+			if (rb[0] == 'f' && rb[1] == 'f' && rb[2] == 'f') {
+				close(client_sock_fd);
+				break;
+			}
+
+		}
+	}
+
+	return EXIT_SUCCESS;
+}
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2022-09-14 11:32 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-14 11:31 [RFC PATCH mptcp-next v5 01/10] mptcp: Fast Open Mechanism Dmytro Shytyi
2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 02/10] Initiator: MSG_FASTOPEN in sendto triggers the mptcp_sendsmg_fastopen. It requests a MPTFO cookie. Suggestion @palbeni(JAN 17): 'split the patch in several small one, clearly documenting in the individual commit message what each patch is doing and why' Dmytro Shytyi
2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 03/10] Initiator: mptcp_sendmsg_fastopen. Usage of lock_sock() / release_sock() leads to hangup' Dmytro Shytyi
2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 04/10] Treat a socket option TCP_FASTOPEN on Lister side. Suggestion @mmartineau(MAY 22): 'Need to use ssk instead of sk in these several lines' (1 AUG): 'Since fastopen is only relevant for the initial subflow (and never with MP_JOIN). __mptcp_nmpc_socket() should give the initial subflow' Dmytro Shytyi
2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 05/10] This fixes the unexpected value of subflow->map_seq for the second packet that leads to packet discard and further retransmit Dmytro Shytyi
2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 06/10] This commit introduces mptfo variables for msk and options. Also fixes the infinite retransmissions in the end of second session. Suggestion @palbeni (SEP 1) during the meting to 'look at data_ack' Dmytro Shytyi
2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 07/10] Add the received skb on the listener side to msk and set flag mptfo to 1 to treat some parts only in MPTFO case. This function is called from the functions presented in the next patch Dmytro Shytyi
2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 08/10] This is temporary modification and will be adressed in the new version of the patch: Remove OPTIONS_TS from the options. See disscusion in the mailing list (JAN 18) [PATCH v2] fastopen with @palbeni Dmytro Shytyi
2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 09/10] These 2 functions are from protocol.c. Cannot import as not in protocol.h. Should I leave them like this? Or add prototypes in protocol.h and reuse? Dmytro Shytyi
2022-09-14 11:31 ` [RFC PATCH mptcp-next v5 10/10] MPTFO tests: these are examples that probably are going to be integrated to the mptcp_connect.* selftests Dmytro Shytyi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).