diff --git a/src/networkd.c b/src/networkd.c index ec9f78203..c3df27652 100644 --- a/src/networkd.c +++ b/src/networkd.c @@ -591,7 +591,7 @@ write_route(NetplanIPRoute* r, GString* s) if (r->onlink) g_string_append_printf(s, "GatewayOnLink=true\n"); if (r->metric != NETPLAN_METRIC_UNSPEC) - g_string_append_printf(s, "Metric=%d\n", r->metric); + g_string_append_printf(s, "Metric=%u\n", r->metric); if (r->table != NETPLAN_ROUTE_TABLE_UNSPEC) g_string_append_printf(s, "Table=%d\n", r->table); if (r->mtubytes != NETPLAN_MTU_UNSPEC) diff --git a/src/nm.c b/src/nm.c index 358cedf48..1b7916b55 100644 --- a/src/nm.c +++ b/src/nm.c @@ -210,7 +210,7 @@ write_routes(const NetplanNetDefinition* def, GKeyFile *kf, int family, GError** tmp_key = g_strdup_printf("route%d", j); tmp_val = g_string_new(destination); if (cur_route->metric != NETPLAN_METRIC_UNSPEC) - g_string_append_printf(tmp_val, ",%s,%d", is_global ? cur_route->via : "", + g_string_append_printf(tmp_val, ",%s,%u", is_global ? cur_route->via : "", cur_route->metric); else if (is_global) // no metric, but global gateway g_string_append_printf(tmp_val, ",%s", cur_route->via); diff --git a/src/validation.c b/src/validation.c index 5649fbeda..4c62f0e01 100644 --- a/src/validation.c +++ b/src/validation.c @@ -555,7 +555,7 @@ defroute_err(struct _defroute_entry *entry, const char *new_netdef_id, GError ** if (entry->metric == NETPLAN_METRIC_UNSPEC) strncpy(metric_name, "metric: default", sizeof(metric_name) - 1); else - snprintf(metric_name, sizeof(metric_name) - 1, "metric: %d", entry->metric); + snprintf(metric_name, sizeof(metric_name) - 1, "metric: %u", entry->metric); g_set_error(error, NETPLAN_VALIDATION_ERROR, NETPLAN_ERROR_CONFIG_GENERIC, "Conflicting default route declarations for %s (%s, %s), first declared in %s but also in %s", diff --git a/tests/generator/test_routing.py b/tests/generator/test_routing.py index 006ec1933..f3ed2b385 100644 --- a/tests/generator/test_routing.py +++ b/tests/generator/test_routing.py @@ -806,6 +806,35 @@ def test_type_local_lp1892272(self): UseMTU=true '''}) + def test_route_metric_rendering_lp2023681(self): + """Validate metric rendering is unsigned + (can render up to 4294967294, 4294967295 is used internally to define an unset value) + """ + + self.generate('''network: + version: 2 + ethernets: + engreen: + addresses: ["192.168.14.2/24"] + routes: + - to: 10.10.10.0/24 + via: 192.168.14.20 + metric: 4294967294 + ''') + + self.assert_networkd({'engreen.network': '''[Match] +Name=engreen + +[Network] +LinkLocalAddressing=ipv6 +Address=192.168.14.2/24 + +[Route] +Destination=10.10.10.0/24 +Gateway=192.168.14.20 +Metric=4294967294 +'''}) + class TestNetworkManager(TestBase): @@ -1537,4 +1566,38 @@ def test_add_duplicate_routes_from_multiple_files(self): [RoutingPolicyRule] From=10.0.0.2 Table=1002 +'''}) + + def test_route_metric_rendering_lp2023681(self): + """Validate metric rendering is unsigned + (can render up to 4294967294, 4294967295 is used internally to define an unset value) + """ + + self.generate('''network: + version: 2 + renderer: NetworkManager + ethernets: + engreen: + addresses: ["192.168.14.2/24"] + routes: + - to: 10.10.10.0/24 + via: 192.168.14.20 + metric: 4294967294 + ''') + + self.assert_nm({'engreen': '''[connection] +id=netplan-engreen +type=ethernet +interface-name=engreen + +[ethernet] +wake-on-lan=0 + +[ipv4] +method=manual +address1=192.168.14.2/24 +route1=10.10.10.0/24,192.168.14.20,4294967294 + +[ipv6] +method=ignore '''})