vlan_core.c 1.6 KB

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