diff options
author | Michael Brown <mcb30@ipxe.org> | 2023-01-14 00:09:20 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2023-01-14 00:09:20 +0000 |
commit | 47af48012e2afaaf56108466fb967009670660bb (patch) | |
tree | 6548d6bf0626faddf1a1aefdc080dbd7b9590626 | |
parent | ab19546386b13d6c54aea1647fac06960c544efc (diff) | |
download | ipxe-47af48012e2afaaf56108466fb967009670660bb.zip ipxe-47af48012e2afaaf56108466fb967009670660bb.tar.gz ipxe-47af48012e2afaaf56108466fb967009670660bb.tar.bz2 |
[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.h | 6 | ||||
-rw-r--r-- | src/interface/efi/efi_pxe.c | 2 | ||||
-rw-r--r-- | src/interface/efi/efi_snp.c | 4 | ||||
-rw-r--r-- | src/net/ipv4.c | 2 | ||||
-rw-r--r-- | src/net/ipv6.c | 12 | ||||
-rw-r--r-- | src/net/ndp.c | 4 | ||||
-rw-r--r-- | src/net/netdevice.c | 31 | ||||
-rw-r--r-- | src/net/peerdisc.c | 2 | ||||
-rw-r--r-- | src/net/udp/dhcpv6.c | 2 | ||||
-rw-r--r-- | src/tests/ipv6_test.c | 4 |
10 files changed, 36 insertions, 33 deletions
diff --git a/src/include/ipxe/netdevice.h b/src/include/ipxe/netdevice.h index 294f7b3..29358db 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 15224a5..843ebb5 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 088a3fd..c4f7d4e 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 b9ce5e7..b91fa2a 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 901203c..ef5e51d 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 c8e8eba..373a936 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 51d1831..597c622 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 d7e0d29..86ff94a 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 253032e..28c6f7b 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 de8edc8..3b7d813 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 ) { |