A DHCP session holds a persistent reference to a network device
authorMichael Brown <mcb30@etherboot.org>
Thu, 4 Jan 2007 03:42:28 +0000 (03:42 +0000)
committerMichael Brown <mcb30@etherboot.org>
Thu, 4 Jan 2007 03:42:28 +0000 (03:42 +0000)
src/include/gpxe/dhcp.h
src/net/udp/dhcp.c

index 9ce8113..60991e7 100644 (file)
@@ -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;
index f810777..59dc807 100644 (file)
@@ -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 );
 }
@@ -689,6 +696,19 @@ static struct udp_operations dhcp_udp_operations = {
        .newdata        = dhcp_newdata,
 };
 
+/**
+ * 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
  *
@@ -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 );