The branch main has been updated by bz:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=6baea3312d92cd7eb25f5b9e0e474132636f62d9

commit 6baea3312d92cd7eb25f5b9e0e474132636f62d9
Author:     Bjoern A. Zeeb <[email protected]>
AuthorDate: 2022-02-16 02:10:10 +0000
Commit:     Bjoern A. Zeeb <[email protected]>
CommitDate: 2022-02-16 02:10:10 +0000

    LinuxKPI: skbuff updates
    
    Various updates to skbuff for new/updated drivers and some housekeeping:
    - update types and struct members, add new (stub) functions
    - improve freeing of frags.
    - fix an issue with sleeping during alloc for dev_alloc_skb().
    - Adjust a KASSERT for skb_reserve() which apparently can be called
      multiple times if no data was put into the skb yet.
    - move the sysctl from linux_8022.c (which may be in a different module)
      to linux_skbuff.c so in case we turn debugging on we do not run into
      unresolved symbols.  Rename the sysctl variable to be less conflicting
      and update debugging macros along with that; also add IMPROVE().
    - add DDB support to show an skbuff.
    - adjust comments/whitespace.
    
    No functional changes intended for iwlwifi.
    
    Sponsored by:   The FreeBSD Foundation (partially)
    MFC after:      3 days
---
 sys/compat/linuxkpi/common/include/linux/skbuff.h | 151 ++++++++++++++++++----
 sys/compat/linuxkpi/common/src/linux_80211.c      |   8 --
 sys/compat/linuxkpi/common/src/linux_skbuff.c     | 104 +++++++++++++--
 3 files changed, 220 insertions(+), 43 deletions(-)

diff --git a/sys/compat/linuxkpi/common/include/linux/skbuff.h 
b/sys/compat/linuxkpi/common/include/linux/skbuff.h
index 37fb6109c784..f5954a9c33cf 100644
--- a/sys/compat/linuxkpi/common/include/linux/skbuff.h
+++ b/sys/compat/linuxkpi/common/include/linux/skbuff.h
@@ -1,6 +1,6 @@
 /*-
- * Copyright (c) 2020-2021 The FreeBSD Foundation
- * Copyright (c) 2021 Bjoern A. Zeeb
+ * Copyright (c) 2020-2022 The FreeBSD Foundation
+ * Copyright (c) 2021-2022 Bjoern A. Zeeb
  *
  * This software was developed by Björn Zeeb under sponsorship from
  * the FreeBSD Foundation.
@@ -43,28 +43,39 @@
 #include <linux/netdev_features.h>
 #include <linux/list.h>
 #include <linux/gfp.h>
+#include <linux/compiler.h>
+#include <linux/spinlock.h>
 
 /* #define     SKB_DEBUG */
 #ifdef SKB_DEBUG
-
 #define        DSKB_TODO       0x01
-#define        DSKB_TRACE      0x02
-#define        DSKB_TRACEX     0x04
-extern int debug_skb;
-
-#define        SKB_TRACE(_s)           if (debug_skb & DSKB_TRACE)             
\
-    printf("SKB_TRACE %s:%d %p\n", __func__, __LINE__, _s)
-#define        SKB_TRACE2(_s, _p)      if (debug_skb & DSKB_TRACE)             
\
-    printf("SKB_TRACE %s:%d %p, %p\n", __func__, __LINE__, _s, _p)
-#define        SKB_TRACE_FMT(_s, _fmt, ...)    if (debug_skb & DSKB_TRACE)     
\
-    printf("SKB_TRACE %s:%d %p" _fmt "\n", __func__, __LINE__, _s, __VA_ARGS__)
-#define        SKB_TODO()              if (debug_skb & DSKB_TODO)              
\
-    printf("SKB_TODO %s:%d\n", __func__, __LINE__)
+#define        DSKB_IMPROVE    0x02
+#define        DSKB_TRACE      0x10
+#define        DSKB_TRACEX     0x20
+extern int linuxkpi_debug_skb;
+
+#define        SKB_TODO()                                                      
\
+    if (linuxkpi_debug_skb & DSKB_TODO)                                        
\
+       printf("SKB_TODO %s:%d\n", __func__, __LINE__)
+#define        SKB_IMPROVE(...)                                                
\
+    if (linuxkpi_debug_skb & DSKB_IMPROVE)                             \
+       printf("SKB_IMPROVE %s:%d\n", __func__, __LINE__)
+#define        SKB_TRACE(_s)                                                   
\
+    if (linuxkpi_debug_skb & DSKB_TRACE)                               \
+       printf("SKB_TRACE %s:%d %p\n", __func__, __LINE__, _s)
+#define        SKB_TRACE2(_s, _p)                                              
\
+    if (linuxkpi_debug_skb & DSKB_TRACE)                               \
+       printf("SKB_TRACE %s:%d %p, %p\n", __func__, __LINE__, _s, _p)
+#define        SKB_TRACE_FMT(_s, _fmt, ...)                                    
\
+   if (linuxkpi_debug_skb & DSKB_TRACE)                                        
\
+       printf("SKB_TRACE %s:%d %p " _fmt "\n", __func__, __LINE__, _s, \
+           __VA_ARGS__)
 #else
