summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/gpxe/dhcp.h3
-rw-r--r--src/net/udp/dhcp.c24
2 files changed, 27 insertions, 0 deletions
diff --git a/src/include/gpxe/dhcp.h b/src/include/gpxe/dhcp.h
index 9ce8113d..60991e7e 100644
--- a/src/include/gpxe/dhcp.h
+++ b/src/include/gpxe/dhcp.h
@@ -13,6 +13,7 @@
#include <gpxe/udp.h>
#include <gpxe/async.h>
#include <gpxe/retry.h>
+#include <gpxe/hotplug.h>
/** BOOTP/DHCP server port */
#define BOOTPS_PORT 67
@@ -452,6 +453,8 @@ struct dhcp_session {
/** Network device being configured */
struct net_device *netdev;
+ /** Persistent reference to network device */
+ struct reference netdev_ref;
/** Options obtained from server */
struct dhcp_option_block *options;
diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c
index f8107777..59dc8071 100644
--- a/src/net/udp/dhcp.c
+++ b/src/net/udp/dhcp.c
@@ -498,6 +498,7 @@ udp_to_dhcp ( struct udp_connection *conn ) {
* @v rc Return status code
*/
static void dhcp_done ( struct dhcp_session *dhcp, int rc ) {
+
/* Free up options if we failed */
if ( rc != 0 ) {
if ( dhcp->options ) {
@@ -506,9 +507,15 @@ static void dhcp_done ( struct dhcp_session *dhcp, int rc ) {
}
}
+ /* Stop retry timer */
+ stop_timer ( &dhcp->timer );
+
/* Close UDP connection */
udp_close ( &dhcp->udp );
+ /* Release reference on net device */
+ ref_del ( &dhcp->netdev_ref );
+
/* Mark async operation as complete */
async_done ( &dhcp->aop, rc );
}
@@ -690,6 +697,19 @@ static struct udp_operations dhcp_udp_operations = {
};
/**
+ * Forget reference to net_device
+ *
+ * @v ref Persistent reference
+ */
+static void dhcp_forget_netdev ( struct reference *ref ) {
+ struct dhcp_session *dhcp
+ = container_of ( ref, struct dhcp_session, netdev_ref );
+
+ /* Kill DHCP session immediately */
+ dhcp_done ( dhcp, -ENETUNREACH );
+}
+
+/**
* Initiate DHCP on a network interface
*
* @v dhcp DHCP session
@@ -714,6 +734,10 @@ struct async_operation * start_dhcp ( struct dhcp_session *dhcp ) {
goto out;
}
+ /* Add persistent reference to net device */
+ dhcp->netdev_ref.forget = dhcp_forget_netdev;
+ ref_add ( &dhcp->netdev_ref, &dhcp->netdev->references );
+
/* Proof of concept: just send a single DHCPDISCOVER */
dhcp_send_request ( dhcp );