summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2024-04-02 20:36:00 +0200
committerMichael Brown2024-04-02 23:59:50 +0200
commitb940d54235579f2534c12494322876fff555cf36 (patch)
treec01091023d13a54e37f0a18b183e41bbf705e721
parent[efi] Add the ability to create a temporary MNP network device (diff)
downloadipxe-b940d54235579f2534c12494322876fff555cf36.tar.gz
ipxe-b940d54235579f2534c12494322876fff555cf36.tar.xz
ipxe-b940d54235579f2534c12494322876fff555cf36.zip
[cachedhcp] Allow cached DHCPACK to apply to temporary network devices
Retain a reference to the cached DHCPACK until the late startup phase, and allow it to be recycled for reuse. This allows the cached DHCPACK to be used for a temporary MNP network device and then subsequently reused for the corresponding real network device. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/core/cachedhcp.c75
-rw-r--r--src/drivers/net/efi/mnpnet.c4
-rw-r--r--src/include/ipxe/cachedhcp.h2
3 files changed, 71 insertions, 10 deletions
diff --git a/src/core/cachedhcp.c b/src/core/cachedhcp.c
index 57226e16..04945e64 100644
--- a/src/core/cachedhcp.c
+++ b/src/core/cachedhcp.c
@@ -46,11 +46,20 @@ struct cached_dhcp_packet {
struct dhcp_packet *dhcppkt;
/** VLAN tag (if applicable) */
unsigned int vlan;
+ /** Flags */
+ unsigned int flags;
};
+/** Cached DHCP packet should be retained */
+#define CACHEDHCP_RETAIN 0x0001
+
+/** Cached DHCP packet has been used */
+#define CACHEDHCP_USED 0x0002
+
/** Cached DHCPACK */
struct cached_dhcp_packet cached_dhcpack = {
.name = DHCP_SETTINGS_NAME,
+ .flags = CACHEDHCP_RETAIN,
};
/** Cached ProxyDHCPOFFER */
@@ -101,8 +110,8 @@ static int cachedhcp_apply ( struct cached_dhcp_packet *cache,
size_t ll_addr_len;
int rc;
- /* Do nothing if cache is empty */
- if ( ! cache->dhcppkt )
+ /* Do nothing if cache is empty or already in use */
+ if ( ( ! cache->dhcppkt ) || ( cache->flags & CACHEDHCP_USED ) )
return 0;
chaddr = cache->dhcppkt->dhcphdr->chaddr;
@@ -169,8 +178,12 @@ static int cachedhcp_apply ( struct cached_dhcp_packet *cache,
return rc;
}
- /* Free cached DHCP packet */
- cachedhcp_free ( cache );
+ /* Mark as used */
+ cache->flags |= CACHEDHCP_USED;
+
+ /* Free cached DHCP packet, if applicable */
+ if ( ! ( cache->flags & CACHEDHCP_RETAIN ) )
+ cachedhcp_free ( cache );
return 0;
}
@@ -246,10 +259,10 @@ int cachedhcp_record ( struct cached_dhcp_packet *cache, unsigned int vlan,
}
/**
- * Cached DHCP packet startup function
+ * Cached DHCP packet early startup function
*
*/
-static void cachedhcp_startup ( void ) {
+static void cachedhcp_startup_early ( void ) {
/* Apply cached ProxyDHCPOFFER, if any */
cachedhcp_apply ( &cached_proxydhcp, NULL );
@@ -258,6 +271,20 @@ static void cachedhcp_startup ( void ) {
/* Apply cached PXEBSACK, if any */
cachedhcp_apply ( &cached_pxebs, NULL );
cachedhcp_free ( &cached_pxebs );
+}
+
+/**
+ * Cache DHCP packet late startup function
+ *
+ */
+static void cachedhcp_startup_late ( void ) {
+
+ /* Clear retention flag */
+ cached_dhcpack.flags &= ~CACHEDHCP_RETAIN;
+
+ /* Free cached DHCPACK, if used by a network device */
+ if ( cached_dhcpack.flags & CACHEDHCP_USED )
+ cachedhcp_free ( &cached_dhcpack );
/* Report unclaimed DHCPACK, if any. Do not free yet, since
* it may still be claimed by a dynamically created device
@@ -284,10 +311,16 @@ static void cachedhcp_shutdown ( int booting __unused ) {
cachedhcp_free ( &cached_dhcpack );
}
-/** Cached DHCPACK startup function */
-struct startup_fn cachedhcp_startup_fn __startup_fn ( STARTUP_LATE ) = {
- .name = "cachedhcp",
- .startup = cachedhcp_startup,
+/** Cached DHCP packet early startup function */
+struct startup_fn cachedhcp_early_fn __startup_fn ( STARTUP_EARLY ) = {
+ .name = "cachedhcp1",
+ .startup = cachedhcp_startup_early,
+};
+
+/** Cached DHCP packet late startup function */
+struct startup_fn cachedhcp_late_fn __startup_fn ( STARTUP_LATE ) = {
+ .name = "cachedhcp2",
+ .startup = cachedhcp_startup_late,
.shutdown = cachedhcp_shutdown,
};
@@ -309,3 +342,25 @@ struct net_driver cachedhcp_driver __net_driver = {
.name = "cachedhcp",
.probe = cachedhcp_probe,
};
+
+/**
+ * Recycle cached DHCPACK
+ *
+ * @v netdev Network device
+ * @v priv Private data
+ */
+void cachedhcp_recycle ( struct net_device *netdev ) {
+ struct cached_dhcp_packet *cache = &cached_dhcpack;
+ struct settings *settings;
+
+ /* Return DHCPACK to cache, if applicable */
+ settings = find_child_settings ( netdev_settings ( netdev ),
+ cache->name );
+ if ( cache->dhcppkt && ( settings == &cache->dhcppkt->settings ) ) {
+ DBGC ( colour, "CACHEDHCP %s recycled from %s\n",
+ cache->name, netdev->name );
+ assert ( cache->flags & CACHEDHCP_USED );
+ unregister_settings ( settings );
+ cache->flags &= ~CACHEDHCP_USED;
+ }
+}
diff --git a/src/drivers/net/efi/mnpnet.c b/src/drivers/net/efi/mnpnet.c
index 84f803f4..eb4b129c 100644
--- a/src/drivers/net/efi/mnpnet.c
+++ b/src/drivers/net/efi/mnpnet.c
@@ -34,6 +34,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/iobuf.h>
#include <ipxe/netdevice.h>
#include <ipxe/ethernet.h>
+#include <ipxe/cachedhcp.h>
#include <ipxe/efi/efi.h>
#include <ipxe/efi/efi_driver.h>
#include <ipxe/efi/efi_service.h>
@@ -551,6 +552,9 @@ void mnptemp_destroy ( struct net_device *netdev ) {
struct mnp_nic *mnp = netdev->priv;
struct efi_device *efidev = mnp->efidev;
+ /* Recycle any cached DHCP packet */
+ cachedhcp_recycle ( netdev );
+
/* Stop temporary network device */
mnpnet_stop ( efidev );
diff --git a/src/include/ipxe/cachedhcp.h b/src/include/ipxe/cachedhcp.h
index 4ce4a9f2..8ebee3b7 100644
--- a/src/include/ipxe/cachedhcp.h
+++ b/src/include/ipxe/cachedhcp.h
@@ -12,6 +12,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stddef.h>
#include <ipxe/uaccess.h>
+struct net_device;
struct cached_dhcp_packet;
extern struct cached_dhcp_packet cached_dhcpack;
@@ -21,5 +22,6 @@ extern struct cached_dhcp_packet cached_pxebs;
extern int cachedhcp_record ( struct cached_dhcp_packet *cache,
unsigned int vlan, userptr_t data,
size_t max_len );
+extern void cachedhcp_recycle ( struct net_device *netdev );
#endif /* _IPXE_CACHEDHCP_H */