diff --git a/man/systemd.network.xml b/man/systemd.network.xml index bc3174b3916..a84fc3d5c87 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -4017,14 +4017,29 @@ ServerAddress=192.168.0.1/24 + + ReachableTimeSec= + + + Configures the time, used in the Neighbor Unreachability Detection algorithm, for which + clients can assume a neighbor is reachable after having received a reachability confirmation. Takes + a time span in the range 0…4294967295 ms. When 0, clients will handle it as if the value wasn't + specified. Defaults to 0. + + + + + RetransmitSec= - Takes a timespan. Configures the retransmit time, used by clients to retransmit Neighbor - Solicitation messages on address resolution and the Neighbor Unreachability Detection algorithm. - An integer, the default unit is seconds, in the range 0…4294967295 msec. Defaults to 0. + + Configures the time, used in the Neighbor Unreachability Detection algorithm, for which + clients can use as retransmit time on address resolution and the Neighbor Unreachability Detection + algorithm. Takes a time span in the range 0…4294967295 ms. When 0, clients will handle it as if + the value wasn't specified. Defaults to 0. - + diff --git a/src/libsystemd-network/radv-internal.h b/src/libsystemd-network/radv-internal.h index 378781c138d..0a535ddf4bd 100644 --- a/src/libsystemd-network/radv-internal.h +++ b/src/libsystemd-network/radv-internal.h @@ -43,9 +43,11 @@ #define RADV_MAX_ROUTER_LIFETIME_USEC (9000 * USEC_PER_SEC) #define RADV_DEFAULT_ROUTER_LIFETIME_USEC (3 * RADV_DEFAULT_MAX_TIMEOUT_USEC) /* RFC 4861 section 4.2. - * Retrans Timer + * Reachable Time and Retrans Timer * 32-bit unsigned integer. The time, in milliseconds. */ -#define RADV_MAX_RETRANSMIT_USEC (UINT32_MAX * USEC_PER_MSEC) +#define RADV_MAX_UINT32_MSEC_USEC (UINT32_MAX * USEC_PER_MSEC) +#define RADV_MAX_REACHABLE_TIME_USEC RADV_MAX_UINT32_MSEC_USEC +#define RADV_MAX_RETRANSMIT_USEC RADV_MAX_UINT32_MSEC_USEC /* draft-ietf-6man-slaac-renum-02 section 4.1.1. * AdvPreferredLifetime: max(AdvDefaultLifetime, 3 * MaxRtrAdvInterval) * AdvValidLifetime: 2 * AdvPreferredLifetime */ @@ -107,6 +109,7 @@ struct sd_radv { uint8_t flags; uint8_t preference; uint32_t mtu; + usec_t reachable_usec; usec_t retransmit_usec; usec_t lifetime_usec; /* timespan */ diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c index f6f30ce3197..a30a805271b 100644 --- a/src/libsystemd-network/sd-radv.c +++ b/src/libsystemd-network/sd-radv.c @@ -163,6 +163,7 @@ static int radv_send_router(sd_radv *ra, const struct in6_addr *dst) { struct nd_router_advert adv = { .nd_ra_type = ND_ROUTER_ADVERT, .nd_ra_router_lifetime = usec_to_be16_sec(ra->lifetime_usec), + .nd_ra_reachable = usec_to_be32_msec(ra->reachable_usec), .nd_ra_retransmit = usec_to_be32_msec(ra->retransmit_usec), }; struct { @@ -538,6 +539,13 @@ int sd_radv_set_hop_limit(sd_radv *ra, uint8_t hop_limit) { return 0; } +int sd_radv_set_reachable_time(sd_radv *ra, uint64_t usec) { + assert_return(ra, -EINVAL); + + ra->reachable_usec = usec; + return 0; +} + int sd_radv_set_retransmit(sd_radv *ra, uint64_t usec) { assert_return(ra, -EINVAL); diff --git a/src/libsystemd-network/test-ndisc-ra.c b/src/libsystemd-network/test-ndisc-ra.c index 78635ee6576..8be7351a098 100644 --- a/src/libsystemd-network/test-ndisc-ra.c +++ b/src/libsystemd-network/test-ndisc-ra.c @@ -199,6 +199,11 @@ TEST(radv) { assert_se(sd_radv_set_other_information(ra, true) >= 0); assert_se(sd_radv_set_other_information(ra, false) >= 0); + ASSERT_RETURN_EXPECTED_SE(sd_radv_set_reachable_time(NULL, 10 * USEC_PER_MSEC) < 0); + assert_se(sd_radv_set_reachable_time(ra, 10 * USEC_PER_MSEC) >= 0); + assert_se(sd_radv_set_reachable_time(ra, 0) >= 0); + assert_se(sd_radv_set_reachable_time(ra, USEC_INFINITY) >= 0); + ASSERT_RETURN_EXPECTED_SE(sd_radv_set_retransmit(NULL, 10 * USEC_PER_MSEC) < 0); assert_se(sd_radv_set_retransmit(ra, 10 * USEC_PER_MSEC) >= 0); assert_se(sd_radv_set_retransmit(ra, 0) >= 0); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 62f11c5c5c9..4124b3270fe 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -393,7 +393,8 @@ DHCPPrefixDelegation.RouteMetric, config_parse_uint32, DHCPPrefixDelegation.NetLabel, config_parse_string, CONFIG_PARSE_STRING_SAFE, offsetof(Network, dhcp_pd_netlabel) DHCPPrefixDelegation.NFTSet, config_parse_nft_set, NFT_SET_PARSE_NETWORK, offsetof(Network, dhcp_pd_nft_set_context) IPv6SendRA.RouterLifetimeSec, config_parse_router_lifetime, 0, offsetof(Network, router_lifetime_usec) -IPv6SendRA.RetransmitSec, config_parse_router_retransmit, 0, offsetof(Network, router_retransmit_usec) +IPv6SendRA.ReachableTimeSec, config_parse_router_uint32_msec_usec, 0, offsetof(Network, router_reachable_usec) +IPv6SendRA.RetransmitSec, config_parse_router_uint32_msec_usec, 0, offsetof(Network, router_retransmit_usec) IPv6SendRA.Managed, config_parse_bool, 0, offsetof(Network, router_managed) IPv6SendRA.OtherInformation, config_parse_bool, 0, offsetof(Network, router_other_information) IPv6SendRA.RouterPreference, config_parse_router_preference, 0, 0 diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index c8573e09734..92d367eccf8 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -246,6 +246,7 @@ struct Network { RADVPrefixDelegation router_prefix_delegation; usec_t router_lifetime_usec; uint8_t router_preference; + usec_t router_reachable_usec; usec_t router_retransmit_usec; uint8_t router_hop_limit; bool router_managed; diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index fa5884a6c35..0f0f3a34ce9 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -577,6 +577,10 @@ static int radv_configure(Link *link) { return r; } + r = sd_radv_set_reachable_time(link->radv, link->network->router_reachable_usec); + if (r < 0) + return r; + if (link->network->router_retransmit_usec > 0) { r = sd_radv_set_retransmit(link->radv, link->network->router_retransmit_usec); if (r < 0) @@ -1496,7 +1500,7 @@ int config_parse_router_lifetime( return 0; } -int config_parse_router_retransmit( +int config_parse_router_uint32_msec_usec( const char *unit, const char *filename, unsigned line, @@ -1508,7 +1512,7 @@ int config_parse_router_retransmit( void *data, void *userdata) { - usec_t usec, *router_retransmit_usec = ASSERT_PTR(data); + usec_t usec, *router_usec = ASSERT_PTR(data); int r; assert(filename); @@ -1517,7 +1521,7 @@ int config_parse_router_retransmit( assert(rvalue); if (isempty(rvalue)) { - *router_retransmit_usec = 0; + *router_usec = 0; return 0; } @@ -1529,13 +1533,13 @@ int config_parse_router_retransmit( } if (usec != USEC_INFINITY && - usec > RADV_MAX_RETRANSMIT_USEC) { + usec > RADV_MAX_UINT32_MSEC_USEC) { log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid [%s] %s=, ignoring assignment: %s", section, lvalue, rvalue); return 0; } - *router_retransmit_usec = usec; + *router_usec = usec; return 0; } diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h index 94834e77a8e..dcb8cfb304e 100644 --- a/src/network/networkd-radv.h +++ b/src/network/networkd-radv.h @@ -86,7 +86,7 @@ RADVPrefixDelegation radv_prefix_delegation_from_string(const char *s) _pure_; CONFIG_PARSER_PROTOTYPE(config_parse_router_prefix_delegation); CONFIG_PARSER_PROTOTYPE(config_parse_router_lifetime); -CONFIG_PARSER_PROTOTYPE(config_parse_router_retransmit); +CONFIG_PARSER_PROTOTYPE(config_parse_router_uint32_msec_usec); CONFIG_PARSER_PROTOTYPE(config_parse_router_preference); CONFIG_PARSER_PROTOTYPE(config_parse_prefix); CONFIG_PARSER_PROTOTYPE(config_parse_prefix_boolean); diff --git a/src/systemd/sd-radv.h b/src/systemd/sd-radv.h index f25622fceb5..3120dd7f00a 100644 --- a/src/systemd/sd-radv.h +++ b/src/systemd/sd-radv.h @@ -57,6 +57,7 @@ int sd_radv_set_link_local_address(sd_radv *ra, const struct in6_addr *addr); int sd_radv_set_mac(sd_radv *ra, const struct ether_addr *mac_addr); int sd_radv_set_mtu(sd_radv *ra, uint32_t mtu); int sd_radv_set_hop_limit(sd_radv *ra, uint8_t hop_limit); +int sd_radv_set_reachable_time(sd_radv *ra, uint64_t usec); int sd_radv_set_retransmit(sd_radv *ra, uint64_t usec); int sd_radv_set_router_lifetime(sd_radv *ra, uint64_t usec); int sd_radv_set_managed_information(sd_radv *ra, int b); diff --git a/test/test-network/conf/25-ipv6-prefix.network b/test/test-network/conf/25-ipv6-prefix.network index 9cf8f257535..e801581a898 100644 --- a/test/test-network/conf/25-ipv6-prefix.network +++ b/test/test-network/conf/25-ipv6-prefix.network @@ -10,6 +10,8 @@ IPv6SendRA=yes DNS=_link_local 2002:da8:1:0::1 DNSLifetimeSec=1min Domains=hogehoge.test +ReachableTimeSec=42 +RetransmitSec=500ms [IPv6Prefix] Prefix=2002:da8:1:0::/64 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 17b45a43391..569563175bf 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -5514,6 +5514,9 @@ class NetworkdRATests(unittest.TestCase, Utilities): print(output) self.assertRegex(output, '2002:da8:1:0') + self.check_ipv6_neigh_sysctl_attr('veth99', 'base_reachable_time_ms', '42000') + self.check_ipv6_neigh_sysctl_attr('veth99', 'retrans_time_ms', '500') + self.check_netlabel('veth99', '2002:da8:1::/64') self.check_netlabel('veth99', '2002:da8:2::/64')