+#define        SKB_TODO()              do { } while(0)
+#define        SKB_IMPROVE(...)        do { } while(0)
 #define        SKB_TRACE(_s)           do { } while(0)
 #define        SKB_TRACE2(_s, _p)      do { } while(0)
 #define        SKB_TRACE_FMT(_s, ...)  do { } while(0)
-#define        SKB_TODO()              do { } while(0)
 #endif
 
 enum sk_buff_pkt_type {
@@ -80,7 +91,7 @@ struct sk_buff_head {
        struct sk_buff          *next;
        struct sk_buff          *prev;
        size_t                  qlen;
-       int                     lock;   /* XXX TYPE */
+       spinlock_t              lock;
 };
 
 enum sk_checksum_flags {
@@ -107,6 +118,7 @@ struct skb_shared_info {
        enum skb_shared_info_gso_type   gso_type;
        uint16_t                        gso_size;
        uint16_t                        nr_frags;
+       struct sk_buff                  *frag_list;
        skb_frag_t                      frags[64];      /* XXX TODO, 16xpage? */
 };
 
@@ -170,13 +182,24 @@ alloc_skb(size_t size, gfp_t gfp)
        return (skb);
 }
 
+static inline struct sk_buff *
+__dev_alloc_skb(size_t len, gfp_t gfp)
+{
+       struct sk_buff *skb;
+
+       skb = alloc_skb(len, gfp);
+       SKB_IMPROVE();
+       SKB_TRACE(skb);
+       return (skb);
+}
+
 static inline struct sk_buff *
 dev_alloc_skb(size_t len)
 {
        struct sk_buff *skb;
 
-       skb = alloc_skb(len, GFP_KERNEL);
-       /* XXX TODO */
+       skb = alloc_skb(len, GFP_NOWAIT);
+       SKB_IMPROVE();
        SKB_TRACE(skb);
        return (skb);
 }
@@ -220,8 +243,15 @@ static inline void
 skb_reserve(struct sk_buff *skb, size_t len)
 {
        SKB_TRACE(skb);
+#if 0
+       /* Apparently it is allowed to call skb_reserve multiple times in a 
row. */
        KASSERT(skb->data == skb->head, ("%s: skb %p not empty head %p data %p "
            "tail %p\n", __func__, skb, skb->head, skb->data, skb->tail));
+#else
+       KASSERT(skb->len == 0 && skb->data == skb->tail, ("%s: skb %p not "
+           "empty head %p data %p tail %p len %u\n", __func__, skb,
+           skb->head, skb->data, skb->tail, skb->len));
+#endif
        skb->data += len;
        skb->tail += len;
 }
@@ -302,9 +332,9 @@ skb_put(struct sk_buff *skb, size_t len)
        skb->tail += len;
        skb->len += len;
 #ifdef SKB_DEBUG
-       if (debug_skb & DSKB_TRACEX)
+       if (linuxkpi_debug_skb & DSKB_TRACEX)
        printf("%s: skb %p (%u) head %p data %p tail %p end %p, s %p len %zu\n",
-           __func__, skb,skb->len, skb->head, skb->data, skb->tail, skb->end,
+           __func__, skb, skb->len, skb->head, skb->data, skb->tail, skb->end,
            s, len);
 #endif
        return (s);
@@ -392,7 +422,7 @@ skb_add_rx_frag(struct sk_buff *skb, int fragno, struct 
page *page,
 
        SKB_TRACE(skb);
 #ifdef SKB_DEBUG
-       if (debug_skb & DSKB_TRACEX)
+       if (linuxkpi_debug_skb & DSKB_TRACEX)
        printf("%s: skb %p head %p data %p tail %p end %p len %u fragno %d "
            "page %#jx offset %ju size %zu truesize %u\n", __func__,
            skb, skb->head, skb->data, skb->tail, skb->end, skb->len, fragno,
@@ -567,6 +597,14 @@ skb_dequeue_tail(struct sk_buff_head *q)
        return (skb);
 }
 
+static inline void
+__skb_queue_head(struct sk_buff_head *q, struct sk_buff *skb)
+{
+
+       SKB_TRACE2(q, skb);
+       __skb_queue_after(q, (struct sk_buff *)q, skb);
+}
+
 static inline void
 skb_queue_head(struct sk_buff_head *q, struct sk_buff *skb)
 {
@@ -578,10 +616,19 @@ skb_queue_head(struct sk_buff_head *q, struct sk_buff 
*skb)
 static inline uint32_t
 skb_queue_len(struct sk_buff_head *head)
 {
+
        SKB_TRACE(head);
        return (head->qlen);
 }
 
+static inline uint32_t
+skb_queue_len_lockless(const struct sk_buff_head *head)
+{
+
+       SKB_TRACE(head);
+       return (READ_ONCE(head->qlen));
+}
+
 static inline void
 __skb_queue_purge(struct sk_buff_head *q)
 {
@@ -715,10 +762,26 @@ skb_mark_not_on_list(struct sk_buff *skb)
 }
 
 static inline void
-skb_queue_splice_init(struct sk_buff_head *qa, struct sk_buff_head *qb)
+skb_queue_splice_init(struct sk_buff_head *q, struct sk_buff_head *h)
 {
-       SKB_TRACE2(qa, qb);
-       SKB_TODO();
+       struct sk_buff *b, *e;
+
+       SKB_TRACE2(q, h);
+
+       if (skb_queue_empty(q))
+               return;
+
+       /* XXX do we need a barrier around this? */
+       b = q->next;
+       e = q->prev;
+
+       b->prev = (struct sk_buff *)h;
+       h->next = b;
+       e->next = h->next;
+       h->next->prev = e;
+
+       h->qlen += q->qlen;
+       __skb_queue_head_init(q);
 }
 
 static inline void
@@ -753,12 +816,12 @@ __skb_linearize(struct sk_buff *skb)
        return (ENXIO);
 }
 
-static inline bool
+static inline int
 pskb_expand_head(struct sk_buff *skb, int x, int len, gfp_t gfp)
 {
        SKB_TRACE(skb);
        SKB_TODO();
-       return (false);
+       return (-ENXIO);
 }
 
 /* Not really seen this one but need it as symmetric accessor function. */
@@ -823,4 +886,38 @@ csum_unfold(__sum16 sum)
        return (sum);
 }
 
+static inline void
+skb_reset_tail_pointer(struct sk_buff *skb)
+{
+
+       SKB_TRACE(skb);
+       skb->tail = (uint8_t *)(uintptr_t)(skb->data - skb->head);
+       SKB_TRACE(skb);
+}
+
+static inline struct sk_buff *
+skb_get(struct sk_buff *skb)
+{
+
+       SKB_TODO();     /* XXX refcnt? as in get/put_device? */
+       return (skb);
+}
+
+static inline struct sk_buff *
+skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom)
+{
+
+       SKB_TODO();
+       return (NULL);
+}
+
+static inline void
+skb_copy_from_linear_data(const struct sk_buff *skb, void *dst, size_t len)
+{
+
+       SKB_TRACE(skb);
+       /* Let us just hope the destination has len space ... */
+       memcpy(dst, skb->data, len);
+}
+
 #endif /* _LINUXKPI_LINUX_SKBUFF_H */
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c 
b/sys/compat/linuxkpi/common/src/linux_80211.c
index 8bce01c25f5b..a1010b23f76f 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -72,14 +72,6 @@ __FBSDID("$FreeBSD$");
 
 static MALLOC_DEFINE(M_LKPI80211, "lkpi80211", "Linux KPI 80211 compat");
 
