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 */
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 *
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;
}
/**
*/
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 );
}
/**
/* 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 {
/* 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 */
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 );
/* 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;
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 ) ) {
*/
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 */
/* 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 */
/* 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 */
/** 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" };
struct ll_protocol *ll_protocol = netdev->ll_protocol;
struct net_driver *driver;
struct net_device *duplicate;
+ unsigned int i;
uint32_t seed;
int rc;
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
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
}
/**
- * 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;
}
/* 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 ) )
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 */
/** 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,
};
/* 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 ) {