Loading include/linux/if_vlan.h +1 −0 Original line number Diff line number Diff line Loading @@ -85,6 +85,7 @@ struct vlan_group { * the vlan is attached to. */ unsigned int nr_vlans; int killall; struct hlist_node hlist; /* linked list */ struct net_device **vlan_devices_arrays[VLAN_GROUP_ARRAY_SPLIT_PARTS]; struct rcu_head rcu; Loading net/8021q/vlan.c +33 −16 Original line number Diff line number Diff line Loading @@ -159,11 +159,12 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) if (real_dev->features & NETIF_F_HW_VLAN_FILTER) ops->ndo_vlan_rx_kill_vid(real_dev, vlan_id); vlan_group_set_device(grp, vlan_id, NULL); grp->nr_vlans--; if (!grp->killall) { vlan_group_set_device(grp, vlan_id, NULL); synchronize_net(); } unregister_netdevice_queue(dev, head); /* If the group is now empty, kill off the group. */ Loading @@ -183,6 +184,34 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) dev_put(real_dev); } void unregister_vlan_dev_alls(struct vlan_group *grp) { LIST_HEAD(list); int i; struct net_device *vlandev; struct vlan_group save; memcpy(&save, grp, sizeof(save)); memset(&grp->vlan_devices_arrays, 0, sizeof(grp->vlan_devices_arrays)); grp->killall = 1; synchronize_net(); /* Delete all VLANs for this dev. */ for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { vlandev = vlan_group_get_device(&save, i); if (!vlandev) continue; unregister_vlan_dev(vlandev, &list); if (grp->nr_vlans == 0) break; } unregister_netdevice_many(&list); for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) kfree(save.vlan_devices_arrays[i]); } static void vlan_transfer_operstate(const struct net_device *dev, struct net_device *vlandev) { Loading Loading @@ -524,19 +553,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, break; case NETDEV_UNREGISTER: /* Delete all VLANs for this dev. */ for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { vlandev = vlan_group_get_device(grp, i); if (!vlandev) continue; /* unregistration of last vlan destroys group, abort * afterwards */ if (grp->nr_vlans == 1) i = VLAN_GROUP_ARRAY_LEN; unregister_vlan_dev(vlandev, NULL); } unregister_vlan_dev_alls(grp); break; } Loading net/core/dev.c +1 −0 Original line number Diff line number Diff line Loading @@ -5303,6 +5303,7 @@ void unregister_netdevice_many(struct list_head *head) net_set_todo(dev); } } EXPORT_SYMBOL(unregister_netdevice_many); /** * unregister_netdev - remove device from the kernel Loading Loading
include/linux/if_vlan.h +1 −0 Original line number Diff line number Diff line Loading @@ -85,6 +85,7 @@ struct vlan_group { * the vlan is attached to. */ unsigned int nr_vlans; int killall; struct hlist_node hlist; /* linked list */ struct net_device **vlan_devices_arrays[VLAN_GROUP_ARRAY_SPLIT_PARTS]; struct rcu_head rcu; Loading
net/8021q/vlan.c +33 −16 Original line number Diff line number Diff line Loading @@ -159,11 +159,12 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) if (real_dev->features & NETIF_F_HW_VLAN_FILTER) ops->ndo_vlan_rx_kill_vid(real_dev, vlan_id); vlan_group_set_device(grp, vlan_id, NULL); grp->nr_vlans--; if (!grp->killall) { vlan_group_set_device(grp, vlan_id, NULL); synchronize_net(); } unregister_netdevice_queue(dev, head); /* If the group is now empty, kill off the group. */ Loading @@ -183,6 +184,34 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) dev_put(real_dev); } void unregister_vlan_dev_alls(struct vlan_group *grp) { LIST_HEAD(list); int i; struct net_device *vlandev; struct vlan_group save; memcpy(&save, grp, sizeof(save)); memset(&grp->vlan_devices_arrays, 0, sizeof(grp->vlan_devices_arrays)); grp->killall = 1; synchronize_net(); /* Delete all VLANs for this dev. */ for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { vlandev = vlan_group_get_device(&save, i); if (!vlandev) continue; unregister_vlan_dev(vlandev, &list); if (grp->nr_vlans == 0) break; } unregister_netdevice_many(&list); for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) kfree(save.vlan_devices_arrays[i]); } static void vlan_transfer_operstate(const struct net_device *dev, struct net_device *vlandev) { Loading Loading @@ -524,19 +553,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, break; case NETDEV_UNREGISTER: /* Delete all VLANs for this dev. */ for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { vlandev = vlan_group_get_device(grp, i); if (!vlandev) continue; /* unregistration of last vlan destroys group, abort * afterwards */ if (grp->nr_vlans == 1) i = VLAN_GROUP_ARRAY_LEN; unregister_vlan_dev(vlandev, NULL); } unregister_vlan_dev_alls(grp); break; } Loading
net/core/dev.c +1 −0 Original line number Diff line number Diff line Loading @@ -5303,6 +5303,7 @@ void unregister_netdevice_many(struct list_head *head) net_set_todo(dev); } } EXPORT_SYMBOL(unregister_netdevice_many); /** * unregister_netdev - remove device from the kernel Loading