git: 07adc4446abc - stable/13 - LinuxKPI: SKB update

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Wed, 18 Jan 2023 16:24:41 UTC
The branch stable/13 has been updated by bz:

URL: https://cgit.FreeBSD.org/src/commit/?id=07adc4446abcd49e678a01fe1e9c6f732e420982

commit 07adc4446abcd49e678a01fe1e9c6f732e420982
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2022-11-28 20:54:57 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2023-01-18 13:23:37 +0000

    LinuxKPI: SKB update
    
    - skb_reset_tail_pointer(): we do not do offsets so do a plain reset
    - skb_add_rx_frag(): adjust data_len to keep track of the frag
    - based on that implement skb_is_nonlinear() and skb_linearize()
    - implement build_skb() and adjust linuxkpi_kfree_skb() and ddb macro.
    
    Sponsored by:   The FreeBSD Foundation (partially)
    
    (cherry picked from commit 5504bd59a39ba0bd0014308ff1aa5d4899432a3e)
---
 sys/compat/linuxkpi/common/include/linux/skbuff.h | 56 +++++++++++++----------
 sys/compat/linuxkpi/common/src/linux_skbuff.c     | 33 ++++++++++++-
 2 files changed, 62 insertions(+), 27 deletions(-)

diff --git a/sys/compat/linuxkpi/common/include/linux/skbuff.h b/sys/compat/linuxkpi/common/include/linux/skbuff.h
index d3a795344f86..b54f5a91769f 100644
--- a/sys/compat/linuxkpi/common/include/linux/skbuff.h
+++ b/sys/compat/linuxkpi/common/include/linux/skbuff.h
@@ -143,7 +143,8 @@ struct sk_buff {
 	uint16_t		l4hdroff;	/* transport header offset from *head */
 	uint32_t		priority;
 	uint16_t		qmap;		/* queue mapping */
-	uint16_t		_spareu16_0;
+	uint16_t		_flags;		/* Internal flags. */
+#define	_SKB_FLAGS_SKBEXTFRAG	0x0001
 	enum sk_buff_pkt_type	pkt_type;
 
 	/* "Scratch" area for layers to store metadata. */
@@ -174,6 +175,7 @@ struct sk_buff {
 
 struct sk_buff *linuxkpi_alloc_skb(size_t, gfp_t);
 struct sk_buff *linuxkpi_dev_alloc_skb(size_t, gfp_t);
+struct sk_buff *linuxkpi_build_skb(void *, size_t);
 void linuxkpi_kfree_skb(struct sk_buff *);
 
 struct sk_buff *linuxkpi_skb_copy(struct sk_buff *, gfp_t);
@@ -241,6 +243,16 @@ dev_kfree_skb_irq(struct sk_buff *skb)
 	dev_kfree_skb(skb);
 }
 
+static inline struct sk_buff *
+build_skb(void *data, unsigned int fragsz)
+{
+	struct sk_buff *skb;
+
+	skb = linuxkpi_build_skb(data, fragsz);
+	SKB_TRACE(skb);
+	return (skb);
+}
+
 /* -------------------------------------------------------------------------- */
 
 /* XXX BZ review this one for terminal condition as Linux "queues" are special. */
@@ -467,6 +479,7 @@ skb_add_rx_frag(struct sk_buff *skb, int fragno, struct page *page,
 	shinfo->frags[fragno].size = size;
 	shinfo->nr_frags = fragno + 1;
         skb->len += size;
+	skb->data_len += size;
         skb->truesize += truesize;
 
 	/* XXX TODO EXTEND truesize? */
@@ -736,13 +749,6 @@ skb_frag_size(const skb_frag_t *frag)
 	return (-1);
 }
 
-static inline bool
-skb_is_nonlinear(struct sk_buff *skb)
-{
-	SKB_TRACE(skb);
-	return ((skb->data_len > 0) ? true : false);
-}
-
 #define	skb_walk_frags(_skb, _frag)					\
 	for ((_frag) = (_skb); false; (_frag)++)
 
@@ -847,6 +853,13 @@ skb_network_header(struct sk_buff *skb)
         return (skb->head + skb->l3hdroff);
 }
 
+static inline bool
+skb_is_nonlinear(struct sk_buff *skb)
+{
+	SKB_TRACE(skb);
+	return ((skb->data_len > 0) ? true : false);
+}
+
 static inline int
 __skb_linearize(struct sk_buff *skb)
 {
@@ -855,6 +868,13 @@ __skb_linearize(struct sk_buff *skb)
 	return (ENXIO);
 }
 
