Skip to content

Commit

Permalink
networkmanager: add support for "routing-policy"
Browse files Browse the repository at this point in the history
NetworkManager supports ip rules via the "routing-ruleX" field.  Let's
teach the networkmanager backend to emit "routing-ruleX" entries for
each "routing-policy" entry in the netplan yaml.

Update the tests for the new behavior.
  • Loading branch information
drafnel committed Nov 2, 2024
1 parent 83a8d8c commit 416e30c
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 4 deletions.
55 changes: 55 additions & 0 deletions src/nm.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,54 @@ write_routes_nm(const NetplanNetDefinition* def, GKeyFile *kf, gint family, GErr
j++;
}
}

return TRUE;
}

STATIC gboolean
write_ip_rules_nm(const NetplanNetDefinition* def, GKeyFile *kf, gint family, __unused GError** error)
{
const gchar* group = NULL;
gchar* tmp_key = NULL;
GString* tmp_val = NULL;

if (family == AF_INET)
group = "ipv4";
else if (family == AF_INET6)
group = "ipv6";
g_assert(group != NULL);

if (def->ip_rules != NULL) {
for (unsigned i = 0, j = 1; i < def->ip_rules->len; ++i) {
const NetplanIPRule *cur_rule = g_array_index(def->ip_rules, NetplanIPRule*, i);

if (cur_rule->family != family)
continue;

tmp_key = g_strdup_printf("routing-rule%d", j);
tmp_val = g_string_new(NULL);

if (cur_rule->from)
g_string_append_printf(tmp_val, "from %s ", cur_rule->from);
if (cur_rule->to)
g_string_append_printf(tmp_val, "to %s ", cur_rule->to);
if (cur_rule->tos != NETPLAN_IP_RULE_TOS_UNSPEC)
g_string_append_printf(tmp_val, "tos %u ", cur_rule->tos);
if (cur_rule->fwmark != NETPLAN_IP_RULE_FW_MARK_UNSPEC)
g_string_append_printf(tmp_val, "fwmark %u ", cur_rule->fwmark);
if (cur_rule->table != NETPLAN_ROUTE_TABLE_UNSPEC)
g_string_append_printf(tmp_val, "table %u ", cur_rule->table);
if (cur_rule->priority != NETPLAN_IP_RULE_PRIO_UNSPEC)
g_string_append_printf(tmp_val, "priority %u ", cur_rule->priority);
g_string_truncate(tmp_val, tmp_val->len - 1); //remove trailing space
g_key_file_set_string(kf, group, tmp_key, tmp_val->str);
g_free(tmp_key);
g_string_free(tmp_val, TRUE);

j++;
}
}

return TRUE;
}

Expand Down Expand Up @@ -716,6 +764,8 @@ write_nm_conf_access_point(const NetplanNetDefinition* def, const char* rootdir,
g_key_file_set_uint64(kf, "vrf", "table", def->vrf_table);
if (!write_routes_nm(def, kf, AF_INET, error) || !write_routes_nm(def, kf, AF_INET6, error))
return FALSE;
if (!write_ip_rules_nm(def, kf, AF_INET, error) || !write_ip_rules_nm(def, kf, AF_INET6, error))
return FALSE;
}

if (def->type == NETPLAN_DEF_TYPE_VETH && def->veth_peer_link) {
Expand Down Expand Up @@ -871,6 +921,8 @@ write_nm_conf_access_point(const NetplanNetDefinition* def, const char* rootdir,
write_search_domains(def, "ipv4", kf);
if (!write_routes_nm(def, kf, AF_INET, error))
return FALSE;
if (!write_ip_rules_nm(def, kf, AF_INET, error))
return FALSE;
}

if (!def->dhcp4_overrides.use_routes) {
Expand Down Expand Up @@ -917,6 +969,9 @@ write_nm_conf_access_point(const NetplanNetDefinition* def, const char* rootdir,
if (!write_routes_nm(def, kf, AF_INET6, error))
return FALSE;

if (!write_ip_rules_nm(def, kf, AF_INET6, error))
return FALSE;

if (!def->dhcp6_overrides.use_routes) {
g_key_file_set_boolean(kf, "ipv6", "ignore-auto-routes", TRUE);
g_key_file_set_boolean(kf, "ipv6", "never-default", TRUE);
Expand Down
1 change: 1 addition & 0 deletions tests/generator/test_vrfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ def test_vrf_set_table(self):
[ipv4]
route1=0.0.0.0/0,1.2.3.4
route1_options=table=1005
routing-rule1=from 2.3.4.5 table 1005
method=link-local
[ipv6]
Expand Down
6 changes: 2 additions & 4 deletions tests/integration/routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,10 +332,8 @@ def test_vrf_basic(self):
self.assertIn('11.11.11.0/24 via 10.10.10.2 dev {}'.format(self.dev_e_client), out)

# verify routing policy was setup correctly to the VRF's table
# 'routing-policy' is not supported on NetworkManager
if self.backend == 'networkd':
out = subprocess.check_output(['ip', 'rule', 'show'], text=True)
self.assertIn('from 10.10.10.42 lookup 1000', out)
out = subprocess.check_output(['ip', 'rule', 'show'], text=True)
self.assertIn('from 10.10.10.42 lookup 1000', out)

def test_route_advmss_v6(self):
self.setup_eth(None)
Expand Down

0 comments on commit 416e30c

Please sign in to comment.