Zbigniew Jędrzejewski-Szmek 62fe94
From 346e13a25dc6f76d3bc9d8decd40dc4782b02d2a Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek 62fe94
From: Patrik Flykt <patrik.flykt@linux.intel.com>
Zbigniew Jędrzejewski-Szmek 62fe94
Date: Mon, 1 Sep 2014 13:21:33 +0300
Zbigniew Jędrzejewski-Szmek 62fe94
Subject: [PATCH] sd-dhcp6-client: Implement Elapsed Time option
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
Implement Elapsed Time option as it is defined as MUST in RFC 3315,
Zbigniew Jędrzejewski-Szmek 62fe94
section 22.9. The elapsed time value is a 1/100th of a second with
Zbigniew Jędrzejewski-Szmek 62fe94
a max value of 0xffff, i.e. 655.35 seconds.
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
As the main loop might not be running yet when sd_dhcp6_client_start() is
Zbigniew Jędrzejewski-Szmek 62fe94
called, fetch the monotonic time directly and not from the event loop
Zbigniew Jędrzejewski-Szmek 62fe94
while in state DHCP6_STATE_STOPPED.
Zbigniew Jędrzejewski-Szmek 62fe94
---
Zbigniew Jędrzejewski-Szmek 62fe94
 src/libsystemd-network/sd-dhcp6-client.c | 40 ++++++++++++++++++++++++--------
Zbigniew Jędrzejewski-Szmek 62fe94
 1 file changed, 30 insertions(+), 10 deletions(-)
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
Zbigniew Jędrzejewski-Szmek 62fe94
index 6860c66858..c190b560ea 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/libsystemd-network/sd-dhcp6-client.c
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/libsystemd-network/sd-dhcp6-client.c
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -49,6 +49,7 @@ struct sd_dhcp6_client {
Zbigniew Jędrzejewski-Szmek 62fe94
         struct ether_addr mac_addr;
Zbigniew Jędrzejewski-Szmek 62fe94
         DHCP6IA ia_na;
Zbigniew Jędrzejewski-Szmek 62fe94
         be32_t transaction_id;
Zbigniew Jędrzejewski-Szmek 62fe94
+        usec_t transaction_start;
Zbigniew Jędrzejewski-Szmek 62fe94
         struct sd_dhcp6_lease *lease;
Zbigniew Jędrzejewski-Szmek 62fe94
         int fd;
Zbigniew Jędrzejewski-Szmek 62fe94
         be16_t *req_opts;
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -203,6 +204,7 @@ static int client_reset(sd_dhcp6_client *client) {
Zbigniew Jędrzejewski-Szmek 62fe94
         client->fd = safe_close(client->fd);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         client->transaction_id = 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+        client->transaction_start = 0;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         client->ia_na.timeout_t1 =
Zbigniew Jędrzejewski-Szmek 62fe94
                 sd_event_source_unref(client->ia_na.timeout_t1);
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -230,13 +232,15 @@ static void client_stop(sd_dhcp6_client *client, int error) {
Zbigniew Jędrzejewski-Szmek 62fe94
         client_reset(client);
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-static int client_send_message(sd_dhcp6_client *client) {
Zbigniew Jędrzejewski-Szmek 62fe94
+static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
Zbigniew Jędrzejewski-Szmek 62fe94
         _cleanup_free_ DHCP6Message *message = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
         struct in6_addr all_servers =
Zbigniew Jędrzejewski-Szmek 62fe94
                 IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT;
Zbigniew Jędrzejewski-Szmek 62fe94
         size_t len, optlen = 512;
Zbigniew Jędrzejewski-Szmek 62fe94
         uint8_t *opt;
Zbigniew Jędrzejewski-Szmek 62fe94
         int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        usec_t elapsed_usec;
Zbigniew Jędrzejewski-Szmek 62fe94
+        be16_t elapsed_time;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         len = sizeof(DHCP6Message) + optlen;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -308,6 +312,17 @@ static int client_send_message(sd_dhcp6_client *client) {
Zbigniew Jędrzejewski-Szmek 62fe94
         if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
                 return r;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+        elapsed_usec = time_now - client->transaction_start;
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (elapsed_usec < 0xffff * USEC_PER_MSEC * 10)
Zbigniew Jędrzejewski-Szmek 62fe94
+                elapsed_time = htobe16(elapsed_usec / USEC_PER_MSEC / 10);
Zbigniew Jędrzejewski-Szmek 62fe94
+        else
Zbigniew Jędrzejewski-Szmek 62fe94
+                elapsed_time = 0xffff;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_ELAPSED_TIME,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                sizeof(elapsed_time), &elapsed_time);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
         r = dhcp6_network_send_udp_socket(client->fd, &all_servers, message,
Zbigniew Jędrzejewski-Szmek 62fe94
                                           len - optlen);
Zbigniew Jędrzejewski-Szmek 62fe94
         if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -455,15 +470,14 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
Zbigniew Jędrzejewski-Szmek 62fe94
                 return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-        r = client_send_message(client);
Zbigniew Jędrzejewski-Szmek 62fe94
-        if (r >= 0)
Zbigniew Jędrzejewski-Szmek 62fe94
-                client->retransmit_count++;
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
         r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
Zbigniew Jędrzejewski-Szmek 62fe94
         if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
                 goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = client_send_message(client, time_now);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r >= 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                client->retransmit_count++;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
         if (!client->retransmit_time) {
Zbigniew Jędrzejewski-Szmek 62fe94
                 client->retransmit_time =
Zbigniew Jędrzejewski-Szmek 62fe94
                         client_timeout_compute_random(init_retransmit_time);
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -882,6 +896,15 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
Zbigniew Jędrzejewski-Szmek 62fe94
         client->retransmit_time = 0;
Zbigniew Jędrzejewski-Szmek 62fe94
         client->retransmit_count = 0;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (client->state == DHCP6_STATE_STOPPED) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                time_now = now(clock_boottime_or_monotonic());
Zbigniew Jędrzejewski-Szmek 62fe94
+        } else {
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = sd_event_now(client->event, clock_boottime_or_monotonic(),
Zbigniew Jędrzejewski-Szmek 62fe94
+                                 &time_now);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
         switch (state) {
Zbigniew Jędrzejewski-Szmek 62fe94
         case DHCP6_STATE_STOPPED:
Zbigniew Jędrzejewski-Szmek 62fe94
         case DHCP6_STATE_SOLICITATION:
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -926,10 +949,6 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         case DHCP6_STATE_BOUND:
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
Zbigniew Jędrzejewski-Szmek 62fe94
-                if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
-                        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
                 if (client->lease->ia.lifetime_t1 == 0xffffffff ||
Zbigniew Jędrzejewski-Szmek 62fe94
                     client->lease->ia.lifetime_t2 == 0xffffffff) {
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -996,6 +1015,7 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         client->transaction_id = random_u32() & htobe32(0x00ffffff);
Zbigniew Jędrzejewski-Szmek 62fe94
+        client->transaction_start = time_now;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         r = sd_event_add_time(client->event, &client->timeout_resend,
Zbigniew Jędrzejewski-Szmek 62fe94
                               clock_boottime_or_monotonic(), 0, 0, client_timeout_resend,