+static inline int
+skb_linearize(struct sk_buff *skb)
+{
+
+	return (skb_is_nonlinear(skb) ? __skb_linearize(skb) : 0);
+}
+
 static inline int
 pskb_expand_head(struct sk_buff *skb, int x, int len, gfp_t gfp)
 {
@@ -936,7 +956,10 @@ skb_reset_tail_pointer(struct sk_buff *skb)
 {
 
 	SKB_TRACE(skb);
+#ifdef SKB_DOING_OFFSETS_US_NOT
 	skb->tail = (uint8_t *)(uintptr_t)(skb->data - skb->head);
+#endif
+	skb->tail = skb->data;
 	SKB_TRACE(skb);
 }
 
@@ -965,14 +988,6 @@ skb_copy_from_linear_data(const struct sk_buff *skb, void *dst, size_t len)
 	memcpy(dst, skb->data, len);
 }
 
-static inline struct sk_buff *
-build_skb(void *data, unsigned int fragsz)
-{
-
-	SKB_TODO();
-	return (NULL);
-}
-
 static inline int
 skb_pad(struct sk_buff *skb, int pad)
 {
@@ -998,15 +1013,6 @@ napi_consume_skb(struct sk_buff *skb, int budget)
 	SKB_TODO();
 }
 
-static inline bool
-skb_linearize(struct sk_buff *skb)
-{
-
-	SKB_TRACE(skb);
-	SKB_TODO();
-	return (false);
-}
-
 #define	SKB_WITH_OVERHEAD(_s)						\
 	(_s) - ALIGN(sizeof(struct skb_shared_info), CACHE_LINE_SIZE)
 
diff --git a/sys/compat/linuxkpi/common/src/linux_skbuff.c b/sys/compat/linuxkpi/common/src/linux_skbuff.c
index df8e3fda8d56..c23a59b3c536 100644
--- a/sys/compat/linuxkpi/common/src/linux_skbuff.c
+++ b/sys/compat/linuxkpi/common/src/linux_skbuff.c
@@ -150,6 +150,28 @@ linuxkpi_dev_alloc_skb(size_t size, gfp_t gfp)
 	return (skb);
 }
 
+struct sk_buff *
+linuxkpi_build_skb(void *data, size_t fragsz)
+{
+	struct sk_buff *skb;
+
+	if (data == NULL || fragsz == 0)
+		return (NULL);
+
+	/* Just allocate a skb without data area. */
+	skb = linuxkpi_alloc_skb(0, GFP_KERNEL);
+	if (skb == NULL)
+		return (NULL);
+
+	skb->_flags |= _SKB_FLAGS_SKBEXTFRAG;
+	skb->truesize = fragsz;
+	skb->head = skb->data = data;
+	skb_reset_tail_pointer(skb);	/* XXX is that correct? */
+	skb->end = (void *)((uintptr_t)skb->head + fragsz);
+
+	return (skb);
+}
+
 struct sk_buff *
 linuxkpi_skb_copy(struct sk_buff *skb, gfp_t gfp)
 {
@@ -233,6 +255,13 @@ linuxkpi_kfree_skb(struct sk_buff *skb)
 		}
 	}
 
+	if ((skb->_flags & _SKB_FLAGS_SKBEXTFRAG) != 0) {
+		void *p;
+
+		p = skb->head;
+		skb_free_frag(p);
+	}
+
 #ifdef __LP64__
 	if (__predict_true(linuxkpi_skb_memlimit == 0))
 		free(skb, M_LKPISKB);
@@ -268,6 +297,7 @@ DB_SHOW_COMMAND(skb, db_show_skb)
 	    skb->pkt_type, skb->dev, skb->sk);
 	db_printf("\tcsum_offset %d csum_start %d ip_summed %d protocol %d\n",
 	    skb->csum_offset, skb->csum_start, skb->ip_summed, skb->protocol);
+	db_printf("\t_flags %#06x\n", skb->_flags);		/* XXX-BZ print names? */
 	db_printf("\thead %p data %p tail %p end %p\n",
 	    skb->head, skb->data, skb->tail, skb->end);
 	db_printf("\tshinfo %p m %p m_free_func %p\n",
@@ -298,7 +328,6 @@ DB_SHOW_COMMAND(skb, db_show_skb)
 	}
 	db_printf("}\n");
 
-	db_printf("\t_spareu16_0 %#06x __scratch[0] %p\n",
-	    skb->_spareu16_0, skb->__scratch);
+	db_printf("\t__scratch[0] %p\n", skb->__scratch);
 };
 #endif