Skip to content

Commit 98d09a1

Browse files
committedJul 30, 2014
[netdevice] Avoid registering duplicate network devices
Reject network devices which appear to be duplicates of those already available via a different underlying hardware device. On a Xen PV-HVM system, this allows us to filter out the emulated PCI NICs (which would otherwise appear alongside the netfront NICs). Note that we cannot use the Xen facility to "unplug" the emulated PCI NICs, since there is no guarantee that the OS we subsequently load will have a native netfront driver. We permit devices with the same MAC address if they are attached to the same underlying hardware device (e.g. VLAN devices). Inspired-by: Marin Hannache <git@mareo.fr> Signed-off-by: Michael Brown <mcb30@ipxe.org>
1 parent 057eb9e commit 98d09a1

File tree

2 files changed

+42
-5
lines changed

2 files changed

+42
-5
lines changed
 

‎src/include/ipxe/netdevice.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,8 @@ extern struct net_device * find_netdev ( const char *name );
685685
extern struct net_device * find_netdev_by_index ( unsigned int index );
686686
extern struct net_device * find_netdev_by_location ( unsigned int bus_type,
687687
unsigned int location );
688+
extern struct net_device *
689+
find_netdev_by_ll_addr ( struct ll_protocol *ll_protocol, const void *ll_addr );
688690
extern struct net_device * last_opened_netdev ( void );
689691
extern int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
690692
struct net_protocol *net_protocol, const void *ll_dest,

‎src/net/netdevice.c

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -602,21 +602,34 @@ struct net_device * alloc_netdev ( size_t priv_len ) {
602602
int register_netdev ( struct net_device *netdev ) {
603603
struct ll_protocol *ll_protocol = netdev->ll_protocol;
604604
struct net_driver *driver;
605+
struct net_device *duplicate;
605606
uint32_t seed;
606607
int rc;
607608

609+
/* Set initial link-layer address, if not already set */
610+
if ( ! netdev_has_ll_addr ( netdev ) ) {
611+
ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
612+
}
613+
614+
/* Reject network devices that are already available via a
615+
* different hardware device.
616+
*/
617+
duplicate = find_netdev_by_ll_addr ( ll_protocol, netdev->ll_addr );
618+
if ( duplicate && ( duplicate->dev != netdev->dev ) ) {
619+
DBGC ( netdev, "NETDEV rejecting duplicate (phys %s) of %s "
620+
"(phys %s)\n", netdev->dev->name, duplicate->name,
621+
duplicate->dev->name );
622+
rc = -EEXIST;
623+
goto err_duplicate;
624+
}
625+
608626
/* Record device index and create device name */
609627
netdev->index = netdev_index++;
610628
if ( netdev->name[0] == '\0' ) {
611629
snprintf ( netdev->name, sizeof ( netdev->name ), "net%d",
612630
netdev->index );
613631
}
614632

615-
/* Set initial link-layer address, if not already set */
616-
if ( ! netdev_has_ll_addr ( netdev ) ) {
617-
ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
618-
}
619-
620633
/* Use least significant bits of the link-layer address to
621634
* improve the randomness of the (non-cryptographic) random
622635
* number generator.
@@ -660,6 +673,7 @@ int register_netdev ( struct net_device *netdev ) {
660673
clear_settings ( netdev_settings ( netdev ) );
661674
unregister_settings ( netdev_settings ( netdev ) );
662675
err_register_settings:
676+
err_duplicate:
663677
return rc;
664678
}
665679

@@ -852,6 +866,27 @@ struct net_device * find_netdev_by_location ( unsigned int bus_type,
852866
return NULL;
853867
}
854868

869+
/**
870+
* Get network device by link-layer address
871+
*
872+
* @v ll_protocol Link-layer protocol
873+
* @v ll_addr Link-layer address
874+
* @ret netdev Network device, or NULL
875+
*/
876+
struct net_device * find_netdev_by_ll_addr ( struct ll_protocol *ll_protocol,
877+
const void *ll_addr ) {
878+
struct net_device *netdev;
879+
880+
list_for_each_entry ( netdev, &net_devices, list ) {
881+
if ( ( netdev->ll_protocol == ll_protocol ) &&
882+
( memcmp ( netdev->ll_addr, ll_addr,
883+
ll_protocol->ll_addr_len ) == 0 ) )
884+
return netdev;
885+
}
886+
887+
return NULL;
888+
}
889+
855890
/**
856891
* Get most recently opened network device
857892
*

0 commit comments

Comments
 (0)
Please sign in to comment.