]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[netdevice] Allocate private data for each network upper-layer driver
authorMichael Brown <mcb30@ipxe.org>
Wed, 13 Sep 2023 15:29:59 +0000 (16:29 +0100)
committerMichael Brown <mcb30@ipxe.org>
Wed, 13 Sep 2023 19:23:46 +0000 (20:23 +0100)
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>
13 files changed:
src/arch/x86/interface/pxe/pxe_call.c
src/arch/x86/interface/vmware/guestinfo.c
src/core/cachedhcp.c
src/drivers/net/netfront.c
src/include/ipxe/netdevice.h
src/interface/efi/efi_snp.c
src/net/fcoe.c
src/net/infiniband/xsigo.c
src/net/ipv6.c
src/net/lldp.c
src/net/neighbour.c
src/net/netdevice.c
src/net/vlan.c

index 671182991c2141a753f5fa077d604b41ba9088c2..0e8d5c5a8706d8aefbe5c2cfdecbb19c12e4e59a 100644 (file)
@@ -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 )
index a0530c8d179daffc630b326a8cd0b8c8536ef4bb..b52c2e87bba1d308946b20301930a929c4534609 100644 (file)
@@ -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;
 
index 60213f02d182101f64b5509a33e87ba722bdff32..57226e1652ffb5ea556371fe56ab46e056f94563 100644 (file)
@@ -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 );
index 90930a5a3467fb8a644e772eb6050ce43d39f5f5..12713c5b41d18340dc5d6d442de0055133fe89d2 100644 (file)
@@ -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 */
index a65dbfd235f540b449d070368473fdc5db373434..caa83b44bd2acd3955e640b6d04ce12d6136cb99 100644 (file)
@@ -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 );
index c4f7d4ea89afccb53e96044948cdc0a655a240ec..8443be997eff6ae032b135b0fe7837916fd0cf5f 100644 (file)
@@ -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;
index f910eeeade644cdbe3107bcda3e35a1df5cf6040..70804dd0347113d64d4e782f4332d77fd9ac45e1 100644 (file)
@@ -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 */
index 4f5c618d79efb0f4426da186910479f2235ce92b..5e805fa0264c6da19769c4be2ee27c25148d9414 100644 (file)
@@ -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;
index ef5e51daa6a2b3cbd79ea5df1f96801d1c84ee4c..a0173dfb1df1e184491ce9e0c1d09f8ffeb6e307 100644 (file)
@@ -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;
index 72e3ecdf6924e25e66aa1b6323741504ca24f00b..2ef32cb0cef5a406db468d8d6561df1509d73797 100644 (file)
@@ -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;
 
index 7f66d9992c081166a8430e782a5dd01a97bc961c..13a8bc3ba050537e389f4eecea9705eb5f8241ba 100644 (file)
@@ -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;
 
index 91517821899561140fc7308421b8e90521fa8496..a9ed181346374722987db10f855e675c1f4fddeb 100644 (file)
@@ -109,6 +109,51 @@ static int netdev_has_ll_addr ( struct net_device *netdev ) {
        return 0;
 }
 
+/**
+ * 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
  *
@@ -116,10 +161,12 @@ static int netdev_has_ll_addr ( struct net_device *netdev ) {
  */
 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 */
index d73a957110efe802128ca8fac838e3cb9d353106..c61bb850e8d5214eabb13fcdd3cc8aadd94ef75b 100644 (file)
@@ -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.