diff mbox

in kernel 2.6.x, tun/tap nic supports vlan packets

Message ID 534F4C1E.1000006@gmail.com
State Not Applicable, archived
Delegated to: David Miller
Headers show

Commit Message

Zhu Yanjun April 17, 2014, 3:35 a.m. UTC
Hi, all

In kernel 2.6.x, linux depends on nic vlan hardware acceleration to 
insert/extract
vlan tag. In this scene, in kernel 2.6.x

                  _____        ________
     A           |     | B    |        | C
  vlan packets-->| tap |----->|vlan nic|--->
                 |_____|      |________|

We hope vlan packets pass through tap and vlan nic from A to c.
But in kernel 2.6.x, linux kernel can not extract vlan tag. It depends
on nic vlan hardware acceleration. It is well known that tap nic has no
vlan acceleration. So in the above scene, vlan packets can not be handled by
tap nic. These vlan packets will be discarded in B. They can not arrive 
at C.

In kernel 3.x, linux can handle vlan packets. It does not depend on nic vlan
hardware acceleration. So the above scene can work well in kernel 3.x.

To resolve the above in kernel 2.6.x, we simulated vlan hardware 
acceleration in
tun/tap driver. Then followed the logic of commit commit 4fba4ca4
[vlan: Centralize handling of hardware acceleration] to modify the vlan 
packets
process in kernel 2.6.x. In the end, the above scene can work well in 
patched
kernel 2.6.x.

Please comment on it. Any reply is appreciated.

Hi, Willy

These 2 patches are for linux2.6.x. These can work well here. Please 
help to merge
linux 2.6.32.x. Thanks a lot.

Best Regards!
Zhu Yanjun

Comments

Willy Tarreau April 17, 2014, 5:02 a.m. UTC | #1
Hi Zhu,

On Thu, Apr 17, 2014 at 11:35:58AM +0800, zhuyj wrote:
> Hi, all
> 
> In kernel 2.6.x, linux depends on nic vlan hardware acceleration to 
> insert/extract
> vlan tag. In this scene, in kernel 2.6.x
> 
>                  _____        ________
>     A           |     | B    |        | C
>  vlan packets-->| tap |----->|vlan nic|--->
>                 |_____|      |________|
> 
> We hope vlan packets pass through tap and vlan nic from A to c.
> But in kernel 2.6.x, linux kernel can not extract vlan tag. It depends
> on nic vlan hardware acceleration. It is well known that tap nic has no
> vlan acceleration. So in the above scene, vlan packets can not be handled by
> tap nic. These vlan packets will be discarded in B. They can not arrive 
> at C.

It's not clear to me what you want to achieve. Are you trying to create
vlan interfaces on top of a tap interface ? Eg: tap1.12, tap1.23 etc ?

> In kernel 3.x, linux can handle vlan packets. It does not depend on nic vlan
> hardware acceleration. So the above scene can work well in kernel 3.x.
> 
> To resolve the above in kernel 2.6.x, we simulated vlan hardware 
> acceleration in
> tun/tap driver. Then followed the logic of commit commit 4fba4ca4
> [vlan: Centralize handling of hardware acceleration] to modify the vlan 
> packets
> process in kernel 2.6.x. In the end, the above scene can work well in 
> patched
> kernel 2.6.x.
> 
> Please comment on it. Any reply is appreciated.
> 
> Hi, Willy
> 
> These 2 patches are for linux2.6.x. These can work well here. Please 
> help to merge
> linux 2.6.32.x. Thanks a lot.

Well, 2.6.32.x is in deep freeze mode and it receives only critical fixes
once in a while. While I can appreciate that the patch above might solve
the issue you're facing, I'm wondering if there are not any acceptable
workarounds for such a deep freeze kernel. You patch is not huge, but it
definitely affects a working driver, and I wouldn't like risking to break
the tap driver for other users, and I reall don't have the skills to audit
it completely to ensure this is not the case. And if it breaks, I'll have
to revert it or seek for some help on netdev.

So I'd say that I'd rather not merge it unless I get an Acked-by from some
netdev people who are willing to help in case of any future regression,
which is unlikely but still possible.

