diff options
-rw-r--r-- | net/8021q/vlan.c | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index fa76220708ce..3948949a609a 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -69,7 +69,7 @@ static struct packet_type vlan_packet_type = { | |||
69 | 69 | ||
70 | /* Bits of netdev state that are propagated from real device to virtual */ | 70 | /* Bits of netdev state that are propagated from real device to virtual */ |
71 | #define VLAN_LINK_STATE_MASK \ | 71 | #define VLAN_LINK_STATE_MASK \ |
72 | ((1<<__LINK_STATE_PRESENT)|(1<<__LINK_STATE_NOCARRIER)) | 72 | ((1<<__LINK_STATE_PRESENT)|(1<<__LINK_STATE_NOCARRIER)|(1<<__LINK_STATE_DORMANT)) |
73 | 73 | ||
74 | /* End of global variables definitions. */ | 74 | /* End of global variables definitions. */ |
75 | 75 | ||
@@ -344,6 +344,26 @@ static void vlan_setup(struct net_device *new_dev) | |||
344 | new_dev->do_ioctl = vlan_dev_ioctl; | 344 | new_dev->do_ioctl = vlan_dev_ioctl; |
345 | } | 345 | } |
346 | 346 | ||
347 | static void vlan_transfer_operstate(const struct net_device *dev, struct net_device *vlandev) | ||
348 | { | ||
349 | /* Have to respect userspace enforced dormant state | ||
350 | * of real device, also must allow supplicant running | ||
351 | * on VLAN device | ||
352 | */ | ||
353 | if (dev->operstate == IF_OPER_DORMANT) | ||
354 | netif_dormant_on(vlandev); | ||
355 | else | ||
356 | netif_dormant_off(vlandev); | ||
357 | |||
358 | if (netif_carrier_ok(dev)) { | ||
359 | if (!netif_carrier_ok(vlandev)) | ||
360 | netif_carrier_on(vlandev); | ||
361 | } else { | ||
362 | if (netif_carrier_ok(vlandev)) | ||
363 | netif_carrier_off(vlandev); | ||
364 | } | ||
365 | } | ||
366 | |||
347 | /* Attach a VLAN device to a mac address (ie Ethernet Card). | 367 | /* Attach a VLAN device to a mac address (ie Ethernet Card). |
348 | * Returns the device that was created, or NULL if there was | 368 | * Returns the device that was created, or NULL if there was |
349 | * an error of some kind. | 369 | * an error of some kind. |
@@ -450,7 +470,7 @@ static struct net_device *register_vlan_device(const char *eth_IF_name, | |||
450 | new_dev->flags = real_dev->flags; | 470 | new_dev->flags = real_dev->flags; |
451 | new_dev->flags &= ~IFF_UP; | 471 | new_dev->flags &= ~IFF_UP; |
452 | 472 | ||
453 | new_dev->state = real_dev->state & VLAN_LINK_STATE_MASK; | 473 | new_dev->state = real_dev->state & ~(1<<__LINK_STATE_START); |
454 | 474 | ||
455 | /* need 4 bytes for extra VLAN header info, | 475 | /* need 4 bytes for extra VLAN header info, |
456 | * hope the underlying device can handle it. | 476 | * hope the underlying device can handle it. |
@@ -498,6 +518,10 @@ static struct net_device *register_vlan_device(const char *eth_IF_name, | |||
498 | if (register_netdevice(new_dev)) | 518 | if (register_netdevice(new_dev)) |
499 | goto out_free_newdev; | 519 | goto out_free_newdev; |
500 | 520 | ||
521 | new_dev->iflink = real_dev->ifindex; | ||
522 | vlan_transfer_operstate(real_dev, new_dev); | ||
523 | linkwatch_fire_event(new_dev); /* _MUST_ call rfc2863_policy() */ | ||
524 | |||
501 | /* So, got the sucker initialized, now lets place | 525 | /* So, got the sucker initialized, now lets place |
502 | * it into our local structure. | 526 | * it into our local structure. |
503 | */ | 527 | */ |
@@ -573,25 +597,12 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
573 | switch (event) { | 597 | switch (event) { |
574 | case NETDEV_CHANGE: | 598 | case NETDEV_CHANGE: |
575 | /* Propagate real device state to vlan devices */ | 599 | /* Propagate real device state to vlan devices */ |
576 | flgs = dev->state & VLAN_LINK_STATE_MASK; | ||
577 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 600 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { |
578 | vlandev = grp->vlan_devices[i]; | 601 | vlandev = grp->vlan_devices[i]; |
579 | if (!vlandev) | 602 | if (!vlandev) |
580 | continue; | 603 | continue; |
581 | 604 | ||
582 | if (netif_carrier_ok(dev)) { | 605 | vlan_transfer_operstate(dev, vlandev); |
583 | if (!netif_carrier_ok(vlandev)) | ||
584 | netif_carrier_on(vlandev); | ||
585 | } else { | ||
586 | if (netif_carrier_ok(vlandev)) | ||
587 | netif_carrier_off(vlandev); | ||
588 | } | ||
589 | |||
590 | if ((vlandev->state & VLAN_LINK_STATE_MASK) != flgs) { | ||
591 | vlandev->state = (vlandev->state &~ VLAN_LINK_STATE_MASK) | ||
592 | | flgs; | ||
593 | netdev_state_change(vlandev); | ||
594 | } | ||
595 | } | 606 | } |
596 | break; | 607 | break; |
597 | 608 | ||