aboutsummaryrefslogtreecommitdiffstats
path: root/net/8021q/vlan_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/8021q/vlan_core.c')
-rw-r--r--net/8021q/vlan_core.c43
1 files changed, 31 insertions, 12 deletions
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 118adef476c3..dd86a1dc4cd0 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -3,11 +3,20 @@
3#include <linux/if_vlan.h> 3#include <linux/if_vlan.h>
4#include "vlan.h" 4#include "vlan.h"
5 5
6struct vlan_hwaccel_cb {
7 struct net_device *dev;
8};
9
10static inline struct vlan_hwaccel_cb *vlan_hwaccel_cb(struct sk_buff *skb)
11{
12 return (struct vlan_hwaccel_cb *)skb->cb;
13}
14
6/* VLAN rx hw acceleration helper. This acts like netif_{rx,receive_skb}(). */ 15/* VLAN rx hw acceleration helper. This acts like netif_{rx,receive_skb}(). */
7int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, 16int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
8 u16 vlan_tci, int polling) 17 u16 vlan_tci, int polling)
9{ 18{
10 struct net_device_stats *stats; 19 struct vlan_hwaccel_cb *cb = vlan_hwaccel_cb(skb);
11 20
12 if (skb_bond_should_drop(skb)) { 21 if (skb_bond_should_drop(skb)) {
13 dev_kfree_skb_any(skb); 22 dev_kfree_skb_any(skb);
@@ -15,22 +24,33 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
15 } 24 }
16 25
17 skb->vlan_tci = vlan_tci; 26 skb->vlan_tci = vlan_tci;
27 cb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK);
28
29 return (polling ? netif_receive_skb(skb) : netif_rx(skb));
30}
31EXPORT_SYMBOL(__vlan_hwaccel_rx);
32
33int vlan_hwaccel_do_receive(struct sk_buff *skb)
34{
35 struct vlan_hwaccel_cb *cb = vlan_hwaccel_cb(skb);
36 struct net_device *dev = cb->dev;
37 struct net_device_stats *stats;
38
18 netif_nit_deliver(skb); 39 netif_nit_deliver(skb);
19 40
20 skb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK); 41 if (dev == NULL) {
21 if (skb->dev == NULL) { 42 kfree_skb(skb);
22 dev_kfree_skb_any(skb); 43 return -1;
23 /* Not NET_RX_DROP, this is not being dropped
24 * due to congestion. */
25 return NET_RX_SUCCESS;
26 } 44 }
45
46 skb->dev = dev;
47 skb->priority = vlan_get_ingress_priority(dev, skb->vlan_tci);
27 skb->vlan_tci = 0; 48 skb->vlan_tci = 0;
28 49
29 stats = &skb->dev->stats; 50 stats = &dev->stats;
30 stats->rx_packets++; 51 stats->rx_packets++;
31 stats->rx_bytes += skb->len; 52 stats->rx_bytes += skb->len;
32 53
33 skb->priority = vlan_get_ingress_priority(skb->dev, vlan_tci);
34 switch (skb->pkt_type) { 54 switch (skb->pkt_type) {
35 case PACKET_BROADCAST: 55 case PACKET_BROADCAST:
36 break; 56 break;
@@ -42,13 +62,12 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
42 * This allows the VLAN to have a different MAC than the 62 * This allows the VLAN to have a different MAC than the
43 * underlying device, and still route correctly. */ 63 * underlying device, and still route correctly. */
44 if (!compare_ether_addr(eth_hdr(skb)->h_dest, 64 if (!compare_ether_addr(eth_hdr(skb)->h_dest,
45 skb->dev->dev_addr)) 65 dev->dev_addr))
46 skb->pkt_type = PACKET_HOST; 66 skb->pkt_type = PACKET_HOST;
47 break; 67 break;
48 }; 68 };
49 return (polling ? netif_receive_skb(skb) : netif_rx(skb)); 69 return 0;
50} 70}
51EXPORT_SYMBOL(__vlan_hwaccel_rx);
52 71
53struct net_device *vlan_dev_real_dev(const struct net_device *dev) 72struct net_device *vlan_dev_real_dev(const struct net_device *dev)
54{ 73{