netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next] skbuff: increase verbosity when dumping skb data
@ 2019-07-02 19:39 Willem de Bruijn
  2019-07-03  3:28 ` Yunsheng Lin
  0 siblings, 1 reply; 3+ messages in thread
From: Willem de Bruijn @ 2019-07-02 19:39 UTC (permalink / raw)
  To: netdev
  Cc: davem, xiyou.wangcong, herbert, eric.dumazet, saeedm, Willem de Bruijn

From: Willem de Bruijn <willemb@google.com>

skb_warn_bad_offload and netdev_rx_csum_fault trigger on hard to debug
issues. Dump more state and the header.

Optionally dump the entire packet and linear segment. This is required
to debug checksum bugs that may include bytes past skb_tail_pointer().

Both call sites call this function inside a net_ratelimit() block.
Limit full packet log further to a hard limit of can_dump_full (5).

Based on an earlier patch by Cong Wang, see link below.

Link: https://patchwork.ozlabs.org/patch/1000841/
Signed-off-by: Willem de Bruijn <willemb@google.com>
---
 include/linux/skbuff.h |   1 +
 net/core/dev.c         |  16 ++-----
 net/core/skbuff.c      | 103 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 108 insertions(+), 12 deletions(-)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index b5d427b149c92..48b08549a8b78 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1024,6 +1024,7 @@ static inline bool skb_unref(struct sk_buff *skb)
 void skb_release_head_state(struct sk_buff *skb);
 void kfree_skb(struct sk_buff *skb);
 void kfree_skb_list(struct sk_buff *segs);
+void skb_dump(const char *level, const struct sk_buff *skb, bool full_pkt);
 void skb_tx_error(struct sk_buff *skb);
 void consume_skb(struct sk_buff *skb);
 void __consume_stateless_skb(struct sk_buff *skb);
diff --git a/net/core/dev.c b/net/core/dev.c
index 58529318b3a94..fc676b2610e3c 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2900,12 +2900,10 @@ static void skb_warn_bad_offload(const struct sk_buff *skb)
 		else
 			name = netdev_name(dev);
 	}
-	WARN(1, "%s: caps=(%pNF, %pNF) len=%d data_len=%d gso_size=%d "
-	     "gso_type=%d ip_summed=%d\n",
+	skb_dump(KERN_WARNING, skb, false);
+	WARN(1, "%s: caps=(%pNF, %pNF)\n",
 	     name, dev ? &dev->features : &null_features,
-	     skb->sk ? &skb->sk->sk_route_caps : &null_features,
-	     skb->len, skb->data_len, skb_shinfo(skb)->gso_size,
-	     skb_shinfo(skb)->gso_type, skb->ip_summed);
+	     skb->sk ? &skb->sk->sk_route_caps : &null_features);
 }
 
 /*
@@ -3124,13 +3122,7 @@ void netdev_rx_csum_fault(struct net_device *dev, struct sk_buff *skb)
 {
 	if (net_ratelimit()) {
 		pr_err("%s: hw csum failure\n", dev ? dev->name : "<unknown>");
-		if (dev)
-			pr_err("dev features: %pNF\n", &dev->features);
-		pr_err("skb len=%u data_len=%u pkt_type=%u gso_size=%u gso_type=%u nr_frags=%u ip_summed=%u csum=%x csum_complete_sw=%d csum_valid=%d csum_level=%u\n",
-		       skb->len, skb->data_len, skb->pkt_type,
-		       skb_shinfo(skb)->gso_size, skb_shinfo(skb)->gso_type,
-		       skb_shinfo(skb)->nr_frags, skb->ip_summed, skb->csum,
-		       skb->csum_complete_sw, skb->csum_valid, skb->csum_level);
+		skb_dump(KERN_ERR, skb, true);
 		dump_stack();
 	}
 }
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 5323441a12ccf..5d501066d00ca 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -707,6 +707,109 @@ void kfree_skb_list(struct sk_buff *segs)
 }
 EXPORT_SYMBOL(kfree_skb_list);
 
+/* Dump skb information and contents.
+ *
+ * Must only be called from net_ratelimit()-ed paths.
+ *
+ * Dumps up to can_dump_full whole packets if full_pkt, headers otherwise.
+ */
+void skb_dump(const char *level, const struct sk_buff *skb, bool full_pkt)
+{
+	static atomic_t can_dump_full = ATOMIC_INIT(5);
+	struct skb_shared_info *sh = skb_shinfo(skb);
+	struct net_device *dev = skb->dev;
+	struct sock *sk = skb->sk;
+	struct sk_buff *list_skb;
+	bool has_mac, has_trans;
+	int headroom, tailroom;
+	int i, len, seg_len;
+
+	if (full_pkt)
+		full_pkt = atomic_dec_if_positive(&can_dump_full) >= 0;
+
+	if (full_pkt)
+		len = skb->len;
+	else
+		len = min_t(int, skb->len, MAX_HEADER + 128);
+
+	headroom = skb_headroom(skb);
+	tailroom = skb_tailroom(skb);
+
+	has_mac = skb_mac_header_was_set(skb);
+	has_trans = skb_transport_header_was_set(skb);
+
+	printk("%sskb len=%u headroom=%u headlen=%u tailroom=%u\n"
+	       "mac=(%d,%d) net=(%d,%d) trans=%d\n"
+	       "shinfo(txflags=%u nr_frags=%u gso(size=%hu type=%u segs=%hu))\n"
+	       "csum(0x%x ip_summed=%u complete_sw=%u valid=%u level=%u)\n"
+	       "hash(0x%x sw=%u l4=%u) proto=0x%04x pkttype=%u iif=%d\n",
+	       level, skb->len, headroom, skb_headlen(skb), tailroom,
+	       has_mac ? skb->mac_header : -1,
+	       has_mac ? skb_mac_header_len(skb) : -1,
+	       skb->network_header,
+	       has_trans ? skb_network_header_len(skb) : -1,
+	       has_trans ? skb->transport_header : -1,
+	       sh->tx_flags, sh->nr_frags,
+	       sh->gso_size, sh->gso_type, sh->gso_segs,
+	       skb->csum, skb->ip_summed, skb->csum_complete_sw,
+	       skb->csum_valid, skb->csum_level,
+	       skb->hash, skb->sw_hash, skb->l4_hash,
+	       ntohs(skb->protocol), skb->pkt_type, skb->skb_iif);
+
+	if (dev)
+		printk("%sdev name=%s feat=0x%pNF\n",
+		       level, dev->name, &dev->features);
+	if (sk)
+		printk("%ssk family=%hu type=%hu proto=%hu\n",
+		       level, sk->sk_family, sk->sk_type, sk->sk_protocol);
+
+	if (full_pkt && headroom)
+		print_hex_dump(level, "skb headroom: ", DUMP_PREFIX_OFFSET,
+			       16, 1, skb->head, headroom, false);
+
+	seg_len = min_t(int, skb_headlen(skb), len);
+	if (seg_len)
+		print_hex_dump(level, "skb linear:   ", DUMP_PREFIX_OFFSET,
+			       16, 1, skb->data, seg_len, false);
+	len -= seg_len;
+
+	if (full_pkt && tailroom)
+		print_hex_dump(level, "skb tailroom: ", DUMP_PREFIX_OFFSET,
+			       16, 1, skb_tail_pointer(skb), tailroom, false);
+
+	for (i = 0; len && i < skb_shinfo(skb)->nr_frags; i++) {
+		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+		u32 p_off, p_len, copied;
+		struct page *p;
+		u8 *vaddr;
+
+		skb_frag_foreach_page(frag, frag->page_offset,
+				      skb_frag_size(frag), p, p_off, p_len,
+				      copied) {
+			seg_len = min_t(int, p_len, len);
+			vaddr = kmap_atomic(p);
+			print_hex_dump(level, "skb frag:     ",
+				       DUMP_PREFIX_OFFSET,
+				       16, 1, vaddr + p_off, seg_len, false);
+			kunmap_atomic(vaddr);
+			len -= seg_len;
+			if (!len)
+				break;
+		}
+	}
+
+	if (len && skb_has_frag_list(skb)) {
+		printk("skb fraglist:\n");
+		skb_walk_frags(skb, list_skb) {
+			if (len <= 0)
+				break;
+			skb_dump(level, list_skb, len);
+			len -= list_skb->len;
+		}
+	}
+}
+EXPORT_SYMBOL(skb_dump);
+
 /**
  *	skb_tx_error - report an sk_buff xmit error
  *	@skb: buffer that triggered an error
-- 
2.22.0.410.gd8fdbe21b5-goog


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH net-next] skbuff: increase verbosity when dumping skb data
  2019-07-02 19:39 [PATCH net-next] skbuff: increase verbosity when dumping skb data Willem de Bruijn
@ 2019-07-03  3:28 ` Yunsheng Lin
  2019-07-03 14:55   ` Willem de Bruijn
  0 siblings, 1 reply; 3+ messages in thread
From: Yunsheng Lin @ 2019-07-03  3:28 UTC (permalink / raw)
  To: Willem de Bruijn, netdev
  Cc: davem, xiyou.wangcong, herbert, eric.dumazet, saeedm, Willem de Bruijn

On 2019/7/3 3:39, Willem de Bruijn wrote:
> From: Willem de Bruijn <willemb@google.com>
> 
> skb_warn_bad_offload and netdev_rx_csum_fault trigger on hard to debug
> issues. Dump more state and the header.
> 
> Optionally dump the entire packet and linear segment. This is required
> to debug checksum bugs that may include bytes past skb_tail_pointer().
> 
> Both call sites call this function inside a net_ratelimit() block.
> Limit full packet log further to a hard limit of can_dump_full (5).
> 
> Based on an earlier patch by Cong Wang, see link below.
> 
> Link: https://patchwork.ozlabs.org/patch/1000841/
> Signed-off-by: Willem de Bruijn <willemb@google.com>
> ---
>  include/linux/skbuff.h |   1 +
>  net/core/dev.c         |  16 ++-----
>  net/core/skbuff.c      | 103 +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 108 insertions(+), 12 deletions(-)
> 
> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> index b5d427b149c92..48b08549a8b78 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -1024,6 +1024,7 @@ static inline bool skb_unref(struct sk_buff *skb)
>  void skb_release_head_state(struct sk_buff *skb);
>  void kfree_skb(struct sk_buff *skb);
>  void kfree_skb_list(struct sk_buff *segs);
> +void skb_dump(const char *level, const struct sk_buff *skb, bool full_pkt);
>  void skb_tx_error(struct sk_buff *skb);
>  void consume_skb(struct sk_buff *skb);
>  void __consume_stateless_skb(struct sk_buff *skb);
> diff --git a/net/core/dev.c b/net/core/dev.c
> index 58529318b3a94..fc676b2610e3c 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -2900,12 +2900,10 @@ static void skb_warn_bad_offload(const struct sk_buff *skb)
>  		else
>  			name = netdev_name(dev);
>  	}
> -	WARN(1, "%s: caps=(%pNF, %pNF) len=%d data_len=%d gso_size=%d "
> -	     "gso_type=%d ip_summed=%d\n",
> +	skb_dump(KERN_WARNING, skb, false);
> +	WARN(1, "%s: caps=(%pNF, %pNF)\n",
>  	     name, dev ? &dev->features : &null_features,
> -	     skb->sk ? &skb->sk->sk_route_caps : &null_features,
> -	     skb->len, skb->data_len, skb_shinfo(skb)->gso_size,
> -	     skb_shinfo(skb)->gso_type, skb->ip_summed);
> +	     skb->sk ? &skb->sk->sk_route_caps : &null_features);
>  }
>  
>  /*
> @@ -3124,13 +3122,7 @@ void netdev_rx_csum_fault(struct net_device *dev, struct sk_buff *skb)
>  {
>  	if (net_ratelimit()) {
>  		pr_err("%s: hw csum failure\n", dev ? dev->name : "<unknown>");
> -		if (dev)
> -			pr_err("dev features: %pNF\n", &dev->features);
> -		pr_err("skb len=%u data_len=%u pkt_type=%u gso_size=%u gso_type=%u nr_frags=%u ip_summed=%u csum=%x csum_complete_sw=%d csum_valid=%d csum_level=%u\n",
> -		       skb->len, skb->data_len, skb->pkt_type,
> -		       skb_shinfo(skb)->gso_size, skb_shinfo(skb)->gso_type,
> -		       skb_shinfo(skb)->nr_frags, skb->ip_summed, skb->csum,
> -		       skb->csum_complete_sw, skb->csum_valid, skb->csum_level);
> +		skb_dump(KERN_ERR, skb, true);
>  		dump_stack();
>  	}
>  }
> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
> index 5323441a12ccf..5d501066d00ca 100644
> --- a/net/core/skbuff.c
> +++ b/net/core/skbuff.c
> @@ -707,6 +707,109 @@ void kfree_skb_list(struct sk_buff *segs)
>  }
>  EXPORT_SYMBOL(kfree_skb_list);
>  
> +/* Dump skb information and contents.
> + *
> + * Must only be called from net_ratelimit()-ed paths.
> + *
> + * Dumps up to can_dump_full whole packets if full_pkt, headers otherwise.
> + */
> +void skb_dump(const char *level, const struct sk_buff *skb, bool full_pkt)
> +{
> +	static atomic_t can_dump_full = ATOMIC_INIT(5);
> +	struct skb_shared_info *sh = skb_shinfo(skb);
> +	struct net_device *dev = skb->dev;
> +	struct sock *sk = skb->sk;
> +	struct sk_buff *list_skb;
> +	bool has_mac, has_trans;
> +	int headroom, tailroom;
> +	int i, len, seg_len;
> +
> +	if (full_pkt)
> +		full_pkt = atomic_dec_if_positive(&can_dump_full) >= 0;
> +
> +	if (full_pkt)
> +		len = skb->len;

Minor question:
Here we set the len to skb->len if full_pkt is true when skb_dump is
called with frag_list skb and full_pkt being true below, which may
cause some problem?

Maybe change the definition to:
void skb_dump(const char *level, const struct sk_buff *skb, int len, bool full_pkt)


skb_dump(KERN_ERR, skb, skb->len, true);

> +	else
> +		len = min_t(int, skb->len, MAX_HEADER + 128);
> +
> +	headroom = skb_headroom(skb);
> +	tailroom = skb_tailroom(skb);
> +
> +	has_mac = skb_mac_header_was_set(skb);
> +	has_trans = skb_transport_header_was_set(skb);
> +
> +	printk("%sskb len=%u headroom=%u headlen=%u tailroom=%u\n"
> +	       "mac=(%d,%d) net=(%d,%d) trans=%d\n"
> +	       "shinfo(txflags=%u nr_frags=%u gso(size=%hu type=%u segs=%hu))\n"
> +	       "csum(0x%x ip_summed=%u complete_sw=%u valid=%u level=%u)\n"
> +	       "hash(0x%x sw=%u l4=%u) proto=0x%04x pkttype=%u iif=%d\n",
> +	       level, skb->len, headroom, skb_headlen(skb), tailroom,
> +	       has_mac ? skb->mac_header : -1,
> +	       has_mac ? skb_mac_header_len(skb) : -1,
> +	       skb->network_header,
> +	       has_trans ? skb_network_header_len(skb) : -1,
> +	       has_trans ? skb->transport_header : -1,
> +	       sh->tx_flags, sh->nr_frags,
> +	       sh->gso_size, sh->gso_type, sh->gso_segs,
> +	       skb->csum, skb->ip_summed, skb->csum_complete_sw,
> +	       skb->csum_valid, skb->csum_level,
> +	       skb->hash, skb->sw_hash, skb->l4_hash,
> +	       ntohs(skb->protocol), skb->pkt_type, skb->skb_iif);
> +
> +	if (dev)
> +		printk("%sdev name=%s feat=0x%pNF\n",
> +		       level, dev->name, &dev->features);
> +	if (sk)
> +		printk("%ssk family=%hu type=%hu proto=%hu\n",
> +		       level, sk->sk_family, sk->sk_type, sk->sk_protocol);
> +
> +	if (full_pkt && headroom)
> +		print_hex_dump(level, "skb headroom: ", DUMP_PREFIX_OFFSET,
> +			       16, 1, skb->head, headroom, false);
> +
> +	seg_len = min_t(int, skb_headlen(skb), len);
> +	if (seg_len)
> +		print_hex_dump(level, "skb linear:   ", DUMP_PREFIX_OFFSET,
> +			       16, 1, skb->data, seg_len, false);
> +	len -= seg_len;
> +
> +	if (full_pkt && tailroom)
> +		print_hex_dump(level, "skb tailroom: ", DUMP_PREFIX_OFFSET,
> +			       16, 1, skb_tail_pointer(skb), tailroom, false);
> +
> +	for (i = 0; len && i < skb_shinfo(skb)->nr_frags; i++) {
> +		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
> +		u32 p_off, p_len, copied;
> +		struct page *p;
> +		u8 *vaddr;
> +
> +		skb_frag_foreach_page(frag, frag->page_offset,
> +				      skb_frag_size(frag), p, p_off, p_len,
> +				      copied) {
> +			seg_len = min_t(int, p_len, len);
> +			vaddr = kmap_atomic(p);
> +			print_hex_dump(level, "skb frag:     ",
> +				       DUMP_PREFIX_OFFSET,
> +				       16, 1, vaddr + p_off, seg_len, false);
> +			kunmap_atomic(vaddr);
> +			len -= seg_len;
> +			if (!len)
> +				break;
> +		}
> +	}
> +
> +	if (len && skb_has_frag_list(skb)) {
> +		printk("skb fraglist:\n");
> +		skb_walk_frags(skb, list_skb) {
> +			if (len <= 0)
> +				break;
> +			skb_dump(level, list_skb, len);

Here we call skb_dump passing len as full_pkt.

Maybe call it with skb_dump(level, list_skb, len, full_pkt);

> +			len -= list_skb->len;
> +		}
> +	}
> +}
> +EXPORT_SYMBOL(skb_dump);
> +
>  /**
>   *	skb_tx_error - report an sk_buff xmit error
>   *	@skb: buffer that triggered an error
> 


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH net-next] skbuff: increase verbosity when dumping skb data
  2019-07-03  3:28 ` Yunsheng Lin
