linux/net/8021q/vlan_core.c
<<
>>
Prefs
   1#include <linux/skbuff.h>
   2#include <linux/netdevice.h>
   3#include <linux/if_vlan.h>
   4#include "vlan.h"
   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
  15/* VLAN rx hw acceleration helper.  This acts like netif_{rx,receive_skb}(). */
  16int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
  17                      u16 vlan_tci, int polling)
  18{
  19        struct vlan_hwaccel_cb *cb = vlan_hwaccel_cb(skb);
  20
  21        if (skb_bond_should_drop(skb)) {
  22                dev_kfree_skb_any(skb);
  23                return NET_RX_DROP;
  24        }
  25
  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
  39        netif_nit_deliver(skb);
  40
  41        if (dev == NULL) {
  42                kfree_skb(skb);
  43                return -1;
  44        }
  45
  46        skb->dev = dev;
  47        skb->priority = vlan_get_ingress_priority(dev, skb->vlan_tci);
  48        skb->vlan_tci = 0;
  49
  50        dev->last_rx = jiffies;
  51
  52        stats = &dev->stats;
  53        stats->rx_packets++;
  54        stats->rx_bytes += skb->len;
  55
  56        switch (skb->pkt_type) {
  57        case PACKET_BROADCAST:
  58                break;
  59        case PACKET_MULTICAST:
  60                stats->multicast++;
  61                break;
  62        case PACKET_OTHERHOST:
  63                /* Our lower layer thinks this is not local, let's make sure.
  64                 * This allows the VLAN to have a different MAC than the
  65                 * underlying device, and still route correctly. */
  66                if (!compare_ether_addr(eth_hdr(skb)->h_dest,
  67                                        dev->dev_addr))
  68                        skb->pkt_type = PACKET_HOST;
  69                break;
  70        };
  71        return 0;
  72}
  73
  74struct net_device *vlan_dev_real_dev(const struct net_device *dev)
  75{
  76        return vlan_dev_info(dev)->real_dev;
  77}
  78EXPORT_SYMBOL_GPL(vlan_dev_real_dev);
  79
  80u16 vlan_dev_vlan_id(const struct net_device *dev)
  81{
  82        return vlan_dev_info(dev)->vlan_id;
  83}
  84EXPORT_SYMBOL_GPL(vlan_dev_vlan_id);
  85