Your message dated Sun, 1 Nov 2009 14:43:22 -0800
with message-id <20091101224322.ga3...@icarus.andrew.net.au>
has caused the   report #509089,
regarding dhcp lease negotiation takes longer than necessary
to be marked as having been forwarded to the upstream software
author(s) dhcp-b...@isc.org

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact ow...@bugs.debian.org
immediately.)


-- 
509089: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=509089
Debian Bug Tracking System
Contact ow...@bugs.debian.org with problems
--- Begin Message ---
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-d...@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 -----


--- End Message ---

Reply via email to