Just out of curiosity, what is the motivation for ongoing development on
top of 2.6.32 ? Are there any important deployments that cannot upgrade
for any specific reason ? I'm asking because most 2.6.32.x kernels that
are stuffed into embedded boxes very likely come with their own number
of in-house patches to add whatever feature is needed in such contexts,
so I'm wondering why having this patch in mainline would help in your
situation compared to having it into your own patch set only.

Thanks,
Willy

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Zhu Yanjun April 17, 2014, 5:50 a.m. UTC | #2
On 04/17/2014 01:02 PM, Willy Tarreau wrote:
> Hi Zhu,
>
> On Thu, Apr 17, 2014 at 11:35:58AM +0800, zhuyj wrote:
>> Hi, all
>>
>> In kernel 2.6.x, linux depends on nic vlan hardware acceleration to
>> insert/extract
>> vlan tag. In this scene, in kernel 2.6.x
>>
>>                   _____        ________
>>      A           |     | B    |        | C
>>   vlan packets-->| tap |----->|vlan nic|--->
>>                  |_____|      |________|
>>
>> We hope vlan packets pass through tap and vlan nic from A to c.
>> But in kernel 2.6.x, linux kernel can not extract vlan tag. It depends
>> on nic vlan hardware acceleration. It is well known that tap nic has no
>> vlan acceleration. So in the above scene, vlan packets can not be handled by
>> tap nic. These vlan packets will be discarded in B. They can not arrive
>> at C.
> It's not clear to me what you want to achieve. Are you trying to create
> vlan interfaces on top of a tap interface ? Eg: tap1.12, tap1.23 etc ?
Hi, Willy

Yes. These 2 patches are trying create vlan interfaces on top of a tap 
interface.

Zhu Yanjun
>
>> In kernel 3.x, linux can handle vlan packets. It does not depend on nic vlan
>> hardware acceleration. So the above scene can work well in kernel 3.x.
>>
>> To resolve the above in kernel 2.6.x, we simulated vlan hardware
>> acceleration in
>> tun/tap driver. Then followed the logic of commit commit 4fba4ca4
>> [vlan: Centralize handling of hardware acceleration] to modify the vlan
>> packets
>> process in kernel 2.6.x. In the end, the above scene can work well in
>> patched
>> kernel 2.6.x.
>>
>> Please comment on it. Any reply is appreciated.
>>
>> Hi, Willy
>>
>> These 2 patches are for linux2.6.x. These can work well here. Please
>> help to merge
>> linux 2.6.32.x. Thanks a lot.
> Well, 2.6.32.x is in deep freeze mode and it receives only critical fixes
> once in a while. While I can appreciate that the patch above might solve
> the issue you're facing, I'm wondering if there are not any acceptable
> workarounds for such a deep freeze kernel. You patch is not huge, but it
> definitely affects a working driver, and I wouldn't like risking to break
> the tap driver for other users, and I reall don't have the skills to audit
> it completely to ensure this is not the case. And if it breaks, I'll have
> to revert it or seek for some help on netdev.
>
> So I'd say that I'd rather not merge it unless I get an Acked-by from some
> netdev people who are willing to help in case of any future regression,
> which is unlikely but still possible.
>
> Just out of curiosity, what is the motivation for ongoing development on
> top of 2.6.32 ? Are there any important deployments that cannot upgrade
> for any specific reason ? I'm asking because most 2.6.32.x kernels that
> are stuffed into embedded boxes very likely come with their own number
> of in-house patches to add whatever feature is needed in such contexts,
> so I'm wondering why having this patch in mainline would help in your
> situation compared to having it into your own patch set only.
>
> Thanks,
> Willy
>
>

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Zhu Yanjun April 19, 2014, 1:43 p.m. UTC | #3
On 04/17/2014 01:02 PM, Willy Tarreau wrote:
> Hi Zhu,
>
> On Thu, Apr 17, 2014 at 11:35:58AM +0800, zhuyj wrote:
>> Hi, all
>>
>> In kernel 2.6.x, linux depends on nic vlan hardware acceleration to
>> insert/extract
>> vlan tag. In this scene, in kernel 2.6.x
>>
>>                   _____        ________
>>      A           |     | B    |        | C
>>   vlan packets-->| tap |----->|vlan nic|--->
>>                  |_____|      |________|
>>
>> We hope vlan packets pass through tap and vlan nic from A to c.
>> But in kernel 2.6.x, linux kernel can not extract vlan tag. It depends
>> on nic vlan hardware acceleration. It is well known that tap nic has no
>> vlan acceleration. So in the above scene, vlan packets can not be handled by
>> tap nic. These vlan packets will be discarded in B. They can not arrive
>> at C.
> It's not clear to me what you want to achieve. Are you trying to create
> vlan interfaces on top of a tap interface ? Eg: tap1.12, tap1.23 etc ?
>
>> In kernel 3.x, linux can handle vlan packets. It does not depend on nic vlan
>> hardware acceleration. So the above scene can work well in kernel 3.x.
>>
>> To resolve the above in kernel 2.6.x, we simulated vlan hardware
>> acceleration in
>> tun/tap driver. Then followed the logic of commit commit 4fba4ca4
>> [vlan: Centralize handling of hardware acceleration] to modify the vlan
>> packets
>> process in kernel 2.6.x. In the end, the above scene can work well in
>> patched
>> kernel 2.6.x.
>>
>> Please comment on it. Any reply is appreciated.
>>
>> Hi, Willy
>>
>> These 2 patches are for linux2.6.x. These can work well here. Please
>> help to merge
>> linux 2.6.32.x. Thanks a lot.
> Well, 2.6.32.x is in deep freeze mode and it receives only critical fixes
> once in a while. While I can appreciate that the patch above might solve
> the issue you're facing, I'm wondering if there are not any acceptable
> workarounds for such a deep freeze kernel. You patch is not huge, but it
> definitely affects a working driver, and I wouldn't like risking to break
> the tap driver for other users, and I reall don't have the skills to audit
> it completely to ensure this is not the case. And if it breaks, I'll have
> to revert it or seek for some help on netdev.
>
> So I'd say that I'd rather not merge it unless I get an Acked-by from some
> netdev people who are willing to help in case of any future regression,
> which is unlikely but still possible.
>
> Just out of curiosity, what is the motivation for ongoing development on
> top of 2.6.32 ? Are there any important deployments that cannot upgrade
> for any specific reason ? I'm asking because most 2.6.32.x kernels that
> are stuffed into embedded boxes very likely come with their own number
> of in-house patches to add whatever feature is needed in such contexts,
> so I'm wondering why having this patch in mainline would help in your
> situation compared to having it into your own patch set only.
Hi, Willy

I want to submit these 2 patches to this long-term kernel. I have 2 
purposes:

1. I want to share these 2 patches with the ones who need this kind of 
feature. Maybe these 2 patches can help them.
2. When many people make use of these 2 patches, we will find some 
defects. Then we fix them and make this kind of feature better.

Zhu Yanjun
> Thanks,
> Willy
>
>

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Ben Hutchings April 22, 2014, 5:53 p.m. UTC | #4
On Thu, 2014-04-17 at 07:02 +0200, Willy Tarreau wrote:
> Hi Zhu,
> 
> On Thu, Apr 17, 2014 at 11:35:58AM +0800, zhuyj wrote:
> > Hi, all
> > 
> > In kernel 2.6.x, linux depends on nic vlan hardware acceleration to 
> > insert/extract
> > vlan tag.

This is a gross overstatement.

The problem I know of is that prior to Linux 2.6.37 the RX path behaved
differently for VLAN-tagged packets depending on whether they were
extracted by the driver/hardware.

If you put a bridge (or bond) and VLAN device on top of a single
physical device that doesn't do VLAN tag extraction, the VLAN device
didn't get any packets because the bridge packet handler was called
first.  Whereas, if the driver called the 'VLAN accelerated' RX path,
the VLAN packet handler was called first.  (Linux 2.6.37 actually
standardised on the former behaviour, and 3.2 fixed it to be the
latter.)

I don't know whether that's the problem zhuyj has run into.

[...]
> Well, 2.6.32.x is in deep freeze mode and it receives only critical fixes
> once in a while. While I can appreciate that the patch above might solve
> the issue you're facing, I'm wondering if there are not any acceptable
> workarounds for such a deep freeze kernel. You patch is not huge,