@ 2019-07-03 14:55   ` Willem de Bruijn
  0 siblings, 0 replies; 3+ messages in thread
From: Willem de Bruijn @ 2019-07-03 14:55 UTC (permalink / raw)
  To: Yunsheng Lin
  Cc: Network Development, David Miller, Cong Wang, Herbert Xu,
	Eric Dumazet, Saeed Mahameed, Willem de Bruijn

On Tue, Jul 2, 2019 at 11:28 PM Yunsheng Lin <linyunsheng@huawei.com> wrote:
>
> On 2019/7/3 3:39, Willem de Bruijn wrote:
> > From: Willem de Bruijn <willemb@google.com>
> >
> > skb_warn_bad_offload and netdev_rx_csum_fault trigger on hard to debug
> > issues. Dump more state and the header.
> >
> > Optionally dump the entire packet and linear segment. This is required
> > to debug checksum bugs that may include bytes past skb_tail_pointer().
> >
> > Both call sites call this function inside a net_ratelimit() block.
> > Limit full packet log further to a hard limit of can_dump_full (5).
> >
> > Based on an earlier patch by Cong Wang, see link below.
> >
> > Link: https://patchwork.ozlabs.org/patch/1000841/
> > Signed-off-by: Willem de Bruijn <willemb@google.com>
> > ---

> > +void skb_dump(const char *level, const struct sk_buff *skb, bool full_pkt)
> > +{
> > +     static atomic_t can_dump_full = ATOMIC_INIT(5);
> > +     struct skb_shared_info *sh = skb_shinfo(skb);
> > +     struct net_device *dev = skb->dev;
> > +     struct sock *sk = skb->sk;
> > +     struct sk_buff *list_skb;
> > +     bool has_mac, has_trans;
> > +     int headroom, tailroom;
> > +     int i, len, seg_len;
> > +
> > +     if (full_pkt)
> > +             full_pkt = atomic_dec_if_positive(&can_dump_full) >= 0;
> > +
> > +     if (full_pkt)
> > +             len = skb->len;
>
> Minor question:
> Here we set the len to skb->len if full_pkt is true when skb_dump is
> called with frag_list skb and full_pkt being true below, which may
> cause some problem?

Good catch, thanks!

That recursive call to skb_dump on the frag_list below was not updated
from a previous revision that passed an explicit length.

> Maybe change the definition to:
> void skb_dump(const char *level, const struct sk_buff *skb, int len, bool full_pkt)

Indeed. It is less important when full_pkt, as then the entire
frag_list will be printed.

But if len is truncated, but somehow len != 0 when reaching the
frag_list, it might overshoot the limit. Will fix for v2.

> skb_dump(KERN_ERR, skb, skb->len, true);
>
> > +     else
> > +             len = min_t(int, skb->len, MAX_HEADER + 128);
> > +
> > +     headroom = skb_headroom(skb);
> > +     tailroom = skb_tailroom(skb);
> > +
> > +     has_mac = skb_mac_header_was_set(skb);
> > +     has_trans = skb_transport_header_was_set(skb);
> > +
> > +     printk("%sskb len=%u headroom=%u headlen=%u tailroom=%u\n"
> > +            "mac=(%d,%d) net=(%d,%d) trans=%d\n"
> > +            "shinfo(txflags=%u nr_frags=%u gso(size=%hu type=%u segs=%hu))\n"
> > +            "csum(0x%x ip_summed=%u complete_sw=%u valid=%u level=%u)\n"
> > +            "hash(0x%x sw=%u l4=%u) proto=0x%04x pkttype=%u iif=%d\n",
> > +            level, skb->len, headroom, skb_headlen(skb), tailroom,
> > +            has_mac ? skb->mac_header : -1,
> > +            has_mac ? skb_mac_header_len(skb) : -1,
> > +            skb->network_header,
> > +            has_trans ? skb_network_header_len(skb) : -1,
> > +            has_trans ? skb->transport_header : -1,
> > +            sh->tx_flags, sh->nr_frags,
> > +            sh->gso_size, sh->gso_type, sh->gso_segs,
> > +            skb->csum, skb->ip_summed, skb->csum_complete_sw,
> > +            skb->csum_valid, skb->csum_level,
> > +            skb->hash, skb->sw_hash, skb->l4_hash,
> > +            ntohs(skb->protocol), skb->pkt_type, skb->skb_iif);
> > +
> > +     if (dev)
> > +             printk("%sdev name=%s feat=0x%pNF\n",
> > +                    level, dev->name, &dev->features);
> > +     if (sk)
> > +             printk("%ssk family=%hu type=%hu proto=%hu\n",
> > +                    level, sk->sk_family, sk->sk_type, sk->sk_protocol);
> > +
> > +     if (full_pkt && headroom)
> > +             print_hex_dump(level, "skb headroom: ", DUMP_PREFIX_OFFSET,
> > +                            16, 1, skb->head, headroom, false);
> > +
> > +     seg_len = min_t(int, skb_headlen(skb), len);
> > +     if (seg_len)
> > +             print_hex_dump(level, "skb linear:   ", DUMP_PREFIX_OFFSET,
> > +                            16, 1, skb->data, seg_len, false);
> > +     len -= seg_len;
> > +
> > +     if (full_pkt && tailroom)
> > +             print_hex_dump(level, "skb tailroom: ", DUMP_PREFIX_OFFSET,
> > +                            16, 1, skb_tail_pointer(skb), tailroom, false);
> > +
> > +     for (i = 0; len && i < skb_shinfo(skb)->nr_frags; i++) {
> > +             skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
> > +             u32 p_off, p_len, copied;
> > +             struct page *p;
> > +             u8 *vaddr;
> > +
> > +             skb_frag_foreach_page(frag, frag->page_offset,
> > +                                   skb_frag_size(frag), p, p_off, p_len,
> > +                                   copied) {
> > +                     seg_len = min_t(int, p_len, len);
> > +                     vaddr = kmap_atomic(p);
> > +                     print_hex_dump(level, "skb frag:     ",
> > +                                    DUMP_PREFIX_OFFSET,
> > +                                    16, 1, vaddr + p_off, seg_len, false);
> > +                     kunmap_atomic(vaddr);
> > +                     len -= seg_len;
> > +                     if (!len)
> > +                             break;
> > +             }
> > +     }
> > +
> > +     if (len && skb_has_frag_list(skb)) {
> > +             printk("skb fraglist:\n");
> > +             skb_walk_frags(skb, list_skb) {
> > +                     if (len <= 0)
> > +                             break;
> > +                     skb_dump(level, list_skb, len);
>
> Here we call skb_dump passing len as full_pkt.
>
> Maybe call it with skb_dump(level, list_skb, len, full_pkt);
>
> > +                     len -= list_skb->len;
> > +             }
> > +     }
> > +}
> > +EXPORT_SYMBOL(skb_dump);

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2019-07-03 14:55 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-02 19:39 [PATCH net-next] skbuff: increase verbosity when dumping skb data Willem de Bruijn
2019-07-03  3:28 ` Yunsheng Lin
2019-07-03 14:55   ` Willem de Bruijn

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).