network/ipv4acd: split out sd_ipv4acd management from Address to Link

Then, we can start IPv4ACD without adding corresponding Address object
to Link.

Hopefully, no functional change, just refactoring and preparation for
later commits.
This commit is contained in:
Yu Watanabe
2023-07-30 23:16:41 +09:00
parent 9701be563a
commit 5385e5f940
6 changed files with 101 additions and 87 deletions
+6 -6
View File
@@ -133,9 +133,9 @@ Address *address_free(Address *address) {
if (address->family == AF_INET6 &&
in6_addr_equal(&address->in_addr.in6, &address->link->ipv6ll_address))
memzero(&address->link->ipv6ll_address, sizeof(struct in6_addr));
}
sd_ipv4acd_unref(address->acd);
ipv4acd_detach(address->link, address);
}
config_section_free(address->section);
free(address->label);
@@ -153,8 +153,9 @@ static bool address_lifetime_is_valid(const Address *a) {
bool address_is_ready(const Address *a) {
assert(a);
assert(a->link);
if (!ipv4acd_bound(a))
if (!ipv4acd_bound(a->link, a))
return false;
if (FLAGS_SET(a->flags, IFA_F_TENTATIVE))
@@ -462,7 +463,6 @@ int address_dup(const Address *src, Address **ret) {
dest->section = NULL;
dest->link = NULL;
dest->label = NULL;
dest->acd = NULL;
dest->netlabel = NULL;
if (src->family == AF_INET) {
@@ -1206,7 +1206,7 @@ static bool address_is_ready_to_configure(Link *link, const Address *address) {
if (!link_is_ready_to_configure(link, false))
return false;
if (!ipv4acd_bound(address))
if (!ipv4acd_bound(link, address))
return false;
/* Refuse adding more than the limit */
@@ -1302,7 +1302,7 @@ int link_request_address(
existing->lifetime_preferred_usec = address->lifetime_preferred_usec;
}
r = ipv4acd_configure(existing);
r = ipv4acd_configure(link, existing);
if (r < 0)
return r;
-4
View File
@@ -5,8 +5,6 @@
#include <stdbool.h>
#include <stdio.h>
#include "sd-ipv4acd.h"
#include "conf-parser.h"
#include "in-addr-util.h"
#include "networkd-link.h"
@@ -58,8 +56,6 @@ struct Address {
/* duplicate_address_detection is only used by static or IPv4 dynamic addresses.
* To control DAD for IPv6 dynamic addresses, set IFA_F_NODAD to flags. */
AddressFamily duplicate_address_detection;
sd_ipv4acd *acd;
bool acd_bound;
/* Called when address become ready */
address_ready_callback_t callback;
+88 -75
View File
@@ -13,6 +13,11 @@
#include "networkd-link.h"
#include "networkd-manager.h"
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
ipv4acd_hash_ops,
void, trivial_hash_func, trivial_compare_func,
sd_ipv4acd, sd_ipv4acd_unref);
bool link_ipv4acd_supported(Link *link) {
assert(link);
@@ -40,9 +45,9 @@ bool link_ipv4acd_supported(Link *link) {
return true;
}
static bool address_ipv4acd_enabled(Address *address) {
static bool address_ipv4acd_enabled(Link *link, const Address *address) {
assert(link);
assert(address);
assert(address->link);
if (address->family != AF_INET)
return false;
@@ -54,19 +59,23 @@ static bool address_ipv4acd_enabled(Address *address) {
if (!IN_SET(address->source, NETWORK_CONFIG_SOURCE_STATIC, NETWORK_CONFIG_SOURCE_DHCP4))
return false;
if (!link_ipv4acd_supported(address->link))
return false;
return true;
return link_ipv4acd_supported(link);
}
bool ipv4acd_bound(const Address *address) {
bool ipv4acd_bound(Link *link, const Address *address) {
sd_ipv4acd *acd;
assert(link);
assert(address);
if (!address->acd)
if (address->family != AF_INET)
return true;
return address->acd_bound;
acd = hashmap_get(link->ipv4acd_by_address, IN4_ADDR_TO_PTR(&address->in_addr.in));
if (!acd)
return true;
return sd_ipv4acd_is_bound(acd) > 0;
}
static int static_ipv4acd_address_remove(Link *link, Address *address, bool on_conflict) {
@@ -114,23 +123,25 @@ static int dhcp4_address_on_conflict(Link *link) {
}
static void on_acd(sd_ipv4acd *acd, int event, void *userdata) {
Address *address = ASSERT_PTR(userdata);
Link *link = ASSERT_PTR(userdata);
Address *address = NULL;
struct in_addr a;
Link *link;
int r;
assert(acd);
assert(address->acd == acd);
assert(address->link);
assert(address->family == AF_INET);
assert(IN_SET(address->source, NETWORK_CONFIG_SOURCE_STATIC, NETWORK_CONFIG_SOURCE_DHCP4));
link = address->link;
a = address->in_addr.in;
r = sd_ipv4acd_get_address(acd, &a);
if (r < 0) {
log_link_warning_errno(link, r, "Failed to get address from IPv4ACD: %m");
link_enter_failed(link);
}
(void) link_get_ipv4_address(link, &a, 0, &address);
switch (event) {
case SD_IPV4ACD_EVENT_STOP:
address->acd_bound = false;
if (!address)
break;
if (address->source == NETWORK_CONFIG_SOURCE_STATIC) {
r = static_ipv4acd_address_remove(link, address, /* on_conflict = */ false);
@@ -143,13 +154,12 @@ 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 %s", IN4_ADDR_TO_STRING(&a));
break;
case SD_IPV4ACD_EVENT_CONFLICT:
address->acd_bound = false;
if (!address)
break;
log_link_warning(link, "Dropping address %s, as an address conflict was detected.", IN4_ADDR_TO_STRING(&a));
@@ -180,75 +190,89 @@ 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);
static int ipv4acd_start_one(Link *link, sd_ipv4acd *acd) {
assert(link);
assert(acd);
if (!address->acd)
if (sd_ipv4acd_is_running(acd))
return 0;
if (sd_ipv4acd_is_running(address->acd))
if (!link_has_carrier(link))
return 0;
if (!link_has_carrier(address->link))
return 0;
return sd_ipv4acd_start(address->acd, true);
return sd_ipv4acd_start(acd, /* reset_conflicts = */ true);
}
int ipv4acd_configure(Address *address) {
Link *link;
int ipv4acd_configure(Link *link, const Address *address) {
_cleanup_(sd_ipv4acd_unrefp) sd_ipv4acd *acd = NULL;
sd_ipv4acd *existing;
int r;
assert(link);
assert(link->manager);
assert(address);
link = ASSERT_PTR(address->link);
if (!address_ipv4acd_enabled(address)) {
address->acd = sd_ipv4acd_unref(address->acd);
address->acd_bound = false;
if (address->family != AF_INET)
return 0;
}
if (address->acd)
return address_ipv4acd_start(address);
existing = hashmap_get(link->ipv4acd_by_address, IN4_ADDR_TO_PTR(&address->in_addr.in));
if (!address_ipv4acd_enabled(link, address))
return sd_ipv4acd_stop(existing);
if (existing)
return ipv4acd_start_one(link, existing);
log_link_debug(link, "Configuring IPv4ACD for address %s.", IN4_ADDR_TO_STRING(&address->in_addr.in));
r = sd_ipv4acd_new(&address->acd);
r = sd_ipv4acd_new(&acd);
if (r < 0)
return r;
r = sd_ipv4acd_attach_event(address->acd, link->manager->event, 0);
r = sd_ipv4acd_attach_event(acd, link->manager->event, 0);
if (r < 0)
return r;
r = sd_ipv4acd_set_ifindex(address->acd, link->ifindex);
r = sd_ipv4acd_set_ifindex(acd, link->ifindex);
if (r < 0)
return r;
r = sd_ipv4acd_set_mac(address->acd, &link->hw_addr.ether);
r = sd_ipv4acd_set_mac(acd, &link->hw_addr.ether);
if (r < 0)
return r;
r = sd_ipv4acd_set_address(address->acd, &address->in_addr.in);
r = sd_ipv4acd_set_address(acd, &address->in_addr.in);
if (r < 0)
return r;
r = sd_ipv4acd_set_callback(address->acd, on_acd, address);
r = sd_ipv4acd_set_callback(acd, on_acd, link);
if (r < 0)
return r;
r = sd_ipv4acd_set_check_mac_callback(address->acd, ipv4acd_check_mac, link->manager);
r = sd_ipv4acd_set_check_mac_callback(acd, ipv4acd_check_mac, link->manager);
if (r < 0)
return r;
return address_ipv4acd_start(address);
r = hashmap_ensure_put(&link->ipv4acd_by_address, &ipv4acd_hash_ops, IN4_ADDR_TO_PTR(&address->in_addr.in), acd);
if (r < 0)
return r;
return ipv4acd_start_one(link, TAKE_PTR(acd));
}
void ipv4acd_detach(Link *link, const Address *address) {
assert(link);
assert(address);
if (address->family != AF_INET)
return;
sd_ipv4acd_unref(hashmap_remove(link->ipv4acd_by_address, IN4_ADDR_TO_PTR(&address->in_addr.in)));
}
int ipv4acd_update_mac(Link *link) {
Address *address;
int k, r = 0;
sd_ipv4acd *acd;
int r;
assert(link);
@@ -257,28 +281,23 @@ int ipv4acd_update_mac(Link *link) {
if (ether_addr_is_null(&link->hw_addr.ether))
return 0;
SET_FOREACH(address, link->addresses) {
if (!address->acd)
continue;
k = sd_ipv4acd_set_mac(address->acd, &link->hw_addr.ether);
if (k < 0)
r = k;
HASHMAP_FOREACH(acd, link->ipv4acd_by_address) {
r = sd_ipv4acd_set_mac(acd, &link->hw_addr.ether);
if (r < 0)
return r;
}
if (r < 0)
link_enter_failed(link);
return r;
return 0;
}
int ipv4acd_start(Link *link) {
Address *address;
sd_ipv4acd *acd;
int r;
assert(link);
SET_FOREACH(address, link->addresses) {
r = address_ipv4acd_start(address);
HASHMAP_FOREACH(acd, link->ipv4acd_by_address) {
r = ipv4acd_start_one(link, acd);
if (r < 0)
return r;
}
@@ -287,16 +306,13 @@ int ipv4acd_start(Link *link) {
}
int ipv4acd_stop(Link *link) {
Address *address;
sd_ipv4acd *acd;
int k, r = 0;
assert(link);
SET_FOREACH(address, link->addresses) {
if (!address->acd)
continue;
k = sd_ipv4acd_stop(address->acd);
HASHMAP_FOREACH(acd, link->ipv4acd_by_address) {
k = sd_ipv4acd_stop(acd);
if (k < 0)
r = k;
}
@@ -305,16 +321,13 @@ int ipv4acd_stop(Link *link) {
}
int ipv4acd_set_ifname(Link *link) {
Address *address;
sd_ipv4acd *acd;
int r;
assert(link);
SET_FOREACH(address, link->addresses) {
if (!address->acd)
continue;
r = sd_ipv4acd_set_ifname(address->acd, link->ifname);
HASHMAP_FOREACH(acd, link->ipv4acd_by_address) {
r = sd_ipv4acd_set_ifname(acd, link->ifname);
if (r < 0)
return r;
}
+3 -2
View File
@@ -5,8 +5,9 @@ typedef struct Address Address;
typedef struct Link Link;
bool link_ipv4acd_supported(Link *link);
bool ipv4acd_bound(const Address *address);
int ipv4acd_configure(Address *address);
bool ipv4acd_bound(Link *link, const Address *address);
int ipv4acd_configure(Link *link, const Address *address);
void ipv4acd_detach(Link *link, const Address *address);
int ipv4acd_update_mac(Link *link);
int ipv4acd_start(Link *link);
int ipv4acd_stop(Link *link);
+2
View File
@@ -160,6 +160,8 @@ static void link_free_engines(Link *link) {
link->lldp_rx = sd_lldp_rx_unref(link->lldp_rx);
link->lldp_tx = sd_lldp_tx_unref(link->lldp_tx);
link->ipv4acd_by_address = hashmap_free(link->ipv4acd_by_address);
link->ipv4ll = sd_ipv4ll_unref(link->ipv4ll);
link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
+2
View File
@@ -130,6 +130,8 @@ typedef struct Link {
bool dhcp4_configured:1;
char *dhcp4_6rd_tunnel_name;
Hashmap *ipv4acd_by_address;
sd_ipv4ll *ipv4ll;
bool ipv4ll_address_configured:1;