aboutsummaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2023-01-14 00:31:54 +0000
committerMichael Brown <mcb30@ipxe.org>2023-01-15 00:42:52 +0000
commitc4c03e5be867a9b7be4dc48fe6576deca1dce8d8 (patch)
tree58243f0e5ae2b1907f7291de19de9416b288a565 /src/drivers
parent47af48012e2afaaf56108466fb967009670660bb (diff)
downloadipxe-c4c03e5be867a9b7be4dc48fe6576deca1dce8d8.zip
ipxe-c4c03e5be867a9b7be4dc48fe6576deca1dce8d8.tar.gz
ipxe-c4c03e5be867a9b7be4dc48fe6576deca1dce8d8.tar.bz2
[netdevice] Allow duplicate MAC addresses
Many laptops now include the ability to specify a "system-specific MAC address" (also known as "pass-through MAC"), which is supposed to be used for both the onboard NIC and for any attached docking station or other USB NIC. This is intended to simplify interoperability with software or hardware that relies on a MAC address to recognise an individual machine: for example, a deployment server may associate the MAC address with a particular operating system image to be deployed. This therefore creates legitimate situations in which duplicate MAC addresses may exist within the same system. As described in commit 98d09a1 ("[netdevice] Avoid registering duplicate network devices"), the Xen netfront driver relies on the rejection of duplicate MAC addresses in order to inhibit registration of the emulated PCI devices that a Xen PV-HVM guest will create to shadow each of the paravirtual network devices. Move the code that rejects duplicate MAC addresses from the network device core to the Xen netfront driver, to allow for the existence of duplicate MAC addresses in non-Xen setups. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/net/ecm.c5
-rw-r--r--src/drivers/net/netfront.c49
-rw-r--r--src/drivers/net/netfront.h5
3 files changed, 56 insertions, 3 deletions
diff --git a/src/drivers/net/ecm.c b/src/drivers/net/ecm.c
index 68ac962..ab1f983 100644
--- a/src/drivers/net/ecm.c
+++ b/src/drivers/net/ecm.c
@@ -121,10 +121,9 @@ int ecm_fetch_mac ( struct usb_function *func,
}
/* Apply system-specific MAC address as current link-layer
- * address, if present and not already used.
+ * address, if present.
*/
- if ( ( ( rc = acpi_mac ( amac ) ) == 0 ) &&
- ! find_netdev_by_ll_addr ( &ethernet_protocol, amac ) ) {
+ if ( ( rc = acpi_mac ( amac ) ) == 0 ) {
memcpy ( netdev->ll_addr, amac, ETH_ALEN );
DBGC ( usb, "USB %s using system-specific MAC %s\n",
func->name, eth_ntoa ( netdev->ll_addr ) );
diff --git a/src/drivers/net/netfront.c b/src/drivers/net/netfront.c
index 1203e58..90930a5 100644
--- a/src/drivers/net/netfront.c
+++ b/src/drivers/net/netfront.c
@@ -59,6 +59,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
EUNIQ ( EINFO_EIO, ( -(status) & 0x1f ), \
EIO_NETIF_RSP_ERROR, EIO_NETIF_RSP_DROPPED )
+/** List of netfront devices */
+static LIST_HEAD ( netfront_devices );
+
/******************************************************************************
*
* XenStore interface
@@ -952,6 +955,7 @@ static int netfront_probe ( struct xen_device *xendev ) {
netdev->dev = &xendev->dev;
netfront = netdev->priv;
netfront->xendev = xendev;
+ netfront->netdev = netdev;
INIT_LIST_HEAD ( &netfront->rx_partial );
DBGC ( netfront, "NETFRONT %s backend=\"%s\" in domain %ld\n",
xendev->key, xendev->backend, xendev->backend_id );
@@ -991,9 +995,13 @@ static int netfront_probe ( struct xen_device *xendev ) {
/* Set initial link state */
netdev_link_down ( netdev );
+ /* Add to list of netfront devices */
+ list_add_tail ( &netfront->list, &netfront_devices );
+
xen_set_drvdata ( xendev, netdev );
return 0;
+ list_del ( &netfront->list );
unregister_netdev ( netdev );
err_register_netdev:
err_read_mac:
@@ -1015,6 +1023,9 @@ static void netfront_remove ( struct xen_device *xendev ) {
struct netfront_nic *netfront = netdev->priv;
struct xen_hypervisor *xen = xendev->xen;
+ /* Remove from list of netfront devices */
+ list_del ( &netfront->list );
+
/* Unregister network device */
unregister_netdev ( netdev );
@@ -1033,3 +1044,41 @@ struct xen_driver netfront_driver __xen_driver = {
.probe = netfront_probe,
.remove = netfront_remove,
};
+
+/******************************************************************************
+ *
+ * Emulated PCI device inhibitor
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Inhibit emulated PCI devices
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int netfront_net_probe ( struct net_device *netdev ) {
+ struct netfront_nic *netfront;
+
+ /* Inhibit emulated PCI devices matching an existing netfront device */
+ list_for_each_entry ( netfront, &netfront_devices, list ) {
+ if ( ( netdev->dev != netfront->netdev->dev ) &&
+ ( netdev->ll_protocol->ll_addr_len == ETH_ALEN ) &&
+ ( memcmp ( netdev->hw_addr, netfront->netdev->hw_addr,
+ ETH_ALEN ) == 0 ) ) {
+ DBGC ( netfront, "NETFRONT %s inhibiting emulated %s "
+ "%s\n", netfront->xendev->key,
+ netdev->dev->driver_name, netdev->dev->name );
+ return -EEXIST;
+ }
+ }
+
+ return 0;
+}
+
+/** Emulated PCI device inhibitor driver */
+struct net_driver netfront_net_driver __net_driver = {
+ .name = "netfront",
+ .probe = netfront_net_probe,
+};
diff --git a/src/drivers/net/netfront.h b/src/drivers/net/netfront.h
index dca3ff1..de16d52 100644
--- a/src/drivers/net/netfront.h
+++ b/src/drivers/net/netfront.h
@@ -159,6 +159,11 @@ struct netfront_nic {
/** Grant references */
grant_ref_t refs[NETFRONT_REF_COUNT];
+ /** Network device */
+ struct net_device *netdev;
+ /** List of netfront NICs */
+ struct list_head list;
+
/** Transmit ring */
struct netfront_ring tx;
/** Transmit front ring */