-/* -------------------------------------------------------------------------- 
*/
-/* These are unrelated to 802.11 sysctl bug debugging during 802.11 work so   *
- * keep them here rather than in a more general file.                         
*/
-
-int debug_skb;
-SYSCTL_INT(_compat_linuxkpi, OID_AUTO, debug_skb, CTLFLAG_RWTUN,
-    &debug_skb, 0, "SKB debug level");
-
 /* -------------------------------------------------------------------------- 
*/
 
 int debug_80211;
diff --git a/sys/compat/linuxkpi/common/src/linux_skbuff.c 
b/sys/compat/linuxkpi/common/src/linux_skbuff.c
index e9935e65b466..0a4974d74d9d 100644
--- a/sys/compat/linuxkpi/common/src/linux_skbuff.c
+++ b/sys/compat/linuxkpi/common/src/linux_skbuff.c
@@ -1,6 +1,6 @@
 /*-
- * Copyright (c) 2020-2021 The FreeBSD Foundation
- * Copyright (c) 2021 Bjoern A. Zeeb
+ * Copyright (c) 2020-2022 The FreeBSD Foundation
+ * Copyright (c) 2021-2022 Bjoern A. Zeeb
  *
  * This software was developed by Björn Zeeb under sponsorship from
  * the FreeBSD Foundation.
@@ -38,13 +38,31 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_ddb.h"
+
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
+#include <sys/sysctl.h>
+
+#ifdef DDB
+#include <ddb/ddb.h>
+#endif
 
 #include <linux/skbuff.h>
 #include <linux/slab.h>
+#include <linux/gfp.h>
+
+#ifdef SKB_DEBUG
+SYSCTL_DECL(_compat_linuxkpi);
+SYSCTL_NODE(_compat_linuxkpi, OID_AUTO, skb, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
+    "LinuxKPI skbuff");
+
+int linuxkpi_debug_skb;
+SYSCTL_INT(_compat_linuxkpi_skb, OID_AUTO, debug, CTLFLAG_RWTUN,
+    &linuxkpi_debug_skb, 0, "SKB debug level");
+#endif
 
 static MALLOC_DEFINE(M_LKPISKB, "lkpiskb", "Linux KPI skbuff compat");
 
@@ -56,7 +74,7 @@ linuxkpi_alloc_skb(size_t size, gfp_t gfp)
 
        len = sizeof(*skb) + size + sizeof(struct skb_shared_info);
        /*
-        * Using or own type here not backing my kmalloc.
+        * Using our own type here not backing my kmalloc.
         * We assume no one calls kfree directly on the skb.
         */
        skb = malloc(len, M_LKPISKB, linux_check_m_flags(gfp) | M_ZERO);
