.func = vlan_skb_recv, /* VLAN receive method */
};
+/* Bits of netdev state that are propagated from real device to virtual */
+#define VLAN_LINK_STATE_MASK \
+ ((1<<__LINK_STATE_PRESENT)|(1<<__LINK_STATE_NOCARRIER))
+
/* End of global variables definitions. */
/*
new_dev->do_ioctl = vlan_dev_ioctl;
}
-static void vlan_transfer_operstate(const struct net_device *dev, struct net_device *vlandev)
-{
- /* Have to respect userspace enforced dormant state
- * of real device, also must allow supplicant running
- * on VLAN device
- */
- if (dev->operstate == IF_OPER_DORMANT)
- netif_dormant_on(vlandev);
- else
- netif_dormant_off(vlandev);
-
- if (netif_carrier_ok(dev)) {
- if (!netif_carrier_ok(vlandev))
- netif_carrier_on(vlandev);
- } else {
- if (netif_carrier_ok(vlandev))
- netif_carrier_off(vlandev);
- }
-}
-
-/*
- * vlan network devices have devices nesting below it, and are a special
- * "super class" of normal network devices; split their locks off into a
- * separate class since they always nest.
- */
-static struct lock_class_key vlan_netdev_xmit_lock_key;
-
-
/* Attach a VLAN device to a mac address (ie Ethernet Card).
* Returns the device that was created, or NULL if there was
* an error of some kind.
new_dev = alloc_netdev(sizeof(struct vlan_dev_info), name,
vlan_setup);
-
if (new_dev == NULL)
goto out_unlock;
new_dev->flags = real_dev->flags;
new_dev->flags &= ~IFF_UP;
- new_dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
- (1<<__LINK_STATE_DORMANT))) |
- (1<<__LINK_STATE_PRESENT);
+ new_dev->state = real_dev->state & VLAN_LINK_STATE_MASK;
/* need 4 bytes for extra VLAN header info,
* hope the underlying device can handle it.
if (register_netdevice(new_dev))
goto out_free_newdev;
- lockdep_set_class(&new_dev->_xmit_lock, &vlan_netdev_xmit_lock_key);
-
- new_dev->iflink = real_dev->ifindex;
- vlan_transfer_operstate(real_dev, new_dev);
- linkwatch_fire_event(new_dev); /* _MUST_ call rfc2863_policy() */
-
/* So, got the sucker initialized, now lets place
* it into our local structure.
*/
* so it cannot "appear" on us.
*/
if (!grp) { /* need to add a new group */
- grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
+ grp = kmalloc(sizeof(struct vlan_group), GFP_KERNEL);
if (!grp)
goto out_free_unregister;
/* printk(KERN_ALERT "VLAN REGISTER: Allocated new group.\n"); */
+ memset(grp, 0, sizeof(struct vlan_group));
grp->real_dev_ifindex = real_dev->ifindex;
hlist_add_head_rcu(&grp->hlist,
switch (event) {
case NETDEV_CHANGE:
/* Propagate real device state to vlan devices */
+ flgs = dev->state & VLAN_LINK_STATE_MASK;
for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
vlandev = grp->vlan_devices[i];
if (!vlandev)
continue;
- vlan_transfer_operstate(dev, vlandev);
+ if (netif_carrier_ok(dev)) {
+ if (!netif_carrier_ok(vlandev))
+ netif_carrier_on(vlandev);
+ } else {
+ if (netif_carrier_ok(vlandev))
+ netif_carrier_off(vlandev);
+ }
+
+ if ((vlandev->state & VLAN_LINK_STATE_MASK) != flgs) {
+ vlandev->state = (vlandev->state &~ VLAN_LINK_STATE_MASK)
+ | flgs;
+ netdev_state_change(vlandev);
+ }
}
break;