[systemd-devel] [PATCH] libsystemd-network: Support setting DHCP client initial delay

2014-04-03 Thread Patrik Flykt
Section 4.4.1 in RFC 2131 says that a DHCP client SHOULD wait a
random time between one and ten seconds to desynchronize DHCP
clients on startup. This is supported such that the application
can optionally set an initial delay of approximately two and eight
seconds or leave the initial value unset relying only on any
machine specific randomness chosen for the main loop.

The maximum delay of slightly more than eight seconds was chosen
as it's more convenient to compute in addition to following RFC
2131 in spirit with a sensible margin towards the 17 years passed
since the exact wording of the document. The two second initial
delay variant was added to include a more neutral timeout hopefully
good enough on a very busy network. By default no initial delay is
added, as the implementation is geared towards maximum speed.

Thanks to Ted Lemon and to Jayson Vantul pointing out the reasons
having DHCP initial delay support.
---
 src/libsystemd-network/sd-dhcp-client.c | 28 +++-
 src/systemd/sd-dhcp-client.h|  9 +
 2 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/src/libsystemd-network/sd-dhcp-client.c 
b/src/libsystemd-network/sd-dhcp-client.c
index 06b2d1c..eb84708 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -37,6 +37,7 @@ struct sd_dhcp_client {
 DHCPState state;
 sd_event *event;
 int event_priority;
+enum sd_dhcp_client_initial_delay delay;
 sd_event_source *timeout_resend;
 int index;
 int fd;
@@ -167,6 +168,15 @@ int sd_dhcp_client_set_mac(sd_dhcp_client *client,
 return 0;
 }
 
+int sd_dhcp_client_set_initial_delay(sd_dhcp_client *client,
+ enum sd_dhcp_client_initial_delay delay) {
+assert_return(client, -EINVAL);
+
+client-delay = delay;
+
+return 0;
+}
+
 int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
 assert_return(client, -EINVAL);
 assert_return(ret, -EINVAL);
@@ -542,6 +552,7 @@ error:
 
 static int client_initialize_events(sd_dhcp_client *client,
 sd_event_io_handler_t io_callback) {
+usec_t delay = 0;
 int r;
 
 assert(client);
@@ -560,10 +571,25 @@ static int client_initialize_events(sd_dhcp_client 
*client,
 
 client-timeout_resend = sd_event_source_unref(client-timeout_resend);
 
+if (IN_SET(client-state, DHCP_STATE_INIT, DHCP_STATE_INIT_REBOOT)) {
+switch (client-delay) {
+case DHCP_INITIAL_DELAY_DEFAULT:
+break;
+
+case DHCP_INITIAL_DELAY_LOW:
+delay = random_u32()  0x1f;
+break;
+
+case DHCP_INITIAL_DELAY_MAX:
+delay = random_u32()  0x7f;
+break;
+}
+}
+
 r = sd_event_add_time(client-event,
   client-timeout_resend,
   CLOCK_MONOTONIC,
-  0, 0,
+  delay, 0,
   client_timeout_resend, client);
 if (r  0)
 goto error;
diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h
index a60bb58..e5e8550 100644
--- a/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/sd-dhcp-client.h
@@ -36,6 +36,12 @@ enum {
 DHCP_EVENT_EXPIRED  = 4,
 };
 
+enum sd_dhcp_client_initial_delay {
+DHCP_INITIAL_DELAY_DEFAULT  = 0,
+DHCP_INITIAL_DELAY_LOW  = 2,
+DHCP_INITIAL_DELAY_MAX  = 8,
+};
+
 typedef struct sd_dhcp_client sd_dhcp_client;
 
 typedef void (*sd_dhcp_client_cb_t)(sd_dhcp_client *client, int event,
@@ -50,6 +56,9 @@ int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
 int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index);
 int sd_dhcp_client_set_mac(sd_dhcp_client *client,
const struct ether_addr *addr);
+int sd_dhcp_client_set_initial_delay(sd_dhcp_client *client,
+ enum sd_dhcp_client_initial_delay delay);
+
 int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret);
 
 int sd_dhcp_client_stop(sd_dhcp_client *client);
-- 
1.8.5.3

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH] libsystemd-network: Support setting DHCP client initial delay

2014-04-03 Thread Tom Gundersen
On Thu, Apr 3, 2014 at 9:28 AM, Patrik Flykt
patrik.fl...@linux.intel.com wrote:
 Section 4.4.1 in RFC 2131 says that a DHCP client SHOULD wait a
 random time between one and ten seconds to desynchronize DHCP
 clients on startup. This is supported such that the application
 can optionally set an initial delay of approximately two and eight
 seconds or leave the initial value unset relying only on any
 machine specific randomness chosen for the main loop.

 The maximum delay of slightly more than eight seconds was chosen
 as it's more convenient to compute in addition to following RFC
 2131 in spirit with a sensible margin towards the 17 years passed
 since the exact wording of the document. The two second initial
 delay variant was added to include a more neutral timeout hopefully
 good enough on a very busy network.

As discussed on G+, there is no gain in setting the minimum above 0,
all we would care about is the range between min and max.

 By default no initial delay is
 added, as the implementation is geared towards maximum speed.

 Thanks to Ted Lemon and to Jayson Vantul pointing out the reasons
 having DHCP initial delay support.

Hm, so I'm definitely open to adding this sort of thing should it
prove to be a problem in some scenario (it is a SHOULD in the RFC
after all).

However, I'm wondering if this really can be an issue. If the initial
DISCOVER really does flood the network and the packets get dropped (or
the answer does not get back in time), then we will just resend the
DISCOVER message after a (randomized) hold-off, so the follow up
DISCOVER(s) will no longer be in sync across the network. Even if the
DHCP server takes some seconds to recover from the initial flood, we
will just keep sending DISCOVER's at increasing intervals (with
increasingly random delays), so even in the absolute worst case we
will recover within tens of seconds (and we really don't care how slow
this is in the worst case, as it should be extremely rare).

Or am I missing something here?

Cheers,

Tom
___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel