From ed0d7c4f6f8db7bda1e74567693a0c525b9cf159 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 10 Nov 2015 14:05:46 +0000 Subject: [PATCH] [dhcp] Limit maximum number of DHCP discovery deferrals For switches which remain permanently in the non-forwarding state (or which erroneously report a non-forwarding state), ensure that iPXE will eventually give up waiting for the link to become unblocked. Originally-fixed-by: Wissam Shoukair Signed-off-by: Michael Brown --- src/config/dhcp.h | 6 ++++++ src/net/udp/dhcp.c | 8 ++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/config/dhcp.h b/src/config/dhcp.h index 49fe16b9..bff5b56d 100644 --- a/src/config/dhcp.h +++ b/src/config/dhcp.h @@ -24,6 +24,12 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); //#define DHCP_DISC_START_TIMEOUT_SEC 4 /* as per PXE spec */ //#define DHCP_DISC_END_TIMEOUT_SEC 32 /* as per PXE spec */ +/* + * Maximum number of discovery deferrals due to blocked links + * (e.g. from non-forwarding STP ports) + */ +#define DHCP_DISC_MAX_DEFERRALS 60 + /* * ProxyDHCP offers are given precedence by continue to wait for them * after a valid DHCPOFFER is received. We'll wait through this diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c index 9c7b2fdc..9342ad21 100644 --- a/src/net/udp/dhcp.c +++ b/src/net/udp/dhcp.c @@ -444,7 +444,8 @@ static void dhcp_discovery_expired ( struct dhcp_session *dhcp ) { unsigned long elapsed = ( currticks() - dhcp->start ); /* If link is blocked, defer DHCP discovery (and reset timeout) */ - if ( netdev_link_blocked ( dhcp->netdev ) ) { + if ( netdev_link_blocked ( dhcp->netdev ) && + ( dhcp->count <= DHCP_DISC_MAX_DEFERRALS ) ) { DBGC ( dhcp, "DHCP %p deferring discovery\n", dhcp ); dhcp->start = currticks(); start_timer_fixed ( &dhcp->timer, @@ -1115,7 +1116,7 @@ static int dhcp_tx ( struct dhcp_session *dhcp ) { * session state into packet traces. Useful for extracting * debug information from non-debug builds. */ - dhcppkt.dhcphdr->secs = htons ( ( ++(dhcp->count) << 2 ) | + dhcppkt.dhcphdr->secs = htons ( ( dhcp->count << 2 ) | ( dhcp->offer.s_addr ? 0x02 : 0 ) | ( dhcp->proxy_offer ? 0x01 : 0 ) ); @@ -1259,6 +1260,9 @@ static void dhcp_timer_expired ( struct retry_timer *timer, int fail ) { return; } + /* Increment transmission counter */ + dhcp->count++; + /* Handle timer expiry based on current state */ dhcp->state->expired ( dhcp ); }