Patrick McHardy | 7750f40 | 2008-07-08 03:23:36 -0700 | [diff] [blame] | 1 | #include <linux/skbuff.h> |
| 2 | #include <linux/netdevice.h> |
| 3 | #include <linux/if_vlan.h> |
| 4 | #include "vlan.h" |
| 5 | |
| 6 | /* VLAN rx hw acceleration helper. This acts like netif_{rx,receive_skb}(). */ |
| 7 | int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, |
Patrick McHardy | 9bb8582 | 2008-07-08 03:24:44 -0700 | [diff] [blame] | 8 | u16 vlan_tci, int polling) |
Patrick McHardy | 7750f40 | 2008-07-08 03:23:36 -0700 | [diff] [blame] | 9 | { |
| 10 | struct net_device_stats *stats; |
| 11 | |
| 12 | if (skb_bond_should_drop(skb)) { |
| 13 | dev_kfree_skb_any(skb); |
| 14 | return NET_RX_DROP; |
| 15 | } |
| 16 | |
Patrick McHardy | bc1d041 | 2008-07-14 22:49:30 -0700 | [diff] [blame] | 17 | skb->vlan_tci = vlan_tci; |
| 18 | netif_nit_deliver(skb); |
| 19 | |
Patrick McHardy | 9bb8582 | 2008-07-08 03:24:44 -0700 | [diff] [blame] | 20 | skb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK); |
Patrick McHardy | 7750f40 | 2008-07-08 03:23:36 -0700 | [diff] [blame] | 21 | if (skb->dev == NULL) { |
| 22 | dev_kfree_skb_any(skb); |
| 23 | /* Not NET_RX_DROP, this is not being dropped |
| 24 | * due to congestion. */ |
| 25 | return NET_RX_SUCCESS; |
| 26 | } |
| 27 | skb->dev->last_rx = jiffies; |
Patrick McHardy | bc1d041 | 2008-07-14 22:49:30 -0700 | [diff] [blame] | 28 | skb->vlan_tci = 0; |
Patrick McHardy | 7750f40 | 2008-07-08 03:23:36 -0700 | [diff] [blame] | 29 | |
| 30 | stats = &skb->dev->stats; |
| 31 | stats->rx_packets++; |
| 32 | stats->rx_bytes += skb->len; |
| 33 | |
Patrick McHardy | 9bb8582 | 2008-07-08 03:24:44 -0700 | [diff] [blame] | 34 | skb->priority = vlan_get_ingress_priority(skb->dev, vlan_tci); |
Patrick McHardy | 7750f40 | 2008-07-08 03:23:36 -0700 | [diff] [blame] | 35 | switch (skb->pkt_type) { |
| 36 | case PACKET_BROADCAST: |
| 37 | break; |
| 38 | case PACKET_MULTICAST: |
| 39 | stats->multicast++; |
| 40 | break; |
| 41 | case PACKET_OTHERHOST: |
| 42 | /* Our lower layer thinks this is not local, let's make sure. |
| 43 | * This allows the VLAN to have a different MAC than the |
| 44 | * underlying device, and still route correctly. */ |
| 45 | if (!compare_ether_addr(eth_hdr(skb)->h_dest, |
| 46 | skb->dev->dev_addr)) |
| 47 | skb->pkt_type = PACKET_HOST; |
| 48 | break; |
| 49 | }; |
| 50 | return (polling ? netif_receive_skb(skb) : netif_rx(skb)); |
| 51 | } |
| 52 | EXPORT_SYMBOL(__vlan_hwaccel_rx); |
Patrick McHardy | 22d1ba7 | 2008-07-08 03:23:57 -0700 | [diff] [blame] | 53 | |
| 54 | struct net_device *vlan_dev_real_dev(const struct net_device *dev) |
| 55 | { |
| 56 | return vlan_dev_info(dev)->real_dev; |
| 57 | } |
| 58 | EXPORT_SYMBOL_GPL(vlan_dev_real_dev); |
| 59 | |
| 60 | u16 vlan_dev_vlan_id(const struct net_device *dev) |
| 61 | { |
| 62 | return vlan_dev_info(dev)->vlan_id; |
| 63 | } |
| 64 | EXPORT_SYMBOL_GPL(vlan_dev_vlan_id); |