From 7fafa8925800f3b6caf4983efd731b0c680caa49 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 4 Jan 2007 03:42:28 +0000 Subject: [PATCH] A DHCP session holds a persistent reference to a network device --- src/include/gpxe/dhcp.h | 3 +++ src/net/udp/dhcp.c | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+) 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 #include #include +#include /** 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 ); } @@ -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 );