|
@@ -69,7 +69,7 @@ static struct packet_type vlan_packet_type = {
|
|
|
|
|
|
/* 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))
|
|
|
+ ((1<<__LINK_STATE_PRESENT)|(1<<__LINK_STATE_NOCARRIER)|(1<<__LINK_STATE_DORMANT))
|
|
|
|
|
|
/* End of global variables definitions. */
|
|
|
|
|
@@ -344,6 +344,26 @@ static void vlan_setup(struct net_device *new_dev)
|
|
|
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);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/* 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.
|
|
@@ -450,7 +470,7 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
|
|
|
new_dev->flags = real_dev->flags;
|
|
|
new_dev->flags &= ~IFF_UP;
|
|
|
|
|
|
- new_dev->state = real_dev->state & VLAN_LINK_STATE_MASK;
|
|
|
+ new_dev->state = real_dev->state & ~(1<<__LINK_STATE_START);
|
|
|
|
|
|
/* need 4 bytes for extra VLAN header info,
|
|
|
* hope the underlying device can handle it.
|
|
@@ -498,6 +518,10 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
|
|
|
if (register_netdevice(new_dev))
|
|
|
goto out_free_newdev;
|
|
|
|
|
|
+ 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.
|
|
|
*/
|
|
@@ -573,25 +597,12 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
|
|
|
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;
|
|
|
|
|
|
- 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);
|
|
|
- }
|
|
|
+ vlan_transfer_operstate(dev, vlandev);
|
|
|
}
|
|
|
break;
|
|
|
|