network: several follow-ups for proxy neighbor setting (#43408)
Follow-ups for 08bebda611.
This commit is contained in:
@@ -278,12 +278,9 @@ CHANGES WITH 262:
|
||||
|
||||
Changes in systemd-networkd:
|
||||
|
||||
* A new IPv4ProxyARPAddress= setting has been added to the [Network]
|
||||
section of .network files. It is the IPv4 counterpart to
|
||||
IPv6ProxyNDPAddress= and allows manual entries to be added to the
|
||||
kernel's IPv4 neighbor proxy table. The setting implies
|
||||
IPv4ProxyARP=yes but has no effect if IPv4ProxyARP= has been set to
|
||||
false. This mirrors the behavior of IPv6ProxyNDPAddress=.
|
||||
* The IPv6ProxyNDPAddress= setting in the [Network] section of .network
|
||||
files has been renamed to ProxyNeighbor=. The setting can now also be
|
||||
used to add IPv4 addresses to the kernel's IPv4 neighbor proxy table.
|
||||
|
||||
* "networkctl reload" gained --no-reconfigure to reload .network and
|
||||
.netdev files from disk without reconfiguring existing links. It uses
|
||||
|
||||
+10
-27
@@ -1150,25 +1150,6 @@ DuplicateAddressDetection=none</programlisting></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>IPv4ProxyARPAddress=</varname></term>
|
||||
<listitem>
|
||||
<para>An IPv4 address, for which ARP requests will be proxied. This option may be specified
|
||||
more than once. <command>systemd-networkd</command> will add the
|
||||
<varname>IPv4ProxyARPAddress=</varname> entries to the kernel's IPv4 neighbor proxy table.
|
||||
When <varname>IPv4ProxyARP=</varname> is unset, this setting implies
|
||||
<varname>IPv4ProxyARP=yes</varname>: the per-interface <literal>proxy_arp</literal> sysctl
|
||||
is enabled automatically, which also activates automatic proxy ARP for every address the
|
||||
interface has a route toward on connected subnets, in addition to answering the listed
|
||||
entries. If <varname>IPv4ProxyARP=</varname> has been set to false, the
|
||||
<varname>IPv4ProxyARPAddress=</varname> entries listed here are discarded and not
|
||||
programmed into the kernel. This mirrors the behaviour of
|
||||
<varname>IPv6ProxyNDPAddress=</varname>/<varname>IPv6ProxyNDP=</varname>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v262"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>IPv6ProxyNDP=</varname></term>
|
||||
<listitem>
|
||||
@@ -1188,16 +1169,18 @@ DuplicateAddressDetection=none</programlisting></para>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>IPv6ProxyNDPAddress=</varname></term>
|
||||
<term><varname>ProxyNeighbor=</varname></term>
|
||||
<listitem>
|
||||
<para>An IPv6 address, for which Neighbour Advertisement messages will be proxied. This
|
||||
option may be specified more than once. <command>systemd-networkd</command> will add the
|
||||
<varname>IPv6ProxyNDPAddress=</varname> entries to the kernel's IPv6 neighbor proxy table.
|
||||
This setting implies <varname>IPv6ProxyNDP=yes</varname> but has no effect if
|
||||
<varname>IPv6ProxyNDP=</varname> has been set to false. When unset, the kernel's default will
|
||||
be used.</para>
|
||||
<para>Takes an IPv4 or IPv6 address for which ARP requests or Neighbour Advertisement messages will
|
||||
be proxied. This option may be specified more than once. <command>systemd-networkd</command> will
|
||||
add the specified address to the kernel's neighbour proxy table. For an IPv4 address, a proxy ARP
|
||||
entry will be added. For an IPv6 address, a proxy NDP entry will be added. When an IPv6 address is
|
||||
specified, <varname>IPv6ProxyNDP=yes</varname> is implied. If <varname>IPv6ProxyNDP=</varname> is
|
||||
explicitly disabled, IPv6 addresses specified with <varname>ProxyNeighbor=</varname> are ignored.
|
||||
Note, unlike IPv6, specifying an IPv4 address does <emphasis>not</emphasis> imply
|
||||
<varname>IPv4ProxyARP=</varname>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v233"/>
|
||||
<xi:include href="version-info.xml" xpointer="v262"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
@@ -20,6 +20,13 @@ int sysctl_read_ip_property_uint32(int af, const char *ifname, const char *prope
|
||||
int sysctl_write_ip_property(int af, const char *ifname, const char *property, const char *value, Hashmap **shadow);
|
||||
int sysctl_write_ip_property_boolean(int af, const char *ifname, const char *property, bool value, Hashmap **shadow);
|
||||
|
||||
static inline int sysctl_write_ip_property_tristate(int af, const char *ifname, const char *property, int value, Hashmap **shadow) {
|
||||
if (value < 0)
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_boolean(af, ifname, property, value, shadow);
|
||||
}
|
||||
|
||||
int sysctl_write_ip_neighbor_property(int af, const char *ifname, const char *property, const char *value, Hashmap **shadow);
|
||||
int sysctl_write_ip_neighbor_property_uint32(int af, const char *ifname, const char *property, uint32_t value, Hashmap **shadow);
|
||||
|
||||
|
||||
@@ -15,61 +15,37 @@
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
bool network_has_neighbor_proxy_address(const Network *network, int family) {
|
||||
struct in_addr_data *a;
|
||||
|
||||
assert(network);
|
||||
assert(IN_SET(family, AF_INET, AF_INET6));
|
||||
|
||||
SET_FOREACH(a, network->neighbor_proxy_addresses)
|
||||
if (a->family == family)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void network_drop_neighbor_proxy_addresses(Network *network, int family) {
|
||||
struct in_addr_data *a;
|
||||
|
||||
assert(network);
|
||||
assert(IN_SET(family, AF_INET, AF_INET6));
|
||||
|
||||
SET_FOREACH(a, network->neighbor_proxy_addresses)
|
||||
if (a->family == family)
|
||||
free(set_remove(network->neighbor_proxy_addresses, a));
|
||||
|
||||
if (set_isempty(network->neighbor_proxy_addresses))
|
||||
network->neighbor_proxy_addresses = set_free(network->neighbor_proxy_addresses);
|
||||
}
|
||||
|
||||
void network_adjust_neighbor_proxy(Network *network) {
|
||||
assert(network);
|
||||
|
||||
if (set_isempty(network->neighbor_proxy_addresses))
|
||||
return;
|
||||
struct in_addr_data *a;
|
||||
SET_FOREACH(a, network->neighbor_proxy_addresses) {
|
||||
switch (a->family) {
|
||||
case AF_INET6:
|
||||
if (!socket_ipv6_is_supported()) {
|
||||
log_warning("%s: Specified IPv6 proxy NDP address %s, but IPv6 is not supported by the kernel, ignoring.",
|
||||
network->filename, IN_ADDR_TO_STRING(a->family, &a->address));
|
||||
free(set_remove(network->neighbor_proxy_addresses, a));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If IPv6 is not supported by the kernel, drop any IPv6 entries up front. */
|
||||
if (!socket_ipv6_is_supported() &&
|
||||
network_has_neighbor_proxy_address(network, AF_INET6)) {
|
||||
log_once(LOG_WARNING,
|
||||
"%s: IPv6 proxy NDP addresses are set, but IPv6 is not supported by kernel, "
|
||||
"ignoring IPv6 proxy NDP addresses.", network->filename);
|
||||
network_drop_neighbor_proxy_addresses(network, AF_INET6);
|
||||
}
|
||||
if (network->ipv6_proxy_ndp == 0) {
|
||||
log_warning("%s: Specified IPv6 proxy NDP address %s, but IPv6ProxyNDP= is disabled, ignoring.",
|
||||
network->filename, IN_ADDR_TO_STRING(a->family, &a->address));
|
||||
free(set_remove(network->neighbor_proxy_addresses, a));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Drop per-family entries when the corresponding proxy sysctl was explicitly disabled.
|
||||
* For IPv6 the proxy_ndp sysctl is required for manual entries to take effect; for IPv4 we
|
||||
* apply the same rule for consistency so that an explicit IPv4ProxyARP=no is respected. */
|
||||
int family;
|
||||
FOREACH_ARGUMENT(family, AF_INET, AF_INET6) {
|
||||
int tristate = family == AF_INET ? network->proxy_arp : network->ipv6_proxy_ndp;
|
||||
/* IPv6 proxy NDP entry requires that proxy_ndp sysctl is enabled. */
|
||||
network->ipv6_proxy_ndp = true;
|
||||
break;
|
||||
|
||||
if (tristate == 0 && network_has_neighbor_proxy_address(network, family)) {
|
||||
log_warning("%s: %s is disabled. Ignoring %s.",
|
||||
network->filename,
|
||||
family == AF_INET ? "IPv4ProxyARP=" : "IPv6ProxyNDP=",
|
||||
family == AF_INET ? "IPv4ProxyARPAddress=" : "IPv6ProxyNDPAddress=");
|
||||
network_drop_neighbor_proxy_addresses(network, family);
|
||||
case AF_INET:
|
||||
/* IPv4 proxy ARP entry does NOT require that proxy_arp sysctl is enabled. */
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,62 +166,49 @@ int config_parse_neighbor_proxy_address(
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_free_ struct in_addr_data *address = NULL;
|
||||
Network *network = ASSERT_PTR(userdata);
|
||||
int family = ltype;
|
||||
union in_addr_union buffer = {};
|
||||
Set **neighbor_proxy_addresses = ASSERT_PTR(data);
|
||||
int r;
|
||||
|
||||
assert(IN_SET(family, AF_INET, AF_INET6));
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
/* Drop only entries belonging to this family, so that
|
||||
* IPv4ProxyARPAddress= and IPv6ProxyNDPAddress= can be reset independently. */
|
||||
network_drop_neighbor_proxy_addresses(network, family);
|
||||
*neighbor_proxy_addresses = set_free(*neighbor_proxy_addresses);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = in_addr_from_string(family, rvalue, &buffer);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to parse %s, ignoring: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
struct in_addr_data a = {};
|
||||
r = in_addr_from_string_auto(rvalue, &a.family, &a.address);
|
||||
if (r < 0)
|
||||
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
|
||||
|
||||
if (in_addr_is_null(family, &buffer)) {
|
||||
if (in_addr_is_null(a.family, &a.address)) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"%s cannot be the ANY address, ignoring: %s", lvalue, rvalue);
|
||||
"%s= cannot be the ANY address, ignoring: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Reject address classes that do not qualify as proxy targets and that the kernel would
|
||||
* reject: multicast for both families, plus the IPv4 limited broadcast 255.255.255.255. */
|
||||
if (in_addr_is_multicast(family, &buffer) > 0) {
|
||||
if (in_addr_is_multicast(a.family, &a.address) > 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"%s cannot be a multicast address, ignoring: %s", lvalue, rvalue);
|
||||
"%s= cannot be a multicast address, ignoring: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (family == AF_INET && buffer.in.s_addr == htobe32(INADDR_BROADCAST)) {
|
||||
if (a.family == AF_INET && a.address.in.s_addr == htobe32(INADDR_BROADCAST)) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"%s cannot be the limited broadcast address, ignoring: %s",
|
||||
"%s= cannot be the limited broadcast address, ignoring: %s",
|
||||
lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
address = new(struct in_addr_data, 1);
|
||||
if (!address)
|
||||
struct in_addr_data *copied = newdup(struct in_addr_data, &a, 1);
|
||||
if (!copied)
|
||||
return log_oom();
|
||||
|
||||
*address = (struct in_addr_data) {
|
||||
.family = family,
|
||||
.address = buffer,
|
||||
};
|
||||
|
||||
r = set_ensure_consume(&network->neighbor_proxy_addresses, &in_addr_data_hash_ops_free, TAKE_PTR(address));
|
||||
r = set_ensure_consume(neighbor_proxy_addresses, &in_addr_data_hash_ops_free, copied);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
#include "networkd-forward.h"
|
||||
|
||||
bool network_has_neighbor_proxy_address(const Network *network, int family);
|
||||
|
||||
void network_adjust_neighbor_proxy(Network *network);
|
||||
|
||||
int link_request_static_neighbor_proxy_addresses(Link *link);
|
||||
|
||||
@@ -176,8 +176,8 @@ Network.PrimarySlave, config_parse_bool,
|
||||
Network.IPv4ProxyARP, config_parse_tristate, 0, offsetof(Network, proxy_arp)
|
||||
Network.IPv4ProxyARPPrivateVLAN, config_parse_tristate, 0, offsetof(Network, proxy_arp_pvlan)
|
||||
Network.ProxyARP, config_parse_tristate, 0, offsetof(Network, proxy_arp)
|
||||
Network.IPv4ProxyARPAddress, config_parse_neighbor_proxy_address, AF_INET, 0
|
||||
Network.IPv6ProxyNDPAddress, config_parse_neighbor_proxy_address, AF_INET6, 0
|
||||
Network.IPv6ProxyNDPAddress, config_parse_neighbor_proxy_address, 0, offsetof(Network, neighbor_proxy_addresses) /* deprecated */
|
||||
Network.ProxyNeighbor, config_parse_neighbor_proxy_address, 0, offsetof(Network, neighbor_proxy_addresses)
|
||||
Network.IPv4ReversePathFilter, config_parse_ip_reverse_path_filter, 0, offsetof(Network, ipv4_rp_filter)
|
||||
Network.MulticastIGMPVersion, config_parse_ipv4_force_igmp_version, 0, offsetof(Network, ipv4_force_igmp_version)
|
||||
Network.MPLSRouting, config_parse_tristate, 0, offsetof(Network, mpls_input)
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "networkd-lldp-tx.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-ndisc.h"
|
||||
#include "networkd-neighbor-proxy.h"
|
||||
#include "networkd-network.h"
|
||||
#include "networkd-sysctl.h"
|
||||
#include "path-util.h"
|
||||
@@ -212,17 +211,19 @@ static void manager_set_ip_forwarding(Manager *manager, int family) {
|
||||
return;
|
||||
|
||||
t = manager->ip_forwarding[family == AF_INET6];
|
||||
if (t < 0)
|
||||
return; /* keep */
|
||||
|
||||
/* First, set the default value. */
|
||||
r = sysctl_write_ip_property_boolean(family, "default", "forwarding", t, manager_get_sysctl_shadow(manager));
|
||||
r = sysctl_write_ip_property_tristate(
|
||||
family, "default", "forwarding", t,
|
||||
manager_get_sysctl_shadow(manager));
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to %s the default %s forwarding: %m",
|
||||
enable_disable(t), af_to_ipv4_ipv6(family));
|
||||
|
||||
/* Then, set the value to all interfaces. */
|
||||
r = sysctl_write_ip_property_boolean(family, "all", "forwarding", t, manager_get_sysctl_shadow(manager));
|
||||
r = sysctl_write_ip_property_tristate(
|
||||
family, "all", "forwarding", t,
|
||||
manager_get_sysctl_shadow(manager));
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to %s %s forwarding for all interfaces: %m",
|
||||
enable_disable(t), af_to_ipv4_ipv6(family));
|
||||
@@ -267,29 +268,21 @@ static int link_update_ipv6_sysctl(Link *link) {
|
||||
if (!link_ipv6_enabled(link))
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "disable_ipv6", false, manager_get_sysctl_shadow(link->manager));
|
||||
return sysctl_write_ip_property_boolean(
|
||||
AF_INET6, link->ifname, "disable_ipv6", false,
|
||||
manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static int link_set_proxy_arp(Link *link) {
|
||||
bool v;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
|
||||
if (!link_is_configured_for_family(link, AF_INET))
|
||||
return 0;
|
||||
|
||||
if (link->network->proxy_arp >= 0)
|
||||
v = link->network->proxy_arp;
|
||||
else if (network_has_neighbor_proxy_address(link->network, AF_INET))
|
||||
/* If IPv4ProxyARP= is not explicitly set, but per-address IPv4ProxyARPAddress=
|
||||
* entries are configured, implicitly enable the proxy_arp sysctl. This matches
|
||||
* the behavior of IPv6ProxyNDPAddress= which implies IPv6ProxyNDP=yes. */
|
||||
v = true;
|
||||
else
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "proxy_arp", v, manager_get_sysctl_shadow(link->manager));
|
||||
return sysctl_write_ip_property_tristate(
|
||||
AF_INET, link->ifname, "proxy_arp", link->network->proxy_arp,
|
||||
manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static int link_set_proxy_arp_pvlan(Link *link) {
|
||||
@@ -299,10 +292,9 @@ static int link_set_proxy_arp_pvlan(Link *link) {
|
||||
if (!link_is_configured_for_family(link, AF_INET))
|
||||
return 0;
|
||||
|
||||
if (link->network->proxy_arp_pvlan < 0)
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "proxy_arp_pvlan", link->network->proxy_arp_pvlan > 0, manager_get_sysctl_shadow(link->manager));
|
||||
return sysctl_write_ip_property_tristate(
|
||||
AF_INET, link->ifname, "proxy_arp_pvlan", link->network->proxy_arp_pvlan,
|
||||
manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
int link_get_ip_forwarding(Link *link, int family) {
|
||||
@@ -339,10 +331,9 @@ static int link_set_ip_forwarding_impl(Link *link, int family) {
|
||||
return 0;
|
||||
|
||||
t = link_get_ip_forwarding(link, family);
|
||||
if (t < 0)
|
||||
return 0; /* keep */
|
||||
|
||||
r = sysctl_write_ip_property_boolean(family, link->ifname, "forwarding", t, manager_get_sysctl_shadow(link->manager));
|
||||
r = sysctl_write_ip_property_tristate(
|
||||
family, link->ifname, "forwarding", t,
|
||||
manager_get_sysctl_shadow(link->manager));
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to %s %s forwarding, ignoring: %m",
|
||||
enable_disable(t), af_to_ipv4_ipv6(family));
|
||||
@@ -512,20 +503,15 @@ static int link_set_ipv6_retransmission_time(Link *link) {
|
||||
}
|
||||
|
||||
static int link_set_ipv6_proxy_ndp(Link *link) {
|
||||
bool v;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
|
||||
if (!link_is_configured_for_family(link, AF_INET6))
|
||||
return 0;
|
||||
|
||||
if (link->network->ipv6_proxy_ndp >= 0)
|
||||
v = link->network->ipv6_proxy_ndp;
|
||||
else
|
||||
v = network_has_neighbor_proxy_address(link->network, AF_INET6);
|
||||
|
||||
return sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "proxy_ndp", v, manager_get_sysctl_shadow(link->manager));
|
||||
return sysctl_write_ip_property_tristate(
|
||||
AF_INET6, link->ifname, "proxy_ndp", link->network->ipv6_proxy_ndp,
|
||||
manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
int link_set_ipv6_mtu(Link *link, int log_level) {
|
||||
@@ -653,10 +639,9 @@ static int link_set_ipv4_accept_local(Link *link) {
|
||||
if (!link_is_configured_for_family(link, AF_INET))
|
||||
return 0;
|
||||
|
||||
if (link->network->ipv4_accept_local < 0)
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "accept_local", link->network->ipv4_accept_local > 0, manager_get_sysctl_shadow(link->manager));
|
||||
return sysctl_write_ip_property_tristate(
|
||||
AF_INET, link->ifname, "accept_local", link->network->ipv4_accept_local,
|
||||
manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static int link_set_ipv4_route_localnet(Link *link) {
|
||||
@@ -666,10 +651,9 @@ static int link_set_ipv4_route_localnet(Link *link) {
|
||||
if (!link_is_configured_for_family(link, AF_INET))
|
||||
return 0;
|
||||
|
||||
if (link->network->ipv4_route_localnet < 0)
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "route_localnet", link->network->ipv4_route_localnet > 0, manager_get_sysctl_shadow(link->manager));
|
||||
return sysctl_write_ip_property_tristate(
|
||||
AF_INET, link->ifname, "route_localnet", link->network->ipv4_route_localnet,
|
||||
manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static int link_set_ipv4_src_valid_mark(Link *link) {
|
||||
@@ -680,10 +664,9 @@ static int link_set_ipv4_src_valid_mark(Link *link) {
|
||||
if (!link_is_configured_for_family(link, AF_INET))
|
||||
return 0;
|
||||
|
||||
if (link->network->ipv4_src_valid_mark < 0)
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "src_valid_mark", link->network->ipv4_src_valid_mark > 0, manager_get_sysctl_shadow(link->manager));
|
||||
return sysctl_write_ip_property_tristate(
|
||||
AF_INET, link->ifname, "src_valid_mark", link->network->ipv4_src_valid_mark,
|
||||
manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static int link_set_ipv4_promote_secondaries(Link *link) {
|
||||
@@ -698,7 +681,9 @@ static int link_set_ipv4_promote_secondaries(Link *link) {
|
||||
* otherwise. The way systemd-networkd works is that the new IP of a lease is added as a
|
||||
* secondary IP and when the primary one expires it relies on the kernel to promote the
|
||||
* secondary IP. See also https://github.com/systemd/systemd/issues/7163 */
|
||||
return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "promote_secondaries", true, manager_get_sysctl_shadow(link->manager));
|
||||
return sysctl_write_ip_property_boolean(
|
||||
AF_INET, link->ifname, "promote_secondaries", true,
|
||||
manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static int link_set_mpls_input(Link *link) {
|
||||
@@ -708,10 +693,9 @@ static int link_set_mpls_input(Link *link) {
|
||||
if (!link_is_configured_for_family(link, AF_MPLS))
|
||||
return 0;
|
||||
|
||||
if (link->network->mpls_input < 0)
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_boolean(AF_MPLS, link->ifname, "input", link->network->mpls_input > 0, manager_get_sysctl_shadow(link->manager));
|
||||
return sysctl_write_ip_property_tristate(
|
||||
AF_MPLS, link->ifname, "input", link->network->mpls_input,
|
||||
manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
int link_set_sysctl(Link *link) {
|
||||
|
||||
@@ -4,7 +4,7 @@ Name=dummy98
|
||||
|
||||
[Network]
|
||||
IPv4ProxyARP=no
|
||||
IPv4ProxyARPAddress=192.0.2.1
|
||||
IPv4ProxyARPAddress=192.0.2.2
|
||||
ProxyNeighbor=192.0.3.1
|
||||
ProxyNeighbor=192.0.3.2
|
||||
IPv6AcceptRA=no
|
||||
Address=10.0.0.1/24
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
Name=dummy98
|
||||
|
||||
[Network]
|
||||
IPv4ProxyARPAddress=192.0.2.1
|
||||
IPv4ProxyARPAddress=192.0.2.2
|
||||
IPv4ProxyARPAddress=192.0.2.3
|
||||
IPv4ProxyARPAddress=192.0.2.4
|
||||
IPv4ProxyARPAddress=192.0.2.5
|
||||
ProxyNeighbor=192.0.2.1
|
||||
ProxyNeighbor=192.0.2.2
|
||||
ProxyNeighbor=192.0.2.3
|
||||
ProxyNeighbor=192.0.2.4
|
||||
ProxyNeighbor=192.0.2.5
|
||||
IPv6AcceptRA=no
|
||||
Address=10.0.0.1/24
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
Name=dummy98
|
||||
|
||||
[Network]
|
||||
IPv6ProxyNDPAddress=2607:5300:203:5215:5::1
|
||||
IPv6ProxyNDPAddress=2607:5300:203:5215:4::1
|
||||
IPv6ProxyNDPAddress=2607:5300:203:5215:3::1
|
||||
IPv6ProxyNDPAddress=2607:5300:203:5215:2::1
|
||||
IPv6ProxyNDPAddress=2607:5300:203:5215:1::1
|
||||
ProxyNeighbor=2607:5300:203:5215:5::1
|
||||
ProxyNeighbor=2607:5300:203:5215:4::1
|
||||
ProxyNeighbor=2607:5300:203:5215:3::1
|
||||
ProxyNeighbor=2607:5300:203:5215:2::1
|
||||
ProxyNeighbor=2607:5300:203:5215:1::1
|
||||
IPv6AcceptRA=no
|
||||
Address=66.70.129.136/32
|
||||
Address=66.70.129.142/32
|
||||
|
||||
@@ -5370,9 +5370,30 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
|
||||
output = check_output('ip neighbor show proxy dev dummy98')
|
||||
print(output)
|
||||
for i in range(1, 5):
|
||||
for i in range(1, 6):
|
||||
self.assertRegex(output, f'2607:5300:203:5215:{i}::1 *proxy')
|
||||
|
||||
# When a proxy NDP address is specified, IPv6ProxyNDP=yes is implied.
|
||||
self.check_ipv6_sysctl_attr('dummy98', 'proxy_ndp', '1')
|
||||
|
||||
with open(
|
||||
os.path.join(network_unit_dir, '25-ipv6-proxy-ndp.network'), mode='a', encoding='utf-8'
|
||||
) as f:
|
||||
f.write('[Network]\nIPv6ProxyNDP=no\n')
|
||||
|
||||
stop_networkd()
|
||||
remove_link('dummy98')
|
||||
start_networkd()
|
||||
self.wait_online('dummy98:routable')
|
||||
|
||||
# If IPv6ProxyNDP= is disabled, proxy NDP addresses are ignored.
|
||||
output = check_output('ip neighbor show proxy dev dummy98')
|
||||
print(output)
|
||||
for i in range(1, 6):
|
||||
self.assertNotRegex(output, f'2607:5300:203:5215:{i}::1 *proxy')
|
||||
|
||||
self.check_ipv6_sysctl_attr('dummy98', 'proxy_ndp', '0')
|
||||
|
||||
def test_ipv4_proxy_arp(self):
|
||||
copy_network_unit('25-ipv4-proxy-arp.network', '12-dummy.netdev')
|
||||
start_networkd()
|
||||
@@ -5384,13 +5405,9 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
for i in range(1, 6):
|
||||
self.assertRegex(output, f'192.0.2.{i} *proxy')
|
||||
|
||||
# IPv4ProxyARPAddress= implies IPv4ProxyARP=yes, mirroring IPv6ProxyNDPAddress=.
|
||||
self.check_ipv4_sysctl_attr('dummy98', 'proxy_arp', '1')
|
||||
# Even if a proxy ARP address is specified, IPv4ProxyARP=yes is NOT implied.
|
||||
self.check_ipv4_sysctl_attr('dummy98', 'proxy_arp', '0')
|
||||
|
||||
# Explicit IPv4ProxyARP=no must suppress all IPv4ProxyARPAddress= entries and
|
||||
# must not force proxy_arp=1. The module is add-only (no reconcile/remove pass),
|
||||
# so phase 2 starts from a clean interface: stop networkd, delete the dummy to
|
||||
# flush the kernel neighbor-proxy table, swap the .network file, and restart.
|
||||
stop_networkd()
|
||||
remove_link('dummy98')
|
||||
remove_network_unit('25-ipv4-proxy-arp.network')
|
||||
@@ -5398,10 +5415,14 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
start_networkd()
|
||||
self.wait_online('dummy98:routable')
|
||||
|
||||
# Even if IPv4ProxyARP= is disabled, proxy ARP addresses can be configured.
|
||||
output = check_output('ip -4 neighbor show proxy dev dummy98')
|
||||
print(output)
|
||||
for i in range(1, 6):
|
||||
self.assertNotIn(f'192.0.2.{i}', output)
|
||||
self.assertNotRegex(output, f'192.0.2.{i} *proxy')
|
||||
for i in range(1, 3):
|
||||
self.assertRegex(output, f'192.0.3.{i} *proxy')
|
||||
|
||||
self.check_ipv4_sysctl_attr('dummy98', 'proxy_arp', '0')
|
||||
|
||||
def test_ipv6_neigh_retrans_time(self):
|
||||
@@ -11143,21 +11164,21 @@ class NetworkdSysctlTest(unittest.TestCase, Utilities):
|
||||
call('sysctl -w net.ipv6.conf.dummy98.accept_ra=1')
|
||||
call('sysctl -w net.ipv6.conf.dummy98.mtu=1360')
|
||||
call('sysctl -w net.ipv4.conf.dummy98.promote_secondaries=0')
|
||||
call('sysctl -w net.ipv6.conf.dummy98.proxy_ndp=1')
|
||||
|
||||
# And unmanaged ones
|
||||
call('sysctl -w net.ipv6.conf.dummy98.hop_limit=4')
|
||||
call('sysctl -w net.ipv6.conf.dummy98.max_addresses=10')
|
||||
call('sysctl -w net.ipv6.conf.dummy98.proxy_ndp=1')
|
||||
|
||||
log = read_networkd_log()
|
||||
# fmt: off
|
||||
self.assertRegex(log, r"Foreign process 'sysctl\[\d+\]' changed sysctl '/proc/sys/net/ipv6/conf/dummy98/accept_ra' from '0' to '1', conflicting with our setting to '0'")
|
||||
self.assertRegex(log, r"Foreign process 'sysctl\[\d+\]' changed sysctl '/proc/sys/net/ipv6/conf/dummy98/mtu' from '1550' to '1360', conflicting with our setting to '1550'")
|
||||
self.assertRegex(log, r"Foreign process 'sysctl\[\d+\]' changed sysctl '/proc/sys/net/ipv4/conf/dummy98/promote_secondaries' from '1' to '0', conflicting with our setting to '1'")
|
||||
self.assertRegex(log, r"Foreign process 'sysctl\[\d+\]' changed sysctl '/proc/sys/net/ipv6/conf/dummy98/proxy_ndp' from '0' to '1', conflicting with our setting to '0'")
|
||||
# fmt: on
|
||||
self.assertNotIn("changed sysctl '/proc/sys/net/ipv6/conf/dummy98/hop_limit'", log)
|
||||
self.assertNotIn("changed sysctl '/proc/sys/net/ipv6/conf/dummy98/max_addresses'", log)
|
||||
self.assertNotIn("changed sysctl '/proc/sys/net/ipv6/conf/dummy98/proxy_ndp'", log)
|
||||
self.assertNotIn('Sysctl monitor BPF returned error', log)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user