I think it's huge by the standards of 2.6.32.y.

> but it
> definitely affects a working driver, and I wouldn't like risking to break
> the tap driver for other users, and I reall don't have the skills to audit
> it completely to ensure this is not the case. And if it breaks, I'll have
> to revert it or seek for some help on netdev.
> 
> So I'd say that I'd rather not merge it unless I get an Acked-by from some
> netdev people who are willing to help in case of any future regression,
> which is unlikely but still possible.
[...]

For what it's worth, I would recommend against applying this.  I don't
think even Red Hat has backported the VLAN changes, and they have been
quite aggressive about backporting features to RHEL 6.

Ben.
Zhu Yanjun April 23, 2014, 7:48 a.m. UTC | #5
On 04/23/2014 01:53 AM, Ben Hutchings wrote:
> On Thu, 2014-04-17 at 07:02 +0200, Willy Tarreau wrote:
>> Hi Zhu,
>>
>> On Thu, Apr 17, 2014 at 11:35:58AM +0800, zhuyj wrote:
>>> Hi, all
>>>
>>> In kernel 2.6.x, linux depends on nic vlan hardware acceleration to
>>> insert/extract
>>> vlan tag.
Hi, Ben

Thanks for your reply.
> This is a gross overstatement.
>
> The problem I know of is that prior to Linux 2.6.37 the RX path behaved
> differently for VLAN-tagged packets depending on whether they were
> extracted by the driver/hardware.
Yes. You are right. So I backported 
0002-vlan-Centralize-handling-of-hardware-acceleration.patch to fix this 
problem.
>
> If you put a bridge (or bond) and VLAN device on top of a single
> physical device that doesn't do VLAN tag extraction, the VLAN device
> didn't get any packets because the bridge packet handler was called
> first.  Whereas, if the driver called the 'VLAN accelerated' RX path,
> the VLAN packet handler was called first.  (Linux 2.6.37 actually
> standardised on the former behaviour, and 3.2 fixed it to be the
> latter.)
Yes. So I made a patch 
"0001-tun-tap-add-the-feature-of-vlan-rx-extraction.patch" to make tap 
driver extract vlan tag.
>
> I don't know whether that's the problem zhuyj has run into.
>
> [...]
>> Well, 2.6.32.x is in deep freeze mode and it receives only critical fixes
>> once in a while. While I can appreciate that the patch above might solve
>> the issue you're facing, I'm wondering if there are not any acceptable
>> workarounds for such a deep freeze kernel. You patch is not huge,
> I think it's huge by the standards of 2.6.32.y.
>
>> but it
>> definitely affects a working driver, and I wouldn't like risking to break
>> the tap driver for other users, and I reall don't have the skills to audit
>> it completely to ensure this is not the case. And if it breaks, I'll have
>> to revert it or seek for some help on netdev.
>>
>> So I'd say that I'd rather not merge it unless I get an Acked-by from some
>> netdev people who are willing to help in case of any future regression,
>> which is unlikely but still possible.
> [...]
>
> For what it's worth, I would recommend against applying this.  I don't
> think even Red Hat has backported the VLAN changes, and they have been
> quite aggressive about backporting features to RHEL 6.
If we do not merge these patches, maybe RHEL 6 can not make tap driver 
support vlan well.

Best Regards!
Zhu Yanjun
>
> Ben.
>

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Ben Hutchings April 23, 2014, 11:41 a.m. UTC | #6
On Wed, 2014-04-23 at 15:48 +0800, zhuyj wrote:
> On 04/23/2014 01:53 AM, Ben Hutchings wrote:
[...]
> > For what it's worth, I would recommend against applying this.  I don't
> > think even Red Hat has backported the VLAN changes, and they have been
> > quite aggressive about backporting features to RHEL 6.
> If we do not merge these patches, maybe RHEL 6 can not make tap driver 
> support vlan well.

RHEL 6 isn't based on 2.6.32.y, they do all their own backporting.

