mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 08:25:20 +09:00
network: enable ARP when IPv4LL and/or IPv4ACD is enabled (#37190)
This commit is contained in:
@@ -189,13 +189,14 @@
|
||||
<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>
|
||||
@@ -459,6 +460,9 @@
|
||||
<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>
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user