From af26b19dae35ec88cbe3a8f24a3e6c8d3125b1cd Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Thu, 29 Sep 2022 12:15:30 +0200 Subject: [PATCH] route: introduce weight property for ipv4 routes Introduce the weight property for IPv4 ECMP routes. The value will be ignored if there is only a single nexthop. --- src/core/NetworkManagerUtils.c | 1 + .../settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 7 +++++++ .../settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 4 +++- .../network-scripts/route-test-wired-static-routes | 2 +- .../settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 12 ++++++++++++ .../keyfile/tests/keyfiles/Test_Wired_Connection | 2 +- .../plugins/keyfile/tests/test-keyfile-settings.c | 2 ++ src/libnm-core-impl/nm-setting-ip-config.c | 3 +++ src/libnm-core-impl/tests/test-general.c | 10 +++++++++- src/libnm-core-public/nm-setting-ip-config.h | 1 + 10 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/core/NetworkManagerUtils.c b/src/core/NetworkManagerUtils.c index 9acf329635..21f8d19d44 100644 --- a/src/core/NetworkManagerUtils.c +++ b/src/core/NetworkManagerUtils.c @@ -1382,6 +1382,7 @@ nm_utils_ip_route_attribute_to_platform(int addr_family, GET_ATTR(NM_IP_ROUTE_ATTRIBUTE_TOS, r4->tos, BYTE, byte, 0); GET_ATTR(NM_IP_ROUTE_ATTRIBUTE_SCOPE, scope, BYTE, byte, RT_SCOPE_NOWHERE); + GET_ATTR(NM_IP_ROUTE_ATTRIBUTE_WEIGHT, r4->weight, BYTE, byte, 0); r4->scope_inv = nm_platform_route_scope_inv(scope); } diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index de726b4cc2..cd241caa76 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -887,6 +887,7 @@ enum { PARSE_LINE_ATTR_ROUTE_ADVMSS, PARSE_LINE_ATTR_ROUTE_RTO_MIN, PARSE_LINE_ATTR_ROUTE_QUICKACK, + PARSE_LINE_ATTR_ROUTE_WEIGHT, /* iproute2 arguments that only matter when parsing the file. */ PARSE_LINE_ATTR_ROUTE_TO, @@ -966,6 +967,12 @@ parse_route_line(const char *line, .int_base_16 = TRUE, .ignore = PARSE_LINE_AF_FLAG_FOR_IPV6, }, + [PARSE_LINE_ATTR_ROUTE_WEIGHT] = + { + .key = NM_IP_ROUTE_ATTRIBUTE_WEIGHT, + .type = PARSE_LINE_TYPE_UINT8, + .disabled = PARSE_LINE_AF_FLAG_FOR_IPV6, + }, [PARSE_LINE_ATTR_ROUTE_SCOPE] = { .key = NM_IP_ROUTE_ATTRIBUTE_SCOPE, diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index 99e35d5bd7..ee1282311a 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -2360,7 +2360,9 @@ get_route_attributes_string(NMIPRoute *route, int family) /* we also have a corresponding attribute with the numeric value. The * lock setting is handled above. */ } - } else if (nm_streq(names[i], NM_IP_ROUTE_ATTRIBUTE_SCOPE)) { + } else if (NM_IN_STRSET(names[i], + NM_IP_ROUTE_ATTRIBUTE_SCOPE, + NM_IP_ROUTE_ATTRIBUTE_WEIGHT)) { g_string_append_printf(str, "%s %u", names[i], (unsigned) g_variant_get_byte(attr)); } else if (nm_streq(names[i], NM_IP_ROUTE_ATTRIBUTE_TOS)) { g_string_append_printf(str, "%s 0x%02x", names[i], (unsigned) g_variant_get_byte(attr)); diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes index 717ad1ac98..728e8e964a 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes @@ -6,7 +6,7 @@ ADDRESS1=44.55.66.77 NETMASK1=255.255.255.255 GATEWAY1=192.168.1.7 METRIC1=3 -OPTIONS1="mtu lock 9000 cwnd 12 src 1.1.1.1 tos 0x28 window 30000 scope 10 initcwnd lock 13 initrwnd 14 rto_min 300 advmss 1300 quickack 1" +OPTIONS1="mtu lock 9000 cwnd 12 src 1.1.1.1 tos 0x28 window 30000 scope 10 initcwnd lock 13 initrwnd 14 rto_min 300 advmss 1300 quickack 1 weight 5" ADDRESS2=44.55.66.78 NETMASK2=255.255.255.255 diff --git a/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index a281ab8c12..7d8cf0ebad 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -1365,6 +1365,7 @@ test_read_wired_static_routes(void) nmtst_assert_route_attribute_byte(ip4_route, NM_IP_ROUTE_ATTRIBUTE_TOS, 0x28); nmtst_assert_route_attribute_uint32(ip4_route, NM_IP_ROUTE_ATTRIBUTE_WINDOW, 30000); nmtst_assert_route_attribute_uint32(ip4_route, NM_IP_ROUTE_ATTRIBUTE_CWND, 12); + nmtst_assert_route_attribute_byte(ip4_route, NM_IP_ROUTE_ATTRIBUTE_WEIGHT, 5); nmtst_assert_route_attribute_uint32(ip4_route, NM_IP_ROUTE_ATTRIBUTE_INITCWND, 13); nmtst_assert_route_attribute_uint32(ip4_route, NM_IP_ROUTE_ATTRIBUTE_INITRWND, 14); nmtst_assert_route_attribute_uint32(ip4_route, NM_IP_ROUTE_ATTRIBUTE_MTU, 9000); @@ -4279,6 +4280,7 @@ static void test_write_wired_static(void) { nmtst_auto_unlinkfile char *testfile = NULL; + nmtst_auto_unlinkfile char *route4file = NULL; nmtst_auto_unlinkfile char *route6file = NULL; gs_unref_object NMConnection *connection = NULL; gs_unref_object NMConnection *reread = NULL; @@ -4288,6 +4290,7 @@ test_write_wired_static(void) NMSettingIPConfig *s_ip6, *reread_s_ip6; NMIPAddress *addr; NMIPAddress *addr6; + NMIPRoute *route4; NMIPRoute *route6; GError *error = NULL; @@ -4392,6 +4395,13 @@ test_write_wired_static(void) nm_setting_ip_config_add_route(s_ip6, route6); nm_ip_route_unref(route6); + route4 = nm_ip_route_new(AF_INET, "1.1.1.1", 24, "1.2.3.4", 99, &error); + g_assert_no_error(error); + nm_ip_route_set_attribute(route4, NM_IP_ROUTE_ATTRIBUTE_CWND, g_variant_new_uint32(100)); + nm_ip_route_set_attribute(route4, NM_IP_ROUTE_ATTRIBUTE_WEIGHT, g_variant_new_byte(5)); + nm_setting_ip_config_add_route(s_ip4, route4); + nm_ip_route_unref(route4); + /* DNS servers */ nm_setting_ip_config_add_dns(s_ip6, "fade:0102:0103::face"); nm_setting_ip_config_add_dns(s_ip6, "cafe:ffff:eeee:dddd:cccc:bbbb:aaaa:feed"); @@ -4403,7 +4413,9 @@ test_write_wired_static(void) nmtst_assert_connection_verifies(connection); _writer_new_connection(connection, TEST_SCRATCH_DIR, &testfile); + route6file = utils_get_route6_path(testfile); + route4file = utils_get_route_path(testfile); reread = _connection_from_file(testfile, NULL, TYPE_ETHERNET, NULL); diff --git a/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection index f9ccc003df..eb3754a2f6 100644 --- a/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection @@ -36,7 +36,7 @@ routes9=1.1.1.9/19,0.0.0.0,0 route10=1.1.1.10/21,,0 routes10=1.1.1.10/20,,0 routes11=1.1.1.11/21,,21 -routes11_options=cwnd=10,lock-cwnd=true,mtu=1430,src=7.7.7.7,type=unicast +routes11_options=cwnd=10,lock-cwnd=true,mtu=1430,src=7.7.7.7,type=unicast,weight=5 routes12=1.2.3.4/32 routes12_options=type=local address30=1.2.3.30/24 diff --git a/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c index 169a64c5a1..2d4adfbcfe 100644 --- a/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c +++ b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c @@ -311,6 +311,7 @@ test_read_valid_wired_connection(void) nmtst_assert_route_attribute_uint32(route, NM_IP_ROUTE_ATTRIBUTE_CWND, 10); nmtst_assert_route_attribute_uint32(route, NM_IP_ROUTE_ATTRIBUTE_MTU, 1430); + nmtst_assert_route_attribute_byte(route, NM_IP_ROUTE_ATTRIBUTE_WEIGHT, 5); nmtst_assert_route_attribute_boolean(route, NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, TRUE); nmtst_assert_route_attribute_string(route, NM_IP_ROUTE_ATTRIBUTE_SRC, "7.7.7.7"); nmtst_assert_route_attribute_string(route, NM_IP_ROUTE_ATTRIBUTE_TYPE, "unicast"); @@ -495,6 +496,7 @@ test_write_wired_connection(void) g_assert_no_error(error); nm_ip_route_set_attribute(rt, NM_IP_ROUTE_ATTRIBUTE_CWND, g_variant_new_uint32(10)); nm_ip_route_set_attribute(rt, NM_IP_ROUTE_ATTRIBUTE_MTU, g_variant_new_uint32(1492)); + nm_ip_route_set_attribute(rt, NM_IP_ROUTE_ATTRIBUTE_WEIGHT, g_variant_new_byte(5)); nm_ip_route_set_attribute(rt, NM_IP_ROUTE_ATTRIBUTE_SRC, g_variant_new_string("1.2.3.4")); g_assert(nm_setting_ip_config_add_route(s_ip4, rt)); nm_ip_route_unref(rt); diff --git a/src/libnm-core-impl/nm-setting-ip-config.c b/src/libnm-core-impl/nm-setting-ip-config.c index 496e7297e8..389fe3f259 100644 --- a/src/libnm-core-impl/nm-setting-ip-config.c +++ b/src/libnm-core-impl/nm-setting-ip-config.c @@ -1278,6 +1278,9 @@ static const NMVariantAttributeSpec *const ip_route_attribute_spec[] = { .v4 = TRUE, .v6 = TRUE, .type_detail = 'T', ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_WEIGHT, + G_VARIANT_TYPE_BYTE, + .v4 = TRUE, ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_WINDOW, G_VARIANT_TYPE_UINT32, .v4 = TRUE, diff --git a/src/libnm-core-impl/tests/test-general.c b/src/libnm-core-impl/tests/test-general.c index 74e3430895..a7651f5f12 100644 --- a/src/libnm-core-impl/tests/test-general.c +++ b/src/libnm-core-impl/tests/test-general.c @@ -2501,6 +2501,9 @@ test_setting_ip_route_attributes(void) TEST_ATTR("tos", byte, 127, AF_INET, TRUE, TRUE); TEST_ATTR("tos", string, "0x28", AF_INET, FALSE, TRUE); + TEST_ATTR("weight", byte, 100, AF_INET, TRUE, TRUE); + TEST_ATTR("weight", string, "100", AF_INET, FALSE, TRUE); + TEST_ATTR("advmss", uint32, 1400, AF_INET, TRUE, TRUE); TEST_ATTR("advmss", string, "1400", AF_INET, FALSE, TRUE); @@ -9971,7 +9974,7 @@ test_route_attributes_parse(void) g_assert(!ht); g_clear_error(&error); - ht = nm_utils_parse_variant_attributes("mtu.1400 src.1\\.2\\.3\\.4 ", + ht = nm_utils_parse_variant_attributes("mtu.1400 weight.5 src.1\\.2\\.3\\.4 ", ' ', '.', FALSE, @@ -9984,6 +9987,11 @@ test_route_attributes_parse(void) g_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32)); g_assert_cmpuint(g_variant_get_uint32(variant), ==, 1400); + variant = g_hash_table_lookup(ht, NM_IP_ROUTE_ATTRIBUTE_WEIGHT); + g_assert(variant); + g_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_BYTE)); + g_assert_cmpuint(g_variant_get_byte(variant), ==, 5); + variant = g_hash_table_lookup(ht, NM_IP_ROUTE_ATTRIBUTE_SRC); g_assert(variant); g_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)); diff --git a/src/libnm-core-public/nm-setting-ip-config.h b/src/libnm-core-public/nm-setting-ip-config.h index c7556e624a..ca65fb592f 100644 --- a/src/libnm-core-public/nm-setting-ip-config.h +++ b/src/libnm-core-public/nm-setting-ip-config.h @@ -144,6 +144,7 @@ gboolean nm_ip_route_attribute_validate(const char *name, #define NM_IP_ROUTE_ATTRIBUTE_TOS "tos" #define NM_IP_ROUTE_ATTRIBUTE_TYPE "type" #define NM_IP_ROUTE_ATTRIBUTE_WINDOW "window" +#define NM_IP_ROUTE_ATTRIBUTE_WEIGHT "weight" /*****************************************************************************/