]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd: allow route table names for VRF.Table=
authorJoão Taveira Araújo <jta@openai.com>
Thu, 16 Apr 2026 19:13:30 +0000 (12:13 -0700)
committerLennart Poettering <lennart@poettering.net>
Thu, 23 Apr 2026 20:06:12 +0000 (22:06 +0200)
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>
man/systemd.netdev.xml
src/network/netdev/netdev-gperf.gperf
src/network/netdev/vrf.c
src/network/netdev/vrf.h
src/network/test-network.c

index 6a84b7a648cef2c9ec55a8b405beaefe3225e8bb..6879518b4b8a3bb5c9e1469f6575d70130a6cd6d 100644 (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>
index 250b6cf7bcde90fe7b0cf4419751049ce967a2ee..269a97454240846d24a111ce7406342e198aae7a 100644 (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)
index 540c269f2d38dd00034257a951999ba7440c2fc8..d91ccf394ae324c177be1003ff105ded002474b5 100644 (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);
index 7bf94478567a7506810a3a73d832ac20c464734d..a794c237c98de5cd891a184bad79fdc745ce1141 100644 (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);
index 6582d3b07407914b98cc8788607dc157dfaa3d14..ab3a86e10b193272525c57e03ff6c508eec1cb4f 100644 (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;