network: add support to RoutingPolicyRule lookup table name

This commit is contained in:
Susant Sahani 2021-01-19 12:58:53 +01:00 committed by Luca Boccassi
parent 656e5aa452
commit c038ce4606
8 changed files with 132 additions and 20 deletions

View file

@ -70,6 +70,14 @@
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>

View 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>

View 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)

View 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);

View 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;

View 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;

View 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);

View 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;
}