networkd: allow route table names for VRF.Table=

Allow `[VRF] Table=` to accept route table names in addition to
numeric table identifiers. These may be predefined route table names
or names configured with `networkd.conf` `RouteTable=`.

There was an earlier attempt to make `VRF.Table=` accept names in
f98dd1e707, but it wired the setting to
`config_parse_route_table()`. That parser was a `[Route]` section
parser, not a generic scalar parser for netdevs: it expected
network/route parser state and created a `Route` object. It was
therefore reverted by 40352cf0c1.

This commit replaces the uint32 parser with
`manager_get_route_table_from_string()`, the generic table parser
already used by route/rule, DHCP/RA `RouteTable=`, and WireGuard
`RouteTable=` in `.netdev` files. The VRF semantics stay
unchanged. The commit retains the existing behavior of the
deprecated `TableId=` field.

Co-developed-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
João Taveira Araújo
2026-04-23 22:06:12 +02:00
committed by Lennart Poettering
parent 42506e6dd1
commit bbadd35596
5 changed files with 63 additions and 2 deletions
+4 -1
View File
@@ -2683,7 +2683,10 @@ Ports=eth2</programlisting>
<varlistentry>
<term><varname>Table=</varname></term>
<listitem>
<para>The numeric routing table identifier. This setting is compulsory.</para>
<para>The routing table identifier. Takes a route table name or number. Route table names
may be predefined or configured with <varname>RouteTable=</varname> in
<citerefentry><refentrytitle>networkd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
This setting is compulsory.</para>
<xi:include href="version-info.xml" xpointer="v243"/>
</listitem>
+1 -1
View File
@@ -249,7 +249,7 @@ Bridge.MulticastIGMPVersion, config_parse_bridge_igmp_version,
Bridge.FDBMaxLearned, config_parse_bridge_fdb_max_learned, 0, offsetof(Bridge, fdb_max_learned)
Bridge.LinkLocalLearning, config_parse_tristate, 0, offsetof(Bridge, linklocal_learn)
VRF.TableId, config_parse_uint32, 0, offsetof(Vrf, table) /* deprecated */
VRF.Table, config_parse_uint32, 0, offsetof(Vrf, table)
VRF.Table, config_parse_vrf_table, 0, offsetof(Vrf, table)
BareUDP.DestinationPort, config_parse_ip_port, 0, offsetof(BareUDP, dest_port)
BareUDP.MinSourcePort, config_parse_ip_port, 0, offsetof(BareUDP, min_port)
BareUDP.EtherType, config_parse_bare_udp_iftype, 0, offsetof(BareUDP, iftype)
+32
View File
@@ -4,8 +4,40 @@
#include "sd-netlink.h"
#include "networkd-route-util.h"
#include "vrf.h"
int config_parse_vrf_table(
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) {
Vrf *vrf = ASSERT_PTR(userdata);
uint32_t *table = ASSERT_PTR(data);
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
r = manager_get_route_table_from_string(vrf->meta.manager, rvalue, table);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse %s=, ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
return 0;
}
static int netdev_vrf_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
assert(!link);
assert(m);
+2
View File
@@ -11,3 +11,5 @@ typedef struct Vrf {
DEFINE_NETDEV_CAST(VRF, Vrf);
extern const NetDevVTable vrf_vtable;
CONFIG_PARSER_PROTOTYPE(config_parse_vrf_table);
+24
View File
@@ -11,6 +11,7 @@
#include "networkd-route-util.h"
#include "strv.h"
#include "tests.h"
#include "vrf.h"
TEST(deserialize_in_addr) {
_cleanup_free_ struct in_addr *addresses = NULL;
@@ -150,6 +151,29 @@ TEST(route_tables) {
test_route_tables_one(manager, "local", 255);
}
TEST(vrf_table) {
_cleanup_(manager_freep) Manager *manager = NULL;
Vrf vrf = {};
ASSERT_OK(manager_new(&manager, /* test_mode= */ true));
ASSERT_OK(manager_setup(manager));
vrf.meta.manager = manager;
ASSERT_OK(config_parse_vrf_table("netdev", "filename", 1, "VRF", 1, "Table", 0, "default", &vrf.table, &vrf));
ASSERT_EQ(vrf.table, 253U);
ASSERT_OK(config_parse_route_table_names("manager", "filename", 1, "section", 1, "RouteTable", 0, "vrf-test:1234", manager, manager));
ASSERT_OK(config_parse_vrf_table("netdev", "filename", 1, "VRF", 1, "Table", 0, "vrf-test", &vrf.table, &vrf));
ASSERT_EQ(vrf.table, 1234U);
ASSERT_OK(config_parse_vrf_table("netdev", "filename", 1, "VRF", 1, "Table", 0, "5678", &vrf.table, &vrf));
ASSERT_EQ(vrf.table, 5678U);
ASSERT_OK(config_parse_vrf_table("netdev", "filename", 1, "VRF", 1, "Table", 0, "no-such-table", &vrf.table, &vrf));
ASSERT_EQ(vrf.table, 5678U);
}
TEST(manager_enumerate) {
_cleanup_(manager_freep) Manager *manager = NULL;