diff options
author | Thomas Haller <thaller@redhat.com> | 2017-11-13 11:50:44 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2017-11-13 11:51:08 +0100 |
commit | d44a3eb80caeeccc3f34c2c2a1b69828f0ef75aa (patch) | |
tree | 14030512f24f23aa549a208dc5702a77a5a62e8c | |
parent | a33baf8bf7e66d95bf9678c0c66ca869006c3b0f (diff) | |
parent | cb47ed0fcdddf7a6b13514a117b5566ffbdd4eda (diff) | |
download | NetworkManager-d44a3eb80caeeccc3f34c2c2a1b69828f0ef75aa.tar.gz |
all: merge branch 'th/platform-routes-onlink-rh1428334'
https://bugzilla.redhat.com/show_bug.cgi?id=1428334
22 files changed, 572 insertions, 298 deletions
diff --git a/Makefile.am b/Makefile.am index af1d445d86..eafc8ca54d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ diff --git a/configure.ac b/configure.ac index ad188a7763..a2405c625b 100644 --- a/configure.ac +++ b/configure.ac @@ -1227,6 +1227,22 @@ fi AC_SUBST(SANITIZERS, [$sanitizers]) +AC_MSG_CHECKING([CC support C11 _Generic()]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[int foo(void); int foo() { int a = 0; int b = _Generic (a, int: 4); return b + a; }]], + [[foo();]])], + [cc_support_generic=1], + [cc_support_generic=0]) +AC_MSG_RESULT($cc_support_generic) +AC_DEFINE_UNQUOTED(_NM_CC_SUPPORT_GENERIC, $cc_support_generic, [Define whether the compiler supports C11 _Generic()]) + +AC_MSG_CHECKING([CC support gcc __auto_type]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[int foo(void); int foo() { int a = 0; __auto_type b = a; return b + a; }]], + [[foo();]])], + [cc_support_auto_type=1], + [cc_support_auto_type=0]) +AC_MSG_RESULT($cc_support_auto_type) +AC_DEFINE_UNQUOTED(_NM_CC_SUPPORT_AUTO_TYPE, $cc_support_auto_type, [Define whether the compiler support gcc __auto_type]) + dnl ------------------------- dnl Vala bindings dnl ------------------------- diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c index 7265fdc51e..41ae0993f6 100644 --- a/libnm-core/nm-setting-ip-config.c +++ b/libnm-core/nm-setting-ip-config.c @@ -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 ), diff --git a/libnm-core/nm-setting-ip-config.h b/libnm-core/nm-setting-ip-config.h index 84ce84657a..96e61bb5c9 100644 --- a/libnm-core/nm-setting-ip-config.h +++ b/libnm-core/nm-setting-ip-config.h @@ -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" diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h index d07e298ea2..2d62ba7d97 100644 --- a/shared/nm-utils/nm-macros-internal.h +++ b/shared/nm-utils/nm-macros-internal.h @@ -263,11 +263,25 @@ NM_G_ERROR_MSG (GError *error) /*****************************************************************************/ -#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 9 ))) || (defined (__clang__)) +#ifndef _NM_CC_SUPPORT_AUTO_TYPE +#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9 ))) +#define _NM_CC_SUPPORT_AUTO_TYPE 1 +#else +#define _NM_CC_SUPPORT_AUTO_TYPE 0 +#endif +#endif + +#ifndef _NM_CC_SUPPORT_GENERIC +#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9 ))) || (defined (__clang__)) #define _NM_CC_SUPPORT_GENERIC 1 #else #define _NM_CC_SUPPORT_GENERIC 0 #endif +#endif + +#if _NM_CC_SUPPORT_AUTO_TYPE +#define _nm_auto_type __auto_type +#endif #if _NM_CC_SUPPORT_GENERIC #define _NM_CONSTCAST_FULL_1(type, obj_expr, obj) \ @@ -372,6 +386,16 @@ NM_G_ERROR_MSG (GError *error) #define _NM_ENSURE_TYPE(type, value) (value) #endif +#if _NM_CC_SUPPORT_GENERIC +#define NM_PROPAGATE_CONST(test_expr, ptr) \ + (_Generic ((test_expr), \ + const typeof (*(test_expr)) *: ((const typeof (*(ptr)) *) (ptr)), \ + default: (_Generic ((test_expr), \ + typeof (*(test_expr)) *: (ptr))))) +#else +#define NM_PROPAGATE_CONST(test_expr, ptr) (ptr) +#endif + /*****************************************************************************/ #define _NM_IN_SET_EVAL_1( op, _x, y) (_x == (y)) @@ -651,8 +675,17 @@ _notify (obj_type *obj, _PropertyEnums prop) \ /*****************************************************************************/ -#define _NM_GET_PRIVATE( self, type, is_check, ...) (&(NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__)->_priv)) -#define _NM_GET_PRIVATE_PTR( self, type, is_check, ...) ( (NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__)->_priv)) +#define _NM_GET_PRIVATE(self, type, is_check, ...) (&(NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__)->_priv)) +#if _NM_CC_SUPPORT_AUTO_TYPE +#define _NM_GET_PRIVATE_PTR(self, type, is_check, ...) \ + ({ \ + _nm_auto_type _self = NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__); \ + \ + NM_PROPAGATE_CONST (_self, _self->_priv); \ + }) +#else +#define _NM_GET_PRIVATE_PTR(self, type, is_check, ...) (NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__)->_priv) +#endif /*****************************************************************************/ diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h index 96aab5341e..a092a6b780 100644 --- a/shared/nm-utils/nm-shared-utils.h +++ b/shared/nm-utils/nm-shared-utils.h @@ -26,23 +26,6 @@ /*****************************************************************************/ -typedef struct { - union { - guint8 addr_ptr[1]; - in_addr_t addr4; - struct in6_addr addr6; - - /* NMIPAddr is really a union for IP addresses. - * However, as ethernet addresses fit in here nicely, use - * it also for an ethernet MAC address. */ - guint8 addr_eth[6 /*ETH_ALEN*/]; - }; -} NMIPAddr; - -extern const NMIPAddr nm_ip_addr_zero; - -/*****************************************************************************/ - static inline char nm_utils_addr_family_to_char (int addr_family) { @@ -68,6 +51,36 @@ nm_utils_addr_family_to_size (int addr_family) /*****************************************************************************/ +typedef struct { + union { + guint8 addr_ptr[1]; + in_addr_t addr4; + struct in6_addr addr6; + + /* NMIPAddr is really a union for IP addresses. + * However, as ethernet addresses fit in here nicely, use + * it also for an ethernet MAC address. */ + guint8 addr_eth[6 /*ETH_ALEN*/]; + }; +} NMIPAddr; + +extern const NMIPAddr nm_ip_addr_zero; + +static inline void +nm_ip_addr_set (int addr_family, gpointer dst, const NMIPAddr *src) +{ + nm_assert_addr_family (addr_family); + nm_assert (dst); + nm_assert (src); + + if (addr_family != AF_INET6) + *((in_addr_t *) dst) = src->addr4; + else + *((struct in6_addr *) dst) = src->addr6; +} + +/*****************************************************************************/ + #define NM_CMP_RETURN(c) \ G_STMT_START { \ const int _cc = (c); \ diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 010172dc06..1fe6f064da 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -1164,9 +1164,9 @@ nm_device_get_ip_iface (NMDevice *self) } int -nm_device_get_ip_ifindex (NMDevice *self) +nm_device_get_ip_ifindex (const NMDevice *self) { - NMDevicePrivate *priv; + const NMDevicePrivate *priv; g_return_val_if_fail (self != NULL, 0); diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index bd8104b4bf..b0d299e4ea 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -438,7 +438,7 @@ int nm_device_get_ifindex (NMDevice *dev); gboolean nm_device_is_software (NMDevice *dev); gboolean nm_device_is_real (NMDevice *dev); const char * nm_device_get_ip_iface (NMDevice *dev); -int nm_device_get_ip_ifindex (NMDevice *dev); +int nm_device_get_ip_ifindex (const NMDevice *dev); const char * nm_device_get_driver (NMDevice *dev); const char * nm_device_get_driver_version (NMDevice *dev); const char * nm_device_get_type_desc (NMDevice *dev); diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 06137764f5..94f4a28e15 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -806,44 +806,87 @@ nm_ip4_config_commit (const NMIP4Config *self, return success; } -static void -merge_route_attributes (NMIPRoute *s_route, - NMPlatformIP4Route *r, - guint32 route_table) +void +_nm_ip_config_merge_route_attributes (int addr_family, + NMIPRoute *s_route, + NMPlatformIPRoute *r, + guint32 route_table) { GVariant *variant; - guint32 u32; - in_addr_t addr; - -#define GET_ATTR(name, field, variant_type, type) \ - variant = nm_ip_route_get_attribute (s_route, name); \ - if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE_ ## variant_type)) \ - r->field = g_variant_get_ ## type (variant); - - variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_TABLE); - u32 = variant && g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32) - ? g_variant_get_uint32 (variant) - : 0; - r->table_coerced = nm_platform_route_table_coerce (u32 ?: (route_table ?: RT_TABLE_MAIN)); - - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TOS, tos, BYTE, byte); - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_WINDOW, window, UINT32, uint32); - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_CWND, cwnd, UINT32, uint32); - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_INITCWND, initcwnd, UINT32, uint32); - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_INITRWND, initrwnd, UINT32, uint32); - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_MTU, mtu, UINT32, uint32); - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, lock_window, BOOLEAN, boolean); - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, lock_cwnd, BOOLEAN, boolean); - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, lock_initcwnd, BOOLEAN, boolean); - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND, lock_initrwnd, BOOLEAN, boolean); - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, lock_mtu, BOOLEAN, boolean); + guint32 table; + NMIPAddr addr; + NMPlatformIP4Route *r4 = (NMPlatformIP4Route *) r; + NMPlatformIP6Route *r6 = (NMPlatformIP6Route *) r; + gboolean onlink; + + nm_assert (s_route); + nm_assert_addr_family (addr_family); + nm_assert (r); + +#define GET_ATTR(name, dst, variant_type, type, dflt) \ + G_STMT_START { \ + GVariant *_variant = nm_ip_route_get_attribute (s_route, ""name""); \ + \ + if ( _variant \ + && g_variant_is_of_type (_variant, G_VARIANT_TYPE_ ## variant_type)) \ + (dst) = g_variant_get_ ## type (_variant); \ + else \ + (dst) = (dflt); \ + } G_STMT_END + + 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) { + 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); + GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_INITCWND, r->initcwnd, UINT32, uint32, 0); + GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_INITRWND, r->initrwnd, UINT32, uint32, 0); + GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_MTU, r->mtu, UINT32, uint32, 0); + GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, r->lock_window, BOOLEAN, boolean, FALSE); + GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, r->lock_cwnd, BOOLEAN, boolean, FALSE); + GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, r->lock_initcwnd, BOOLEAN, boolean, FALSE); + GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND, r->lock_initrwnd, BOOLEAN, boolean, FALSE); + GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, r->lock_mtu, BOOLEAN, boolean, FALSE); if ( (variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_SRC)) && g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) { - if (inet_pton (AF_INET, g_variant_get_string (variant, NULL), &addr) == 1) - r->pref_src = addr; + if (inet_pton (addr_family, g_variant_get_string (variant, NULL), &addr) == 1) { + if (addr_family == AF_INET) + r4->pref_src = addr.addr4; + else + r6->pref_src = addr.addr6; + } } + if ( addr_family == AF_INET6 + && (variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_FROM)) + && g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) { + gs_free char *string = NULL; + guint8 plen = 128; + char *sep; + + string = g_variant_dup_string (variant, NULL); + sep = strchr (string, '/'); + if (sep) { + *sep = 0; + plen = _nm_utils_ascii_str_to_int64 (sep + 1, 10, 1, 128, 255); + } + if ( plen <= 128 + && inet_pton (AF_INET6, string, &addr) == 1) { + r6->src = addr.addr6; + r6->src_plen = plen; + } + } #undef GET_ATTR } @@ -939,7 +982,10 @@ nm_ip4_config_merge_setting (NMIP4Config *self, route.network = nm_utils_ip4_address_clear_host_address (route.network, route.plen); - merge_route_attributes (s_route, &route, route_table); + _nm_ip_config_merge_route_attributes (AF_INET, + s_route, + NM_PLATFORM_IP_ROUTE_CAST (&route), + route_table); _add_route (self, NULL, &route, NULL); } diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index e7fb2703eb..7c345d2052 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -113,6 +113,11 @@ const NMDedupMultiEntry *_nm_ip_config_lookup_ip_route (const NMDedupMultiIndex const NMPObject *needle, NMPlatformIPRouteCmpType cmp_type); +void _nm_ip_config_merge_route_attributes (int addr_family, + NMIPRoute *s_route, + NMPlatformIPRoute *r, + guint32 route_table); + /*****************************************************************************/ #define NM_TYPE_IP4_CONFIG (nm_ip4_config_get_type ()) @@ -272,40 +277,56 @@ gboolean nm_ip4_config_equal (const NMIP4Config *a, const NMIP4Config *b); #include "nm-ip6-config.h" +static inline gboolean +NM_IS_IP_CONFIG (gconstpointer config) +{ + return NM_IS_IP4_CONFIG (config) || NM_IS_IP6_CONFIG (config); +} + #if _NM_CC_SUPPORT_GENERIC -#define NM_IP_CONFIG_CAST(config) \ +/* _NM_IS_IP_CONFIG() is a bit unusual. If _Generic() is supported, + * it checks whether @config is either NM_IS_IP4_CONFIG() or NM_IS_IP6_CONFIG(), + * depending on the pointer type of @config. + * + * For example, with _Generic() support, the following assertions would fail: + * NMIP6Config *ptr = (NMIP6Config *) nm_ip4_config_new(...); + * g_assert (_NM_IS_IP_CONFIG (ptr, ptr)); + * but the following would pass: + * NMIP4Config *ptr = nm_ip4_config_new(...); + * g_assert (_NM_IS_IP_CONFIG (ptr, ptr)); + */ +#define _NM_IS_IP_CONFIG(typeexpr, config) \ ({ \ const void *const _config = (config); \ - \ - nm_assert (_Generic ((config), \ - const void *: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \ - void *: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \ - const NMIPConfig *: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \ - NMIPConfig *: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \ - const NMIP4Config *: (NM_IS_IP4_CONFIG (_config)), \ - NMIP4Config *: (NM_IS_IP4_CONFIG (_config)), \ - const NMIP6Config *: (NM_IS_IP6_CONFIG (_config)), \ - NMIP6Config *: (NM_IS_IP6_CONFIG (_config)))); \ - \ - _Generic ((config), \ - const void *: ((const NMIPConfig *) _config), \ - void *: (( NMIPConfig *) _config), \ - const NMIPConfig *: ((const NMIPConfig *) _config), \ - NMIPConfig *: (( NMIPConfig *) _config), \ - const NMIP4Config *: ((const NMIPConfig *) _config), \ - NMIP4Config *: (( NMIPConfig *) _config), \ - const NMIP6Config *: ((const NMIPConfig *) _config), \ - NMIP6Config *: (( NMIPConfig *) _config)); \ + _Generic ((typeexpr), \ + const void *const: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \ + const void * : (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \ + void *const: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \ + void * : (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \ + const NMIPConfig *const: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \ + const NMIPConfig * : (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \ + NMIPConfig *const: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \ + NMIPConfig * : (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \ + const NMIP4Config *const: (NM_IS_IP4_CONFIG (_config)), \ + const NMIP4Config * : (NM_IS_IP4_CONFIG (_config)), \ + NMIP4Config *const: (NM_IS_IP4_CONFIG (_config)), \ + NMIP4Config * : (NM_IS_IP4_CONFIG (_config)), \ + const NMIP6Config *const: (NM_IS_IP6_CONFIG (_config)), \ + const NMIP6Config * : (NM_IS_IP6_CONFIG (_config)), \ + NMIP6Config *const: (NM_IS_IP6_CONFIG (_config)), \ + NMIP6Config * : (NM_IS_IP6_CONFIG (_config))); \ }) #else -#define NM_IP_CONFIG_CAST(config) ((NMIPConfig *) (config)) +#define _NM_IS_IP_CONFIG(typeexpr, config) NM_IS_IP_CONFIG(config) #endif -static inline gboolean -NM_IS_IP_CONFIG (gconstpointer config) -{ - return NM_IS_IP4_CONFIG (config) || NM_IS_IP6_CONFIG (config); -} +#define NM_IP_CONFIG_CAST(config) \ + ({ \ + const void *const _configx = (config); \ + \ + nm_assert (!_configx || _NM_IS_IP_CONFIG ((config), _configx)); \ + NM_CONSTCAST_FULL (NMIPConfig, (config), _configx, NMIP4Config, NMIP6Config); \ + }) static inline int nm_ip_config_get_addr_family (const NMIPConfig *config) diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 3f0bbfe75c..28841e3434 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -571,65 +571,6 @@ nm_ip6_config_commit (const NMIP6Config *self, return success; } -static void -merge_route_attributes (NMIPRoute *s_route, - NMPlatformIP6Route *r, - guint32 route_table) -{ - GVariant *variant; - guint32 u32; - struct in6_addr addr; - -#define GET_ATTR(name, field, variant_type, type) \ - variant = nm_ip_route_get_attribute (s_route, name); \ - if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE_ ## variant_type)) \ - r->field = g_variant_get_ ## type (variant); - - variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_TABLE); - u32 = variant && g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32) - ? g_variant_get_uint32 (variant) - : 0; - r->table_coerced = nm_platform_route_table_coerce (u32 ?: (route_table ?: RT_TABLE_MAIN)); - - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_WINDOW, window, UINT32, uint32); - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_CWND, cwnd, UINT32, uint32); - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_INITCWND, initcwnd, UINT32, uint32); - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_INITRWND, initrwnd, UINT32, uint32); - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_MTU, mtu, UINT32, uint32); - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, lock_window, BOOLEAN, boolean); - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, lock_cwnd, BOOLEAN, boolean); - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, lock_initcwnd, BOOLEAN, boolean); - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND, lock_initrwnd, BOOLEAN, boolean); - GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, lock_mtu, BOOLEAN, boolean); - - - if ( (variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_SRC)) - && g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) { - if (inet_pton (AF_INET6, g_variant_get_string (variant, NULL), &addr) == 1) - r->pref_src = addr; - } - - if ( (variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_FROM)) - && g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) { - gs_free char *string = NULL; - guint8 plen = 128; - char *sep; - - string = g_variant_dup_string (variant, NULL); - sep = strchr (string, '/'); - if (sep) { - *sep = 0; - plen = _nm_utils_ascii_str_to_int64 (sep + 1, 10, 1, 128, 255); - } - if ( plen <= 128 - && inet_pton (AF_INET6, string, &addr) == 1) { - r->src = addr; - r->src_plen = plen; - } - } -#undef GET_ATTR -} - void nm_ip6_config_merge_setting (NMIP6Config *self, NMSettingIPConfig *setting, @@ -716,7 +657,10 @@ nm_ip6_config_merge_setting (NMIP6Config *self, nm_utils_ip6_address_clear_host_address (&route.network, &route.network, route.plen); - merge_route_attributes (s_route, &route, route_table); + _nm_ip_config_merge_route_attributes (AF_INET, + s_route, + NM_PLATFORM_IP_ROUTE_CAST (&route), + route_table); _add_route (self, NULL, &route, NULL); } diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 9efdd41327..46b7bd209e 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -2291,17 +2291,7 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only) obj->ip6_route.rt_pref = nla_get_u8 (tb[RTA_PREF]); } - if (NM_FLAGS_HAS (rtm->rtm_flags, RTM_F_CLONED)) { - /* we must not straight way reject cloned routes, because we might have cached - * a non-cloned route. If we now receive an update of the route with the route - * being cloned, we must still return the object, so that we can remove the old - * one from the cache. - * - * This happens, because this route is not nmp_object_is_alive(). - * */ - obj->ip_route.rt_cloned = TRUE; - } - + obj->ip_route.r_rtm_flags = rtm->rtm_flags; obj->ip_route.rt_source = nmp_utils_ip_config_source_from_rtprot (rtm->rtm_protocol); obj_result = obj; @@ -2700,7 +2690,9 @@ _nl_msg_new_route (int nlmsg_type, ? nm_platform_route_scope_inv (obj->ip4_route.scope_inv) : RT_SCOPE_NOWHERE, .rtm_type = RTN_UNICAST, - .rtm_flags = 0, + .rtm_flags = obj->ip_route.r_rtm_flags & (is_v4 + ? (unsigned) (RTNH_F_ONLINK) + : (unsigned) 0), .rtm_dst_len = obj->ip_route.plen, .rtm_src_len = is_v4 ? 0 @@ -4189,7 +4181,7 @@ event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_event gboolean resync_required = FALSE; gboolean only_dirty = FALSE; - if (obj->ip_route.rt_cloned) { + if (NM_FLAGS_HAS (obj->ip_route.r_rtm_flags, RTM_F_CLONED)) { /* a cloned route might be a response for RTM_GETROUTE. Check, whether it is. */ nm_assert (!nmp_object_is_alive (obj)); priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index ffc4b3956d..f94d93e257 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -4976,6 +4976,40 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address, char *bu return buf; } +NM_UTILS_FLAGS2STR_DEFINE_STATIC (_rtm_flags_to_string, unsigned, + NM_UTILS_FLAGS2STR (RTNH_F_DEAD, "dead"), + NM_UTILS_FLAGS2STR (RTNH_F_PERVASIVE, "pervasive"), + NM_UTILS_FLAGS2STR (RTNH_F_ONLINK, "onlink"), + NM_UTILS_FLAGS2STR (8 /*RTNH_F_OFFLOAD*/, "offload"), + NM_UTILS_FLAGS2STR (16 /*RTNH_F_LINKDOWN*/, "linkdown"), + NM_UTILS_FLAGS2STR (32 /*RTNH_F_UNRESOLVED*/, "unresolved"), + + NM_UTILS_FLAGS2STR (RTM_F_NOTIFY, "notify"), + NM_UTILS_FLAGS2STR (RTM_F_CLONED, "cloned"), + NM_UTILS_FLAGS2STR (RTM_F_EQUALIZE, "equalize"), + NM_UTILS_FLAGS2STR (RTM_F_PREFIX, "prefix"), + NM_UTILS_FLAGS2STR (0x1000 /*RTM_F_LOOKUP_TABLE*/, "lookup-table"), + NM_UTILS_FLAGS2STR (0x2000 /*RTM_F_FIB_MATCH*/, "fib-match"), +); + +#define _RTM_FLAGS_TO_STRING_MAXLEN 200 + +static const char * +_rtm_flags_to_string_full (char *buf, gsize buf_size, unsigned rtm_flags) +{ + const char *buf0 = buf; + + nm_assert (buf_size >= _RTM_FLAGS_TO_STRING_MAXLEN); + + if (!rtm_flags) + return ""; + + nm_utils_strbuf_append_str (&buf, &buf_size, " rtm_flags "); + _rtm_flags_to_string (rtm_flags, buf, buf_size); + nm_assert (strlen (buf) < buf_size); + return buf0; +} + /** * nm_platform_ip4_route_to_string: * @route: pointer to NMPlatformIP4Route route structure @@ -4997,6 +5031,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi char str_table[30]; char str_scope[30], s_source[50]; char str_tos[32], str_window[32], str_cwnd[32], str_initcwnd[32], str_initrwnd[32], str_mtu[32]; + char str_rtm_flags[_RTM_FLAGS_TO_STRING_MAXLEN]; if (!nm_utils_to_string_buffer_init_null (route, &buf, &len)) return buf; @@ -5015,7 +5050,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi " metric %"G_GUINT32_FORMAT " mss %"G_GUINT32_FORMAT " rt-src %s" /* protocol */ - "%s" /* cloned */ + "%s" /* rtm_flags */ "%s%s" /* scope */ "%s%s" /* pref-src */ "%s" /* tos */ @@ -5033,7 +5068,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi route->metric, route->mss, nmp_utils_ip_config_source_to_string (route->rt_source, s_source, sizeof (s_source)), - route->rt_cloned ? " cloned" : "", + _rtm_flags_to_string_full (str_rtm_flags, sizeof (str_rtm_flags), route->r_rtm_flags), route->scope_inv ? " scope " : "", route->scope_inv ? (nm_platform_route_scope2str (nm_platform_route_scope_inv (route->scope_inv), str_scope, sizeof (str_scope))) : "", route->pref_src ? " pref-src " : "", @@ -5069,6 +5104,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi char str_pref2[30]; char str_dev[TO_STRING_DEV_BUF_SIZE], s_source[50]; char str_window[32], str_cwnd[32], str_initcwnd[32], str_initrwnd[32], str_mtu[32]; + char str_rtm_flags[_RTM_FLAGS_TO_STRING_MAXLEN]; if (!nm_utils_to_string_buffer_init_null (route, &buf, &len)) return buf; @@ -5092,7 +5128,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi " mss %"G_GUINT32_FORMAT " rt-src %s" /* protocol */ "%s" /* source */ - "%s" /* cloned */ + "%s" /* rtm_flags */ "%s%s" /* pref-src */ "%s" /* window */ "%s" /* cwnd */ @@ -5112,7 +5148,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi route->src_plen || !IN6_IS_ADDR_UNSPECIFIED (&route->src) ? nm_sprintf_buf (s_src_all, " src %s/%u", nm_utils_inet6_ntop (&route->src, s_src), (unsigned) route->src_plen) : "", - route->rt_cloned ? " cloned" : "", + _rtm_flags_to_string_full (str_rtm_flags, sizeof (str_rtm_flags), route->r_rtm_flags), s_pref_src[0] ? " pref-src " : "", s_pref_src[0] ? s_pref_src : "", route->window || route->lock_window ? nm_sprintf_buf (str_window, " window %s%"G_GUINT32_FORMAT, route->lock_window ? "lock " : "", route->window) : "", @@ -5538,6 +5574,7 @@ nm_platform_ip4_route_hash_update (const NMPlatformIP4Route *obj, NMPlatformIPRo obj->initcwnd, obj->initrwnd, obj->mtu, + obj->r_rtm_flags & RTNH_F_ONLINK, NM_HASH_COMBINE_BOOLS (guint8, obj->lock_window, obj->lock_cwnd, @@ -5563,8 +5600,8 @@ nm_platform_ip4_route_hash_update (const NMPlatformIP4Route *obj, NMPlatformIPRo obj->initcwnd, obj->initrwnd, obj->mtu, + obj->r_rtm_flags & (RTM_F_CLONED | RTNH_F_ONLINK), NM_HASH_COMBINE_BOOLS (guint8, - obj->rt_cloned, obj->lock_window, obj->lock_cwnd, obj->lock_initcwnd, @@ -5589,8 +5626,8 @@ nm_platform_ip4_route_hash_update (const NMPlatformIP4Route *obj, NMPlatformIPRo obj->initcwnd, obj->initrwnd, obj->mtu, + obj->r_rtm_flags, NM_HASH_COMBINE_BOOLS (guint8, - obj->rt_cloned, obj->lock_window, obj->lock_cwnd, obj->lock_initcwnd, @@ -5627,6 +5664,8 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route NM_CMP_FIELD (a, b, initcwnd); NM_CMP_FIELD (a, b, initrwnd); NM_CMP_FIELD (a, b, mtu); + NM_CMP_DIRECT (a->r_rtm_flags & RTNH_F_ONLINK, + b->r_rtm_flags & RTNH_F_ONLINK); NM_CMP_FIELD_UNSAFE (a, b, lock_window); NM_CMP_FIELD_UNSAFE (a, b, lock_cwnd); NM_CMP_FIELD_UNSAFE (a, b, lock_initcwnd); @@ -5660,7 +5699,11 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route } NM_CMP_FIELD (a, b, mss); NM_CMP_FIELD (a, b, pref_src); - NM_CMP_FIELD_UNSAFE (a, b, rt_cloned); + if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { + NM_CMP_DIRECT (a->r_rtm_flags & (RTM_F_CLONED | RTNH_F_ONLINK), + b->r_rtm_flags & (RTM_F_CLONED | RTNH_F_ONLINK)); + } else + NM_CMP_FIELD (a, b, r_rtm_flags); NM_CMP_FIELD (a, b, tos); NM_CMP_FIELD_UNSAFE (a, b, lock_window); NM_CMP_FIELD_UNSAFE (a, b, lock_cwnd); @@ -5717,8 +5760,8 @@ nm_platform_ip6_route_hash_update (const NMPlatformIP6Route *obj, NMPlatformIPRo obj->src_plen, nmp_utils_ip_config_source_round_trip_rtprot (obj->rt_source), obj->mss, + obj->r_rtm_flags & RTM_F_CLONED, NM_HASH_COMBINE_BOOLS (guint8, - obj->rt_cloned, obj->lock_window, obj->lock_cwnd, obj->lock_initcwnd, @@ -5744,8 +5787,8 @@ nm_platform_ip6_route_hash_update (const NMPlatformIP6Route *obj, NMPlatformIPRo obj->src_plen, obj->rt_source, obj->mss, + obj->r_rtm_flags, NM_HASH_COMBINE_BOOLS (guint8, - obj->rt_cloned, obj->lock_window, obj->lock_cwnd, obj->lock_initcwnd, @@ -5810,7 +5853,11 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route NM_CMP_FIELD (a, b, rt_source); } NM_CMP_FIELD (a, b, mss); - NM_CMP_FIELD_UNSAFE (a, b, rt_cloned); + if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { + NM_CMP_DIRECT (a->r_rtm_flags & RTM_F_CLONED, + b->r_rtm_flags & RTM_F_CLONED); + } else + NM_CMP_FIELD (a, b, r_rtm_flags); NM_CMP_FIELD_UNSAFE (a, b, lock_window); NM_CMP_FIELD_UNSAFE (a, b, lock_cwnd); NM_CMP_FIELD_UNSAFE (a, b, lock_initcwnd); diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index d155c1092e..3336642b8b 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -375,13 +375,6 @@ typedef union { \ guint8 plen; \ \ - /* the route has rtm_flags set to RTM_F_CLONED. Such a route - * is hidden by platform and does not exist from the point-of-view - * of platform users. This flag is internal to track those hidden - * routes. Such a route is not alive, according to nmp_object_is_alive(). */ \ - bool rt_cloned:1; \ - \ - \ /* RTA_METRICS: * * For IPv4 routes, these properties are part of their @@ -401,6 +394,18 @@ typedef union { bool lock_initrwnd:1; \ bool lock_mtu:1; \ \ + /* rtnh_flags + * + * Routes with rtm_flags RTM_F_CLONED are hidden by platform and + * do not exist from the point-of-view of platform users. + * Such a route is not alive, according to nmp_object_is_alive(). + * + * XXX: currently we ignore all flags except RTM_F_CLONED + * and RTNH_F_ONLINK for IPv4. + * We also may not properly consider the flags as part of the ID + * in route-cmp. */ \ + unsigned r_rtm_flags; \ + \ /* RTA_METRICS.RTAX_ADVMSS (iproute2: advmss) */ \ guint32 mss; \ \ @@ -441,23 +446,11 @@ typedef struct { }; } NMPlatformIPRoute; -#if _NM_CC_SUPPORT_GENERIC -#define NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route) \ - (_Generic ((route), \ - const NMPlatformIPRoute *: ((const NMPlatformIPRoute *) (route))->plen, \ - NMPlatformIPRoute *: ((const NMPlatformIPRoute *) (route))->plen, \ - const NMPlatformIPXRoute *: ((const NMPlatformIPRoute *) (route))->plen, \ - NMPlatformIPXRoute *: ((const NMPlatformIPRoute *) (route))->plen, \ - const NMPlatformIP4Route *: ((const NMPlatformIPRoute *) (route))->plen, \ - NMPlatformIP4Route *: ((const NMPlatformIPRoute *) (route))->plen, \ - const NMPlatformIP6Route *: ((const NMPlatformIPRoute *) (route))->plen, \ - NMPlatformIP6Route *: ((const NMPlatformIPRoute *) (route))->plen, \ - const void *: ((const NMPlatformIPRoute *) (route))->plen, \ - void *: ((const NMPlatformIPRoute *) (route))->plen) == 0) -#else +#define NM_PLATFORM_IP_ROUTE_CAST(route) \ + NM_CONSTCAST (NMPlatformIPRoute, (route), NMPlatformIPXRoute, NMPlatformIP4Route, NMPlatformIP6Route) + #define NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route) \ - ( ((const NMPlatformIPRoute *) (route))->plen <= 0 ) -#endif + (NM_PLATFORM_IP_ROUTE_CAST (route)->plen <= 0) struct _NMPlatformIP4Route { __NMPlatformIPRoute_COMMON; diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index a860070545..0c951dd4fc 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -1170,7 +1170,8 @@ _vt_cmd_obj_is_alive_ipx_route (const NMPObject *obj) * Instead we create a dead object, and nmp_cache_update_netlink() * will remove the old version of the update. **/ - return obj->object.ifindex > 0 && !obj->ip_route.rt_cloned; + return obj->object.ifindex > 0 + && !NM_FLAGS_HAS (obj->ip_route.r_rtm_flags, RTM_F_CLONED); } gboolean diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c index 2c00fadaab..04f4ff494a 100644 --- a/src/platform/tests/test-route.c +++ b/src/platform/tests/test-route.c @@ -31,6 +31,42 @@ #define EX NMTSTP_ENV1_EX static void +_wait_for_ipv4_addr_device_route (NMPlatform *platform, + gint64 timeout_ms, + int ifindex, + in_addr_t addr, + guint8 plen) +{ + /* Wait that the addresses gets a device-route. After adding a address, + * the device route is not added immediately. It takes a moment... */ + + addr = nm_utils_ip4_address_clear_host_address (addr, plen); + NMTST_WAIT_ASSERT (400, { + NMDedupMultiIter iter; + NMPLookup lookup; + const NMPObject *o; + + nmp_cache_iter_for_each (&iter, + nm_platform_lookup (platform, + nmp_lookup_init_addrroute (&lookup, + NMP_OBJECT_TYPE_IP4_ROUTE, + ifindex)), + &o) { + const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE (o); + + if ( r->plen == plen + && addr == nm_utils_ip4_address_clear_host_address (r->network, plen) + && r->metric == 0 + && r->scope_inv == nm_platform_route_scope_inv (RT_SCOPE_LINK) + && r->rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL) + return; + } + nmtstp_assert_wait_for_signal (platform, + (nmtst_wait_end_us - g_get_monotonic_time ()) / 1000); + }); +} + +static void _wait_for_ipv6_addr_non_tentative (NMPlatform *platform, gint64 timeout_ms, int ifindex, @@ -44,7 +80,7 @@ _wait_for_ipv6_addr_non_tentative (NMPlatform *platform, * small amount of time, which prevents the immediate addition of the route * with RTA_PREFSRC */ - NMTST_WAIT_ASSERT (400, { + NMTST_WAIT_ASSERT (timeout_ms, { gboolean should_wait = FALSE; const NMPlatformIP6Address *plt_addr; @@ -63,7 +99,6 @@ _wait_for_ipv6_addr_non_tentative (NMPlatform *platform, }); } - static void ip4_route_callback (NMPlatform *platform, int obj_type_i, int ifindex, const NMPlatformIP4Route *received, int change_type_i, SignalData *data) { @@ -417,7 +452,7 @@ test_ip_route_get (void) g_assert (!NMP_OBJECT_IS_STACKINIT (route)); g_assert (route->parent._ref_count == 1); r = NMP_OBJECT_CAST_IP4_ROUTE (route); - g_assert (r->rt_cloned); + g_assert (NM_FLAGS_HAS (r->r_rtm_flags, RTM_F_CLONED)); g_assert (r->ifindex == ifindex); g_assert (r->network == a); g_assert (r->plen == 32); @@ -448,63 +483,114 @@ test_ip4_zero_gateway (void) } static void -test_ip4_route_options (void) +test_ip4_route_options (gconstpointer test_data) { - int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - NMPlatformIP4Route route = { }; - in_addr_t network; - GPtrArray *routes; - NMPlatformIP4Route rts[1]; + const int TEST_IDX = GPOINTER_TO_INT (test_data); + const int IFINDEX = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); + gs_unref_ptrarray GPtrArray *routes = NULL; +#define RTS_MAX 3 + NMPlatformIP4Route rts_add[RTS_MAX] = { }; + NMPlatformIP4Route rts_cmp[RTS_MAX] = { }; + NMPlatformIP4Address addr[1] = { }; + guint i; + guint rts_n = 0; + guint addr_n = 0; - inet_pton (AF_INET, "172.16.1.0", &network); + switch (TEST_IDX) { + case 1: + rts_add[rts_n++] = ((NMPlatformIP4Route) { + .ifindex = IFINDEX, + .rt_source = NM_IP_CONFIG_SOURCE_USER, + .network = nmtst_inet4_from_string ("172.16.1.0"), + .plen = 24, + .metric = 20, + .tos = 0x28, + .window = 10000, + .cwnd = 16, + .initcwnd = 30, + .initrwnd = 50, + .mtu = 1350, + .lock_cwnd = TRUE, + }); + break; + case 2: + addr[addr_n++] = ((NMPlatformIP4Address) { + .ifindex = IFINDEX, + .address = nmtst_inet4_from_string ("172.16.1.5"), + .peer_address = nmtst_inet4_from_string ("172.16.1.5"), + .plen = 24, + .lifetime = NM_PLATFORM_LIFETIME_PERMANENT, + .preferred = NM_PLATFORM_LIFETIME_PERMANENT, + .n_ifa_flags = 0, + }); + rts_add[rts_n++] = ((NMPlatformIP4Route) { + .ifindex = IFINDEX, + .rt_source = NM_IP_CONFIG_SOURCE_USER, + .network = nmtst_inet4_from_string ("172.17.1.0"), + .gateway = nmtst_inet4_from_string ("172.16.1.1"), + .plen = 24, + .metric = 20, + }); + rts_add[rts_n++] = ((NMPlatformIP4Route) { + .ifindex = IFINDEX, + .rt_source = NM_IP_CONFIG_SOURCE_USER, + .network = nmtst_inet4_from_string ("172.19.1.0"), + .gateway = nmtst_inet4_from_string ("172.18.1.1"), + .r_rtm_flags = RTNH_F_ONLINK, + .plen = 24, + .metric = 20, + }); + break; + default: + g_assert_not_reached (); + break; + } + g_assert (rts_n <= G_N_ELEMENTS (rts_add)); + g_assert (addr_n <= G_N_ELEMENTS (addr)); - route.ifindex = ifindex; - route.rt_source = NM_IP_CONFIG_SOURCE_USER; - route.network = network; - route.plen = 24; - route.metric = 20; - route.tos = 0x28; - route.window = 10000; - route.cwnd = 16; - route.initcwnd = 30; - route.initrwnd = 50; - route.mtu = 1350; - route.lock_cwnd = TRUE; + for (i = 0; i < addr_n; i++) { + const NMPlatformIP4Address *a = &addr[i]; + + g_assert (a->ifindex == IFINDEX); + g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, + a->ifindex, + a->address, + a->plen, + a->peer_address, + a->lifetime, + a->preferred, + a->n_ifa_flags, + a->label)); + if (a->peer_address == a->address) + _wait_for_ipv4_addr_device_route (NM_PLATFORM_GET, 200, a->ifindex, a->address, a->plen); + } - g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &route) == NM_PLATFORM_ERROR_SUCCESS); + for (i = 0; i < rts_n; i++) + g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &rts_add[i]) == NM_PLATFORM_ERROR_SUCCESS); - /* Test route listing */ - routes = nmtstp_ip4_route_get_all (NM_PLATFORM_GET, ifindex); - memset (rts, 0, sizeof (rts)); - rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); - rts[0].scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK); - rts[0].network = network; - rts[0].plen = 24; - rts[0].ifindex = ifindex; - rts[0].metric = 20; - rts[0].tos = 0x28; - rts[0].window = 10000; - rts[0].cwnd = 16; - rts[0].initcwnd = 30; - rts[0].initrwnd = 50; - rts[0].mtu = 1350; - rts[0].lock_cwnd = TRUE; - g_assert_cmpint (routes->len, ==, 1); - nmtst_platform_ip4_routes_equal_aptr ((const NMPObject *const*) routes->pdata, rts, routes->len, TRUE); + for (i = 0; i < rts_n; i++) { + rts_cmp[i] = rts_add[i]; + nm_platform_ip_route_normalize (AF_INET, NM_PLATFORM_IP_ROUTE_CAST (&rts_cmp[i])); + } - /* Remove route */ - g_assert (nm_platform_ip_route_delete (NM_PLATFORM_GET, routes->pdata[0])); + routes = nmtstp_ip4_route_get_all (NM_PLATFORM_GET, IFINDEX); + g_assert_cmpint (routes->len, ==, rts_n); + nmtst_platform_ip4_routes_equal_aptr ((const NMPObject *const*) routes->pdata, rts_cmp, routes->len, TRUE); - g_ptr_array_unref (routes); + for (i = 0; i < rts_n; i++) { + g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, IFINDEX, + rts_add[i].network, rts_add[i].plen, + rts_add[i].metric)); + } +#undef RTS_MAX } - static void test_ip6_route_options (gconstpointer test_data) { const int TEST_IDX = GPOINTER_TO_INT (test_data); const int IFINDEX = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - GPtrArray *routes; + gs_unref_ptrarray GPtrArray *routes = NULL; #define RTS_MAX 3 NMPlatformIP6Route rts_add[RTS_MAX] = { }; NMPlatformIP6Route rts_cmp[RTS_MAX] = { }; @@ -582,6 +668,8 @@ test_ip6_route_options (gconstpointer test_data) default: g_assert_not_reached (); } + g_assert (rts_n <= G_N_ELEMENTS (rts_add)); + g_assert (addr_n <= G_N_ELEMENTS (addr)); for (i = 0; i < addr_n; i++) { g_assert (addr[i].ifindex == IFINDEX); @@ -595,28 +683,19 @@ test_ip6_route_options (gconstpointer test_data) addr[i].preferred, addr[i].n_ifa_flags)); } - _wait_for_ipv6_addr_non_tentative (NM_PLATFORM_GET, 400, IFINDEX, addr_n, addr_in6); for (i = 0; i < rts_n; i++) g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &rts_add[i]) == NM_PLATFORM_ERROR_SUCCESS); - routes = nmtstp_ip6_route_get_all (NM_PLATFORM_GET, IFINDEX); - switch (TEST_IDX) { - case 1: - case 2: - case 3: - for (i = 0; i < rts_n; i++) { - rts_cmp[i] = rts_add[i]; - rts_cmp[i].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); - } - break; - default: - g_assert_not_reached (); + for (i = 0; i < rts_n; i++) { + rts_cmp[i] = rts_add[i]; + nm_platform_ip_route_normalize (AF_INET6, NM_PLATFORM_IP_ROUTE_CAST (&rts_cmp[i])); } + + routes = nmtstp_ip6_route_get_all (NM_PLATFORM_GET, IFINDEX); g_assert_cmpint (routes->len, ==, rts_n); nmtst_platform_ip6_routes_equal_aptr ((const NMPObject *const*) routes->pdata, rts_cmp, routes->len, TRUE); - g_ptr_array_unref (routes); for (i = 0; i < rts_n; i++) { g_assert (nmtstp_platform_ip6_route_delete (NM_PLATFORM_GET, IFINDEX, @@ -631,6 +710,7 @@ test_ip6_route_options (gconstpointer test_data) rts_add[i].network, rts_add[i].plen); } +#undef RTS_MAX } /*****************************************************************************/ @@ -771,7 +851,9 @@ _nmtstp_setup_tests (void) add_test_func ("/route/ip4", test_ip4_route); add_test_func ("/route/ip6", test_ip6_route); add_test_func ("/route/ip4_metric0", test_ip4_route_metric0); - add_test_func ("/route/ip4_options", test_ip4_route_options); + add_test_func_data ("/route/ip4_options/1", test_ip4_route_options, GINT_TO_POINTER (1)); + if (nmtstp_is_root_test ()) + add_test_func_data ("/route/ip4_options/2", test_ip4_route_options, GINT_TO_POINTER (2)); add_test_func_data ("/route/ip6_options/1", test_ip6_route_options, GINT_TO_POINTER (1)); add_test_func_data ("/route/ip6_options/2", test_ip6_route_options, GINT_TO_POINTER (2)); add_test_func_data ("/route/ip6_options/3", test_ip6_route_options, GINT_TO_POINTER (3)); diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index 66add713b0..b1cf80ad91 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -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: @@ -601,42 +603,45 @@ parse_route_line (const char *line, char buf1[256]; char buf2[256]; ParseLineInfo infos[] = { - [PARSE_LINE_ATTR_ROUTE_TABLE] = { .key = NM_IP_ROUTE_ATTRIBUTE_TABLE, - .type = PARSE_LINE_TYPE_UINT32, }, - [PARSE_LINE_ATTR_ROUTE_SRC] = { .key = NM_IP_ROUTE_ATTRIBUTE_SRC, - .type = PARSE_LINE_TYPE_ADDR, }, - [PARSE_LINE_ATTR_ROUTE_FROM] = { .key = NM_IP_ROUTE_ATTRIBUTE_FROM, - .type = PARSE_LINE_TYPE_ADDR_WITH_PREFIX, - .disabled = (addr_family != AF_INET6), }, - [PARSE_LINE_ATTR_ROUTE_TOS] = { .key = NM_IP_ROUTE_ATTRIBUTE_TOS, - .type = PARSE_LINE_TYPE_UINT8, - .int_base_16 = TRUE, - .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, - .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, }, - [PARSE_LINE_ATTR_ROUTE_INITCWND] = { .key = NM_IP_ROUTE_ATTRIBUTE_INITCWND, - .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, }, - [PARSE_LINE_ATTR_ROUTE_INITRWND] = { .key = NM_IP_ROUTE_ATTRIBUTE_INITRWND, - .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, }, - [PARSE_LINE_ATTR_ROUTE_MTU] = { .key = NM_IP_ROUTE_ATTRIBUTE_MTU, - .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, }, - - [PARSE_LINE_ATTR_ROUTE_TO] = { .key = "to", - .type = PARSE_LINE_TYPE_ADDR_WITH_PREFIX, - .disabled = (options_route != NULL), }, - [PARSE_LINE_ATTR_ROUTE_VIA] = { .key = "via", - .type = PARSE_LINE_TYPE_ADDR, - .disabled = (options_route != NULL), }, - [PARSE_LINE_ATTR_ROUTE_METRIC] = { .key = "metric", - .type = PARSE_LINE_TYPE_UINT32, - .disabled = (options_route != NULL), }, - - [PARSE_LINE_ATTR_ROUTE_DEV] = { .key = "dev", - .type = PARSE_LINE_TYPE_IFNAME, - .ignore = TRUE, - .disabled = (options_route != NULL), }, + [PARSE_LINE_ATTR_ROUTE_TABLE] = { .key = NM_IP_ROUTE_ATTRIBUTE_TABLE, + .type = PARSE_LINE_TYPE_UINT32, }, + [PARSE_LINE_ATTR_ROUTE_SRC] = { .key = NM_IP_ROUTE_ATTRIBUTE_SRC, + .type = PARSE_LINE_TYPE_ADDR, }, + [PARSE_LINE_ATTR_ROUTE_FROM] = { .key = NM_IP_ROUTE_ATTRIBUTE_FROM, + .type = PARSE_LINE_TYPE_ADDR_WITH_PREFIX, + .disabled = (addr_family != AF_INET6), }, + [PARSE_LINE_ATTR_ROUTE_TOS] = { .key = NM_IP_ROUTE_ATTRIBUTE_TOS, + .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, + .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, }, + [PARSE_LINE_ATTR_ROUTE_INITCWND] = { .key = NM_IP_ROUTE_ATTRIBUTE_INITCWND, + .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, }, + [PARSE_LINE_ATTR_ROUTE_INITRWND] = { .key = NM_IP_ROUTE_ATTRIBUTE_INITRWND, + .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, }, + [PARSE_LINE_ATTR_ROUTE_MTU] = { .key = NM_IP_ROUTE_ATTRIBUTE_MTU, + .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, }, + + [PARSE_LINE_ATTR_ROUTE_TO] = { .key = "to", + .type = PARSE_LINE_TYPE_ADDR_WITH_PREFIX, + .disabled = (options_route != NULL), }, + [PARSE_LINE_ATTR_ROUTE_VIA] = { .key = "via", + .type = PARSE_LINE_TYPE_ADDR, + .disabled = (options_route != NULL), }, + [PARSE_LINE_ATTR_ROUTE_METRIC] = { .key = "metric", + .type = PARSE_LINE_TYPE_UINT32, + .disabled = (options_route != NULL), }, + + [PARSE_LINE_ATTR_ROUTE_DEV] = { .key = "dev", + .type = PARSE_LINE_TYPE_IFNAME, + .ignore = TRUE, + .disabled = (options_route != NULL), }, }; nm_assert (line); @@ -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; diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index 5c8de7d12a..e413da1ef4 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -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)); diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected new file mode 100644 index 0000000000..c0e47c48d8 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected @@ -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 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes index 10a63b674f..8d6aaac2f6 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes @@ -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" diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index 5044a2d7d8..17b6ca4940 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -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, - TEST_SCRATCH_DIR "/network-scripts/", - &testfile); + _writer_new_connection_reread (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &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)); - reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL); + nmtst_assert_connection_equals (connection, TRUE, reread, FALSE); routefile = utils_get_route_path (testfile); - - nmtst_assert_connection_equals (connection, TRUE, reread, FALSE); } static void diff --git a/src/tests/test-ip4-config.c b/src/tests/test-ip4-config.c index 649b443f2a..4c3c344e46 100644 --- a/src/tests/test-ip4-config.c +++ b/src/tests/test-ip4-config.c @@ -38,6 +38,8 @@ build_test_config (void) /* Build up the config to subtract */ config = nmtst_ip4_config_new (1); + nm_assert (NM_IP_CONFIG_CAST (config)); + addr = *nmtst_platform_ip4_address ("192.168.1.10", "1.2.3.4", 24); nm_ip4_config_add_address (config, &addr); |