summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2023-01-14 00:09:20 +0000
committerMichael Brown <mcb30@ipxe.org>2023-01-14 00:09:20 +0000
commit47af48012e2afaaf56108466fb967009670660bb (patch)
tree6548d6bf0626faddf1a1aefdc080dbd7b9590626
parentab19546386b13d6c54aea1647fac06960c544efc (diff)
downloadqemu-ipxe-47af48012e2afaaf56108466fb967009670660bb.tar.gz
[netdevice] Separate concept of scope ID from network device name index
The network device index currently serves two purposes: acting as a sequential index for network device names ("net0", "net1", etc), and acting as an opaque unique integer identifier used in socket address scope IDs. There is no particular need for these usages to be linked, and it can lead to situations in which devices are named unexpectedly. For example: if a system has two network devices "net0" and "net1", a VLAN is created as "net1-42", and then a USB NIC is connected, then the USB NIC will be named "net3" rather than the expected "net2" since the VLAN device "net1-42" will have consumed an index. Separate the usages: rename the "index" field to "scope_id" (matching its one and only use case), and assign the name without reference to the scope ID by finding the first unused name. For consistency, assign the scope ID by similarly finding the first unused scope ID. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/include/ipxe/netdevice.h6
-rw-r--r--src/interface/efi/efi_pxe.c2
-rw-r--r--src/interface/efi/efi_snp.c4
-rw-r--r--src/net/ipv4.c2
-rw-r--r--src/net/ipv6.c12
-rw-r--r--src/net/ndp.c4
-rw-r--r--src/net/netdevice.c31
-rw-r--r--src/net/peerdisc.c2
-rw-r--r--src/net/udp/dhcpv6.c2
-rw-r--r--src/tests/ipv6_test.c4
10 files changed, 36 insertions, 33 deletions
diff --git a/src/include/ipxe/netdevice.h b/src/include/ipxe/netdevice.h
index 294f7b36..29358dba 100644
--- a/src/include/ipxe/netdevice.h
+++ b/src/include/ipxe/netdevice.h
@@ -356,8 +356,8 @@ struct net_device {
struct list_head list;
/** List of open network devices */
struct list_head open_list;
- /** Index of this network device */
- unsigned int index;
+ /** Scope ID */
+ unsigned int scope_id;
/** Name of this network device */
char name[NETDEV_NAME_LEN];
/** Underlying hardware device */
@@ -726,7 +726,7 @@ extern void netdev_close ( struct net_device *netdev );
extern void unregister_netdev ( struct net_device *netdev );
extern void netdev_irq ( struct net_device *netdev, int enable );
extern struct net_device * find_netdev ( const char *name );
-extern struct net_device * find_netdev_by_index ( unsigned int index );
+extern struct net_device * find_netdev_by_scope_id ( unsigned int scope_id );
extern struct net_device * find_netdev_by_location ( unsigned int bus_type,
unsigned int location );
extern struct net_device *
diff --git a/src/interface/efi/efi_pxe.c b/src/interface/efi/efi_pxe.c
index 15224a5e..843ebb5e 100644
--- a/src/interface/efi/efi_pxe.c
+++ b/src/interface/efi/efi_pxe.c
@@ -199,7 +199,7 @@ static void efi_pxe_ip_sockaddr ( struct efi_pxe *pxe, EFI_IP_ADDRESS *ip,
memset ( sockaddr, 0, sizeof ( *sockaddr ) );
sockaddr->sa.sa_family = pxe->tcpip->sa_family;
memcpy ( &sockaddr->se.se_addr, ip, pxe->net->net_addr_len );
- sockaddr->se.se_scope_id = pxe->netdev->index;
+ sockaddr->se.se_scope_id = pxe->netdev->scope_id;
}
/**
diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c
index 088a3fdb..c4f7d4ea 100644
--- a/src/interface/efi/efi_snp.c
+++ b/src/interface/efi/efi_snp.c
@@ -934,11 +934,11 @@ static uint8_t efi_undi_checksum ( void *data, size_t len ) {
*/
static unsigned int efi_undi_ifnum ( struct efi_snp_device *snpdev ) {
- /* iPXE network device indexes are one-based (leaving zero
+ /* iPXE network device scope IDs are one-based (leaving zero
* meaning "unspecified"). UNDI interface numbers are
* zero-based.
*/
- return ( snpdev->netdev->index - 1 );
+ return ( snpdev->netdev->scope_id - 1 );
}
/**
diff --git a/src/net/ipv4.c b/src/net/ipv4.c
index b9ce5e7f..b91fa2ad 100644
--- a/src/net/ipv4.c
+++ b/src/net/ipv4.c
@@ -163,7 +163,7 @@ static struct ipv4_miniroute * ipv4_route ( unsigned int scope_id,
/* If destination is non-global, and the scope ID
* matches this network device, then use this route.
*/
- if ( miniroute->netdev->index == scope_id )
+ if ( miniroute->netdev->scope_id == scope_id )
return miniroute;
} else {
diff --git a/src/net/ipv6.c b/src/net/ipv6.c
index 901203c4..ef5e51da 100644
--- a/src/net/ipv6.c
+++ b/src/net/ipv6.c
@@ -330,7 +330,7 @@ struct ipv6_miniroute * ipv6_route ( unsigned int scope_id,
/* Skip entries with a non-matching scope ID, if
* destination specifies a scope ID.
*/
- if ( scope_id && ( miniroute->netdev->index != scope_id ) )
+ if ( scope_id && ( miniroute->netdev->scope_id != scope_id ) )
continue;
/* Skip entries that are out of scope */
@@ -789,12 +789,12 @@ static int ipv6_rx ( struct io_buffer *iobuf, struct net_device *netdev,
src.sin6.sin6_family = AF_INET6;
memcpy ( &src.sin6.sin6_addr, &iphdr->src,
sizeof ( src.sin6.sin6_addr ) );
- src.sin6.sin6_scope_id = netdev->index;
+ src.sin6.sin6_scope_id = netdev->scope_id;
memset ( &dest, 0, sizeof ( dest ) );
dest.sin6.sin6_family = AF_INET6;
memcpy ( &dest.sin6.sin6_addr, &iphdr->dest,
sizeof ( dest.sin6.sin6_addr ) );
- dest.sin6.sin6_scope_id = netdev->index;
+ dest.sin6.sin6_scope_id = netdev->scope_id;
iob_pull ( iobuf, hdrlen );
pshdr_csum = ipv6_pshdr_chksum ( iphdr, iob_len ( iobuf ),
next_header, TCPIP_EMPTY_CSUM );
@@ -957,7 +957,7 @@ static const char * ipv6_sock_ntoa ( struct sockaddr *sa ) {
/* Identify network device, if applicable */
if ( IN6_IS_ADDR_LINKLOCAL ( in ) || IN6_IS_ADDR_MULTICAST ( in ) ) {
- netdev = find_netdev_by_index ( sin6->sin6_scope_id );
+ netdev = find_netdev_by_scope_id ( sin6->sin6_scope_id );
netdev_name = ( netdev ? netdev->name : "UNKNOWN" );
} else {
netdev_name = NULL;
@@ -1020,7 +1020,7 @@ static int ipv6_sock_aton ( const char *string, struct sockaddr *sa ) {
rc = -ENODEV;
goto err_find_netdev;
}
- sin6->sin6_scope_id = netdev->index;
+ sin6->sin6_scope_id = netdev->scope_id;
} else if ( IN6_IS_ADDR_LINKLOCAL ( &in ) ||
IN6_IS_ADDR_MULTICAST ( &in ) ) {
@@ -1031,7 +1031,7 @@ static int ipv6_sock_aton ( const char *string, struct sockaddr *sa ) {
*/
netdev = last_opened_netdev();
if ( netdev )
- sin6->sin6_scope_id = netdev->index;
+ sin6->sin6_scope_id = netdev->scope_id;
}
/* Copy IPv6 address portion to socket address */
diff --git a/src/net/ndp.c b/src/net/ndp.c
index c8e8ebad..373a9360 100644
--- a/src/net/ndp.c
+++ b/src/net/ndp.c
@@ -140,7 +140,7 @@ static int ndp_tx_request ( struct net_device *netdev,
/* Construct multicast destination address */
memset ( &sin6_dest, 0, sizeof ( sin6_dest ) );
sin6_dest.sin6_family = AF_INET6;
- sin6_dest.sin6_scope_id = netdev->index;
+ sin6_dest.sin6_scope_id = netdev->scope_id;
ipv6_solicited_node ( &sin6_dest.sin6_addr, net_dest );
/* Construct neighbour header */
@@ -177,7 +177,7 @@ static int ndp_tx_router_solicitation ( struct net_device *netdev ) {
/* Construct multicast destination address */
memset ( &sin6_dest, 0, sizeof ( sin6_dest ) );
sin6_dest.sin6_family = AF_INET6;
- sin6_dest.sin6_scope_id = netdev->index;
+ sin6_dest.sin6_scope_id = netdev->scope_id;
ipv6_all_routers ( &sin6_dest.sin6_addr );
/* Construct router solicitation */
diff --git a/src/net/netdevice.c b/src/net/netdevice.c
index 51d1831c..597c6228 100644
--- a/src/net/netdevice.c
+++ b/src/net/netdevice.c
@@ -55,9 +55,6 @@ struct list_head net_devices = LIST_HEAD_INIT ( net_devices );
/** List of open network devices, in reverse order of opening */
static struct list_head open_net_devices = LIST_HEAD_INIT ( open_net_devices );
-/** Network device index */
-static unsigned int netdev_index = 0;
-
/** Network polling profiler */
static struct profiler net_poll_profiler __profiler = { .name = "net.poll" };
@@ -723,6 +720,7 @@ int register_netdev ( struct net_device *netdev ) {
struct ll_protocol *ll_protocol = netdev->ll_protocol;
struct net_driver *driver;
struct net_device *duplicate;
+ unsigned int i;
uint32_t seed;
int rc;
@@ -757,12 +755,21 @@ int register_netdev ( struct net_device *netdev ) {
goto err_duplicate;
}
- /* Record device index and create device name */
+ /* Assign a unique device name, if not already set */
if ( netdev->name[0] == '\0' ) {
- snprintf ( netdev->name, sizeof ( netdev->name ), "net%d",
- netdev_index );
+ for ( i = 0 ; ; i++ ) {
+ snprintf ( netdev->name, sizeof ( netdev->name ),
+ "net%d", i );
+ if ( find_netdev ( netdev->name ) == NULL )
+ break;
+ }
+ }
+
+ /* Assign a unique non-zero scope ID */
+ for ( netdev->scope_id = 1 ; ; netdev->scope_id++ ) {
+ if ( find_netdev_by_scope_id ( netdev->scope_id ) == NULL )
+ break;
}
- netdev->index = ++netdev_index;
/* Use least significant bits of the link-layer address to
* improve the randomness of the (non-cryptographic) random
@@ -916,10 +923,6 @@ void unregister_netdev ( struct net_device *netdev ) {
DBGC ( netdev, "NETDEV %s unregistered\n", netdev->name );
list_del ( &netdev->list );
netdev_put ( netdev );
-
- /* Reset network device index if no devices remain */
- if ( list_empty ( &net_devices ) )
- netdev_index = 0;
}
/** Enable or disable interrupts
@@ -962,17 +965,17 @@ struct net_device * find_netdev ( const char *name ) {
}
/**
- * Get network device by index
+ * Get network device by scope ID
*
* @v index Network device index
* @ret netdev Network device, or NULL
*/
-struct net_device * find_netdev_by_index ( unsigned int index ) {
+struct net_device * find_netdev_by_scope_id ( unsigned int scope_id ) {
struct net_device *netdev;
/* Identify network device by index */
list_for_each_entry ( netdev, &net_devices, list ) {
- if ( netdev->index == index )
+ if ( netdev->scope_id == scope_id )
return netdev;
}
diff --git a/src/net/peerdisc.c b/src/net/peerdisc.c
index d7e0d298..86ff94a8 100644
--- a/src/net/peerdisc.c
+++ b/src/net/peerdisc.c
@@ -189,7 +189,7 @@ static void peerdisc_socket_tx ( const char *uuid, const char *id ) {
/* Skip unopened network devices */
if ( ! netdev_is_open ( netdev ) )
continue;
- address.st.st_scope_id = netdev->index;
+ address.st.st_scope_id = netdev->scope_id;
/* Discard request (for test purposes) if applicable */
if ( inject_fault ( PEERDISC_DISCARD_RATE ) )
diff --git a/src/net/udp/dhcpv6.c b/src/net/udp/dhcpv6.c
index 253032e4..28c6f7be 100644
--- a/src/net/udp/dhcpv6.c
+++ b/src/net/udp/dhcpv6.c
@@ -955,7 +955,7 @@ int start_dhcpv6 ( struct interface *job, struct net_device *netdev,
addresses.client.sin6.sin6_port = htons ( DHCPV6_CLIENT_PORT );
addresses.server.sin6.sin6_family = AF_INET6;
ipv6_all_dhcp_relay_and_servers ( &addresses.server.sin6.sin6_addr );
- addresses.server.sin6.sin6_scope_id = netdev->index;
+ addresses.server.sin6.sin6_scope_id = netdev->scope_id;
addresses.server.sin6.sin6_port = htons ( DHCPV6_SERVER_PORT );
/* Construct client DUID from system UUID */
diff --git a/src/tests/ipv6_test.c b/src/tests/ipv6_test.c
index de8edc8a..3b7d813a 100644
--- a/src/tests/ipv6_test.c
+++ b/src/tests/ipv6_test.c
@@ -127,7 +127,7 @@ static const struct in6_addr sample_multicast = {
/** Dummy network device used for routing tests */
static struct net_device ipv6_test_netdev = {
.refcnt = REF_INIT ( ref_no_free ),
- .index = 42,
+ .scope_id = 42,
.state = NETDEV_OPEN,
};
@@ -349,7 +349,7 @@ static void ipv6_route_okx ( struct ipv6_test_table *table, const char *dest,
/* Perform routing */
actual = &in_dest;
- miniroute = ipv6_route ( ipv6_test_netdev.index, &actual );
+ miniroute = ipv6_route ( ipv6_test_netdev.scope_id, &actual );
/* Validate result */
if ( src ) {