]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd: Allow DHCP4 client to set the number to attempt to reconfigure.
authorSusant Sahani <ssahani@redhat.com>
Sat, 4 May 2019 11:40:54 +0000 (17:10 +0530)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 7 May 2019 15:12:04 +0000 (17:12 +0200)
Otherwise current value is 6 and after 6 it will give up.

man/systemd.network.xml
src/libsystemd-network/sd-dhcp-client.c
src/network/networkd-dhcp4.c
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
src/systemd/sd-dhcp-client.h
test/fuzz/fuzz-network-parser/directives.network

index b86bcf03ef8c9277e309fb1fa4eae75289a0ea1c..7353b57419c6cdc772b8773282fb998e817e3b08 100644 (file)
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term><varname>MaxAttempts=</varname></term>
+          <listitem>
+            <para>Specifies how many times the DHCPv4 client configuration should be attempted. Takes a
+            number or <literal>infinity</literal>. Defaults to <literal>infinity</literal>.
+            Note that the time between retries is increased exponentially, so the network will not be
+            overloaded even if this number is high.</para>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term><varname>DUIDType=</varname></term>
           <listitem>
index 0d7e2e1c99cad52d567b2a6e8b07deade0bb3e19..33a8ef799975bef06b05b11b1b87d41427efb3f1 100644 (file)
@@ -32,8 +32,6 @@
 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN)  /* Arbitrary limit */
 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
 
-#define MAX_CLIENT_ATTEMPT 6
-
 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
 
@@ -90,7 +88,8 @@ struct sd_dhcp_client {
         uint32_t mtu;
         uint32_t xid;
         usec_t start_time;
-        unsigned attempt;
+        uint64_t attempt;
+        uint64_t max_attempts;
         usec_t request_sent;
         sd_event_source *timeout_t1;
         sd_event_source *timeout_t2;
@@ -522,6 +521,14 @@ int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) {
         return 0;
 }
 
+int sd_dhcp_client_set_max_attempts(sd_dhcp_client *client, uint64_t max_attempts) {
+        assert_return(client, -EINVAL);
+
+        client->max_attempts = max_attempts;
+
+        return 0;
+}
+
 int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
         assert_return(client, -EINVAL);
 
