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 20:23:46 +0100
commitae4e85bde97c9b216736a5087039f3309a628d24 (patch)
tree39d706e2f330bd015d11ce38193c1baeab207cc8
parenteeb7cd56e54e2bc649626988872c170fba37c163 (diff)
downloadipxe-ae4e85bde97c9b216736a5087039f3309a628d24.zip
ipxe-ae4e85bde97c9b216736a5087039f3309a628d24.tar.gz
ipxe-ae4e85bde97c9b216736a5087039f3309a628d24.tar.bz2
[netdevice] Allocate private data for each network upper-layer driver
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.h13
-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.c72
-rw-r--r--src/net/vlan.c9
13 files changed, 110 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..caa83b4 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 */
@@ -688,6 +693,8 @@ netdev_rx_frozen ( struct net_device *netdev ) {
return ( netdev->state & NETDEV_RX_FROZEN );
}
+extern void * netdev_priv ( struct net_device *netdev,
+ struct net_driver *driver );
extern void netdev_rx_freeze ( struct net_device *netdev );
extern void netdev_rx_unfreeze ( struct net_device *netdev );
extern void netdev_link_err ( struct net_device *netdev, int rc );
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..a9ed181 100644
--- a/src/net/netdevice.c
+++ b/src/net/netdevice.c
@@ -110,16 +110,63 @@ 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
+ */
+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 +722,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 +742,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 +762,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 +825,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 +839,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 +940,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.