Skip to contentSkip to conversation

tcp: factor out a couple of helpers

RFC PATCH New Paolo Abeni 1 participant 3 messages Oct 16, 2020

Subsystems (4)
lore
Share & tools
lore

Paolo Abeni

author maintainer
#0 lore raw

cover tcp: factor out a couple of helpers

Upcoming improvement in MPTCP subflows management will require to keep write data enqueued at the MPTCP level. As a side effect, such data could be sent via orphaned TCP subflows after close().

To implement the above MPTCP needs to cope directly with memory allocation failures in do_tcp_sendpages(). The solution proposed in patch 1/2 is to factor-out the relevant slice of do_tcp_sendpages().

Other possible alternatives could be:
- duplicating the relevant code inside MPTCP (will require exposing a few additional TCP helpers)
or
- add an explicit check for orphaned socket in do_tcp_sendpages()

Additionally, due to the above, we will need to dispose of already orphaned TCP subflows, avoiding racing with tcp_done(). We need to check the subflow status and destroy it atomically. The solution proposed in patch 2/2 is to factor-out the unlocked body of tcp_close().

These changes are part of a quite larger MPTCP series, with all the other patches touching only MPTCP code. To hopefully simplify the review, such patches are not included here. Please advice if you prefer otherwise
- e.g. the whole series as RFC.

Paolo Abeni (2):
tcp: factor out tcp_build_frag()
tcp: factor out __tcp_close() helper

 include/net/tcp.h |   4 ++
 net/ipv4/tcp.c    | 128 +++++++++++++++++++++++++++-------------------
 2 files changed, 78 insertions(+), 54 deletions(-)
Signature · 1 line
2.26.2
author maintainer
#1 lore raw

RFC PATCH 1/2 tcp: factor out tcp_build_frag()

Will be needed by the next patch, as MPTCP needs to handle directly the error/memory-allocation-needed path.

No functional changes intended.

Additionally let MPTCP code access the tcp_remove_empty_skb() helper.

Signed-off-by Paolo Abeni <pabeni(a)redhat.com>
---
 include/net/tcp.h |   3 ++
 net/ipv4/tcp.c    | 119 ++++++++++++++++++++++++++--------------------
 2 files changed, 70 insertions(+), 52 deletions(-)
include/net/tcp.h +3 -0
index d4ef5bf94168..e41569e55d97 100644
@@ -322,6 +322,7 @@ void tcp_shutdown(struct sock *sk, int how);
 int tcp_v4_early_demux(struct sk_buff *skb);
 int tcp_v4_rcv(struct sk_buff *skb);
 
+void tcp_remove_empty_skb(struct sock *sk, struct sk_buff *skb);
 int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);
 int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size);
 int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size);
@@ -329,6 +330,8 @@ int tcp_sendpage(struct sock *sk, struct page *page, int offset, size_t size,
 		 int flags);
 int tcp_sendpage_locked(struct sock *sk, struct page *page, int offset,
 			size_t size, int flags);
+struct sk_buff *tcp_build_frag(struct sock *sk, int size_goal, int flags,
+			       struct page *page, int offset, size_t *size);
 ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
 		 size_t size, int flags);
 int tcp_send_mss(struct sock *sk, int *size_goal, int flags);
net/ipv4/tcp.c +67 -52

140 lines not on this page · raw message

Signature · 1 line
2.26.2
author maintainer
#2 lore raw

RFC PATCH 2/2 tcp: factor out __tcp_close() helper

In reply to Paolo Abeni

unlocked version of protocol level close, will be used by MPTCP to allow decouple orphaning and subflow level close.

Signed-off-by Paolo Abeni <pabeni(a)redhat.com>
---
 include/net/tcp.h | 1 +
 net/ipv4/tcp.c    | 9 +++++++--
 2 files changed, 8 insertions(+), 2 deletions(-)
include/net/tcp.h +1 -0
index e41569e55d97..75c5ee45aaa8 100644
@@ -395,6 +395,7 @@ void tcp_update_metrics(struct sock *sk);
 void tcp_init_metrics(struct sock *sk);
 void tcp_metrics_init(void);
 bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst);
+void __tcp_close(struct sock *sk, long timeout);
 void tcp_close(struct sock *sk, long timeout);
 void tcp_init_sock(struct sock *sk);
 void tcp_init_transfer(struct sock *sk, int bpf_op, struct sk_buff *skb);
net/ipv4/tcp.c +7 -2
index 259dca2bd3dd..046ac30bb041 100644
@@ -2418,13 +2418,12 @@ bool tcp_check_oom(struct sock *sk, int shift)
 	return too_many_orphans || out_of_socket_memory;
 }
 
-void tcp_close(struct sock *sk, long timeout)
+void __tcp_close(struct sock *sk, long timeout)
 {
 	struct sk_buff *skb;
 	int data_was_unread = 0;
 	int state;
 
-	lock_sock(sk);
 	sk->sk_shutdown = SHUTDOWN_MASK;
 
 	if (sk->sk_state == TCP_LISTEN) {
@@ -2588,6 +2587,12 @@ void tcp_close(struct sock *sk, long timeout)
 out:
 	bh_unlock_sock(sk);
 	local_bh_enable();
+}
+
+void tcp_close(struct sock *sk, long timeout)
+{
+	lock_sock(sk);
+	__tcp_close(sk, timeout);
 	release_sock(sk);
 	sock_put(sk);
 }
Signature · 1 line
2.26.2