Ben.
Zhu Yanjun April 24, 2014, 2:10 a.m. UTC | #7
On 04/23/2014 07:41 PM, Ben Hutchings wrote:
> On Wed, 2014-04-23 at 15:48 +0800, zhuyj wrote:
>> On 04/23/2014 01:53 AM, Ben Hutchings wrote:
> [...]
>>> For what it's worth, I would recommend against applying this.  I don't
>>> think even Red Hat has backported the VLAN changes, and they have been
>>> quite aggressive about backporting features to RHEL 6.
>> If we do not merge these patches, maybe RHEL 6 can not make tap driver
>> support vlan well.
> RHEL 6 isn't based on 2.6.32.y, they do all their own backporting.
Hi, Ben

It is well known that extraction vlan tag is not implemented in kernel 
2.6.32.y.  Kernel 2.6.32.y depends on nic hardware to extract vlan tag.
So if the patches are not applied, tap driver can not support vlan well.

Best Regards!
Zhu Yanjun
> Ben.
>

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Willy Tarreau April 24, 2014, 5:24 a.m. UTC | #8
On Thu, Apr 24, 2014 at 10:10:08AM +0800, zhuyj wrote:
> On 04/23/2014 07:41 PM, Ben Hutchings wrote:
> >On Wed, 2014-04-23 at 15:48 +0800, zhuyj wrote:
> >>On 04/23/2014 01:53 AM, Ben Hutchings wrote:
> >[...]
> >>>For what it's worth, I would recommend against applying this.  I don't
> >>>think even Red Hat has backported the VLAN changes, and they have been
> >>>quite aggressive about backporting features to RHEL 6.
> >>If we do not merge these patches, maybe RHEL 6 can not make tap driver
> >>support vlan well.
> >RHEL 6 isn't based on 2.6.32.y, they do all their own backporting.
> Hi, Ben
> 
> It is well known that extraction vlan tag is not implemented in kernel 
> 2.6.32.y.  Kernel 2.6.32.y depends on nic hardware to extract vlan tag.
> So if the patches are not applied, tap driver can not support vlan well.

What Ben is saying is that RHEL doesn't use 2.6.32.y, but did their own
fork of 2.6.32 so even if we merged your patch, they wouldn't pick it
from this tree anyway. However they could possibly take your patch if
some customers requested the feature even if it's not in 2.6.32.y.

Clearly, the fact that nobody complained about this in 4.5 years of
2.6.32 means that there's no particular reason any user would suddenly
miss it now. 2.6.32.y is mostly used to update existing deployments but
rarely for new deployments. That's why the usefulness of your backport
in this kernel for its users is likely limited, and at the same time
the risk of causing a regression is far from being null for existing
users (eg: if some worked around the issue a different way, their
workaround would likely not work anymore).

Best regards,
Willy

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Zhu Yanjun April 25, 2014, 8:09 a.m. UTC | #9
On 04/24/2014 01:24 PM, Willy Tarreau wrote:
> On Thu, Apr 24, 2014 at 10:10:08AM +0800, zhuyj wrote:
>> On 04/23/2014 07:41 PM, Ben Hutchings wrote:
>>> On Wed, 2014-04-23 at 15:48 +0800, zhuyj wrote:
>>>> On 04/23/2014 01:53 AM, Ben Hutchings wrote:
>>> [...]
>>>>> For what it's worth, I would recommend against applying this.  I don't
>>>>> think even Red Hat has backported the VLAN changes, and they have been
>>>>> quite aggressive about backporting features to RHEL 6.
>>>> If we do not merge these patches, maybe RHEL 6 can not make tap driver
>>>> support vlan well.
>>> RHEL 6 isn't based on 2.6.32.y, they do all their own backporting.
>> Hi, Ben
>>
>> It is well known that extraction vlan tag is not implemented in kernel
>> 2.6.32.y.  Kernel 2.6.32.y depends on nic hardware to extract vlan tag.
>> So if the patches are not applied, tap driver can not support vlan well.
> What Ben is saying is that RHEL doesn't use 2.6.32.y, but did their own
> fork of 2.6.32 so even if we merged your patch, they wouldn't pick it
> from this tree anyway. However they could possibly take your patch if
> some customers requested the feature even if it's not in 2.6.32.y.
OK. as your wish.

