浏览代码

[VLAN]: translate IF_OPER_DORMANT to netif_dormant_on()

this patch adds support to the VLAN driver to translate IF_OPER_DORMANT of the
underlying device to netif_dormant_on(). Beside clean state forwarding, this
allows running independant userspace supplicants on both the real device and
the stacked VLAN. It depends on my RFC2863 patch.

Signed-off-by: Stefan Rompf <stefan@loplof.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Stefan Rompf 19 年之前
父节点
当前提交
ddd7bf9fe4
共有 1 个文件被更改,包括 27 次插入16 次删除
  1. 27 16
      net/8021q/vlan.c

+ 27 - 16
net/8021q/vlan.c

@@ -69,7 +69,7 @@ static struct packet_type vlan_packet_type = {
 
 
 /* Bits of netdev state that are propagated from real device to virtual */
 /* Bits of netdev state that are propagated from real device to virtual */
 #define VLAN_LINK_STATE_MASK \
 #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. */
 /* 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;
 	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).
 /*  Attach a VLAN device to a mac address (ie Ethernet Card).
  *  Returns the device that was created, or NULL if there was
  *  Returns the device that was created, or NULL if there was
  *  an error of some kind.
  *  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 = real_dev->flags;
 	new_dev->flags &= ~IFF_UP;
 	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,
 	/* need 4 bytes for extra VLAN header info,
 	 * hope the underlying device can handle it.
 	 * 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))
 	if (register_netdevice(new_dev))
 		goto out_free_newdev;
 		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
 	/* So, got the sucker initialized, now lets place
 	 * it into our local structure.
 	 * it into our local structure.
 	 */
 	 */
@@ -573,25 +597,12 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
 	switch (event) {
 	switch (event) {
 	case NETDEV_CHANGE:
 	case NETDEV_CHANGE:
 		/* Propagate real device state to vlan devices */
 		/* Propagate real device state to vlan devices */
-		flgs = dev->state & VLAN_LINK_STATE_MASK;
 		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
 		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
 			vlandev = grp->vlan_devices[i];
 			vlandev = grp->vlan_devices[i];
 			if (!vlandev)
 			if (!vlandev)
 				continue;
 				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;
 		break;