]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: add support to RoutingPolicyRule lookup table name
authorSusant Sahani <ssahani@vmware.com>
Tue, 19 Jan 2021 11:58:53 +0000 (12:58 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Tue, 19 Jan 2021 16:37:46 +0000 (16:37 +0000)
man/networkd.conf.xml
man/systemd.network.xml
src/network/networkd-gperf.gperf
src/network/networkd-manager.c
src/network/networkd-manager.h
src/network/networkd-route.c
src/network/networkd-route.h
src/network/networkd-routing-policy-rule.c

index 65aecb62567724a20938d0dcf55d301d96ecfcaf..78b46ad505c1285b06ccc9cd809c83ad160c0120 100644 (file)
         is false. Defaults to yes.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>RouteTable=</varname></term>
+        <listitem><para>Specifies the route table name. Takes a route name and table number separated with a colon.
+        (<literal><replaceable>name</replaceable>:<replaceable>integer</replaceable></literal>. The route table number
+        must be an integer in the range 1..4294967295. This setting can be specified multiple times. If an empty string
+        is specified, then all options specified earlier are cleared. Defaults to unset.</para></listitem>
+      </varlistentry>
+
     </variablelist>
   </refsect1>
 
index 8b7c9ff32a7c617bc3f0632b640abc195f8d457a..0d9f1dce0dcec2a5ac88b22da2f16d3fff07ded7 100644 (file)
@@ -1200,8 +1200,9 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
         <varlistentry>
           <term><varname>Table=</varname></term>
           <listitem>
-            <para>Specifies the routing table identifier to lookup if the rule selector matches. Takes
-            one of <literal>default</literal>, <literal>main</literal>, and <literal>local</literal>,
+            <para>Specifies the routing table identifier to lookup if the rule selector matches. Takes one of predefined names
+            <literal>default</literal>, <literal>main</literal>, and <literal>local</literal>, and names defined in <varname>RouteTable=</varname>
+            in <citerefentry><refentrytitle>networkd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
             or a number between 1 and 4294967295. Defaults to <literal>main</literal>.</para>
           </listitem>
         </varlistentry>
@@ -1409,11 +1410,11 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
         <varlistentry>
           <term><varname>Table=</varname></term>
           <listitem>
-            <para>The table identifier for the route. Takes <literal>default</literal>,
-            <literal>main</literal>, <literal>local</literal> or a number between 1 and 4294967295.
-            The table can be retrieved using <command>ip route show table <replaceable>num</replaceable></command>.
-            If unset and <varname>Type=</varname> is <literal>local</literal>, <literal>broadcast</literal>,
-            <literal>anycast</literal>, or <literal>nat</literal>, then <literal>local</literal> is used.
+            <para>The table identifier for the route. Takes one of predefined names <literal>default</literal>, <literal>main</literal>,
+            and <literal>local</literal>, and names defined in <varname>RouteTable=</varname> in <citerefentry><refentrytitle>networkd.conf</refentrytitle>
+            <manvolnum>5</manvolnum></citerefentry>, or a number between 1 and 4294967295. The table can be retrieved using
+            <command>ip route show table <replaceable>num</replaceable></command>. If unset and <varname>Type=</varname> is <literal>local</literal>,
+            <literal>broadcast</literal>, <literal>anycast</literal>, or <literal>nat</literal>, then <literal>local</literal> is used.
             In other cases, defaults to <literal>main</literal>.
           </para>
           </listitem>
index aaabb3d1b32878956205383a627317ec8a6c1321..2860875a0f670732d27a59c22f647b161926e129 100644 (file)
@@ -6,6 +6,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
 #include "conf-parser.h"
 #include "networkd-conf.h"
 #include "networkd-manager.h"
+#include "networkd-route.h"
 %}
 struct ConfigPerfItem;
 %null_strings
@@ -21,5 +22,6 @@ struct ConfigPerfItem;
 Network.SpeedMeter,            config_parse_bool,                      0,          offsetof(Manager, use_speed_meter)
 Network.SpeedMeterIntervalSec, config_parse_sec,                       0,          offsetof(Manager, speed_meter_interval_usec)
 Network.ManageForeignRoutes,   config_parse_bool,                      0,          offsetof(Manager, manage_foreign_routes)
+Network.RouteTable,            config_parse_route_table_names,         0,          offsetof(Manager, route_tables)
 DHCP.DUIDType,                 config_parse_duid_type,                 0,          offsetof(Manager, duid)
 DHCP.DUIDRawData,              config_parse_duid_rawdata,              0,          offsetof(Manager, duid)
index 47f0edf209b8459242e493706ad83933887ac928..bf15ba653524bde8eb684805813dd5055e01ece8 100644 (file)
@@ -875,6 +875,8 @@ void manager_free(Manager *m) {
 
         ordered_set_free_free(m->address_pools);
 
+        m->route_tables = hashmap_free_free_key(m->route_tables);
+
         /* routing_policy_rule_free() access m->rules and m->rules_foreign.
          * So, it is necessary to set NULL after the sets are freed. */
         m->rules = set_free(m->rules);
index 78ba2b0945dd687580bd93157b44fdd4767b1b17..88b9f6bd2350604db2fe75dc11e9679811dd8ed8 100644 (file)
@@ -65,6 +65,9 @@ struct Manager {
         Set *routes;
         Set *routes_foreign;
 
+        /* Route table name */
+        Hashmap *route_tables;
+
         /* For link speed meter*/
         bool use_speed_meter;
         sd_event_source *speed_meter_event_source;
index 3142bd686f4e1d55482f28ed27278934801375c4..cfb9befc61459cb069c4f4f36968f5410495414f 100644 (file)
@@ -87,7 +87,7 @@ static const char * const route_table_table[] = {
         [RT_TABLE_LOCAL]   = "local",
 };
 
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_table, int);
+DEFINE_STRING_TABLE_LOOKUP(route_table, int);
 
 #define ROUTE_TABLE_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("default") + 1)
 static const char *format_route_table(int table, char *buf, size_t size) {
@@ -1868,6 +1868,28 @@ int config_parse_route_scope(
         return 0;
 }
 
+int route_table_from_string_full(Manager *m, const char *s, uint32_t *ret) {
+        int r;
+
+        assert(s);
+        assert(m);
+        assert(ret);
+
+        r = route_table_from_string(s);
+        if (r >= 0) {
+                *ret = (uint32_t) r;
+                return 0;
+        }
+
+        uint32_t t = PTR_TO_UINT32(hashmap_get(m->route_tables, s));
+        if (t != 0) {
+                *ret = t;
+                return 0;
+        }
+
+        return safe_atou32(s, ret);
+}
+
 int config_parse_route_table(
                 const char *unit,
                 const char *filename,
@@ -1899,16 +1921,11 @@ int config_parse_route_table(
                 return 0;
         }
 
-        r = route_table_from_string(rvalue);
-        if (r >= 0)
-                n->table = r;
-        else {
-                r = safe_atou32(rvalue, &n->table);
-                if (r < 0) {
-                        log_syntax(unit, LOG_WARNING, filename, line, r,
-                                   "Could not parse route table number \"%s\", ignoring assignment: %m", rvalue);
-                        return 0;
-                }
+        r = route_table_from_string_full(network->manager, rvalue, &n->table);
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Could not parse route table number \"%s\", ignoring assignment: %m", rvalue);
+                return 0;
         }
 
         n->table_set = true;
@@ -2356,6 +2373,77 @@ int config_parse_multipath_route(
         return 0;
 }
 
+int config_parse_route_table_names(
+                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) {
+
+        _cleanup_free_ char *name = NULL;
+        Hashmap **s = data;
+        uint32_t table;
+        const char *p;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (isempty(rvalue)) {
+                *s = hashmap_free_free_key(*s);
+                return 0;
+        }
+
+        p = rvalue;
+        r = extract_first_word(&p, &name, ":", 0);
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r <= 0 || isempty(p)) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Invalid RouteTable=, ignoring assignment: %s", rvalue);
+                return 0;
+        }
+
+        if (STR_IN_SET(name, "default", "main","local")) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Route table name %s already preconfigured. Ignoring assignment: %s", name, rvalue);
+                return 0;
+        }
+
+        r = safe_atou32(p, &table);
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to parse RouteTable=, ignoring assignment: %s", p);
+                return 0;
+        }
+
+        if (table == 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, 0,
+                           "Invalid RouteTable=, ignoring assignment: %s", p);
+                return 0;
+        }
+
+        r = hashmap_ensure_put(s, &string_hash_ops, name, UINT32_TO_PTR(table));
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r == -EEXIST) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Specified RouteTable= name and value pair conflicts with others, ignoring assignment: %s", rvalue);
+                return 0;
+        }
+        if (r > 0)
+                TAKE_PTR(name);
+
+        return 0;
+}
+
 static int route_section_verify(Route *route, Network *network) {
         if (section_is_invalid(route->section))
                 return -EINVAL;
index 8923966ddf3bccf053481f2f1e0158ce639091b0..28f6f29128f40c8d90913b5ed25703d78ed64f67 100644 (file)
@@ -86,6 +86,11 @@ int network_add_ipv4ll_route(Network *network);
 int network_add_default_route_on_device(Network *network);
 void network_drop_invalid_routes(Network *network);
 
+int route_table_from_string_full(Manager *m, const char *table, uint32_t *ret);
+
+const char *route_table_to_string(int d) _const_;
+int route_table_from_string(const char *d) _pure_;
+
 CONFIG_PARSER_PROTOTYPE(config_parse_gateway);
 CONFIG_PARSER_PROTOTYPE(config_parse_preferred_src);
 CONFIG_PARSER_PROTOTYPE(config_parse_destination);
@@ -100,3 +105,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_tcp_window);
 CONFIG_PARSER_PROTOTYPE(config_parse_route_mtu);
 CONFIG_PARSER_PROTOTYPE(config_parse_multipath_route);
 CONFIG_PARSER_PROTOTYPE(config_parse_tcp_advmss);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_table_names);
index 6e00e5f9cb66c51bcfcd8aceb6622c5b04b5cde3..3534232822efe7a16540fbf0380cc271b5ffc0b1 100644 (file)
@@ -8,6 +8,7 @@
 #include "conf-parser.h"
 #include "fileio.h"
 #include "format-util.h"
+#include "hashmap.h"
 #include "ip-protocol-list.h"
 #include "netlink-util.h"
 #include "networkd-manager.h"
@@ -1129,9 +1130,10 @@ int config_parse_routing_policy_rule_table(
         if (r < 0)
                 return log_oom();
 
-        r = safe_atou32(rvalue, &n->table);
+        r = route_table_from_string_full(network->manager, rvalue, &n->table);
         if (r < 0) {
-                log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse RPDB rule table, ignoring: %s", rvalue);
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Could not parse RPDB rule route table number \"%s\", ignoring assignment: %m", rvalue);
                 return 0;
         }