mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-08 21:17:47 +03:00
Merge pull request #14956 from ssahani/delegated-prefix-14474
nettwork: introduce delegated prefix assign
This commit is contained in:
commit
5bb67b107f
@ -2038,6 +2038,11 @@
|
||||
to 2592000 seconds (30 days).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>Assign=</varname></term>
|
||||
<listitem><para>Takes a boolean. When true, adds an address from the prefix. Default to false.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
@ -829,6 +829,18 @@ _public_ int sd_radv_prefix_set_prefix(sd_radv_prefix *p, const struct in6_addr
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_radv_prefix_get_prefix(sd_radv_prefix *p, struct in6_addr *ret_in6_addr,
|
||||
unsigned char *ret_prefixlen) {
|
||||
assert_return(p, -EINVAL);
|
||||
assert_return(ret_in6_addr, -EINVAL);
|
||||
assert_return(ret_prefixlen, -EINVAL);
|
||||
|
||||
*ret_in6_addr = p->opt.in6_addr;
|
||||
*ret_prefixlen = p->opt.prefixlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_radv_prefix_set_onlink(sd_radv_prefix *p, int onlink) {
|
||||
assert_return(p, -EINVAL);
|
||||
|
||||
|
@ -20,6 +20,24 @@
|
||||
#define ADDRESSES_PER_LINK_MAX 2048U
|
||||
#define STATIC_ADDRESSES_PER_NETWORK_MAX 1024U
|
||||
|
||||
int generate_ipv6_eui_64_address(Link *link, struct in6_addr *ret) {
|
||||
assert(link);
|
||||
assert(ret);
|
||||
|
||||
/* see RFC4291 section 2.5.1 */
|
||||
ret->s6_addr[8] = link->mac.ether_addr_octet[0];
|
||||
ret->s6_addr[8] ^= 1 << 1;
|
||||
ret->s6_addr[9] = link->mac.ether_addr_octet[1];
|
||||
ret->s6_addr[10] = link->mac.ether_addr_octet[2];
|
||||
ret->s6_addr[11] = 0xff;
|
||||
ret->s6_addr[12] = 0xfe;
|
||||
ret->s6_addr[13] = link->mac.ether_addr_octet[3];
|
||||
ret->s6_addr[14] = link->mac.ether_addr_octet[4];
|
||||
ret->s6_addr[15] = link->mac.ether_addr_octet[5];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int address_new(Address **ret) {
|
||||
_cleanup_(address_freep) Address *address = NULL;
|
||||
|
||||
|
@ -66,6 +66,8 @@ bool address_is_ready(const Address *a);
|
||||
int address_section_verify(Address *a);
|
||||
int configure_ipv4_duplicate_address_detection(Link *link, Address *address);
|
||||
|
||||
int generate_ipv6_eui_64_address(Link *link, struct in6_addr *ret);
|
||||
|
||||
DEFINE_NETWORK_SECTION_FUNCTIONS(Address, address_free);
|
||||
|
||||
extern const struct hash_ops address_hash_ops;
|
||||
|
@ -1222,6 +1222,7 @@ static int link_set_bridge_fdb(Link *link) {
|
||||
static int link_request_set_addresses(Link *link) {
|
||||
AddressLabel *label;
|
||||
Address *ad;
|
||||
Prefix *p;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
@ -1257,6 +1258,35 @@ static int link_request_set_addresses(Link *link) {
|
||||
link->address_messages++;
|
||||
}
|
||||
|
||||
if (IN_SET(link->network->router_prefix_delegation,
|
||||
RADV_PREFIX_DELEGATION_STATIC,
|
||||
RADV_PREFIX_DELEGATION_BOTH))
|
||||
LIST_FOREACH(prefixes, p, link->network->static_prefixes) {
|
||||
_cleanup_(address_freep) Address *address = NULL;
|
||||
|
||||
if (!p->assign)
|
||||
continue;
|
||||
|
||||
r = address_new(&address);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not allocate address: %m");
|
||||
|
||||
r = sd_radv_prefix_get_prefix(p->radv_prefix, &address->in_addr.in6, &address->prefixlen);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = generate_ipv6_eui_64_address(link, &address->in_addr.in6);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
address->family = AF_INET6;
|
||||
r = address_configure(address, link, address_handler, true);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Could not set addresses: %m");
|
||||
if (r > 0)
|
||||
link->address_messages++;
|
||||
}
|
||||
|
||||
LIST_FOREACH(labels, label, link->network->address_labels) {
|
||||
r = address_label_configure(label, link, NULL, false);
|
||||
if (r < 0)
|
||||
|
@ -324,16 +324,10 @@ static int ndisc_router_generate_addresses(Link *link, unsigned prefixlen, uint3
|
||||
|
||||
*new_address = *address;
|
||||
|
||||
/* see RFC4291 section 2.5.1 */
|
||||
new_address->in_addr.in6.s6_addr[8] = link->mac.ether_addr_octet[0];
|
||||
new_address->in_addr.in6.s6_addr[8] ^= 1 << 1;
|
||||
new_address->in_addr.in6.s6_addr[9] = link->mac.ether_addr_octet[1];
|
||||
new_address->in_addr.in6.s6_addr[10] = link->mac.ether_addr_octet[2];
|
||||
new_address->in_addr.in6.s6_addr[11] = 0xff;
|
||||
new_address->in_addr.in6.s6_addr[12] = 0xfe;
|
||||
new_address->in_addr.in6.s6_addr[13] = link->mac.ether_addr_octet[3];
|
||||
new_address->in_addr.in6.s6_addr[14] = link->mac.ether_addr_octet[4];
|
||||
new_address->in_addr.in6.s6_addr[15] = link->mac.ether_addr_octet[5];
|
||||
r = generate_ipv6_eui_64_address(link, &new_address->in_addr.in6);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to generate EUI64 address: %m");
|
||||
|
||||
new_address->prefixlen = prefixlen;
|
||||
new_address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
|
||||
new_address->cinfo.ifa_prefered = lifetime_preferred;
|
||||
|
@ -245,6 +245,7 @@ IPv6Prefix.OnLink, config_parse_prefix_flags,
|
||||
IPv6Prefix.AddressAutoconfiguration, config_parse_prefix_flags, 0, 0
|
||||
IPv6Prefix.ValidLifetimeSec, config_parse_prefix_lifetime, 0, 0
|
||||
IPv6Prefix.PreferredLifetimeSec, config_parse_prefix_lifetime, 0, 0
|
||||
IPv6Prefix.Assign, config_parse_prefix_assign, 0, 0
|
||||
IPv6RoutePrefix.Route, config_parse_route_prefix, 0, 0
|
||||
IPv6RoutePrefix.LifetimeSec, config_parse_route_prefix_lifetime, 0, 0
|
||||
CAN.BitRate, config_parse_si_uint64, 0, offsetof(Network, can_bitrate)
|
||||
|
@ -319,6 +319,46 @@ int config_parse_prefix_lifetime(const char *unit,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_prefix_assign(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
Network *network = userdata;
|
||||
_cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(section);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
r = prefix_new_static(network, filename, section_line, &p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = parse_boolean(rvalue);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||
"Failed to parse %s=, ignoring assignment: %s",
|
||||
lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
p->assign = r;
|
||||
p = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_route_prefix(const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
|
@ -28,6 +28,8 @@ struct Prefix {
|
||||
|
||||
sd_radv_prefix *radv_prefix;
|
||||
|
||||
bool assign;
|
||||
|
||||
LIST_FIELDS(Prefix, prefixes);
|
||||
};
|
||||
|
||||
@ -59,6 +61,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_router_preference);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_prefix);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_prefix_flags);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_prefix_lifetime);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_prefix_assign);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_radv_search_domains);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_route_prefix);
|
||||
|
@ -74,6 +74,8 @@ sd_radv_prefix *sd_radv_prefix_unref(sd_radv_prefix *ra);
|
||||
|
||||
int sd_radv_prefix_set_prefix(sd_radv_prefix *p, const struct in6_addr *in6_addr,
|
||||
unsigned char prefixlen);
|
||||
int sd_radv_prefix_get_prefix(sd_radv_prefix *p, struct in6_addr *ret_in6_addr,
|
||||
unsigned char *ret_prefixlen);
|
||||
int sd_radv_prefix_set_onlink(sd_radv_prefix *p, int onlink);
|
||||
int sd_radv_prefix_set_address_autoconfiguration(sd_radv_prefix *p,
|
||||
int address_autoconfiguration);
|
||||
|
@ -186,6 +186,7 @@ OnLink=
|
||||
PreferredLifetimeSec=
|
||||
AddressAutoconfiguration=
|
||||
ValidLifetimeSec=
|
||||
Assign=
|
||||
[IPv6RoutePrefix]
|
||||
Route=
|
||||
LifetimeSec=
|
||||
|
@ -4,10 +4,13 @@ Name=veth99
|
||||
[Network]
|
||||
DHCP=no
|
||||
IPv6PrefixDelegation=yes
|
||||
Address=2001:db8:0:1::1/64
|
||||
|
||||
[IPv6Prefix]
|
||||
Prefix=2001:db8:0:1::4/64
|
||||
Prefix=2001:db8:0:1::/64
|
||||
|
||||
[IPv6Prefix]
|
||||
Prefix=2001:db8:0:2::/64
|
||||
Assign=yes
|
||||
|
||||
[IPv6RoutePrefix]
|
||||
Route=2001:db0:fff::/64
|
||||
|
@ -3591,10 +3591,15 @@ class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
|
||||
start_networkd()
|
||||
self.wait_online(['veth99:routable', 'veth-peer:routable'])
|
||||
|
||||
output = check_output('ip', '-6', 'route', 'show', 'dev', 'veth-peer')
|
||||
output = check_output('ip -6 route show dev veth-peer')
|
||||
print(output)
|
||||
self.assertRegex(output, '2001:db8:0:1::/64 proto ra')
|
||||
|
||||
output = check_output('ip addr show dev veth99')
|
||||
print(output)
|
||||
self.assertNotRegex(output, '2001:db8:0:1')
|
||||
self.assertRegex(output, '2001:db8:0:2')
|
||||
|
||||
class NetworkdMTUTests(unittest.TestCase, Utilities):
|
||||
links = ['dummy98']
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user