[RHEL7,COMMIT] rh/tcp: provide TCP_FRAG_IN_WRITE/RTX_QUEUE for tcp_fragment use

Submitted by Konstantin Khorenko on Aug. 15, 2019, 3:44 p.m.

Details

Message ID 201908151544.x7FFigtc020592@finist-ce7.sw.ru
State New
Series "rh/tcp: refine memory limit test in tcp_fragment()"
Headers show

Commit Message

Konstantin Khorenko Aug. 15, 2019, 3:44 p.m.
The commit is pushed to "branch-rh7-3.10.0-957.27.2.vz7.107.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-957.27.2.vz7.107.3
------>
commit 94eaeef64746e759e6b0e291a3b14afdd3d240f5
Author: Florian Westphal <fwestpha@redhat.com>
Date:   Tue Jul 2 12:14:27 2019 +0200

    rh/tcp: provide TCP_FRAG_IN_WRITE/RTX_QUEUE for tcp_fragment use
    
    Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1723032
    
    Upstream Status: RHEL-only/partial backport
    This extracts minimal bits from commit
    75c119afe14f74b4dd9 ("tcp: implement rb-tree based retransmit queue"),
    namely the tcp_queue enum and passing it to tcp_fragment().
    Its needed by next patch to tell if the caller is providing an skb
    from write or retransmit queue.
    Signed-off-by: Florian Westphal <fwestpha@redhat.com>
    Signed-off-by: Jiri Benc <jbenc@redhat.com>
    Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
    =================================
    This patch is included into 3.10.0-957.27.4.el7 RHEL7.6 EUS kernel,
    so apply them.
    
    https://jira.sw.ru/browse/PSBM-95578
    
    Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
 include/net/tcp.h     |  8 +++++++-
 net/ipv4/tcp_input.c  |  4 ++--
 net/ipv4/tcp_output.c | 15 ++++++++++-----
 3 files changed, 19 insertions(+), 8 deletions(-)

Patch hide | download patch | download mbox

diff --git a/include/net/tcp.h b/include/net/tcp.h
index abc3adea73aa..6a4d5bc9382a 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -556,7 +556,13 @@  void tcp_retransmit_timer(struct sock *sk);
 void tcp_xmit_retransmit_queue(struct sock *);
 void tcp_simple_retransmit(struct sock *);
 int tcp_trim_head(struct sock *, struct sk_buff *, u32);
-int tcp_fragment(struct sock *, struct sk_buff *, u32, unsigned int);
+enum tcp_queue {
+	TCP_FRAG_IN_WRITE_QUEUE,
+	TCP_FRAG_IN_RTX_QUEUE,
+};
+int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue,
+		 struct sk_buff *skb, u32 len,
+		 unsigned int mss_now);
 
 void tcp_send_probe0(struct sock *);
 void tcp_send_partial(struct sock *);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index b6f476dd7778..e802eb0192bb 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1201,7 +1201,7 @@  static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb,
 		if (pkt_len >= skb->len && !in_sack)
 			return 0;
 
-		err = tcp_fragment(sk, skb, pkt_len, mss);
+		err = tcp_fragment(sk, TCP_FRAG_IN_RTX_QUEUE, skb, pkt_len, mss);
 		if (err < 0)
 			return err;
 	}
@@ -2295,7 +2295,7 @@  static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head)
 			/* If needed, chop off the prefix to mark as lost. */
 			lost = (packets - oldcnt) * mss;
 			if (lost < skb->len &&
-			    tcp_fragment(sk, skb, lost, mss) < 0)
+			    tcp_fragment(sk, TCP_FRAG_IN_RTX_QUEUE, skb, lost, mss) < 0)
 				break;
 			cnt = packets;
 		}
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 69b9ebc20302..48fa7fa40370 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1112,7 +1112,8 @@  static void tcp_adjust_pcount(struct sock *sk, const struct sk_buff *skb, int de
  * packet to the list.  This won't be called frequently, I hope.
  * Remember, these are still headerless SKBs at this point.
  */
-int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len,
+int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue,
+		 struct sk_buff *skb, u32 len,
 		 unsigned int mss_now)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
@@ -1695,7 +1696,8 @@  static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len,
 
 	/* All of a TSO frame must be composed of paged data.  */
 	if (skb->len != skb->data_len)
-		return tcp_fragment(sk, skb, len, mss_now);
+		return tcp_fragment(sk, TCP_FRAG_IN_WRITE_QUEUE,
+				    skb, len, mss_now);
 
 	buff = sk_stream_alloc_skb(sk, 0, gfp);
 	if (unlikely(buff == NULL))
@@ -2193,7 +2195,8 @@  void tcp_send_loss_probe(struct sock *sk)
 		goto rearm_timer;
 
 	if ((pcount > 1) && (skb->len > (pcount - 1) * mss)) {
-		if (unlikely(tcp_fragment(sk, skb, (pcount - 1) * mss, mss)))
+		if (unlikely(tcp_fragment(sk, TCP_FRAG_IN_RTX_QUEUE, skb,
+					  (pcount - 1) * mss, mss)))
 			goto rearm_timer;
 		skb = tcp_write_queue_tail(sk);
 	}
@@ -2535,7 +2538,8 @@  int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
 		return -EAGAIN;
 
 	if (skb->len > cur_mss) {
-		if (tcp_fragment(sk, skb, cur_mss, cur_mss))
+		if (tcp_fragment(sk, TCP_FRAG_IN_RTX_QUEUE, skb,
+				 cur_mss, cur_mss))
 			return -ENOMEM; /* We'll try again later. */
 	} else {
 		int oldpcount = tcp_skb_pcount(skb);
@@ -3368,7 +3372,8 @@  int tcp_write_wakeup(struct sock *sk)
 		    skb->len > mss) {
 			seg_size = min(seg_size, mss);
 			TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_PSH;
-			if (tcp_fragment(sk, skb, seg_size, mss))
+			if (tcp_fragment(sk, TCP_FRAG_IN_WRITE_QUEUE,
+					 skb, seg_size, mss))
 				return -1;
 		} else if (!tcp_skb_pcount(skb))
 			tcp_set_skb_tso_segs(sk, skb, mss);