Merge pull request #17692 from yuwata/ipv4ll

network: fold ipv4ll fallback modes into normal ipv4ll addressing
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2020-12-01 21:59:30 +01:00
committed by GitHub
16 changed files with 108 additions and 150 deletions
+2 -3
View File
@@ -28,13 +28,12 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
scope type name##_from_string(const char *s) { \
int b; \
if (!s) \
return -1; \
b = parse_boolean(s); \
int b = parse_boolean(s); \
if (b == 0) \
return (type) 0; \
else if (b > 0) \
if (b > 0) \
return yes; \
return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \
}
+12 -15
View File
@@ -38,6 +38,9 @@
#define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
#define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
#define TRANSIENT_FAILURE_ATTEMPTS 3 /* Arbitrary limit: how many attempts are considered enough to report
* transient failure. */
typedef struct sd_dhcp_client_id {
uint8_t type;
union {
@@ -1187,7 +1190,7 @@ static int client_timeout_resend(
sd_dhcp_client *client = userdata;
DHCP_CLIENT_DONT_DESTROY(client);
usec_t next_timeout = 0;
usec_t next_timeout;
uint64_t time_now;
uint32_t time_left;
int r;
@@ -1203,17 +1206,14 @@ static int client_timeout_resend(
switch (client->state) {
case DHCP_STATE_RENEWING:
time_left = (client->lease->t2 - client->lease->t1) / 2;
if (time_left < 60)
time_left = 60;
next_timeout = time_now + time_left * USEC_PER_SEC;
break;
case DHCP_STATE_REBINDING:
time_left = (client->lease->lifetime - client->lease->t2) / 2;
if (time_left < 60)
time_left = 60;
@@ -1230,24 +1230,20 @@ static int client_timeout_resend(
r = client_start(client);
if (r < 0)
goto error;
else {
log_dhcp_client(client, "REBOOTED");
return 0;
}
log_dhcp_client(client, "REBOOTED");
return 0;
case DHCP_STATE_INIT:
case DHCP_STATE_INIT_REBOOT:
case DHCP_STATE_SELECTING:
case DHCP_STATE_REQUESTING:
case DHCP_STATE_BOUND:
if (client->attempt < client->max_attempts)
client->attempt++;
else
if (client->attempt >= client->max_attempts)
goto error;
client->attempt++;
next_timeout = time_now + ((UINT64_C(1) << MIN(client->attempt, (uint64_t) 6)) - 1) * USEC_PER_SEC;
break;
case DHCP_STATE_STOPPED:
@@ -1295,12 +1291,10 @@ static int client_timeout_resend(
client->state = DHCP_STATE_REBOOTING;
client->request_sent = time_now;
break;
case DHCP_STATE_REBOOTING:
case DHCP_STATE_BOUND:
break;
case DHCP_STATE_STOPPED:
@@ -1308,6 +1302,9 @@ static int client_timeout_resend(
goto error;
}
if (client->attempt >= TRANSIENT_FAILURE_ATTEMPTS)
client_notify(client, SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE);
return 0;
error:
+3 -5
View File
@@ -62,11 +62,9 @@ static struct DUID fallback_duid = { .type = DUID_TYPE_EN };
DUID* link_get_duid(Link *link) {
if (link->network->duid.type != _DUID_TYPE_INVALID)
return &link->network->duid;
else if (link->hw_addr.length == 0 &&
(link->manager->duid.type == DUID_TYPE_LLT ||
link->manager->duid.type == DUID_TYPE_LL))
/* Fallback to DUID that works without mac addresses.
* This is useful for tunnel devices without mac address. */
else if (link->hw_addr.length == 0 && IN_SET(link->manager->duid.type, DUID_TYPE_LLT, DUID_TYPE_LL))
/* Fallback to DUID that works without MAC address.
* This is useful for tunnel devices without MAC address. */
return &fallback_duid;
else
return &link->manager->duid;
+16 -4
View File
@@ -70,6 +70,10 @@ static void dhcp4_check_ready(Link *link) {
return;
}
r = sd_ipv4ll_stop(link->ipv4ll);
if (r < 0)
log_link_warning_errno(link, r, "Failed to drop IPv4 link-local address, ignoring: %m");
link_check_ready(link);
}
@@ -1048,10 +1052,7 @@ static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
switch (event) {
case SD_DHCP_CLIENT_EVENT_STOP:
if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4)) {
assert(link->ipv4ll);
if (link->ipv4ll) {
log_link_debug(link, "DHCP client is stopped. Acquiring IPv4 link-local address");
r = sd_ipv4ll_start(link->ipv4ll);
@@ -1136,6 +1137,17 @@ static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
return -ENOMSG;
}
break;
case SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE:
if (link->ipv4ll && !sd_ipv4ll_is_running(link->ipv4ll)) {
log_link_debug(link, "Problems acquiring DHCP lease, acquiring IPv4 link-local address");
r = sd_ipv4ll_start(link->ipv4ll);
if (r < 0)
return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
}
break;
default:
if (event < 0)
log_link_warning_errno(link, event, "DHCP error: Client failed: %m");
+1 -1
View File
@@ -148,7 +148,7 @@ int ipv4ll_configure(Link *link) {
assert(link);
if (!link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4))
if (!link_ipv4ll_enabled(link))
return 0;
if (!link->ipv4ll) {
+41 -75
View File
@@ -55,9 +55,8 @@
#include "util.h"
#include "vrf.h"
bool link_ipv4ll_enabled(Link *link, AddressFamily mask) {
bool link_ipv4ll_enabled(Link *link) {
assert(link);
assert((mask & ~(ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4)) == 0);
if (link->flags & IFF_LOOPBACK)
return false;
@@ -80,7 +79,7 @@ bool link_ipv4ll_enabled(Link *link, AddressFamily mask) {
if (link->network->bond)
return false;
return link->network->link_local & mask;
return link->network->link_local & ADDRESS_FAMILY_IPV4;
}
bool link_ipv6ll_enabled(Link *link) {
@@ -734,77 +733,51 @@ void link_check_ready(Link *link) {
if (link->state == LINK_STATE_CONFIGURED)
return;
if (link->state != LINK_STATE_CONFIGURING) {
log_link_debug(link, "%s(): link is in %s state.", __func__, link_state_to_string(link->state));
return;
}
if (link->state != LINK_STATE_CONFIGURING)
return (void) log_link_debug(link, "%s(): link is in %s state.", __func__, link_state_to_string(link->state));
if (!link->network)
return;
if (!link->addresses_configured) {
log_link_debug(link, "%s(): static addresses are not configured.", __func__);
return;
}
if (!link->addresses_configured)
return (void) log_link_debug(link, "%s(): static addresses are not configured.", __func__);
if (!link->neighbors_configured) {
log_link_debug(link, "%s(): static neighbors are not configured.", __func__);
return;
}
if (!link->neighbors_configured)
return (void) log_link_debug(link, "%s(): static neighbors are not configured.", __func__);
SET_FOREACH(a, link->addresses)
if (!address_is_ready(a)) {
_cleanup_free_ char *str = NULL;
(void) in_addr_to_string(a->family, &a->in_addr, &str);
log_link_debug(link, "%s(): an address %s/%d is not ready.", __func__, strnull(str), a->prefixlen);
return;
return (void) log_link_debug(link, "%s(): an address %s/%d is not ready.", __func__, strnull(str), a->prefixlen);
}
if (!link->static_routes_configured) {
log_link_debug(link, "%s(): static routes are not configured.", __func__);
return;
}
if (!link->static_routes_configured)
return (void) log_link_debug(link, "%s(): static routes are not configured.", __func__);
if (!link->static_nexthops_configured) {
log_link_debug(link, "%s(): static nexthops are not configured.", __func__);
return;
}
if (!link->static_nexthops_configured)
return (void) log_link_debug(link, "%s(): static nexthops are not configured.", __func__);
if (!link->routing_policy_rules_configured) {
log_link_debug(link, "%s(): static routing policy rules are not configured.", __func__);
return;
}
if (!link->routing_policy_rules_configured)
return (void) log_link_debug(link, "%s(): static routing policy rules are not configured.", __func__);
if (!link->tc_configured) {
log_link_debug(link, "%s(): traffic controls are not configured.", __func__);
return;
}
if (!link->tc_configured)
return (void) log_link_debug(link, "%s(): traffic controls are not configured.", __func__);
if (!link->sr_iov_configured) {
log_link_debug(link, "%s(): SR-IOV is not configured.", __func__);
return;
}
if (!link->sr_iov_configured)
return (void) log_link_debug(link, "%s(): SR-IOV is not configured.", __func__);
if (!link->bridge_mdb_configured) {
log_link_debug(link, "%s(): Bridge MDB is not configured.", __func__);
return;
}
if (!link->bridge_mdb_configured)
return (void) log_link_debug(link, "%s(): Bridge MDB is not configured.", __func__);
if (link_has_carrier(link) || !link->network->configure_without_carrier) {
bool has_ndisc_address = false;
NDiscAddress *n;
if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4) && !link->ipv4ll_address_configured) {
log_link_debug(link, "%s(): IPv4LL is not configured.", __func__);
return;
}
if (link_ipv6ll_enabled(link) &&
in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address)) {
log_link_debug(link, "%s(): IPv6LL is not configured.", __func__);
return;
}
in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address))
return (void) log_link_debug(link, "%s(): IPv6LL is not configured.", __func__);
SET_FOREACH(n, link->ndisc_addresses)
if (!n->marked) {
@@ -812,28 +785,26 @@ void link_check_ready(Link *link) {
break;
}
if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link)) &&
if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link) || link_ipv4ll_enabled(link)) &&
!link->dhcp_address && set_isempty(link->dhcp6_addresses) && !has_ndisc_address &&
!(link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4) && link->ipv4ll_address_configured)) {
log_link_debug(link, "%s(): DHCP4 or DHCP6 is enabled but no dynamic address is assigned yet.", __func__);
return;
}
!link->ipv4ll_address_configured)
/* When DHCP[46] or IPv4LL is enabled, at least one address is acquired by them. */
return (void) log_link_debug(link, "%s(): DHCP4, DHCP6 or IPv4LL is enabled but no dynamic address is assigned yet.", __func__);
if (link_dhcp4_enabled(link) || link_dhcp6_enabled(link) || link_dhcp6_pd_is_enabled(link) || link_ipv6_accept_ra_enabled(link)) {
if (link_dhcp4_enabled(link) || link_dhcp6_enabled(link) || link_dhcp6_pd_is_enabled(link) ||
link_ipv6_accept_ra_enabled(link) || link_ipv4ll_enabled(link)) {
if (!link->dhcp4_configured &&
!(link->dhcp6_address_configured && link->dhcp6_route_configured) &&
!(link->dhcp6_pd_address_configured && link->dhcp6_pd_route_configured) &&
!(link->ndisc_addresses_configured && link->ndisc_routes_configured) &&
!(link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4) && link->ipv4ll_address_configured)) {
/* When DHCP or RA is enabled, at least one protocol must provide an address, or
* an IPv4ll fallback address must be configured. */
log_link_debug(link, "%s(): dynamic addresses or routes are not configured.", __func__);
return;
}
!link->ipv4ll_address_configured)
/* When DHCP[46], NDisc, or IPv4LL is enabled, at least one protocol must be finished. */
return (void) log_link_debug(link, "%s(): dynamic addresses or routes are not configured.", __func__);
log_link_debug(link, "%s(): dhcp4:%s dhcp6_addresses:%s dhcp_routes:%s dhcp_pd_addresses:%s dhcp_pd_routes:%s ndisc_addresses:%s ndisc_routes:%s",
log_link_debug(link, "%s(): dhcp4:%s ipv4ll:%s dhcp6_addresses:%s dhcp_routes:%s dhcp_pd_addresses:%s dhcp_pd_routes:%s ndisc_addresses:%s ndisc_routes:%s",
__func__,
yes_no(link->dhcp4_configured),
yes_no(link->ipv4ll_address_configured),
yes_no(link->dhcp6_address_configured),
yes_no(link->dhcp6_route_configured),
yes_no(link->dhcp6_pd_address_configured),
@@ -844,8 +815,6 @@ void link_check_ready(Link *link) {
}
link_enter_configured(link);
return;
}
static int link_set_static_configs(Link *link) {
@@ -1230,22 +1199,19 @@ static int link_acquire_ipv4_conf(Link *link) {
assert(link->manager);
assert(link->manager->event);
if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4)) {
assert(link->ipv4ll);
log_link_debug(link, "Acquiring IPv4 link-local address");
r = sd_ipv4ll_start(link->ipv4ll);
if (r < 0)
return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
}
if (link->dhcp_client) {
log_link_debug(link, "Acquiring DHCPv4 lease");
r = sd_dhcp_client_start(link->dhcp_client);
if (r < 0)
return log_link_warning_errno(link, r, "Could not acquire DHCPv4 lease: %m");
} else if (link->ipv4ll) {
log_link_debug(link, "Acquiring IPv4 link-local address");
r = sd_ipv4ll_start(link->ipv4ll);
if (r < 0)
return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
}
return 0;
+1 -1
View File
@@ -231,7 +231,7 @@ int link_ipv6ll_gained(Link *link, const struct in6_addr *address);
int link_set_mtu(Link *link, uint32_t mtu);
bool link_ipv4ll_enabled(Link *link, AddressFamily mask);
bool link_ipv4ll_enabled(Link *link);
int link_stop_engines(Link *link, bool may_keep_dhcp);
-7
View File
@@ -210,13 +210,6 @@ int network_verify(Network *network) {
if (network->link_local < 0)
network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
if (FLAGS_SET(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4) &&
!FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV4)) {
log_warning("%s: fallback assignment of IPv4 link local address is enabled but DHCPv4 is disabled. "
"Disabling the fallback assignment.", network->filename);
SET_FLAG(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4, false);
}
/* IPMasquerade=yes implies IPForward=yes */
if (network->ip_masquerade)
network->ip_forward |= ADDRESS_FAMILY_IPV4;
+9 -10
View File
@@ -15,15 +15,6 @@ static const char* const address_family_table[_ADDRESS_FAMILY_MAX] = {
[ADDRESS_FAMILY_IPV6] = "ipv6",
};
static const char* const link_local_address_family_table[_ADDRESS_FAMILY_MAX] = {
[ADDRESS_FAMILY_NO] = "no",
[ADDRESS_FAMILY_YES] = "yes",
[ADDRESS_FAMILY_IPV4] = "ipv4",
[ADDRESS_FAMILY_IPV6] = "ipv6",
[ADDRESS_FAMILY_FALLBACK] = "fallback",
[ADDRESS_FAMILY_FALLBACK_IPV4] = "ipv4-fallback",
};
static const char* const routing_policy_rule_address_family_table[_ADDRESS_FAMILY_MAX] = {
[ADDRESS_FAMILY_YES] = "both",
[ADDRESS_FAMILY_IPV4] = "ipv4",
@@ -47,7 +38,15 @@ static const char* const dhcp_lease_server_type_table[_SD_DHCP_LEASE_SERVER_TYPE
};
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(address_family, AddressFamily, ADDRESS_FAMILY_YES);
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(link_local_address_family, AddressFamily, ADDRESS_FAMILY_YES);
AddressFamily link_local_address_family_from_string(const char *s) {
if (streq_ptr(s, "fallback")) /* compat name */
return ADDRESS_FAMILY_YES;
if (streq_ptr(s, "fallback-ipv4")) /* compat name */
return ADDRESS_FAMILY_IPV4;
return address_family_from_string(s);
}
DEFINE_STRING_TABLE_LOOKUP(routing_policy_rule_address_family, AddressFamily);
DEFINE_STRING_TABLE_LOOKUP(duplicate_address_detection_address_family, AddressFamily);
DEFINE_CONFIG_PARSE_ENUM(config_parse_link_local_address_family, link_local_address_family,
-3
View File
@@ -16,8 +16,6 @@ typedef enum AddressFamily {
ADDRESS_FAMILY_IPV4 = 1 << 0,
ADDRESS_FAMILY_IPV6 = 1 << 1,
ADDRESS_FAMILY_YES = ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_IPV6,
ADDRESS_FAMILY_FALLBACK_IPV4 = 1 << 2,
ADDRESS_FAMILY_FALLBACK = ADDRESS_FAMILY_FALLBACK_IPV4 | ADDRESS_FAMILY_IPV6,
_ADDRESS_FAMILY_MAX,
_ADDRESS_FAMILY_INVALID = -1,
} AddressFamily;
@@ -34,7 +32,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_address_family_with_kernel);
const char *address_family_to_string(AddressFamily b) _const_;
AddressFamily address_family_from_string(const char *s) _pure_;
const char *link_local_address_family_to_string(AddressFamily b) _const_;
AddressFamily link_local_address_family_from_string(const char *s) _pure_;
const char *routing_policy_rule_address_family_to_string(AddressFamily b) _const_;
+2
View File
@@ -40,6 +40,8 @@ enum {
SD_DHCP_CLIENT_EVENT_EXPIRED = 3,
SD_DHCP_CLIENT_EVENT_RENEW = 4,
SD_DHCP_CLIENT_EVENT_SELECTING = 5,
SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE = 6, /* Sent when we have not received a reply after the first few attempts.
* The client may want to start acquiring link-local addresses. */
};
enum {