mirror of
https://github.com/systemd/systemd.git
synced 2026-08-09 17:38:42 +00:00
network: make VLAN= and friends take multiple names
Previously, specifying multiple stacked netdevs of the same type required repeating the corresponding setting, e.g.: ``` [Network] VLAN=vlan_10 VLAN=vlan_20 VLAN=vlan_30 ``` With this change, the same configuration can be written as: ``` [Network] VLAN=vlan_10 vlan_20 vlan_30 ``` Specifying an empty string now also clears all previously assigned stacked netdevs. Closes #43103.
This commit is contained in:
@@ -1298,10 +1298,10 @@ DuplicateAddressDetection=none</programlisting></para>
|
||||
<term><varname>VXLAN=</varname></term>
|
||||
<term><varname>Xfrm=</varname></term>
|
||||
<listitem>
|
||||
<para>The name of an IPoIB, IPVLAN, IPVTAP, MACsec, MACVLAN, MACVTAP, tunnel, VLAN,
|
||||
VXLAN, or Xfrm to be created on the link. See
|
||||
<para>Takes a space-separated list of stacked netdevs to be created on the interface. See
|
||||
<citerefentry><refentrytitle>systemd.netdev</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
This option may be specified more than once.</para>
|
||||
This option may be specified more than once. If an empty string is specified, previous assignments
|
||||
for all netdev types are cleared.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v211"/>
|
||||
</listitem>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "condition.h"
|
||||
#include "conf-files.h"
|
||||
#include "conf-parser.h"
|
||||
#include "extract-word.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "iovec-util.h"
|
||||
#include "net-condition.h"
|
||||
@@ -951,7 +952,6 @@ int config_parse_stacked_netdev(
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_free_ char *name = NULL;
|
||||
NetDevKind kind = ltype;
|
||||
Hashmap **h = ASSERT_PTR(data);
|
||||
int r;
|
||||
@@ -971,29 +971,38 @@ int config_parse_stacked_netdev(
|
||||
NETDEV_KIND_XFRM,
|
||||
_NETDEV_KIND_TUNNEL));
|
||||
|
||||
if (!ifname_valid(rvalue)) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"Invalid netdev name in %s=, ignoring assignment: %s", lvalue, rvalue);
|
||||
if (isempty(rvalue)) {
|
||||
*h = hashmap_free(*h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
name = strdup(rvalue);
|
||||
if (!name)
|
||||
return log_oom();
|
||||
for (const char *p = rvalue;;) {
|
||||
_cleanup_free_ char *name = NULL;
|
||||
|
||||
r = hashmap_ensure_put(h, &string_hash_ops_free, name, INT_TO_PTR(kind));
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0)
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Cannot add NetDev '%s' to network, ignoring assignment: %m", name);
|
||||
else if (r == 0)
|
||||
log_syntax(unit, LOG_DEBUG, filename, line, r,
|
||||
"NetDev '%s' specified twice, ignoring.", name);
|
||||
else
|
||||
TAKE_PTR(name);
|
||||
r = extract_first_word(&p, &name, /* separators= */ NULL, /* flags= */ 0);
|
||||
if (r < 0)
|
||||
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
if (!ifname_valid(name)) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"Invalid netdev name in %s=, ignoring assignment: %s", lvalue, name);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = hashmap_ensure_put(h, &string_hash_ops_free, name, INT_TO_PTR(kind));
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0)
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Cannot add NetDev '%s' to network, ignoring assignment: %m", name);
|
||||
else if (r == 0)
|
||||
log_syntax(unit, LOG_DEBUG, filename, line, r,
|
||||
"NetDev '%s' specified twice, ignoring.", name);
|
||||
else
|
||||
TAKE_PTR(name);
|
||||
}
|
||||
}
|
||||
|
||||
int config_parse_required_for_online(
|
||||
|
||||
@@ -466,4 +466,30 @@ TEST(config_parse_multipath_route) {
|
||||
test_config_parse_multipath_route_one("@wg0 abc", 0, 0); /* Non-numeric */
|
||||
}
|
||||
|
||||
TEST(config_parse_stacked_netdev) {
|
||||
_cleanup_hashmap_free_ Hashmap *netdevs = NULL;
|
||||
ASSERT_OK(config_parse_stacked_netdev("network", "filename", 1, "section", 1, "VLAN", NETDEV_KIND_VLAN, "foo bar baz invalid:name", &netdevs, NULL));
|
||||
ASSERT_OK(config_parse_stacked_netdev("network", "filename", 1, "section", 1, "VXLAN", NETDEV_KIND_VXLAN, "aaa 321 foo bbb", &netdevs, NULL));
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
NetDevKind kind;
|
||||
} expected[] = {
|
||||
{ "foo", NETDEV_KIND_VLAN },
|
||||
{ "bar", NETDEV_KIND_VLAN },
|
||||
{ "baz", NETDEV_KIND_VLAN },
|
||||
{ "aaa", NETDEV_KIND_VXLAN },
|
||||
{ "bbb", NETDEV_KIND_VXLAN },
|
||||
};
|
||||
|
||||
ASSERT_EQ(hashmap_size(netdevs), ELEMENTSOF(expected));
|
||||
FOREACH_ELEMENT(i, expected) {
|
||||
void *p = ASSERT_NOT_NULL(hashmap_get(netdevs, i->name));
|
||||
ASSERT_EQ(PTR_TO_INT(p), i->kind);
|
||||
}
|
||||
|
||||
ASSERT_OK(config_parse_stacked_netdev("network", "filename", 1, "section", 1, "VXLAN", NETDEV_KIND_VXLAN, "", &netdevs, NULL));
|
||||
ASSERT_NULL(netdevs);
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_INFO);
|
||||
|
||||
Reference in New Issue
Block a user