Antonio Cardace 2020-07-08 15:11:51 +02:00
commit 5830694fe3
No known key found for this signature in database
GPG key ID: 6BF80ABD43E377D3
5 changed files with 86 additions and 27 deletions

View file

@ -207,4 +207,5 @@ NM_UTILS_ENUM2STR_DEFINE (nm_utils_route_type2str, guint8,
NM_UTILS_ENUM2STR (RTN_THROW, "throw"),
NM_UTILS_ENUM2STR (RTN_UNICAST, "unicast"),
NM_UTILS_ENUM2STR (RTN_UNREACHABLE, "unreachable"),
NM_UTILS_ENUM2STR (RTN_UNSPEC, "unspecified"),
);

View file

@ -411,8 +411,8 @@ typedef struct _NMDevicePrivate {
bool v4_route_table_initialized:1;
bool v6_route_table_initialized:1;
bool v4_route_table_full_sync_before:1;
bool v6_route_table_full_sync_before:1;
bool v4_route_table_all_sync_before:1;
bool v6_route_table_all_sync_before:1;
NMDeviceAutoconnectBlockedFlags autoconnect_blocked_flags:5;
@ -2737,34 +2737,59 @@ _get_route_table_sync_mode_stateful (NMDevice *self,
int addr_family)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
gboolean full_sync_now;
gboolean full_sync_eff;
NMDedupMultiIter ipconf_iter;
gboolean all_sync_now;
gboolean all_sync_eff;
full_sync_now = _get_route_table (self, addr_family) != 0u;
all_sync_now = _get_route_table (self, addr_family) != 0u;
if (full_sync_now)
full_sync_eff = TRUE;
if (!all_sync_now) {
/* If there's a local route switch to all-sync in order
* to properly manage the local table */
if (addr_family == AF_INET) {
const NMPlatformIP4Route *route;
nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, priv->con_ip_config_4, &route) {
if (nm_platform_route_type_uncoerce (route->type_coerced) == RTN_LOCAL) {
all_sync_now = TRUE;
break;
}
}
} else {
const NMPlatformIP6Route *route;
nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, priv->con_ip_config_6, &route) {
if (nm_platform_route_type_uncoerce (route->type_coerced) == RTN_LOCAL) {
all_sync_now = TRUE;
break;
}
}
}
}
if (all_sync_now)
all_sync_eff = TRUE;
else {
/* When we change from full-sync to no full-sync, we do a last full-sync one
* more time. For that, we determine the effective full-state based on the
* cached/previous full-sync flag.
/* When we change from all-sync to no all-sync, we do a last all-sync one
* more time. For that, we determine the effective all-state based on the
* cached/previous all-sync flag.
*
* The purpose of this is to support reapply of route-table (and thus the
* full-sync mode). If reapply toggles from full-sync to no-full-sync, we must
* all-sync mode). If reapply toggles from all-sync to no-all-sync, we must
* sync one last time. */
if (addr_family == AF_INET)
full_sync_eff = priv->v4_route_table_full_sync_before;
all_sync_eff = priv->v4_route_table_all_sync_before;
else
full_sync_eff = priv->v6_route_table_full_sync_before;
all_sync_eff = priv->v6_route_table_all_sync_before;
}
if (addr_family == AF_INET)
priv->v4_route_table_full_sync_before = full_sync_now;
priv->v4_route_table_all_sync_before = all_sync_now;
else
priv->v6_route_table_full_sync_before = full_sync_now;
priv->v6_route_table_all_sync_before = all_sync_now;
return full_sync_eff
? NM_IP_ROUTE_TABLE_SYNC_MODE_FULL
return all_sync_eff
? NM_IP_ROUTE_TABLE_SYNC_MODE_ALL
: NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN;
}
@ -13244,7 +13269,8 @@ nm_device_set_ip_config (NMDevice *self,
if (IS_IPv4) {
success = nm_ip4_config_commit (NM_IP4_CONFIG (new_config),
nm_device_get_platform (self),
_get_route_table_sync_mode_stateful (self, addr_family));
_get_route_table_sync_mode_stateful (self,
AF_INET));
nm_platform_ip4_dev_route_blacklist_set (nm_device_get_platform (self),
nm_ip_config_get_ifindex (new_config),
ip4_dev_route_blacklist);
@ -13253,7 +13279,8 @@ nm_device_set_ip_config (NMDevice *self,
success = nm_ip6_config_commit (NM_IP6_CONFIG (new_config),
nm_device_get_platform (self),
_get_route_table_sync_mode_stateful (self, addr_family),
_get_route_table_sync_mode_stateful (self,
AF_INET6),
&temporary_not_available);
if (!_rt6_temporary_not_available_set (self, temporary_not_available))
@ -15498,8 +15525,8 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type)
priv->v4_route_table_initialized = FALSE;
priv->v6_route_table_initialized = FALSE;
priv->v4_route_table_full_sync_before = FALSE;
priv->v6_route_table_full_sync_before = FALSE;
priv->v4_route_table_all_sync_before = FALSE;
priv->v6_route_table_all_sync_before = FALSE;
priv->default_route_metric_penalty_ip4_has = FALSE;
priv->default_route_metric_penalty_ip6_has = FALSE;

View file

@ -456,6 +456,24 @@ nm_ip6_config_update_routes_metric (NMIP6Config *self, gint64 metric)
g_object_thaw_notify (G_OBJECT (self));
}
static void
_add_multicast_route6 (NMIP6Config *self, int ifindex)
{
nm_auto_nmpobj NMPObject *r = NULL;
NMPlatformIP6Route *route;
r = nmp_object_new (NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
route = NMP_OBJECT_CAST_IP6_ROUTE (r);
route->ifindex = ifindex;
route->network.s6_addr[0] = 0xffu;
route->plen = 8;
route->table_coerced = nm_platform_route_table_coerce (RT_TABLE_LOCAL);
route->type_coerced = nm_platform_route_type_coerce (RTN_UNICAST);
route->metric = 256;
_add_route (self, r, NULL, NULL);
}
void
nm_ip6_config_add_dependent_routes (NMIP6Config *self,
guint32 route_table,
@ -476,6 +494,9 @@ nm_ip6_config_add_dependent_routes (NMIP6Config *self,
*
* For manually added IPv6 routes, add the device routes explicitly. */
/* Pre-generate multicast route */
_add_multicast_route6 (self, ifindex);
nm_ip_config_iter_ip6_address_for_each (&iter, self, &my_addr) {
NMPlatformIP6Route *route;
gboolean has_peer;

View file

@ -3398,6 +3398,7 @@ rta_multipath_done:
obj = nmp_object_new (is_v4 ? NMP_OBJECT_TYPE_IP4_ROUTE : NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
obj->ip_route.type_coerced = nm_platform_route_type_coerce (rtm->rtm_type);
obj->ip_route.table_coerced = nm_platform_route_table_coerce ( tb[RTA_TABLE]
? nla_get_u32 (tb[RTA_TABLE])
: (guint32) rtm->rtm_table);

View file

@ -4230,9 +4230,18 @@ nm_platform_ip_route_get_prune_list (NMPlatform *self,
} else if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN) {
if (!nm_platform_route_table_is_main (NMP_OBJECT_CAST_IP_ROUTE (obj)->table_coerced))
continue;
} else
} else {
nm_assert (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_ALL);
/* IPv6 routes having metric 0 and routes having rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL
* are entirely managed by kernel, let's not touch them */
if (addr_family == AF_INET6 && NMP_OBJECT_CAST_IP6_ROUTE (obj)->metric == 0)
continue;
if ( nm_platform_route_table_uncoerce (NMP_OBJECT_CAST_IP_ROUTE (obj)->table_coerced, TRUE) == RT_TABLE_LOCAL
&& NMP_OBJECT_CAST_IP_ROUTE (obj)->rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL)
continue;
}
g_ptr_array_add (routes_prune, (gpointer) nmp_object_ref (obj));
}
@ -6082,11 +6091,11 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
char s_network[INET_ADDRSTRLEN], s_gateway[INET_ADDRSTRLEN];
char s_pref_src[INET_ADDRSTRLEN];
char str_dev[TO_STRING_DEV_BUF_SIZE];
char str_type[30];
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];
char str_type[30];
if (!nm_utils_to_string_buffer_init_null (route, &buf, &len))
return buf;
@ -6097,7 +6106,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
_to_string_dev (NULL, route->ifindex, str_dev, sizeof (str_dev));
g_snprintf (buf, len,
"%s" /* type */
"type %s " /* type */
"%s" /* table */
"%s/%d"
" via %s"
@ -6115,7 +6124,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
"%s" /* initrwnd */
"%s" /* mtu */
"",
route->type_coerced ? nm_sprintf_buf (str_type, "type %s ", nm_utils_route_type2str (nm_platform_route_type_uncoerce (route->type_coerced), NULL, 0)) : "",
nm_utils_route_type2str (nm_platform_route_type_uncoerce (route->type_coerced), str_type, sizeof (str_type)),
route->table_coerced ? nm_sprintf_buf (str_table, "table %u ", nm_platform_route_table_uncoerce (route->table_coerced, FALSE)) : "",
s_network,
route->plen,
@ -6185,7 +6194,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi
_to_string_dev (NULL, route->ifindex, str_dev, sizeof (str_dev));
g_snprintf (buf, len,
"%s" /* type */
"type %s " /* type */
"%s" /* table */
"%s/%d"
" via %s"
@ -6203,7 +6212,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi
"%s" /* mtu */
"%s" /* pref */
"",
route->type_coerced ? nm_sprintf_buf (str_type, "type %s ", nm_utils_route_type2str (nm_platform_route_type_uncoerce (route->type_coerced), NULL, 0)) : "",
nm_utils_route_type2str (nm_platform_route_type_uncoerce (route->type_coerced), str_type, sizeof (str_type)),
route->table_coerced ? nm_sprintf_buf (str_table, "table %u ", nm_platform_route_table_uncoerce (route->table_coerced, FALSE)) : "",
s_network,
route->plen,