@@ -1052,12 +1059,12 @@ static int client_timeout_resend(
         case DHCP_STATE_REQUESTING:
         case DHCP_STATE_BOUND:
 
-                if (client->attempt < MAX_CLIENT_ATTEMPT)
+                if (client->attempt < client->max_attempts)
                         client->attempt++;
                 else
                         goto error;
 
-                next_timeout = time_now + ((UINT64_C(1) << client->attempt) - 1) * USEC_PER_SEC;
+                next_timeout = time_now + ((UINT64_C(1) << MIN(client->attempt, (uint64_t) 6)) - 1) * USEC_PER_SEC;
 
                 break;
 
@@ -1082,16 +1089,14 @@ static int client_timeout_resend(
                 if (r >= 0) {
                         client->state = DHCP_STATE_SELECTING;
                         client->attempt = 0;
-                } else {
-                        if (client->attempt >= MAX_CLIENT_ATTEMPT)
-                                goto error;
-                }
+                } else if (client->attempt >= client->max_attempts)
+                        goto error;
 
                 break;
 
         case DHCP_STATE_SELECTING:
                 r = client_send_discover(client);
-                if (r < 0 && client->attempt >= MAX_CLIENT_ATTEMPT)
+                if (r < 0 && client->attempt >= client->max_attempts)
                         goto error;
 
                 break;
@@ -1101,7 +1106,7 @@ static int client_timeout_resend(
         case DHCP_STATE_RENEWING:
         case DHCP_STATE_REBINDING:
                 r = client_send_request(client);
-                if (r < 0 && client->attempt >= MAX_CLIENT_ATTEMPT)
+                if (r < 0 && client->attempt >= client->max_attempts)
                          goto error;
 
                 if (client->state == DHCP_STATE_INIT_REBOOT)
@@ -1934,6 +1939,7 @@ int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) {
                 .mtu = DHCP_DEFAULT_MIN_SIZE,
                 .port = DHCP_PORT_CLIENT,
                 .anonymize = !!anonymize,
+                .max_attempts = (uint64_t) -1,
         };
         /* NOTE: this could be moved to a function. */
         if (anonymize) {
index c630359027bce8285a3903dc7caa456aaddf68c0..8d6769ca7e7f00b595a0a15cf27896628223db0d 100644 (file)
@@ -833,5 +833,11 @@ int dhcp4_configure(Link *link) {
                         return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set listen port: %m");
         }
 
+        if (link->network->dhcp_max_attempts > 0) {
+                r = sd_dhcp_client_set_max_attempts(link->dhcp_client, link->network->dhcp_max_attempts);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set max attempts: %m");
+        }
+
         return dhcp4_set_client_identifier(link);
 }
index 8232b069a848f9ccad7cdb605dd92a59fef4431a..646cd91e9388627333c78bdae4ebb2e6b92620b9 100644 (file)
@@ -140,6 +140,7 @@ DHCP.Hostname,                          config_parse_hostname,
 DHCP.RequestBroadcast,                  config_parse_bool,                               0,                             offsetof(Network, dhcp_broadcast)
 DHCP.CriticalConnection,                config_parse_bool,                               0,                             offsetof(Network, dhcp_critical)
 DHCP.VendorClassIdentifier,             config_parse_string,                             0,                             offsetof(Network, dhcp_vendor_class_identifier)
+DHCP.MaxAttempts,                       config_parse_dhcp_max_attempts,                  0,                             0
 DHCP.UserClass,                         config_parse_dhcp_user_class,                    0,                             offsetof(Network, dhcp_user_class)
 DHCP.DUIDType,                          config_parse_duid_type,                          0,                             offsetof(Network, duid)
 DHCP.DUIDRawData,                       config_parse_duid_rawdata,                       0,                             offsetof(Network, duid)
index a85d5ede28ed2db50e8e2361cc731a769a33880e..15c34b078d1cee744e5196d3f76b89be8b434201 100644 (file)
@@ -1575,6 +1575,54 @@ int config_parse_section_route_table(
         return 0;
 }
 
+int config_parse_dhcp_max_attempts(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        Network *network = data;
+        uint64_t a;
+        int r;
+
+        assert(network);
+        assert(lvalue);
+        assert(rvalue);
+
+        if (isempty(rvalue)) {
+                network->dhcp_max_attempts = 0;
+                return 0;
+        }
+
+        if (streq(rvalue, "infinity")) {
+                network->dhcp_max_attempts = (uint64_t) -1;
+                return 0;
+        }
+
+        r = safe_atou64(rvalue, &a);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Failed to parse DHCP maximum attempts, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        if (a == 0) {
+                log_syntax(unit, LOG_ERR, filename, line, 0,
+                           "%s= must be positive integer or 'infinity', ignoring: %s", lvalue, rvalue);
+                return 0;
+        }
+
+        network->dhcp_max_attempts = a;
+
+        return 0;
+}
+
 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains,
                          "Failed to parse DHCP use domains setting");
 
index 852144da3c0a0d9d0fbd1803bd59c953170b3dab..052e8d5cc03369a6609c17dba0df4b57e6dfc79e 100644 (file)
@@ -116,6 +116,7 @@ struct Network {
         char *dhcp_vendor_class_identifier;
         char **dhcp_user_class;
         char *dhcp_hostname;
+        uint64_t dhcp_max_attempts;
         unsigned dhcp_route_metric;
         uint32_t dhcp_route_table;
         uint16_t dhcp_client_port;
@@ -315,6 +316,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class);
 CONFIG_PARSER_PROTOTYPE(config_parse_ntp);
 CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
 CONFIG_PARSER_PROTOTYPE(config_parse_required_for_online);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts);
 /* Legacy IPv4LL support */
 CONFIG_PARSER_PROTOTYPE(config_parse_ipv4ll);
 
index bd0d429df60d657dd09597429919f083799c076f..d9b57e2c734ceb27e47989e79d988e440f9910f0 100644 (file)
@@ -154,6 +154,9 @@ int sd_dhcp_client_get_client_id(
 int sd_dhcp_client_set_mtu(
                 sd_dhcp_client *client,
                 uint32_t mtu);
+int sd_dhcp_client_set_max_attempts(
+                sd_dhcp_client *client,
+                uint64_t attempt);
 int sd_dhcp_client_set_client_port(
                 sd_dhcp_client *client,
                 uint16_t port);
index fd3256e78406bee26abf9be6fc5a7c39251ee725..8149a35d1ebf36a7c7281ff4cb19b7485fa1a1d2 100644 (file)
@@ -199,6 +199,7 @@ MaxLeaseTimeSec=
 DefaultLeaseTimeSec=
 EmitTimezone=
 DNS=
+MaxAttempts=
 [DHCPv4]
 UseHostname=
 UseMTU=