summaryrefslogtreecommitdiff
path: root/src/network/networkd-ipv4acd.c
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2022-08-18 14:15:23 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2022-08-18 15:44:23 +0900
commite402e99eaa59cd15e00c71fb7168f001a03e33ca (patch)
treee61f2f52e5de816ddcb273a3c78e9bfab27a6049 /src/network/networkd-ipv4acd.c
parent5ad8116a87fb2dd63cc935ec36321e7356061b54 (diff)
downloadsystemd-e402e99eaa59cd15e00c71fb7168f001a03e33ca.tar.gz
network: fix DHCPv4 address renewal with IPv4ACD
Previously, when a DHCP address is renewed and if the IPv4ACD for the address is enabled, the address will never drop the probing flag, thus the lifetime of the address will never be updated. This drops NETWORK_CONFIG_STATE_PROBING, and the IPv4ACD status is managed another bit, Address.acd_bound. And, the flag is updated only when the IPv4ACD announced the address or detects conflict.
Diffstat (limited to 'src/network/networkd-ipv4acd.c')
-rw-r--r--src/network/networkd-ipv4acd.c62
1 files changed, 35 insertions, 27 deletions
diff --git a/src/network/networkd-ipv4acd.c b/src/network/networkd-ipv4acd.c
index 4f2563ff9c..f55e998f23 100644
--- a/src/network/networkd-ipv4acd.c
+++ b/src/network/networkd-ipv4acd.c
@@ -39,15 +39,21 @@ bool link_ipv4acd_supported(Link *link) {
return true;
}
+bool ipv4acd_bound(const Address *address) {
+ assert(address);
+
+ if (!address->acd)
+ return true;
+
+ return address->acd_bound;
+}
+
static int static_ipv4acd_address_remove(Link *link, Address *address, bool on_conflict) {
int r;
assert(link);
assert(address);
- /* Prevent form the address being freed. */
- address_enter_probing(address);
-
if (!address_exists(address))
return 0; /* Not assigned. */
@@ -85,9 +91,6 @@ static int dhcp4_address_on_conflict(Link *link, Address *address) {
if (r < 0)
return log_link_warning_errno(link, r, "Failed to drop DHCPv4 lease: %m");
- /* make the address will be freed. */
- address_cancel_probing(address);
-
/* It is not necessary to call address_remove() here, as dhcp4_lease_lost() removes it. */
return 0;
}
@@ -108,6 +111,8 @@ static void on_acd(sd_ipv4acd *acd, int event, void *userdata) {
switch (event) {
case SD_IPV4ACD_EVENT_STOP:
+ address->acd_bound = false;
+
if (address->source == NETWORK_CONFIG_SOURCE_STATIC) {
r = static_ipv4acd_address_remove(link, address, /* on_conflict = */ false);
if (r < 0)
@@ -119,13 +124,15 @@ static void on_acd(sd_ipv4acd *acd, int event, void *userdata) {
break;
case SD_IPV4ACD_EVENT_BIND:
+ address->acd_bound = true;
+
log_link_debug(link, "Successfully claimed address "IPV4_ADDRESS_FMT_STR,
IPV4_ADDRESS_FMT_VAL(address->in_addr.in));
-
- address_cancel_probing(address);
break;
case SD_IPV4ACD_EVENT_CONFLICT:
+ address->acd_bound = false;
+
log_link_warning(link, "Dropping address "IPV4_ADDRESS_FMT_STR", as an address conflict was detected.",
IPV4_ADDRESS_FMT_VAL(address->in_addr.in));
@@ -157,6 +164,22 @@ static int ipv4acd_check_mac(sd_ipv4acd *acd, const struct ether_addr *mac, void
return link_get_by_hw_addr(m, &hw_addr, NULL) >= 0;
}
+static int address_ipv4acd_start(Address *address) {
+ assert(address);
+ assert(address->link);
+
+ if (!address->acd)
+ return 0;
+
+ if (sd_ipv4acd_is_running(address->acd))
+ return 0;
+
+ if (!link_has_carrier(address->link))
+ return 0;
+
+ return sd_ipv4acd_start(address->acd, true);
+}
+
int ipv4acd_configure(Address *address) {
Link *link;
int r;
@@ -177,10 +200,8 @@ int ipv4acd_configure(Address *address) {
/* Currently, only static and DHCP4 addresses are supported. */
assert(IN_SET(address->source, NETWORK_CONFIG_SOURCE_STATIC, NETWORK_CONFIG_SOURCE_DHCP4));
- if (address->acd) {
- address_enter_probing(address);
- return 0;
- }
+ if (address->acd)
+ return address_ipv4acd_start(address);
log_link_debug(link, "Configuring IPv4ACD for address "IPV4_ADDRESS_FMT_STR,
IPV4_ADDRESS_FMT_VAL(address->in_addr.in));
@@ -213,14 +234,7 @@ int ipv4acd_configure(Address *address) {
if (r < 0)
return r;
- if (link_has_carrier(link)) {
- r = sd_ipv4acd_start(address->acd, true);
- if (r < 0)
- return r;
- }
-
- address_enter_probing(address);
- return 0;
+ return address_ipv4acd_start(address);
}
int ipv4acd_update_mac(Link *link) {
@@ -255,13 +269,7 @@ int ipv4acd_start(Link *link) {
assert(link);
SET_FOREACH(address, link->addresses) {
- if (!address->acd)
- continue;
-
- if (sd_ipv4acd_is_running(address->acd))
- continue;
-
- r = sd_ipv4acd_start(address->acd, true);
+ r = address_ipv4acd_start(address);
if (r < 0)
return r;
}