]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/8021q/vlan_dev.c
vlan: fix network_header/mac_header adjustments
[linux-2.6-omap-h63xx.git] / net / 8021q / vlan_dev.c
index 5d055c242ed8e224ea602bce5291c10f059af90c..4a8525927c276f8fbf10c86068d67d6f42d81ad4 100644 (file)
@@ -308,7 +308,6 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
                        vhdr->h_vlan_encapsulated_proto = htons(len);
 
                skb->protocol = htons(ETH_P_8021Q);
-               skb_reset_network_header(skb);
        }
 
        /* Before delegating work to the lower layer, enter our MAC-address */
@@ -507,18 +506,23 @@ int vlan_dev_set_egress_priority(const struct net_device *dev,
 }
 
 /* Flags are defined in the vlan_flags enum in include/linux/if_vlan.h file. */
-int vlan_dev_set_vlan_flag(const struct net_device *dev,
-                          u32 flag, short flag_val)
+int vlan_dev_change_flags(const struct net_device *dev, u32 flags, u32 mask)
 {
-       /* verify flag is supported */
-       if (flag == VLAN_FLAG_REORDER_HDR) {
-               if (flag_val)
-                       vlan_dev_info(dev)->flags |= VLAN_FLAG_REORDER_HDR;
+       struct vlan_dev_info *vlan = vlan_dev_info(dev);
+       u32 old_flags = vlan->flags;
+
+       if (mask & ~(VLAN_FLAG_REORDER_HDR | VLAN_FLAG_GVRP))
+               return -EINVAL;
+
+       vlan->flags = (old_flags & ~mask) | (flags & mask);
+
+       if (netif_running(dev) && (vlan->flags ^ old_flags) & VLAN_FLAG_GVRP) {
+               if (vlan->flags & VLAN_FLAG_GVRP)
+                       vlan_gvrp_request_join(dev);
                else
-                       vlan_dev_info(dev)->flags &= ~VLAN_FLAG_REORDER_HDR;
-               return 0;
+                       vlan_gvrp_request_leave(dev);
        }
-       return -EINVAL;
+       return 0;
 }
 
 void vlan_dev_get_realdev_name(const struct net_device *dev, char *result)
@@ -552,12 +556,19 @@ static int vlan_dev_open(struct net_device *dev)
        if (dev->flags & IFF_PROMISC)
                dev_set_promiscuity(real_dev, 1);
 
+       if (vlan->flags & VLAN_FLAG_GVRP)
+               vlan_gvrp_request_join(dev);
+
        return 0;
 }
 
 static int vlan_dev_stop(struct net_device *dev)
 {
-       struct net_device *real_dev = vlan_dev_info(dev)->real_dev;
+       struct vlan_dev_info *vlan = vlan_dev_info(dev);
+       struct net_device *real_dev = vlan->real_dev;
+
+       if (vlan->flags & VLAN_FLAG_GVRP)
+               vlan_gvrp_request_leave(dev);
 
        dev_mc_unsync(real_dev, dev);
        dev_unicast_unsync(real_dev, dev);