]> xenbits.xen.org Git - xenclient/kernel.git/commitdiff
imported patch bonding-vlan-fixes.patch debug-dump-skb-info-when-invalid
authort_jeang <devnull@localhost>
Tue, 6 Jan 2009 12:06:05 +0000 (12:06 +0000)
committert_jeang <devnull@localhost>
Tue, 6 Jan 2009 12:06:05 +0000 (12:06 +0000)
net/core/dev.c

index 4110f7cdac6d1d67bf86c4f3fb25f392dfc40fe1..3034276c23abe4164e9bbcecd717d49486710b2b 100644 (file)
@@ -88,6 +88,7 @@
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/if_ether.h>
+#include <linux/if_vlan.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/notifier.h>
@@ -1699,6 +1700,8 @@ int netif_rx_ni(struct sk_buff *skb)
 
 EXPORT_SYMBOL(netif_rx_ni);
 
+#include <../drivers/net/bonding/bonding.h>
+
 static inline struct net_device *skb_bond(struct sk_buff *skb)
 {
        struct net_device *dev = skb->dev;
@@ -1709,6 +1712,42 @@ static inline struct net_device *skb_bond(struct sk_buff *skb)
                        return NULL;
                }
                skb->dev = dev->master;
+
+               /* The bonding driver claims to support rx vlan h/w acceleration.
+                * It actually just assumes the slave supports it and offloads the
+                * the responsibility for the acceleration to the slave.
+                * If the slave does not support rx vlan h/w acceleration
+                * then the tagged frames will end up here.
+                * When this happens we need to emulate the rx vlan h/w acceleration
+                * feature that is missing in the slave.
+                */
+               if (!(dev->features & NETIF_F_HW_VLAN_RX) && 
+                       (dev->master->features & NETIF_F_HW_VLAN_RX)) {
+
+                       struct bonding *bond = dev->master->priv;
+                       struct vlan_group *grp = bond->vlgrp;
+                       struct ethhdr *hdr = eth_hdr(skb);
+                       
+                       if (hdr->h_proto == htons(ETH_P_8021Q) && grp && 
+                               skb->len >= VLAN_ETH_HLEN) {
+                               struct vlan_ethhdr *vhdr = vlan_eth_hdr(skb);
+                               u16 vtag = ntohs(vhdr->h_vlan_TCI);
+                               
+                               /* Reset skb->data to the start of the frame */
+                               __skb_push(skb, skb->data - skb->mac.raw);
+                               
+                               /* Ditch the 4 byte vlan shim */
+                               memmove(skb->mac.raw + VLAN_HLEN, skb->mac.raw, ETH_ALEN * 2);
+                               __skb_pull(skb, VLAN_HLEN);
+
+                               /* Update the skb details */
+                               skb->protocol = eth_type_trans(skb, skb->dev);
+                               
+                               /* Pass up the stack as if it came from bond0 */
+                               vlan_hwaccel_rx(skb, grp, vtag);
+                               return NULL;
+                       }
+               }
        }
 
        return dev;