vlan: deliver packets received with VLAN acceleration to network taps
authorPatrick McHardy <kaber@trash.net>
Tue, 15 Jul 2008 05:49:30 +0000 (22:49 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 15 Jul 2008 05:49:30 +0000 (22:49 -0700)
When VLAN header stripping is used, packets currently bypass packet
sockets (and other network taps) completely. For locally existing
VLANs, they appear directly on the VLAN device, for unknown VLANs
they are silently dropped.

Add a new function netif_nit_deliver() to deliver incoming packets
to all network interface taps and use it in __vlan_hwaccel_rx() to
make VLAN packets visible on the underlying device.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/netdevice.h
net/8021q/vlan_core.c
net/core/dev.c

index b54ec16dfbda55b22eebe7ab72f2dd3aad6be872..ba5c4639ea91a58a25094c9ccde58ef7eb762f78 100644 (file)
@@ -1165,6 +1165,7 @@ extern int                netif_rx(struct sk_buff *skb);
 extern int             netif_rx_ni(struct sk_buff *skb);
 #define HAVE_NETIF_RECEIVE_SKB 1
 extern int             netif_receive_skb(struct sk_buff *skb);
+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 *);
index 68df12d3664b56fc68926385f517b1be52d4f8cc..916061f681b6484a95af7900311977fca7752ebc 100644 (file)
@@ -14,6 +14,9 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
                return NET_RX_DROP;
        }
 
+       skb->vlan_tci = vlan_tci;
+       netif_nit_deliver(skb);
+
        skb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK);
        if (skb->dev == NULL) {
                dev_kfree_skb_any(skb);
@@ -22,6 +25,7 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
                return NET_RX_SUCCESS;
        }
        skb->dev->last_rx = jiffies;
+       skb->vlan_tci = 0;
 
        stats = &skb->dev->stats;
        stats->rx_packets++;
index a29a359b15d1657acf898a26da74396387423470..feaab4898a5b9a3d0385cad0e5bfca4d9c019319 100644 (file)
@@ -2068,6 +2068,33 @@ 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();
+}
+
 /**
  *     netif_receive_skb - process receive buffer from network
  *     @skb: buffer to process