Best Regards!
Zhu Yanjun
>
> Clearly, the fact that nobody complained about this in 4.5 years of
> 2.6.32 means that there's no particular reason any user would suddenly
> miss it now. 2.6.32.y is mostly used to update existing deployments but
> rarely for new deployments. That's why the usefulness of your backport
> in this kernel for its users is likely limited, and at the same time
> the risk of causing a regression is far from being null for existing
> users (eg: if some worked around the issue a different way, their
> workaround would likely not work anymore).
>
> Best regards,
> Willy
>
>

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

From 86fff983b7f36750301aab537dfd4e5744d929e7 Mon Sep 17 00:00:00 2001
From: Zhu Yanjun <Yanjun.Zhu@windriver.com>
Date: Wed, 16 Apr 2014 18:57:23 +0800
Subject: [PATCH 2/2] vlan: Centralize handling of hardware acceleration

2.6.x kernels require a similar logic change as commit 4fba4ca4
[vlan: Centralize handling of hardware acceleration] introduces
for newer kernels.

Since there is something wrong with sending/receiving vlan packets
of tun/tap of kernel 2.6.x. In kernel(3.0+), sending/receiving
vlan packets is centralize handling in kernel. But in kernel 2.6.x,
inserting/extraction vlan tag is still based on nic hardware. Thus,
tun/tap nic driver can not support vlan packets. It is necessary
to centralize handling of hardware acceleration and simulate vlan
rx extraction in tun/tap nic driver to make tun/tap support vlan
packets sending/receiving in kernel 2.6.x.

Signed-off-by: Zhu Yanjun <Yanjun.Zhu@windriver.com>
---
 include/linux/if_vlan.h   |    4 +-
 include/linux/netdevice.h |    1 -
 net/8021q/vlan.c          |   49 ++++++++++++++++++++
 net/8021q/vlan_core.c     |  110 +++++----------------------------------------
 net/core/dev.c            |   42 +++++++----------
 5 files changed, 76 insertions(+), 130 deletions(-)

diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 7ff9af1..5538dda 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -114,7 +114,7 @@  extern u16 vlan_dev_vlan_id(const struct net_device *dev);
 
 extern int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
 			     u16 vlan_tci, int polling);
-extern int vlan_hwaccel_do_receive(struct sk_buff *skb);
+extern bool vlan_hwaccel_do_receive(struct sk_buff **skb);
 extern int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp,
 			    unsigned int vlan_tci, struct sk_buff *skb);
 extern int vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp,
@@ -140,7 +140,7 @@  static inline int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
 	return NET_XMIT_SUCCESS;
 }
 
-static inline int vlan_hwaccel_do_receive(struct sk_buff *skb)
+static inline bool vlan_hwaccel_do_receive(struct sk_buff **skb)
 {
 	return 0;
 }
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 04c659b..bdb6b82 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1490,7 +1490,6 @@  static inline void napi_free_frags(struct napi_struct *napi)
 	napi->skb = NULL;
 }
 
-extern void		netif_nit_deliver(struct sk_buff *skb);
 extern int		dev_valid_name(const char *name);
 extern int		dev_ioctl(struct net *net, unsigned int cmd, void __user *);
 extern int		dev_ethtool(struct net *net, struct ifreq *);
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index a29c5ab..385c6e4 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -92,6 +92,54 @@  struct net_device *__find_vlan_dev(struct net_device *real_dev, u16 vlan_id)
 	return NULL;
 }
 
