netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Christian Hopps <chopps@chopps.org>
To: devel@linux-ipsec.org
Cc: Steffen Klassert <steffen.klassert@secunet.com>,
	netdev@vger.kernel.org, Christian Hopps <chopps@chopps.org>,
	Christian Hopps <chopps@labn.net>
Subject: [PATCH ipsec-next v5 10/17] xfrm: iptfs: share page fragments of inner packets
Date: Sun, 14 Jul 2024 16:22:38 -0400	[thread overview]
Message-ID: <20240714202246.1573817-11-chopps@chopps.org> (raw)
In-Reply-To: <20240714202246.1573817-1-chopps@chopps.org>

From: Christian Hopps <chopps@labn.net>

When possible rather than appending secondary (aggregated) inner packets
to the fragment list, share their page fragments with the outer IPTFS
packet. This allows for more efficient packet transmission.

Signed-off-by: Christian Hopps <chopps@labn.net>
---
 net/xfrm/xfrm_iptfs.c | 89 ++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 80 insertions(+), 9 deletions(-)

diff --git a/net/xfrm/xfrm_iptfs.c b/net/xfrm/xfrm_iptfs.c
index 82c9027b85f1..cf6fb012e12d 100644
--- a/net/xfrm/xfrm_iptfs.c
+++ b/net/xfrm/xfrm_iptfs.c
@@ -9,6 +9,7 @@
 
 #include <linux/kernel.h>
 #include <linux/icmpv6.h>
+#include <linux/skbuff_ref.h>
 #include <net/gro.h>
 #include <net/icmp.h>
 #include <net/ip6_route.h>
