aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/8021q/vlan.c43
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
347static 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