]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: enable ARP= when IPv4LL/IPv4ACD is enabled 37190/head
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 20 Apr 2025 01:23:32 +0000 (10:23 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 20 Apr 2025 01:49:15 +0000 (10:49 +0900)
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.

man/systemd.network.xml
src/network/networkd-ipv4acd.c
src/network/networkd-ipv4acd.h
src/network/networkd-setlink.c

index 40aa1b449b36d4311e2f69022e0b032d25a5395c..d77ce61160499d805e91037d9f8503a32978a2af 100644 (file)
       <varlistentry>
         <term><varname>ARP=</varname></term>
         <listitem>
-          <para>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.</para>
-          <para> 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.</para>
+          <para>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 <varname>LinkLocalAddressing=</varname> or an
+          IPv4 address with <varname>DuplicateAddressDetection=</varname> enabled is requested. Otherwise,
+          the kernel's default will be used.</para>
 
           <xi:include href="version-info.xml" xpointer="v232"/>
         </listitem>
           <varname>MACVLAN=</varname>/<varname>MACVTAP=</varname> has <varname>Mode=passthru</varname>,
           or <option>ipv6</option> otherwise.</para>
 
+          <para>When IPv4 link-local addressing is enabled, <varname>ARP=</varname> is enabled unless if it
+          is explicitly configured.</para>
+
           <xi:include href="version-info.xml" xpointer="v219"/>
         </listitem>
       </varlistentry>
@@ -1439,6 +1443,9 @@ DuplicateAddressDetection=none</programlisting></para>
           <literal>ipv4</literal> for IPv4 link-local addresses (169.254.0.0/16), <literal>ipv6</literal>
           for IPv6 addresses, and <literal>none</literal> otherwise.</para>
 
+          <para>When enabled, regradless implicitly or not, <varname>ARP=</varname> is enabled unless it is
+          explicitly configured.</para>
+
           <xi:include href="version-info.xml" xpointer="v232"/>
         </listitem>
       </varlistentry>
index 4785b96f9f32f3da879dfc9e52a5edbff9ac0de5..0ecdee0893ae20aa5c14ae2e039469df4bcfd6a7 100644 (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;
 
index 54da435679631a8a971d1404794a67a7a9d2eee7..fc9f92d4f42794b79da865658b89f8150de61483 100644 (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);
index c0c1da1b16a6f3095920b4a3bd4ae5ae767dfbcd..d4606533a7d241b0926fdce9876f4a592ff84e43 100644 (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)