+bool vlan_hwaccel_do_receive(struct sk_buff **skbp)
+{
+	struct sk_buff *skb = *skbp;
+	u16 vlan_id = skb->vlan_tci & VLAN_VID_MASK;
+	struct net_device *vlan_dev;
+	struct vlan_rx_stats *rx_stats;
+
+	vlan_dev = __find_vlan_dev(skb->dev, vlan_id);
+	if (!vlan_dev) {
+		if (vlan_id)
+			skb->pkt_type = PACKET_OTHERHOST;
+		return false;
+	}
+
+	skb = *skbp = skb_share_check(skb, GFP_ATOMIC);
+	if (unlikely(!skb))
+		return false;
+
+	skb->dev = vlan_dev;
+	skb->priority = vlan_get_ingress_priority(vlan_dev, skb->vlan_tci);
+	skb->vlan_tci = 0;
+
+	rx_stats = per_cpu_ptr(vlan_dev_info(vlan_dev)->vlan_rx_stats,
+				smp_processor_id());
+
+	rx_stats->rx_packets++;
+	rx_stats->rx_bytes += skb->len;
+
+	switch (skb->pkt_type) {
+	case PACKET_BROADCAST:
+		break;
+	case PACKET_MULTICAST:
+		rx_stats->multicast++;
+		break;
+	case PACKET_OTHERHOST:
+		/* Our lower layer thinks this is not local, let's make sure.
+		 * This allows the VLAN to have a different MAC than the
+		 * underlying device, and still route correctly. */
+		if (!compare_ether_addr(eth_hdr(skb)->h_dest,
+					vlan_dev->dev_addr))
+			skb->pkt_type = PACKET_HOST;
+			break;
+	};
+
+	return true;
+}
+extern bool (*__vlan_do_receive)(struct sk_buff **skbp);
+
 static void vlan_group_free(struct vlan_group *grp)
 {
 	int i;
@@ -744,6 +792,7 @@  static int __init vlan_proto_init(void)
 
 	dev_add_pack(&vlan_packet_type);
 	vlan_ioctl_set(vlan_ioctl_handler);
+	__vlan_do_receive = vlan_hwaccel_do_receive;
 	return 0;
 
 err4:
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 7f7de1a..c679535 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -4,64 +4,6 @@ 
 #include <linux/netpoll.h>
 #include "vlan.h"
 
-/* VLAN rx hw acceleration helper.  This acts like netif_{rx,receive_skb}(). */
-int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
-		      u16 vlan_tci, int polling)
-{
-	if (netpoll_rx(skb))
-		return NET_RX_DROP;
-
-	if (skb_bond_should_drop(skb))
-		goto drop;
-
-	skb->vlan_tci = vlan_tci;
-	skb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK);
-
-	if (!skb->dev)
-		goto drop;
-
-	return (polling ? netif_receive_skb(skb) : netif_rx(skb));
-
-drop:
-	dev_kfree_skb_any(skb);
-	return NET_RX_DROP;
-}
-EXPORT_SYMBOL(__vlan_hwaccel_rx);
-
-int vlan_hwaccel_do_receive(struct sk_buff *skb)
-{
-	struct net_device *dev = skb->dev;
-	struct net_device_stats *stats;
-
-	skb->dev = vlan_dev_info(dev)->real_dev;
-	netif_nit_deliver(skb);
-
-	skb->dev = dev;
-	skb->priority = vlan_get_ingress_priority(dev, skb->vlan_tci);
-	skb->vlan_tci = 0;
-
-	stats = &dev->stats;
-	stats->rx_packets++;
-	stats->rx_bytes += skb->len;
-
-	switch (skb->pkt_type) {
-	case PACKET_BROADCAST:
-		break;
-	case PACKET_MULTICAST:
-		stats->multicast++;
-		break;
-	case PACKET_OTHERHOST:
-		/* Our lower layer thinks this is not local, let's make sure.
-		 * This allows the VLAN to have a different MAC than the
-		 * underlying device, and still route correctly. */
-		if (!compare_ether_addr(eth_hdr(skb)->h_dest,
-					dev->dev_addr))
-			skb->pkt_type = PACKET_HOST;
-		break;
-	};
-	return 0;
-}
-
 struct net_device *vlan_dev_real_dev(const struct net_device *dev)
 {
 	return vlan_dev_info(dev)->real_dev;
@@ -74,59 +16,27 @@  u16 vlan_dev_vlan_id(const struct net_device *dev)
 }
 EXPORT_SYMBOL(vlan_dev_vlan_id);
 
