network: enable ARP when IPv4LL and/or IPv4ACD is enabled (#37190)

This commit is contained in:
Yu Watanabe
2025-04-23 08:53:49 +09:00
committed by GitHub
8 changed files with 118 additions and 49 deletions
+10 -14
View File
@@ -16,7 +16,7 @@
#include "networkd-dhcp-prefix-delegation.h"
#include "networkd-dhcp4-bus.h"
#include "networkd-dhcp4.h"
#include "networkd-ipv4acd.h"
#include "networkd-ipv4ll.h"
#include "networkd-link.h"
#include "networkd-manager.h"
#include "networkd-network.h"
@@ -1192,13 +1192,11 @@ static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
return 0;
}
if (link->ipv4ll && !sd_ipv4ll_is_running(link->ipv4ll)) {
log_link_debug(link, "DHCP client is stopped. Acquiring IPv4 link-local address");
r = sd_ipv4ll_start(link->ipv4ll);
if (r < 0 && r != -ESTALE) /* On exit, we cannot and should not start sd-ipv4ll. */
return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
}
r = ipv4ll_start(link);
if (r < 0)
return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
if (r > 0)
log_link_debug(link, "DHCP client is stopped. Acquiring IPv4 link-local address.");
if (link->dhcp_lease) {
if (link->network->dhcp_send_release) {
@@ -1270,13 +1268,11 @@ static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
break;
case SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE:
if (link->ipv4ll && !sd_ipv4ll_is_running(link->ipv4ll)) {
r = ipv4ll_start(link);
if (r < 0)
return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
if (r > 0)
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:
+12
View File
@@ -66,6 +66,18 @@ static bool address_ipv4acd_enabled(Link *link, const Address *address) {
return link_ipv4acd_supported(link);
}
bool link_ipv4acd_enabled(Link *link) {
assert(link);
assert(link->network);
Address *address;
ORDERED_HASHMAP_FOREACH(address, link->network->addresses_by_section)
if (address_ipv4acd_enabled(link, address))
return true;
return false;
}
bool ipv4acd_bound(Link *link, const Address *address) {
sd_ipv4acd *acd;
+1
View File
@@ -5,6 +5,7 @@ typedef struct Address Address;
typedef struct Link Link;
bool link_ipv4acd_supported(Link *link);
bool link_ipv4acd_enabled(Link *link);
bool ipv4acd_bound(Link *link, const Address *address);
int ipv4acd_configure(Link *link, const Address *address);
void ipv4acd_detach(Link *link, const Address *address);
+28
View File
@@ -264,6 +264,34 @@ int ipv4ll_configure(Link *link) {
return sd_ipv4ll_set_check_mac_callback(link->ipv4ll, ipv4ll_check_mac, link->manager);
}
int ipv4ll_start(Link *link) {
int r;
assert(link);
if (!link->ipv4ll)
return 0;
if (sd_ipv4ll_is_running(link->ipv4ll))
return 0;
if (!link_has_carrier(link))
return 0;
/* On exit, we cannot and should not start sd-ipv4ll. */
r = sd_event_get_state(link->manager->event);
if (r < 0)
return r;
if (r == SD_EVENT_FINISHED)
return 0;
r = sd_ipv4ll_start(link->ipv4ll);
if (r < 0)
return r;
return 1; /* started */
}
int link_drop_ipv4ll_config(Link *link, Network *network) {
int ret = 0;
+1
View File
@@ -11,6 +11,7 @@ typedef struct Network Network;
bool link_ipv4ll_enabled(Link *link);
int ipv4ll_configure(Link *link);
int ipv4ll_start(Link *link);
int link_drop_ipv4ll_config(Link *link, Network *network);
int ipv4ll_update_mac(Link *link);
+21 -25
View File
@@ -728,11 +728,11 @@ static int link_acquire_dynamic_ipv4_conf(Link *link) {
return log_link_warning_errno(link, r, "Could not set IPv4 link-local start address: %m");
}
r = sd_ipv4ll_start(link->ipv4ll);
r = ipv4ll_start(link);
if (r < 0)
return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
log_link_debug(link, "Acquiring IPv4 link-local address.");
if (r > 0)
log_link_debug(link, "Acquiring IPv4 link-local address.");
}
r = link_start_dhcp4_server(link);
@@ -1747,6 +1747,8 @@ static int link_carrier_gained(Link *link) {
assert(link);
log_link_info(link, "Gained carrier");
r = event_source_disable(link->carrier_lost_timer);
if (r < 0)
log_link_warning_errno(link, r, "Failed to disable carrier lost timer, ignoring: %m");
@@ -1849,6 +1851,8 @@ static int link_carrier_lost(Link *link) {
assert(link);
log_link_info(link, "Lost carrier");
if (link->iftype == ARPHRD_CAN)
/* let's shortcut things for CAN which doesn't need most of what's done below. */
usec = 0;
@@ -1902,6 +1906,8 @@ static int link_admin_state_up(Link *link) {
/* This is called every time an interface admin state changes to up;
* specifically, when IFF_UP flag changes from unset to set. */
log_link_info(link, "Link UP");
if (!link->network)
return 0;
@@ -1920,6 +1926,8 @@ static int link_admin_state_up(Link *link) {
static int link_admin_state_down(Link *link) {
assert(link);
log_link_info(link, "Link DOWN");
link_forget_nexthops(link);
link_forget_routes(link);
@@ -2167,33 +2175,21 @@ static int link_update_flags(Link *link, sd_netlink_message *message) {
link_update_operstate(link, true);
if (!link_was_admin_up && (link->flags & IFF_UP)) {
log_link_info(link, "Link UP");
r = 0;
if (!link_was_admin_up && (link->flags & IFF_UP))
r = link_admin_state_up(link);
if (r < 0)
return r;
} else if (link_was_admin_up && !(link->flags & IFF_UP)) {
log_link_info(link, "Link DOWN");
else if (link_was_admin_up && !(link->flags & IFF_UP))
r = link_admin_state_down(link);
if (r < 0)
return r;
}
if (!had_carrier && link_has_carrier(link)) {
log_link_info(link, "Gained carrier");
if (r < 0)
return r;
if (!had_carrier && link_has_carrier(link))
r = link_carrier_gained(link);
if (r < 0)
return r;
} else if (had_carrier && !link_has_carrier(link)) {
log_link_info(link, "Lost carrier");
r = link_carrier_lost(link);
if (r < 0)
return r;
}
else if (had_carrier && !link_has_carrier(link))
link_carrier_lost(link);
if (r < 0)
return r;
return 0;
}
+31 -3
View File
@@ -12,6 +12,8 @@
#include "netlink-util.h"
#include "networkd-address.h"
#include "networkd-can.h"
#include "networkd-ipv4acd.h"
#include "networkd-ipv4ll.h"
#include "networkd-link.h"
#include "networkd-manager.h"
#include "networkd-queue.h"
@@ -178,6 +180,30 @@ static int link_set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Request
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_default_handler);
}
static int link_get_arp(Link *link) {
assert(link);
/* This returns tristate. */
if (!link->network)
return -1;
/* If ARP= is explicitly specified, use the setting. */
if (link->network->arp >= 0)
return link->network->arp;
/* Enable ARP when IPv4ACD is enabled. */
if (link_ipv4acd_enabled(link))
return true;
/* Similary, enable ARP when IPv4LL is enabled. */
if (link_ipv4ll_enabled(link))
return true;
/* Otherwise, do not change the flag. */
return -1;
}
static int link_configure_fill_message(
Link *link,
sd_netlink_message *req,
@@ -360,9 +386,11 @@ static int link_configure_fill_message(
case REQUEST_TYPE_SET_LINK_FLAGS: {
unsigned ifi_change = 0, ifi_flags = 0;
if (link->network->arp >= 0) {
int arp = link_get_arp(link);
if (arp >= 0) {
ifi_change |= IFF_NOARP;
SET_FLAG(ifi_flags, IFF_NOARP, link->network->arp == 0);
SET_FLAG(ifi_flags, IFF_NOARP, arp == 0);
}
if (link->network->multicast >= 0) {
@@ -844,7 +872,7 @@ int link_request_to_set_flags(Link *link) {
assert(link);
assert(link->network);
if (link->network->arp < 0 &&
if (link_get_arp(link) < 0 &&
link->network->multicast < 0 &&
link->network->allmulticast < 0 &&
link->network->promiscuous < 0)