Hi, I'm pretty certain that we discussed this bug when we last had lunch together, but I don't think I ever forwarded it upstream and got an upstream bug number for it, so here it is.
Please maintain the cc line to keep our bug tracking system in the loop. regards Andrew ----- Forwarded message from Michel Lespinasse <wal...@zoy.org> ----- Subject: Bug#509089: dhcp lease negotiation takes longer than necessary Reply-To: Michel Lespinasse <wal...@zoy.org>, 509...@bugs.debian.org Resent-From: Michel Lespinasse <wal...@zoy.org> Resent-To: debian-bugs-dist@lists.debian.org Resent-CC: Andrew Pollock <apoll...@debian.org> Resent-Date: Thu, 18 Dec 2008 08:18:02 +0000 Resent-Message-ID: <handler.509089.b.12295880094...@bugs.debian.org> Resent-Sender: ow...@bugs.debian.org X-Debian-PR-Message: report 509089 X-Debian-PR-Package: dhcp3-client X-Debian-PR-Keywords: patch X-Debian-PR-Source: dhcp3 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rietz.debian.org X-Spam-Level: X-Spam-Bayes: score:0.0000 Tokens: new, 154; hammy, 144; neutral, 267; spammy, 7. spammytokens:0.999-1--8396, 0.999-1--8398, 0.999-1--retransmit, 0.998-1--9477, 0.998-1--EXECUTE hammytokens:0.000-+--H*UA:1.5.13, 0.000-+--H*UA:2006-08-11, 0.000-+--H*u:1.5.13, 0.000-+--H*u:2006-08-11, 0.000-+--UD:conf X-Spam-Status: No, score=-9.1 required=4.0 tests=BAYES_00,FOURLA,HAS_PACKAGE, MDO_CABLE_TV3,MURPHY_DRUGS_REL8,MURPHY_SEX_L2,RCVD_IN_DNSWL_LOW autolearn=ham version=3.2.3-bugs.debian.org_2005_01_02 From: Michel Lespinasse <wal...@zoy.org> To: sub...@bugs.debian.org Package: dhcp3-client Version: 3.1.1-5 Tags: patch While trying to figure out why it takes so long to up an interface using dhcp, I had a look at the source code. It seemed to me that a lot of the delays were unnecessary. After fixing what I saw, it now takes about a quarter second to up an interface on my wired network - I thought I should send the patches here, in case there is an interest. dhcp3-client-1.diff fixes the delays between consecutive requests (the backoff algorithm). This algorithm is best explained in the following code comment: /* If we're supposed to increase the interval, do so. If it's currently zero (i.e., we haven't sent any packets yet), set it to initial_interval; otherwise, add to it a random number between zero and two times itself. On average, this means that it will double with every transmission. */ However contrary to what the comment indicates, client->interval has been initialised, before the first request is sent, to the initial_interval value rather than to 0. Because of that, the delay between the first two requests is, on average, double of the initial_interval value, instead of being equal to the initial_interval value. I'm proposing to change the initialization value to zero, in order to match the programmers expectations as documented in that comment, and to have the initial-interval option in dhclient.conf work as per the documented behavior. Additionally, I'm proposing to enforce that the delay between consecutive requests is always at least one second - this was already the case when using the default values, but could be messed with if setting an initial-interval of 0 or a backoff-cutoff of 1. Some people (see for example http://syn.theti.ca/ ) have been suggesting to use a backoff-cutoff of 1, so such configurations do exist in the wild. dhcp3-client-2.diff fixes a separate issue: the dhcp client was waiting a random delay, between 0 and 4 seconds, before sending the first dhcp request. The maximum delay was hardcoded and this behavior was not documented anywhere, but my guess is that this may have been intended to reduce dhcp floods when a large number of machines boot at the same time, following a power failure for example. It seems to me however, that such a delay is not necessary in many common situations, such as when running on a laptop with its own battery... I don't feel bold enough to just remove that random delay, but I think adding a new dhclient.conf option named initial-random-delay, which would default to 4 but be user-settable to any desired maximum random delay value, including 0 for no delay, is a reasonable proposal. Laptop users could then be encouraged to use initial-random-delay = 0. The third delay I identified was in the dhclient-script. The packaged script sleeps for one second after upping the interface with an ip address of 0 (this is, in the PREINIT stage before sending out the first dhcp request). A comment there says this is because the kernel needs some time to get the interface up. I believe this is not true of current kernels. In some situations, I can imagine that link negotiation could take a little time and cause packets to be lost during that interval, but this does not happen for the most common situations of using ifplugd or wpa-supplicant roaming, for example. Also even if it does happen in some wired situations, it seems that the worst case would be that the first request would get dropped and that a subsequent retransmit would work. So, I would propose to drop that one second delay as well. After implementing these proposed changes (as well as an additional change in ifplugd, as documented in bug 509015) I can get a wired dhcp connection within a quarter second of plugging in the ethernet cable. The only configuration parameter I need to apply is initial-random-delay=0 - the other parameters governing the backoff algorithm do not even have to be modified. Without these changes the dhcp connection would take anywhere from 2 to 7 seconds to negociate. Hope this helps, -- Michel "Walken" Lespinasse A program is never fully debugged until the last user dies. diff -ru dhcp3-3.1.1.orig/client/dhclient.c dhcp3-3.1.1/client/dhclient.c --- dhcp3-3.1.1.orig/client/dhclient.c 2008-12-16 22:06:57.000000000 -0800 +++ dhcp3-3.1.1/client/dhclient.c 2008-12-16 23:44:39.000000000 -0800 @@ -578,7 +579,7 @@ make_request (client, client -> active); client -> destination = iaddr_broadcast; client -> first_sending = cur_time; - client -> interval = client -> config -> initial_interval; + client -> interval = 0; /* Zap the medium list... */ client -> medium = (struct string_list *)0; @@ -604,7 +605,7 @@ client -> destination = iaddr_broadcast; client -> state = S_SELECTING; client -> first_sending = cur_time; - client -> interval = client -> config -> initial_interval; + client -> interval = 0; /* Add an immediate timeout to cause the first DHCPDISCOVER packet to go out. */ @@ -676,7 +677,7 @@ client -> destination = iaddr_broadcast; client -> state = S_REQUESTING; client -> first_sending = cur_time; - client -> interval = client -> config -> initial_interval; + client -> interval = 0; /* Make a DHCPREQUEST packet from the lease we picked. */ make_request (client, picked); @@ -947,7 +948,7 @@ client -> destination = iaddr_broadcast; client -> first_sending = cur_time; - client -> interval = client -> config -> initial_interval; + client -> interval = 0; client -> state = S_RENEWING; /* Send the first packet immediately. */ @@ -1487,6 +1488,10 @@ (client -> first_sending + client -> config -> timeout) - cur_time + 1; + /* Make sure the computed interval is at least one second. */ + if (!client->interval) + client->interval = 1; + /* Record the number of seconds since we started sending. */ if (interval < 65536) client -> packet.secs = htons (interval); @@ -1714,6 +1719,10 @@ client -> interval = client -> active -> expiry - cur_time + 1; + /* Make sure the computed interval is at least one second. */ + if (!client->interval) + client->interval = 1; + /* If the lease T2 time has elapsed, or if we're not yet bound, broadcast the DHCPREQUEST rather than unicasting. */ if (client -> state == S_REQUESTING || @@ -2882,7 +2891,7 @@ } else client -> destination = iaddr_broadcast; client -> first_sending = cur_time; - client -> interval = client -> config -> initial_interval; + client -> interval = 0; /* Zap the medium list... */ client -> medium = (struct string_list *)0; diff -ru dhcp3-3.1.1.orig/client/clparse.c dhcp3-3.1.1/client/clparse.c --- dhcp3-3.1.1.orig/client/clparse.c 2008-12-16 22:06:57.000000000 -0800 +++ dhcp3-3.1.1/client/clparse.c 2008-12-16 23:21:38.000000000 -0800 @@ -78,6 +78,7 @@ top_level_config.reboot_timeout = 10; top_level_config.retry_interval = 300; top_level_config.backoff_cutoff = 15; + top_level_config.initial_random_delay = 4; top_level_config.initial_interval = 3; top_level_config.bootp_policy = P_ACCEPT; top_level_config.script_name = path_dhclient_script; @@ -477,6 +478,11 @@ parse_lease_time (cfile, &config -> backoff_cutoff); return; + case INITIAL_RANDOM_DELAY: + token = next_token (&val, (unsigned *)0, cfile); + parse_lease_time (cfile, &config -> initial_random_delay); + return; + case INITIAL_INTERVAL: token = next_token (&val, (unsigned *)0, cfile); parse_lease_time (cfile, &config -> initial_interval); diff -ru dhcp3-3.1.1.orig/client/dhclient.c dhcp3-3.1.1/client/dhclient.c --- dhcp3-3.1.1.orig/client/dhclient.c 2008-12-16 22:06:57.000000000 -0800 +++ dhcp3-3.1.1/client/dhclient.c 2008-12-16 23:44:39.000000000 -0800 @@ -424,7 +424,8 @@ client -> state = S_INIT; /* Set up a timeout to start the initialization process. */ - add_timeout (cur_time + random () % 5, + add_timeout (cur_time + random () % + (client->config->initial_random_delay+1), state_reboot, client, 0, 0); } } @@ -3004,7 +3013,8 @@ client -> state = S_INIT; /* Set up a timeout to start the initialization process. */ - add_timeout (cur_time + random () % 5, + add_timeout (cur_time + random () % + (client->config->initial_random_delay+1), state_reboot, client, 0, 0); } } diff -ru dhcp3-3.1.1.orig/common/conflex.c dhcp3-3.1.1/common/conflex.c --- dhcp3-3.1.1.orig/common/conflex.c 2008-12-16 22:06:57.000000000 -0800 +++ dhcp3-3.1.1/common/conflex.c 2008-12-16 23:20:19.000000000 -0800 @@ -804,6 +804,8 @@ return IS; if (!strcasecmp (atom + 1, "gnore")) return IGNORE; + if (!strcasecmp (atom + 1, "nitial-random-delay")) + return INITIAL_RANDOM_DELAY; break; case 'k': if (!strncasecmp (atom + 1, "nown", 4)) { diff -ru dhcp3-3.1.1.orig/includes/dhcpd.h dhcp3-3.1.1/includes/dhcpd.h --- dhcp3-3.1.1.orig/includes/dhcpd.h 2008-12-16 22:06:59.000000000 -0800 +++ dhcp3-3.1.1/includes/dhcpd.h 2008-12-16 23:18:05.000000000 -0800 @@ -839,6 +839,8 @@ TIME timeout; /* Start to panic if we don't get a lease in this time period when SELECTING. */ + TIME initial_random_delay; /* Maximum random delay before sending + first request. */ TIME initial_interval; /* All exponential backoff intervals start here. */ TIME retry_interval; /* If the protocol failed to produce diff -ru dhcp3-3.1.1.orig/includes/dhctoken.h dhcp3-3.1.1/includes/dhctoken.h --- dhcp3-3.1.1.orig/includes/dhctoken.h 2008-12-16 22:06:59.000000000 -0800 +++ dhcp3-3.1.1/includes/dhctoken.h 2008-12-16 23:19:25.000000000 -0800 @@ -325,7 +325,8 @@ MIN_BALANCE = 629, DOMAIN_LIST = 630, LEASEQUERY = 631, - EXECUTE = 632 + EXECUTE = 632, + INITIAL_RANDOM_DELAY = 633 }; #define is_identifier(x) ((x) >= FIRST_TOKEN && \ ----- End forwarded message ----- -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org