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 */
}
/* 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)
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);