@@ -78,7 +96,7 @@ void
 linuxkpi_kfree_skb(struct sk_buff *skb)
 {
        struct skb_shared_info *shinfo;
-       uint16_t fragno;
+       uint16_t fragno, count;
 
        SKB_TRACE(skb);
        if (skb == NULL)
@@ -103,11 +121,81 @@ linuxkpi_kfree_skb(struct sk_buff *skb)
            ("%s: skb %p m %p != NULL\n", __func__, skb, skb->m));
 
        shinfo = skb->shinfo;
-       for (fragno = 0; fragno < nitems(shinfo->frags); fragno++) {
-
-               if (shinfo->frags[fragno].page != NULL)
-                       __free_page(shinfo->frags[fragno].page);
+       for (count = fragno = 0;
+           count < shinfo->nr_frags && fragno < nitems(shinfo->frags);
+           fragno++) {
+
+               if (shinfo->frags[fragno].page != NULL) {
+                       struct page *p;
+
+                       p = shinfo->frags[fragno].page;
+                       shinfo->frags[fragno].size = 0;
+                       shinfo->frags[fragno].offset = 0;
+                       shinfo->frags[fragno].page = NULL;
+                       __free_page(p);
+                       count++;
+               }
        }
 
        free(skb, M_LKPISKB);
 }
+
+#ifdef DDB
+DB_SHOW_COMMAND(skb, db_show_skb)
+{
+       struct sk_buff *skb;
+       int i;
+
+       if (!have_addr) {
+               db_printf("usage: show skb <addr>\n");
+                       return;
+       }
+
+       skb = (struct sk_buff *)addr;
+
+       db_printf("skb %p\n", skb);
+       db_printf("\tnext %p prev %p\n", skb->next, skb->prev);
+       db_printf("\tlist %d\n", skb->list);
+       db_printf("\t_alloc_len %u len %u data_len %u truesize %u mac_len %u\n",
+           skb->_alloc_len, skb->len, skb->data_len, skb->truesize,
+           skb->mac_len);
+       db_printf("\tcsum %#06x l3hdroff %u l4hdroff %u priority %u qmap %u\n",
+           skb->csum, skb->l3hdroff, skb->l4hdroff, skb->priority, skb->qmap);
+       db_printf("\tpkt_type %d dev %p sk %p\n",
+           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("\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",
+           skb->shinfo, skb->m, skb->m_free_func);
+
+       if (skb->shinfo != NULL) {
+               struct skb_shared_info *shinfo;
+
+               shinfo = skb->shinfo;
+               db_printf("\t\tgso_type %d gso_size %u nr_frags %u\n",
+                   shinfo->gso_type, shinfo->gso_size, shinfo->nr_frags);
+               for (i = 0; i < nitems(shinfo->frags); i++) {
+                       struct skb_frag *frag;
+
+                       frag = &shinfo->frags[i];
+                       if (frag == NULL || frag->page == NULL)
+                               continue;
+                       db_printf("\t\t\tfrag %p fragno %d page %p %p "
+                           "offset %ju size %zu\n",
+                           frag, i, frag->page, linux_page_address(frag->page),
+                           (uintmax_t)frag->offset, frag->size);
+               }
+       }
+       db_printf("\tcb[] %p {", skb->cb);
+       for (i = 0; i < nitems(skb->cb); i++) {
+               db_printf("%#04x%s",
+                   skb->cb[i], (i < (nitems(skb->cb)-1)) ? ", " : "");
+       }
+       db_printf("}\n");
+
+       db_printf("\t_spareu16_0 %#06x __scratch[0] %p\n",
+           skb->_spareu16_0, skb->__scratch);
+};
+#endif

Reply via email to