summaryrefslogtreecommitdiffstats
path: root/src/net/netdevice.c
diff options
context:
space:
mode:
authorMichael Brown2014-03-05 16:25:08 +0100
committerMichael Brown2014-03-05 16:25:08 +0100
commitf17a30d547b40bcd4298161f77ee14258508acf8 (patch)
treec92b42f62a118684fd6fa91b49bca5a16e23458e /src/net/netdevice.c
parent[romprefix] Do not clobber stack segment when returning to BIOS (diff)
downloadipxe-f17a30d547b40bcd4298161f77ee14258508acf8.tar.gz
ipxe-f17a30d547b40bcd4298161f77ee14258508acf8.tar.xz
ipxe-f17a30d547b40bcd4298161f77ee14258508acf8.zip
[netdevice] Mark devices as open before calling open() method
When opening a VLAN device, vlan_open() will call netdev_open() on the trunk device. This will result in a call to netdev_notify(), which will cause vlan_notify() to call vlan_sync() on the original VLAN device, which will see that the trunk device is now open but the VLAN device apparently isn't (since it has not yet been flagged as open by netdev_open()). The upshot is a second attempt to open the VLAN device, which will result in an erroneous second call to vlan_open(). This convoluted chain of events then terminates harmlessly since vlan_open() calls netdev_open() on the trunk device, which just returns immediately since the trunk device is by now flagged as being already open. Prevent this from happening by having netdev_open() flag the device as open prior to calling the device's open() method, and reflagging it as closed if the open() method fails. Originally-fixed-by: Wissam Shoukair <wissams@mellanox.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/net/netdevice.c')
-rw-r--r--src/net/netdevice.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/src/net/netdevice.c b/src/net/netdevice.c
index 9a2f8117..82d0e82b 100644
--- a/src/net/netdevice.c
+++ b/src/net/netdevice.c
@@ -636,13 +636,13 @@ int netdev_open ( struct net_device *netdev ) {
DBGC ( netdev, "NETDEV %s opening\n", netdev->name );
- /* Open the device */
- if ( ( rc = netdev->op->open ( netdev ) ) != 0 )
- return rc;
-
/* Mark as opened */
netdev->state |= NETDEV_OPEN;
+ /* Open the device */
+ if ( ( rc = netdev->op->open ( netdev ) ) != 0 )
+ goto err;
+
/* Add to head of open devices list */
list_add ( &netdev->open_list, &open_net_devices );
@@ -650,6 +650,10 @@ int netdev_open ( struct net_device *netdev ) {
netdev_notify ( netdev );
return 0;
+
+ err:
+ netdev->state &= ~NETDEV_OPEN;
+ return rc;
}
/**