All of lore.kernel.org
 help / color / mirror / Atom feed
From: Patrick McHardy <kaber@trash.net>
To: Lennert Buytenhek <buytenh@wantstofly.org>
Cc: Nicolas Pitre <nico@cam.org>,
	Dale Farnsworth <dale@farnsworth.org>,
	Ashish Karkare <akarkare@marvell.com>,
	Jesper Dangaard Brouer <jdb@comx.dk>,
	netdev@vger.kernel.org, "David S. Miller" <davem@davemloft.net>
Subject: Re: [PATCH 1/2][RFC] vlan: use pskb_copy() when inserting a vlan tag by hand
Date: Tue, 08 Jul 2008 19:41:16 +0200	[thread overview]
Message-ID: <4873A6BC.6030205@trash.net> (raw)
In-Reply-To: <487394CC.7050107@trash.net>

[-- Attachment #1: Type: text/plain, Size: 820 bytes --]

Patrick McHardy wrote:
>> Lennert Buytenhek wrote:
>>>>> When inserting a vlan tag into an skb by hand (in the case the
>>>>> target network device hardware does not support inserting a vlan
>>>>> tag by passing it in via the TX descriptor), making a copy of the
>>>>> skb to be modified by calling skb_copy() is overkill, since
>>>>> skb_copy() will needlessly linearize the skb, copying of all of
>>>>> the fragmented data around, and checksumming the paket in software
>>>>> even if the hardware is perfectly capable of doing that by itself.
>>>>>
>>>>> For this case, pskb_copy() does exactly what is needed and no more,
>>>>> so use that instead. 
> Actually, are you sure this patch is helping for the case
> you describe? The function you changed is only called on
> the RX path.

Could you try this one please?


[-- Attachment #2: x --]
[-- Type: text/plain, Size: 3903 bytes --]

commit 911648966b61f2b1c8d37e6ba972ca5cc908136d
Author: Patrick McHardy <kaber@trash.net>
Date:   Tue Jul 8 19:49:15 2008 +0200

    vlan: avoid header copying and linearisation where possible
    
    - vlan_dev_reorder_header() is only called on the receive path after
      calling skb_share_check(). This means we can use skb_cow() since
      all we need is a writable header.
    
    - vlan_dev_hard_header() includes a work-around for some apparently
      broken out of tree MPLS code. The hard_header functions can expect
      to always have a headroom of at least there own hard_header_len
      available, so the reallocation check is unnecessary.
    
    - __vlan_put_tag() can use skb_cow_header() to avoid the skb_unshare()
      copy when the header is writable.
    
    Signed-off-by: Patrick McHardy <kaber@trash.net>

diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index e8360a2..9e7b49b 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -176,22 +176,10 @@ static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, u16 vlan_tci)
 {
 	struct vlan_ethhdr *veth;
 
-	if (skb_headroom(skb) < VLAN_HLEN) {
-		struct sk_buff *sk_tmp = skb;
-		skb = skb_realloc_headroom(sk_tmp, VLAN_HLEN);
-		kfree_skb(sk_tmp);
-		if (!skb) {
-			printk(KERN_ERR "vlan: failed to realloc headroom\n");
-			return NULL;
-		}
-	} else {
-		skb = skb_unshare(skb, GFP_ATOMIC);
-		if (!skb) {
-			printk(KERN_ERR "vlan: failed to unshare skbuff\n");
-			return NULL;
-		}
+	if (skb_cow_head(skb, VLAN_HLEN) < 0) {
+		kfree_skb(skb);
+		return NULL;
 	}
-
 	veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN);
 
 	/* Move the mac addresses to the beginning of the new header. */
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 2ccac6b..00867e9 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -74,11 +74,8 @@ static int vlan_dev_rebuild_header(struct sk_buff *skb)
 static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb)
 {
 	if (vlan_dev_info(skb->dev)->flags & VLAN_FLAG_REORDER_HDR) {
-		if (skb_shared(skb) || skb_cloned(skb)) {
-			struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC);
-			kfree_skb(skb);
-			skb = nskb;
-		}
+		if (skb_cow(skb, skb_headroom(skb)) < 0)
+			skb = NULL;
 		if (skb) {
 			/* Lifted from Gleb's VLAN code... */
 			memmove(skb->data - ETH_HLEN,
@@ -262,7 +259,9 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
 	u16 vlan_tci = 0;
 	int rc = 0;
 	int build_vlan_header = 0;
-	struct net_device *vdev = dev;
+
+	if (WARN_ON(skb_headroom(skb) < dev->hard_header_len + VLAN_HLEN))
+		return -ENOSPC;
 
 	pr_debug("%s: skb: %p type: %hx len: %u vlan_id: %hx, daddr: %p\n",
 		 __func__, skb, type, len, vlan_dev_info(dev)->vlan_id,
@@ -316,29 +315,6 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
 
 	dev = vlan_dev_info(dev)->real_dev;
 
-	/* MPLS can send us skbuffs w/out enough space.	This check will grow
-	 * the skb if it doesn't have enough headroom. Not a beautiful solution,
-	 * so I'll tick a counter so that users can know it's happening...
-	 * If they care...
-	 */
-
-	/* NOTE: This may still break if the underlying device is not the final
-	 * device (and thus there are more headers to add...) It should work for
-	 * good-ole-ethernet though.
-	 */
-	if (skb_headroom(skb) < dev->hard_header_len) {
-		struct sk_buff *sk_tmp = skb;
-		skb = skb_realloc_headroom(sk_tmp, dev->hard_header_len);
-		kfree_skb(sk_tmp);
-		if (skb == NULL) {
-			struct net_device_stats *stats = &vdev->stats;
-			stats->tx_dropped++;
-			return -ENOMEM;
-		}
-		vlan_dev_info(vdev)->cnt_inc_headroom_on_tx++;
-		pr_debug("%s: %s: had to grow skb\n", __func__, vdev->name);
-	}
-
 	if (build_vlan_header) {
 		/* Now make the underlying real hard header */
 		rc = dev_hard_header(skb, dev, ETH_P_8021Q, daddr, saddr,

  reply	other threads:[~2008-07-08 17:52 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-07-07 20:56 [PATCH 1/2][RFC] vlan: use pskb_copy() when inserting a vlan tag by hand Lennert Buytenhek
2008-07-07 21:01 ` Patrick McHardy
2008-07-07 21:07   ` Lennert Buytenhek
2008-07-07 21:15     ` Patrick McHardy
2008-07-08 16:24       ` Patrick McHardy
2008-07-08 17:41         ` Patrick McHardy [this message]
2008-07-08 18:52         ` Lennert Buytenhek
2008-07-08 18:50           ` Patrick McHardy
2008-07-08 19:33             ` Lennert Buytenhek
2008-07-08 20:15               ` Patrick McHardy
2008-07-08 22:02                 ` David Miller
2008-07-08 22:18                   ` Patrick McHardy
2008-07-08 22:37                     ` David Miller
2008-07-08 22:10             ` Ben Hutchings

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=4873A6BC.6030205@trash.net \
    --to=kaber@trash.net \
    --cc=akarkare@marvell.com \
    --cc=buytenh@wantstofly.org \
    --cc=dale@farnsworth.org \
    --cc=davem@davemloft.net \
    --cc=jdb@comx.dk \
    --cc=netdev@vger.kernel.org \
    --cc=nico@cam.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.