aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2023-09-13 16:29:59 +0100
committerMichael Brown <mcb30@ipxe.org>2023-09-13 16:29:59 +0100
commitf2c4623735929c733114efb04551995c8555ea5d (patch)
tree1c4c6427ef74e7e81e0d1a986e15b55f63493d8d
parenteeb7cd56e54e2bc649626988872c170fba37c163 (diff)
downloadipxe-netstate.zip
ipxe-netstate.tar.gz
ipxe-netstate.tar.bz2
[netdevice] Allocate private data for each network upper-layer drivernetstate
Allow network upper-layer drivers (such as LLDP, which attaches to each network device in order to provide a corresponding LLDP settings block) to specify a size for private data, which will be allocated as part of the network device structure (as with the existing private data allocated for the underlying device driver). This will allow network upper-layer drivers to be simplified by omitting memory allocation and freeing code. If the upper-layer driver requires a reference counter (e.g. for interface initialisation), then it may use the network device's existing reference counter, since this is now the reference counter for the containing block of memory. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/arch/x86/interface/pxe/pxe_call.c3
-rw-r--r--src/arch/x86/interface/vmware/guestinfo.c8
-rw-r--r--src/core/cachedhcp.c3
-rw-r--r--src/drivers/net/netfront.c4
-rw-r--r--src/include/ipxe/netdevice.h11
-rw-r--r--src/interface/efi/efi_snp.c9
-rw-r--r--src/net/fcoe.c9
-rw-r--r--src/net/infiniband/xsigo.c4
-rw-r--r--src/net/ipv6.c4
-rw-r--r--src/net/lldp.c3
-rw-r--r--src/net/neighbour.c3
-rw-r--r--src/net/netdevice.c73
-rw-r--r--src/net/vlan.c9
13 files changed, 109 insertions, 34 deletions
diff --git a/src/arch/x86/interface/pxe/pxe_call.c b/src/arch/x86/interface/pxe/pxe_call.c
index 6711829..0e8d5c5 100644
--- a/src/arch/x86/interface/pxe/pxe_call.c
+++ b/src/arch/x86/interface/pxe/pxe_call.c
@@ -375,9 +375,10 @@ int pxe_start_nbp ( void ) {
* Notify BIOS of existence of network device
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int pxe_notify ( struct net_device *netdev ) {
+static int pxe_notify ( struct net_device *netdev, void *priv __unused ) {
/* Do nothing if we already have a network device */
if ( pxe_netdev )
diff --git a/src/arch/x86/interface/vmware/guestinfo.c b/src/arch/x86/interface/vmware/guestinfo.c
index a0530c8..b52c2e8 100644
--- a/src/arch/x86/interface/vmware/guestinfo.c
+++ b/src/arch/x86/interface/vmware/guestinfo.c
@@ -207,9 +207,11 @@ struct init_fn guestinfo_init_fn __init_fn ( INIT_NORMAL ) = {
* Create per-netdevice GuestInfo settings
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int guestinfo_net_probe ( struct net_device *netdev ) {
+static int guestinfo_net_probe ( struct net_device *netdev,
+ void *priv __unused ) {
struct settings *settings;
int rc;
@@ -247,8 +249,10 @@ static int guestinfo_net_probe ( struct net_device *netdev ) {
* Remove per-netdevice GuestInfo settings
*
* @v netdev Network device
+ * @v priv Private data
*/
-static void guestinfo_net_remove ( struct net_device *netdev ) {
+static void guestinfo_net_remove ( struct net_device *netdev,
+ void *priv __unused ) {
struct settings *parent = netdev_settings ( netdev );
struct settings *settings;
diff --git a/src/core/cachedhcp.c b/src/core/cachedhcp.c
index 60213f0..57226e1 100644
--- a/src/core/cachedhcp.c
+++ b/src/core/cachedhcp.c
@@ -295,9 +295,10 @@ struct startup_fn cachedhcp_startup_fn __startup_fn ( STARTUP_LATE ) = {
* Apply cached DHCPACK to network device, if applicable
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int cachedhcp_probe ( struct net_device *netdev ) {
+static int cachedhcp_probe ( struct net_device *netdev, void *priv __unused ) {
/* Apply cached DHCPACK to network device, if applicable */
return cachedhcp_apply ( &cached_dhcpack, netdev );
diff --git a/src/drivers/net/netfront.c b/src/drivers/net/netfront.c
index 90930a5..12713c5 100644
--- a/src/drivers/net/netfront.c
+++ b/src/drivers/net/netfront.c
@@ -1056,9 +1056,11 @@ struct xen_driver netfront_driver __xen_driver = {
* Inhibit emulated PCI devices
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int netfront_net_probe ( struct net_device *netdev ) {
+static int netfront_net_probe ( struct net_device *netdev,
+ void *priv __unused ) {
struct netfront_nic *netfront;
/* Inhibit emulated PCI devices matching an existing netfront device */
diff --git a/src/include/ipxe/netdevice.h b/src/include/ipxe/netdevice.h
index a65dbfd..16db413 100644
--- a/src/include/ipxe/netdevice.h
+++ b/src/include/ipxe/netdevice.h
@@ -473,22 +473,27 @@ struct net_device {
struct net_driver {
/** Name */
const char *name;
+ /** Size of private data */
+ size_t priv_len;
/** Probe device
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
- int ( * probe ) ( struct net_device *netdev );
+ int ( * probe ) ( struct net_device *netdev, void *priv );
/** Notify of device or link state change
*
* @v netdev Network device
+ * @v priv Private data
*/
- void ( * notify ) ( struct net_device *netdev );
+ void ( * notify ) ( struct net_device *netdev, void *priv );
/** Remove device
*
* @v netdev Network device
+ * @v priv Private data
*/
- void ( * remove ) ( struct net_device *netdev );
+ void ( * remove ) ( struct net_device *netdev, void *priv );
};
/** Network driver table */
diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c
index c4f7d4e..8443be9 100644
--- a/src/interface/efi/efi_snp.c
+++ b/src/interface/efi/efi_snp.c
@@ -1777,9 +1777,10 @@ static struct efi_snp_device * efi_snp_demux ( struct net_device *netdev ) {
* Create SNP device
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int efi_snp_probe ( struct net_device *netdev ) {
+static int efi_snp_probe ( struct net_device *netdev, void *priv __unused ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_device *efidev;
struct efi_snp_device *snpdev;
@@ -2017,8 +2018,9 @@ static int efi_snp_probe ( struct net_device *netdev ) {
* Handle SNP device or link state change
*
* @v netdev Network device
+ * @v priv Private data
*/
-static void efi_snp_notify ( struct net_device *netdev ) {
+static void efi_snp_notify ( struct net_device *netdev, void *priv __unused ) {
struct efi_snp_device *snpdev;
/* Locate SNP device */
@@ -2042,8 +2044,9 @@ static void efi_snp_notify ( struct net_device *netdev ) {
* Destroy SNP device
*
* @v netdev Network device
+ * @v priv Private data
*/
-static void efi_snp_remove ( struct net_device *netdev ) {
+static void efi_snp_remove ( struct net_device *netdev, void *priv __unused ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_snp_device *snpdev;
int leak = efi_shutdown_in_progress;
diff --git a/src/net/fcoe.c b/src/net/fcoe.c
index f910eee..70804dd 100644
--- a/src/net/fcoe.c
+++ b/src/net/fcoe.c
@@ -1110,9 +1110,10 @@ static void fcoe_expired ( struct retry_timer *timer, int over __unused ) {
* Create FCoE port
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int fcoe_probe ( struct net_device *netdev ) {
+static int fcoe_probe ( struct net_device *netdev, void *priv __unused ) {
struct ll_protocol *ll_protocol = netdev->ll_protocol;
struct fcoe_port *fcoe;
int rc;
@@ -1162,8 +1163,9 @@ static int fcoe_probe ( struct net_device *netdev ) {
* Handle FCoE port device or link state change
*
* @v netdev Network device
+ * @v priv Private data
*/
-static void fcoe_notify ( struct net_device *netdev ) {
+static void fcoe_notify ( struct net_device *netdev, void *priv __unused ) {
struct fcoe_port *fcoe;
/* Sanity check */
@@ -1185,8 +1187,9 @@ static void fcoe_notify ( struct net_device *netdev ) {
* Destroy FCoE port
*
* @v netdev Network device
+ * @v priv Private data
*/
-static void fcoe_remove ( struct net_device *netdev ) {
+static void fcoe_remove ( struct net_device *netdev, void *priv __unused ) {
struct fcoe_port *fcoe;
/* Sanity check */
diff --git a/src/net/infiniband/xsigo.c b/src/net/infiniband/xsigo.c
index 4f5c618..5e805fa 100644
--- a/src/net/infiniband/xsigo.c
+++ b/src/net/infiniband/xsigo.c
@@ -1829,8 +1829,10 @@ struct ib_driver xsigo_ib_driver __ib_driver = {
* Handle device or link status change
*
* @v netdev Network device
+ * @v priv Private data
*/
-static void xsigo_net_notify ( struct net_device *netdev ) {
+static void xsigo_net_notify ( struct net_device *netdev,
+ void *priv __unused ) {
struct xsigo_device *xdev;
struct ib_device *ibdev;
struct xsigo_manager *xcm;
diff --git a/src/net/ipv6.c b/src/net/ipv6.c
index ef5e51d..a0173df 100644
--- a/src/net/ipv6.c
+++ b/src/net/ipv6.c
@@ -1224,9 +1224,11 @@ struct ipv6_settings {
* Register IPv6 link-local address settings
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int ipv6_register_settings ( struct net_device *netdev ) {
+static int ipv6_register_settings ( struct net_device *netdev,
+ void *priv __unused ) {
struct settings *parent = netdev_settings ( netdev );
struct ipv6_settings *ipv6set;
int rc;
diff --git a/src/net/lldp.c b/src/net/lldp.c
index 72e3ecd..2ef32cb 100644
--- a/src/net/lldp.c
+++ b/src/net/lldp.c
@@ -296,9 +296,10 @@ struct net_protocol lldp_protocol __net_protocol = {
* Create LLDP settings block
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int lldp_probe ( struct net_device *netdev ) {
+static int lldp_probe ( struct net_device *netdev, void *priv __unused ) {
struct lldp_settings *lldpset;
int rc;
diff --git a/src/net/neighbour.c b/src/net/neighbour.c
index 7f66d99..13a8bc3 100644
--- a/src/net/neighbour.c
+++ b/src/net/neighbour.c
@@ -383,8 +383,9 @@ int neighbour_define ( struct net_device *netdev,
* Update neighbour cache on network device state change or removal
*
* @v netdev Network device
+ * @v priv Private data
*/
-static void neighbour_flush ( struct net_device *netdev ) {
+static void neighbour_flush ( struct net_device *netdev, void *priv __unused ) {
struct neighbour *neighbour;
struct neighbour *tmp;
diff --git a/src/net/netdevice.c b/src/net/netdevice.c
index 9151782..ff08071 100644
--- a/src/net/netdevice.c
+++ b/src/net/netdevice.c
@@ -110,16 +110,64 @@ static int netdev_has_ll_addr ( struct net_device *netdev ) {
}
/**
+ * Get offset of network device driver private data
+ *
+ * @v driver Upper-layer driver, or NULL for device driver
+ * @ret offset Offset of driver private data
+ */
+static size_t netdev_priv_offset ( struct net_driver *driver ) {
+ struct net_device *netdev;
+ unsigned int num_configs;
+ size_t offset;
+
+ /* Allow space for network device */
+ offset = sizeof ( *netdev );
+
+ /* Allow space for configurations */
+ num_configs = table_num_entries ( NET_DEVICE_CONFIGURATORS );
+ offset += ( num_configs * sizeof ( netdev->configs[0] ) );
+
+ /* Place variable-length device driver private data at end */
+ if ( ! driver )
+ driver = table_end ( NET_DRIVERS );
+
+ /* Allow space for preceding upper-layer drivers' private data */
+ for_each_table_entry_continue_reverse ( driver, NET_DRIVERS ) {
+ offset += driver->priv_len;
+ }
+
+ /* Sanity check */
+ assert ( ( offset & ( sizeof ( void * ) - 1 ) ) == 0 );
+
+ return offset;
+}
+
+/**
+ * Get network device driver private data
+ *
+ * @v netdev Network device
+ * @v driver Upper-layer driver, or NULL for device driver
+ * @ret priv Driver private data
+ */
+static void * netdev_priv ( struct net_device *netdev,
+ struct net_driver *driver ) {
+
+ return ( ( ( void * ) netdev ) + netdev_priv_offset ( driver ) );
+}
+
+/**
* Notify drivers of network device or link state change
*
* @v netdev Network device
*/
static void netdev_notify ( struct net_device *netdev ) {
struct net_driver *driver;
+ void *priv;
for_each_table_entry ( driver, NET_DRIVERS ) {
+ priv = netdev_priv ( netdev, driver );
if ( driver->notify )
- driver->notify ( netdev );
+ driver->notify ( netdev, priv );
}
}
@@ -675,14 +723,8 @@ struct net_device * alloc_netdev ( size_t priv_len ) {
struct net_device *netdev;
struct net_device_configurator *configurator;
struct net_device_configuration *config;
- unsigned int num_configs;
- size_t confs_len;
- size_t total_len;
- num_configs = table_num_entries ( NET_DEVICE_CONFIGURATORS );
- confs_len = ( num_configs * sizeof ( netdev->configs[0] ) );
- total_len = ( sizeof ( *netdev ) + confs_len + priv_len );
- netdev = zalloc ( total_len );
+ netdev = zalloc ( netdev_priv_offset ( NULL ) + priv_len );
if ( netdev ) {
ref_init ( &netdev->refcnt, free_netdev );
netdev->link_rc = -EUNKNOWN_LINK_STATUS;
@@ -701,8 +743,7 @@ struct net_device * alloc_netdev ( size_t priv_len ) {
&netdev->refcnt );
config++;
}
- netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) +
- confs_len );
+ netdev->priv = netdev_priv ( netdev, NULL );
}
return netdev;
}
@@ -722,6 +763,7 @@ int register_netdev ( struct net_device *netdev ) {
struct net_device *duplicate;
unsigned int i;
uint32_t seed;
+ void *priv;
int rc;
/* Set initial link-layer address, if not already set */
@@ -784,7 +826,9 @@ int register_netdev ( struct net_device *netdev ) {
/* Probe device */
for_each_table_entry ( driver, NET_DRIVERS ) {
- if ( driver->probe && ( rc = driver->probe ( netdev ) ) != 0 ) {
+ priv = netdev_priv ( netdev, driver );
+ if ( driver->probe &&
+ ( rc = driver->probe ( netdev, priv ) ) != 0 ) {
DBGC ( netdev, "NETDEV %s could not add %s device: "
"%s\n", netdev->name, driver->name,
strerror ( rc ) );
@@ -796,8 +840,9 @@ int register_netdev ( struct net_device *netdev ) {
err_probe:
for_each_table_entry_continue_reverse ( driver, NET_DRIVERS ) {
+ priv = netdev_priv ( netdev, driver );
if ( driver->remove )
- driver->remove ( netdev );
+ driver->remove ( netdev, priv );
}
clear_settings ( netdev_settings ( netdev ) );
unregister_settings ( netdev_settings ( netdev ) );
@@ -896,14 +941,16 @@ void netdev_close ( struct net_device *netdev ) {
*/
void unregister_netdev ( struct net_device *netdev ) {
struct net_driver *driver;
+ void *priv;
/* Ensure device is closed */
netdev_close ( netdev );
/* Remove device */
for_each_table_entry_reverse ( driver, NET_DRIVERS ) {
+ priv = netdev_priv ( netdev, driver );
if ( driver->remove )
- driver->remove ( netdev );
+ driver->remove ( netdev, priv );
}
/* Unregister per-netdev configuration settings */
diff --git a/src/net/vlan.c b/src/net/vlan.c
index d73a957..c61bb85 100644
--- a/src/net/vlan.c
+++ b/src/net/vlan.c
@@ -470,9 +470,10 @@ void vlan_auto ( const void *ll_addr, unsigned int tag ) {
* Create automatic VLAN device
*
* @v trunk Trunk network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int vlan_probe ( struct net_device *trunk ) {
+static int vlan_probe ( struct net_device *trunk, void *priv __unused ) {
int rc;
/* Do nothing unless an automatic VLAN exists */
@@ -498,8 +499,9 @@ static int vlan_probe ( struct net_device *trunk ) {
* Handle trunk network device link state change
*
* @v trunk Trunk network device
+ * @v priv Private data
*/
-static void vlan_notify ( struct net_device *trunk ) {
+static void vlan_notify ( struct net_device *trunk, void *priv __unused ) {
struct net_device *netdev;
struct vlan_device *vlan;
@@ -538,8 +540,9 @@ static int vlan_remove_first ( struct net_device *trunk ) {
* Destroy all VLAN devices for a given trunk
*
* @v trunk Trunk network device
+ * @v priv Private data
*/
-static void vlan_remove ( struct net_device *trunk ) {
+static void vlan_remove ( struct net_device *trunk, void *priv __unused ) {
/* Remove all VLAN devices attached to this trunk, safe
* against arbitrary net device removal.