From: Yu Watanabe Date: Sun, 20 Apr 2025 01:23:32 +0000 (+0900) Subject: network: enable ARP= when IPv4LL/IPv4ACD is enabled X-Git-Tag: v258-rc1~759^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a06e88426444ac50fde712e426ec9a4234ae5576;p=thirdparty%2Fsystemd.git network: enable ARP= when IPv4LL/IPv4ACD is enabled We can run sd-ipv4ll/sd-ipv4acd also on an interface with IFF_NOARP flag, but that may cause address conflict with other hosts. Let's enable ARPing when sd-ipv4ll/sd-ipv4acd are enabled unless ARP= is explicitly disabled. --- diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 40aa1b449b3..d77ce611604 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -189,13 +189,14 @@ ARP= - Takes a boolean. If set to true, the IPv4 ARP (low-level Address Resolution Protocol) - and IPv6 NDP (Neighbor Discovery Protocol) for this interface are enabled. When unset, the - kernel's default will be used. - For example, disabling ARP is useful when creating multiple MACVLAN or VLAN virtual - interfaces atop a single lower-level physical interface, which will then only serve as a - link/"bridge" device aggregating traffic to the same physical link and not participate in - the network otherwise. Defaults to unset. + Takes a boolean. If set to true, the IPv4 ARP (low-level Address Resolution Protocol) and + IPv6 NDP (Neighbor Discovery Protocol) for this interface are enabled. For example, disabling ARP + is useful when creating multiple MACVLAN or VLAN virtual interfaces atop a single lower-level + physical interface, which will then only serve as a link/"bridge" device aggregating traffic to the + same physical link and not participate in the network otherwise. Defaults to unset, and enabled + when the IPv4 link-local addressing is enabled in LinkLocalAddressing= or an + IPv4 address with DuplicateAddressDetection= enabled is requested. Otherwise, + the kernel's default will be used. @@ -459,6 +460,9 @@ MACVLAN=/MACVTAP= has Mode=passthru, or otherwise. + When IPv4 link-local addressing is enabled, ARP= is enabled unless if it + is explicitly configured. + @@ -1439,6 +1443,9 @@ DuplicateAddressDetection=none ipv4 for IPv4 link-local addresses (169.254.0.0/16), ipv6 for IPv6 addresses, and none otherwise. + When enabled, regradless implicitly or not, ARP= is enabled unless it is + explicitly configured. + diff --git a/src/network/networkd-ipv4acd.c b/src/network/networkd-ipv4acd.c index 4785b96f9f3..0ecdee0893a 100644 --- a/src/network/networkd-ipv4acd.c +++ b/src/network/networkd-ipv4acd.c @@ -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; diff --git a/src/network/networkd-ipv4acd.h b/src/network/networkd-ipv4acd.h index 54da4356796..fc9f92d4f42 100644 --- a/src/network/networkd-ipv4acd.h +++ b/src/network/networkd-ipv4acd.h @@ -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); diff --git a/src/network/networkd-setlink.c b/src/network/networkd-setlink.c index c0c1da1b16a..d4606533a7d 100644 --- a/src/network/networkd-setlink.c +++ b/src/network/networkd-setlink.c @@ -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)