@@ -45,6 +46,24 @@ struct xfrm_iptfs_data {
 static u32 iptfs_get_inner_mtu(struct xfrm_state *x, int outer_mtu);
 static enum hrtimer_restart iptfs_delay_timer(struct hrtimer *me);
 
+/* ================= */
+/* SK_BUFF Functions */
+/* ================= */
+
+/**
+ * skb_head_to_frag() - initialize a skb_frag_t based on skb head data
+ * @skb: skb with the head data
+ * @frag: frag to initialize
+ */
+static void skb_head_to_frag(const struct sk_buff *skb, skb_frag_t *frag)
+{
+	struct page *page = virt_to_head_page(skb->data);
+	unsigned char *addr = (unsigned char *)page_address(page);
+
+	BUG_ON(!skb->head_frag);
+	skb_frag_fill_page_desc(frag, page, skb->data - addr, skb_headlen(skb));
+}
+
 /* ================================= */
 /* IPTFS Sending (ingress) Functions */
 /* ================================= */
@@ -264,14 +283,44 @@ static struct sk_buff **iptfs_rehome_fraglist(struct sk_buff **nextp,
 	return nextp;
 }
 
+static void iptfs_consume_frags(struct sk_buff *to, struct sk_buff *from)
+{
+	struct skb_shared_info *fromi = skb_shinfo(from);
+	struct skb_shared_info *toi = skb_shinfo(to);
+	unsigned int new_truesize;
+
+	/* If we have data in a head page, grab it */
+	if (!skb_headlen(from)) {
+		new_truesize = SKB_TRUESIZE(skb_end_offset(from));
+	} else {
+		skb_head_to_frag(from, &toi->frags[toi->nr_frags]);
+		skb_frag_ref(to, toi->nr_frags++);
+		new_truesize = SKB_DATA_ALIGN(sizeof(struct sk_buff));
+	}
+
+	/* Move any other page fragments rather than copy */
+	memcpy(&toi->frags[toi->nr_frags], fromi->frags,
+	       sizeof(fromi->frags[0]) * fromi->nr_frags);
+	toi->nr_frags += fromi->nr_frags;
+	fromi->nr_frags = 0;
+	from->data_len = 0;
+	from->len = 0;
+	to->truesize += from->truesize - new_truesize;
+	from->truesize = new_truesize;
+
+	/* We are done with this SKB */
+	consume_skb(from);
+}
+
 static void iptfs_output_queued(struct xfrm_state *x, struct sk_buff_head *list)
 {
 	struct xfrm_iptfs_data *xtfs = x->mode_data;
 	struct sk_buff *skb, *skb2, **nextp;
-	struct skb_shared_info *shi;
+	struct skb_shared_info *shi, *shi2;
 
 	while ((skb = __skb_dequeue(list))) {
 		u32 mtu = iptfs_get_cur_pmtu(x, xtfs, skb);
+		bool share_ok = true;
 		int remaining;
 
 		/* protocol comes to us cleared sometimes */
@@ -317,7 +366,7 @@ static void iptfs_output_queued(struct xfrm_state *x, struct sk_buff_head *list)
 
 		/* Re-home (un-nest) nested fragment lists. We need to do this
 		 * b/c we will simply be appending any following aggregated
-		 * inner packets to the frag list.
+		 * inner packets using the frag list.
 		 */
 		shi = skb_shinfo(skb);
 		nextp = &shi->frag_list;
@@ -329,6 +378,9 @@ static void iptfs_output_queued(struct xfrm_state *x, struct sk_buff_head *list)
 				nextp = &(*nextp)->next;
 		}
 
+		if (shi->frag_list || skb_cloned(skb) || skb_shared(skb))
+			share_ok = false;
+
 		/* See if we have enough space to simply append.
 		 *
 		 * NOTE: Maybe do not append if we will be mis-aligned,
@@ -354,18 +406,37 @@ static void iptfs_output_queued(struct xfrm_state *x, struct sk_buff_head *list)
 				}
 			}
 
+			/* skb->pp_recycle is passed to __skb_flag_unref for all
+			 * frag pages so we can only share pages with skb's who
+			 * match ourselves.
+			 */
+			shi2 = skb_shinfo(skb2);
+			if (share_ok &&
+			    (shi2->frag_list ||
+			     (!skb2->head_frag && skb_headlen(skb)) ||
+			     skb->pp_recycle != skb2->pp_recycle ||
+			     skb_zcopy(skb2) ||
+			     (shi->nr_frags + shi2->nr_frags + 1 >
+			      MAX_SKB_FRAGS)))
+				share_ok = false;
+
 			/* Do accounting */
 			skb->data_len += skb2->len;
 			skb->len += skb2->len;
 			remaining -= skb2->len;
 
-			/* Append to the frag_list */
-			*nextp = skb2;
-			nextp = &skb2->next;
-			BUG_ON(*nextp);
-			if (skb_has_frag_list(skb2))
-				nextp = iptfs_rehome_fraglist(nextp, skb2);
-			skb->truesize += skb2->truesize;
+			if (share_ok) {
+				iptfs_consume_frags(skb, skb2);
+			} else {
+				/* Append to the frag_list */
+				*nextp = skb2;
+				nextp = &skb2->next;
+				BUG_ON(*nextp);
+				if (skb_has_frag_list(skb2))
+					nextp = iptfs_rehome_fraglist(nextp,
+								      skb2);
+				skb->truesize += skb2->truesize;
+			}
 		}
 
 		xfrm_output(NULL, skb);
-- 
2.45.2


  parent reply	other threads:[~2024-07-14 20:23 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-14 20:22 [PATCH ipsec-next v5 00/17] Add IP-TFS mode to xfrm Christian Hopps
2024-07-14 20:22 ` [PATCH ipsec-next v5 01/17] xfrm: config: add CONFIG_XFRM_IPTFS Christian Hopps
2024-07-14 20:22 ` [PATCH ipsec-next v5 02/17] include: uapi: add ip_tfs_*_hdr packet formats Christian Hopps
2024-07-14 20:22 ` [PATCH ipsec-next v5 03/17] include: uapi: add IPPROTO_AGGFRAG for AGGFRAG in ESP Christian Hopps
2024-07-14 20:22 ` [PATCH ipsec-next v5 04/17] xfrm: sysctl: allow configuration of global default values Christian Hopps
2024-07-18 13:13   ` Sabrina Dubroca
2024-07-18 13:15     ` Christian Hopps
2024-07-14 20:22 ` [PATCH ipsec-next v5 05/17] xfrm: netlink: add config (netlink) options Christian Hopps
2024-07-18 13:45   ` Sabrina Dubroca
2024-07-18 14:08     ` [devel-ipsec] " Christian Hopps
2024-07-14 20:22 ` [PATCH ipsec-next v5 06/17] xfrm: add mode_cbs module functionality Christian Hopps
2024-07-19  6:14   ` [devel-ipsec] " Florian Westphal
2024-07-20  0:06     ` Christian Hopps
2024-07-25 13:32   ` Sabrina Dubroca
2024-07-30 21:29     ` Christian Hopps
2024-07-31 17:10       ` Sabrina Dubroca
2024-07-31 18:32         ` Christian Hopps
2024-07-31 18:41           ` Christian Hopps
2024-07-14 20:22 ` [PATCH ipsec-next v5 07/17] xfrm: add generic iptfs defines and functionality Christian Hopps
2024-07-14 20:22 ` [PATCH ipsec-next v5 08/17] xfrm: iptfs: add new iptfs xfrm mode impl Christian Hopps
2024-07-15 12:39   ` Simon Horman
2024-07-18  5:56     ` [devel-ipsec] " Christian Hopps
2024-07-19  6:16   ` Florian Westphal
2024-07-20  0:30     ` Christian Hopps
2024-07-25 13:33   ` Sabrina Dubroca
2024-07-25 14:56     ` Christian Hopps
2024-07-31 16:29     ` Christian Hopps
2024-07-14 20:22 ` [PATCH ipsec-next v5 09/17] xfrm: iptfs: add user packet (tunnel ingress) handling Christian Hopps
2024-07-15 12:55   ` Simon Horman
2024-07-18  5:35     ` [devel-ipsec] " Christian Hopps
2024-07-18  6:32       ` Christian Hopps
2024-07-16 14:00   ` kernel test robot
2024-07-14 20:22 ` Christian Hopps [this message]
2024-07-14 20:22 ` [PATCH ipsec-next v5 11/17] xfrm: iptfs: add fragmenting of larger than MTU user packets Christian Hopps
2024-07-15 13:12   ` Simon Horman
2024-07-18  5:57     ` [devel-ipsec] " Christian Hopps
2024-07-18  6:56       ` Christian Hopps
2024-07-14 20:22 ` [PATCH ipsec-next v5 12/17] xfrm: iptfs: add basic receive packet (tunnel egress) handling Christian Hopps
2024-07-15 13:16   ` Simon Horman
2024-07-18  6:14     ` [devel-ipsec] " Christian Hopps
2024-07-14 20:22 ` [PATCH ipsec-next v5 13/17] xfrm: iptfs: handle received fragmented inner packets Christian Hopps
2024-07-14 20:22 ` [PATCH ipsec-next v5 14/17] xfrm: iptfs: add reusing received skb for the tunnel egress packet Christian Hopps
2024-07-14 20:22 ` [PATCH ipsec-next v5 15/17] xfrm: iptfs: add skb-fragment sharing code Christian Hopps
2024-07-14 20:22 ` [PATCH ipsec-next v5 16/17] xfrm: iptfs: handle reordering of received packets Christian Hopps
2024-07-14 20:22 ` [PATCH ipsec-next v5 17/17] xfrm: iptfs: add tracepoint functionality Christian Hopps
2024-07-15 11:53   ` kernel test robot
2024-07-17  5:21   ` kernel test robot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240714202246.1573817-11-chopps@chopps.org \
    --to=chopps@chopps.org \
    --cc=chopps@labn.net \
    --cc=devel@linux-ipsec.org \
    --cc=netdev@vger.kernel.org \
    --cc=steffen.klassert@secunet.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).