-static int vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp,
-			   unsigned int vlan_tci, struct sk_buff *skb)
+/* VLAN rx hw acceleration helper.  This acts like netif_{rx,receive_skb}(). */
+int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
+			u16 vlan_tci, int polling)
 {
-	struct sk_buff *p;
-
-	if (skb_bond_should_drop(skb))
-		goto drop;
-
-	skb->vlan_tci = vlan_tci;
-	skb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK);
-
-	if (!skb->dev)
-		goto drop;
-
-	for (p = napi->gro_list; p; p = p->next) {
-		NAPI_GRO_CB(p)->same_flow =
-			p->dev == skb->dev && !compare_ether_header(
-				skb_mac_header(p), skb_gro_mac_header(skb));
-		NAPI_GRO_CB(p)->flush = 0;
-	}
-
-	return dev_gro_receive(napi, skb);
-
-drop:
-	return GRO_DROP;
+	__vlan_hwaccel_put_tag(skb, vlan_tci);
+	return polling ? netif_receive_skb(skb) : netif_rx(skb); 
 }
+EXPORT_SYMBOL(__vlan_hwaccel_rx);
 
 int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp,
 		     unsigned int vlan_tci, struct sk_buff *skb)
 {
-	if (netpoll_rx_on(skb))
-		return vlan_hwaccel_receive_skb(skb, grp, vlan_tci);
-
-	skb_gro_reset_offset(skb);
-
-	return napi_skb_finish(vlan_gro_common(napi, grp, vlan_tci, skb), skb);
+	__vlan_hwaccel_put_tag(skb, vlan_tci);
+	return napi_gro_receive(napi, skb);
 }
 EXPORT_SYMBOL(vlan_gro_receive);
 
 int vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp,
 		   unsigned int vlan_tci)
 {
-	struct sk_buff *skb = napi_frags_skb(napi);
-
-	if (!skb)
-		return NET_RX_DROP;
-
-	if (netpoll_rx_on(skb)) {
-		skb->protocol = eth_type_trans(skb, skb->dev);
-		return vlan_hwaccel_receive_skb(skb, grp, vlan_tci);
-	}
-
-	return napi_frags_finish(napi, skb,
-				 vlan_gro_common(napi, grp, vlan_tci, skb));
+	__vlan_hwaccel_put_tag(napi->skb, vlan_tci);
+	return napi_gro_frags(napi);
 }
 EXPORT_SYMBOL(vlan_gro_frags);
diff --git a/net/core/dev.c b/net/core/dev.c
index a3802ca..b69487e 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2272,33 +2272,8 @@  out:
 }
 #endif
 
-/*
- * 	netif_nit_deliver - deliver received packets to network taps
- * 	@skb: buffer
- *
- * 	This function is used to deliver incoming packets to network
- * 	taps. It should be used when the normal netif_receive_skb path
- * 	is bypassed, for example because of VLAN acceleration.
- */
-void netif_nit_deliver(struct sk_buff *skb)
-{
-	struct packet_type *ptype;
-
-	if (list_empty(&ptype_all))
-		return;
-
-	skb_reset_network_header(skb);
-	skb_reset_transport_header(skb);
-	skb->mac_len = skb->network_header - skb->mac_header;
-
-	rcu_read_lock();
-	list_for_each_entry_rcu(ptype, &ptype_all, list) {
-		if (!ptype->dev || ptype->dev == skb->dev)
-			deliver_skb(skb, ptype, skb->dev);
-	}
-	rcu_read_unlock();
-}
-
+bool (*__vlan_do_receive)(struct sk_buff **skbp) = NULL;
+EXPORT_SYMBOL(__vlan_do_receive);
 /**
  *	netif_receive_skb - process receive buffer from network
  *	@skb: buffer to process
@@ -2354,6 +2329,8 @@  int netif_receive_skb(struct sk_buff *skb)
 
 	rcu_read_lock();
 
+another_round:
+
 #ifdef CONFIG_NET_CLS_ACT
 	if (skb->tc_verd & TC_NCLS) {
 		skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
@@ -2377,6 +2354,17 @@  int netif_receive_skb(struct sk_buff *skb)
 ncls:
 #endif
 
+	if (vlan_tx_tag_present(skb)) {
+		if (pt_prev) {
+			ret = deliver_skb(skb, pt_prev, orig_dev);
+			pt_prev = NULL;
+		}
+		if (__vlan_do_receive && __vlan_do_receive(&skb)) {
+			goto another_round;
+		} else if (unlikely(!skb))
+			goto out;
+	}
+
 	skb = handle_bridge(skb, &pt_prev, &ret, orig_dev);
 	if (!skb)
 		goto out;
-- 
1.7.9.5