mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-10-15 12:34:55 +00:00
all: support route-attribute "onlink" for IPv4
Kernel doesn't support it for IPv6. This is especially useful, if you combine static routes with DHCP. In that case, you might want to get the device-route to the gateway automatically, but add a static-route for it.
This commit is contained in:
parent
88a40f960c
commit
0ed49717ab
|
@ -2104,6 +2104,7 @@ EXTRA_DIST += \
|
|||
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_LEAP.cexpected \
|
||||
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_WEP_104_ASCII.cexpected \
|
||||
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected \
|
||||
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected \
|
||||
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected \
|
||||
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Vlan_test-vlan-interface.cexpected \
|
||||
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-dcb-test.cexpected \
|
||||
|
|
|
@ -1245,6 +1245,7 @@ static const NMVariantAttributeSpec * const ip_route_attribute_spec[] = {
|
|||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_SRC, G_VARIANT_TYPE_STRING, TRUE, TRUE, 'a'),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_FROM, G_VARIANT_TYPE_STRING, FALSE, TRUE, 'p'),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, TRUE, FALSE, 0 ),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_ONLINK, G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_WINDOW, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_CWND, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_INITCWND, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ),
|
||||
|
|
|
@ -146,6 +146,7 @@ gboolean nm_ip_route_attribute_validate (const char *name,
|
|||
#define NM_IP_ROUTE_ATTRIBUTE_SRC "src"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_FROM "from"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_TOS "tos"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_ONLINK "onlink"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_WINDOW "window"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_CWND "cwnd"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_INITCWND "initcwnd"
|
||||
|
|
|
@ -817,6 +817,7 @@ _nm_ip_config_merge_route_attributes (int addr_family,
|
|||
NMIPAddr addr;
|
||||
NMPlatformIP4Route *r4 = (NMPlatformIP4Route *) r;
|
||||
NMPlatformIP6Route *r6 = (NMPlatformIP6Route *) r;
|
||||
gboolean onlink;
|
||||
|
||||
nm_assert (s_route);
|
||||
nm_assert_addr_family (addr_family);
|
||||
|
@ -836,8 +837,15 @@ _nm_ip_config_merge_route_attributes (int addr_family,
|
|||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TABLE, table, UINT32, uint32, 0);
|
||||
r->table_coerced = nm_platform_route_table_coerce (table ?: (route_table ?: RT_TABLE_MAIN));
|
||||
|
||||
if (addr_family == AF_INET)
|
||||
if (addr_family == AF_INET) {
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TOS, r4->tos, BYTE, byte, 0);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_ONLINK, onlink, BOOLEAN, boolean, FALSE);
|
||||
} else
|
||||
onlink = FALSE;
|
||||
|
||||
r->r_rtm_flags = 0;
|
||||
if (onlink)
|
||||
r->r_rtm_flags = RTNH_F_ONLINK;
|
||||
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_WINDOW, r->window, UINT32, uint32, 0);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_CWND, r->cwnd, UINT32, uint32, 0);
|
||||
|
|
|
@ -512,13 +512,13 @@ typedef struct {
|
|||
|
||||
bool int_base_16:1;
|
||||
|
||||
/* the type, one of PARSE_LINE_TYPE_* */
|
||||
char type;
|
||||
|
||||
/* whether the command line option was found, and @v is
|
||||
* initialized. */
|
||||
bool has:1;
|
||||
|
||||
/* the type, one of PARSE_LINE_TYPE_* */
|
||||
char type;
|
||||
|
||||
union {
|
||||
guint8 uint8;
|
||||
guint32 uint32;
|
||||
|
@ -541,6 +541,7 @@ enum {
|
|||
PARSE_LINE_ATTR_ROUTE_SRC,
|
||||
PARSE_LINE_ATTR_ROUTE_FROM,
|
||||
PARSE_LINE_ATTR_ROUTE_TOS,
|
||||
PARSE_LINE_ATTR_ROUTE_ONLINK,
|
||||
PARSE_LINE_ATTR_ROUTE_WINDOW,
|
||||
PARSE_LINE_ATTR_ROUTE_CWND,
|
||||
PARSE_LINE_ATTR_ROUTE_INITCWND,
|
||||
|
@ -562,6 +563,7 @@ enum {
|
|||
#define PARSE_LINE_TYPE_ADDR 'a'
|
||||
#define PARSE_LINE_TYPE_ADDR_WITH_PREFIX 'p'
|
||||
#define PARSE_LINE_TYPE_IFNAME 'i'
|
||||
#define PARSE_LINE_TYPE_FLAG 'f'
|
||||
|
||||
/**
|
||||
* parse_route_line:
|
||||
|
@ -612,6 +614,9 @@ parse_route_line (const char *line,
|
|||
.type = PARSE_LINE_TYPE_UINT8,
|
||||
.int_base_16 = TRUE,
|
||||
.ignore = (addr_family != AF_INET), },
|
||||
[PARSE_LINE_ATTR_ROUTE_ONLINK] = { .key = NM_IP_ROUTE_ATTRIBUTE_ONLINK,
|
||||
.type = PARSE_LINE_TYPE_FLAG,
|
||||
.ignore = (addr_family != AF_INET), },
|
||||
[PARSE_LINE_ATTR_ROUTE_WINDOW] = { .key = NM_IP_ROUTE_ATTRIBUTE_WINDOW,
|
||||
.type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, },
|
||||
[PARSE_LINE_ATTR_ROUTE_CWND] = { .key = NM_IP_ROUTE_ATTRIBUTE_CWND,
|
||||
|
@ -705,6 +710,9 @@ parse_route_line (const char *line,
|
|||
case PARSE_LINE_TYPE_IFNAME:
|
||||
i_words++;
|
||||
goto parse_line_type_ifname;
|
||||
case PARSE_LINE_TYPE_FLAG:
|
||||
i_words++;
|
||||
goto next;
|
||||
default:
|
||||
nm_assert_not_reached ();
|
||||
}
|
||||
|
@ -913,6 +921,15 @@ next:
|
|||
? nm_sprintf_buf (buf2, "/%u", (unsigned) info->v.addr.plen)
|
||||
: ""));
|
||||
break;
|
||||
case PARSE_LINE_TYPE_FLAG:
|
||||
/* XXX: the flag (for "onlink") only allows to explictly set "TRUE".
|
||||
* There is no way to express an explicit "FALSE" setting
|
||||
* of this attribute, hence, the file format cannot encode
|
||||
* that configuration. */
|
||||
nm_ip_route_set_attribute (route,
|
||||
info->key,
|
||||
g_variant_new_boolean (TRUE));
|
||||
break;
|
||||
default:
|
||||
nm_assert_not_reached ();
|
||||
break;
|
||||
|
|
|
@ -1928,8 +1928,11 @@ get_route_attributes_string (NMIPRoute *route, int family)
|
|||
g_string_append_printf (str, "%s 0x%02x", names[i], (unsigned) g_variant_get_byte (attr));
|
||||
} else if (nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_TABLE)) {
|
||||
g_string_append_printf (str, "%s %u", names[i], (unsigned) g_variant_get_uint32 (attr));
|
||||
} else if ( nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_SRC)
|
||||
|| nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_FROM)) {
|
||||
} else if (nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_ONLINK)) {
|
||||
if (g_variant_get_boolean (attr))
|
||||
g_string_append (str, "onlink");
|
||||
} else if (NM_IN_STRSET (names[i], NM_IP_ROUTE_ATTRIBUTE_SRC,
|
||||
NM_IP_ROUTE_ATTRIBUTE_FROM)) {
|
||||
char *arg = nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_SRC) ? "src" : "from";
|
||||
|
||||
g_string_append_printf (str, "%s %s", arg, g_variant_get_string (attr, NULL));
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
HWADDR=31:33:33:37:BE:CD
|
||||
MTU=1492
|
||||
TYPE=Ethernet
|
||||
PROXY_METHOD=none
|
||||
BROWSER_ONLY=no
|
||||
BOOTPROTO=none
|
||||
IPADDR=1.1.1.3
|
||||
PREFIX=24
|
||||
IPADDR1=1.1.1.5
|
||||
PREFIX1=24
|
||||
GATEWAY=1.1.1.1
|
||||
DNS1=4.2.2.1
|
||||
DNS2=4.2.2.2
|
||||
DOMAIN="foobar.com lab.foobar.com"
|
||||
DEFROUTE=yes
|
||||
IPV4_FAILURE_FATAL=no
|
||||
IPV6INIT=no
|
||||
NAME="Test Write Wired Static Routes"
|
||||
UUID=${UUID}
|
||||
ONBOOT=yes
|
|
@ -7,3 +7,9 @@ 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 initcwnd lock 13 initrwnd 14"
|
||||
|
||||
ADDRESS2=44.55.66.78
|
||||
NETMASK2=255.255.255.255
|
||||
GATEWAY2=192.168.1.8
|
||||
METRIC2=3
|
||||
OPTIONS2="mtu lock 9000 cwnd 12 src 1.1.1.1 tos 0x28 onlink window 30000 initcwnd lock 13 initrwnd 14"
|
||||
|
|
|
@ -1318,7 +1318,7 @@ test_read_wired_static_routes (void)
|
|||
g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL);
|
||||
|
||||
/* Routes */
|
||||
g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 2);
|
||||
g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 3);
|
||||
|
||||
ip4_route = nm_setting_ip_config_get_route (s_ip4, 0);
|
||||
g_assert (ip4_route);
|
||||
|
@ -1343,6 +1343,23 @@ test_read_wired_static_routes (void)
|
|||
nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, TRUE);
|
||||
nmtst_assert_route_attribute_string (ip4_route, NM_IP_ROUTE_ATTRIBUTE_SRC, "1.1.1.1");
|
||||
|
||||
ip4_route = nm_setting_ip_config_get_route (s_ip4, 2);
|
||||
g_assert (ip4_route);
|
||||
g_assert_cmpstr (nm_ip_route_get_dest (ip4_route), ==, "44.55.66.78");
|
||||
g_assert_cmpint (nm_ip_route_get_prefix (ip4_route), ==, 32);
|
||||
g_assert_cmpstr (nm_ip_route_get_next_hop (ip4_route), ==, "192.168.1.8");
|
||||
g_assert_cmpint (nm_ip_route_get_metric (ip4_route), ==, 3);
|
||||
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_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);
|
||||
nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, TRUE);
|
||||
nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, TRUE);
|
||||
nmtst_assert_route_attribute_string (ip4_route, NM_IP_ROUTE_ATTRIBUTE_SRC, "1.1.1.1");
|
||||
nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_ONLINK, TRUE);
|
||||
|
||||
g_object_unref (connection);
|
||||
}
|
||||
|
||||
|
@ -4748,6 +4765,7 @@ test_write_wired_static_routes (void)
|
|||
NMIPAddress *addr;
|
||||
NMIPRoute *route;
|
||||
GError *error = NULL;
|
||||
gboolean reread_same = FALSE;
|
||||
|
||||
connection = nm_simple_connection_new ();
|
||||
|
||||
|
@ -4792,11 +4810,15 @@ test_write_wired_static_routes (void)
|
|||
|
||||
/* Write out routes */
|
||||
route = nm_ip_route_new (AF_INET, "1.2.3.0", 24, "222.173.190.239", 0, &error);
|
||||
nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_WINDOW, g_variant_new_uint32 (3455));
|
||||
nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_ONLINK, g_variant_new_boolean (TRUE));
|
||||
g_assert_no_error (error);
|
||||
nm_setting_ip_config_add_route (s_ip4, route);
|
||||
nm_ip_route_unref (route);
|
||||
|
||||
route = nm_ip_route_new (AF_INET, "3.2.1.0", 24, "202.254.186.190", 77, &error);
|
||||
nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_WINDOW, g_variant_new_uint32 (30000));
|
||||
nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_ONLINK, g_variant_new_boolean (FALSE));
|
||||
g_assert_no_error (error);
|
||||
nm_setting_ip_config_add_route (s_ip4, route);
|
||||
nm_ip_route_unref (route);
|
||||
|
@ -4818,15 +4840,28 @@ test_write_wired_static_routes (void)
|
|||
|
||||
nmtst_assert_connection_verifies (connection);
|
||||
|
||||
_writer_new_connection (connection,
|
||||
_writer_new_connection_reread (connection,
|
||||
TEST_SCRATCH_DIR "/network-scripts/",
|
||||
&testfile);
|
||||
|
||||
reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
|
||||
|
||||
routefile = utils_get_route_path (testfile);
|
||||
&testfile,
|
||||
TEST_IFCFG_DIR "/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected",
|
||||
&reread,
|
||||
&reread_same);
|
||||
/* ifcfg does not support setting onlink=0. It gets lost during write+re-read.
|
||||
* Assert that it's missing, and patch it to check whether the rest of the
|
||||
* connection equals. */
|
||||
g_assert (!reread_same);
|
||||
nmtst_assert_connection_verifies_without_normalization (reread);
|
||||
s_ip4 = nm_connection_get_setting_ip4_config (reread);
|
||||
g_assert (s_ip4);
|
||||
g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 2);
|
||||
route = nm_setting_ip_config_get_route (s_ip4, 1);
|
||||
g_assert (route);
|
||||
g_assert (!nm_ip_route_get_attribute (route, NM_IP_ROUTE_ATTRIBUTE_ONLINK));
|
||||
nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_ONLINK, g_variant_new_boolean (FALSE));
|
||||
|
||||
nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
|
||||
|
||||
routefile = utils_get_route_path (testfile);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
Loading…
Reference in a new issue