core: use router preference for IPv6 routes
For routes and the default-route from NDisc, set the router preference RTA_PREF. Also, previously, we would only configure one IPv6 default-route. That by itself was not really a problem, as long as NetworkManager would always make sure that it configured the route to the ~best~ router. Actually, NM should have done that already. It keeps the list of gateways sorted, and prefers them according to their preference. But maybe it didn't, so we have bug rh#1445417 (??). Change that by configuring a default-route for all gateways, with appropriate router prefrence. In case, kernel doesn't support RTA_PREF yet, only configure all routes that share the same maxiumum preference. https://bugzilla.redhat.com/show_bug.cgi?id=1445417
This commit is contained in:
@@ -7397,7 +7397,9 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
|
|||||||
rdata->routes,
|
rdata->routes,
|
||||||
rdata->routes_n,
|
rdata->routes_n,
|
||||||
nm_device_get_route_table (self, AF_INET6, TRUE),
|
nm_device_get_route_table (self, AF_INET6, TRUE),
|
||||||
nm_device_get_route_metric (self, AF_INET6));
|
nm_device_get_route_metric (self, AF_INET6),
|
||||||
|
nm_platform_check_kernel_support (nm_device_get_platform (self),
|
||||||
|
NM_PLATFORM_KERNEL_SUPPORT_RTA_PREF));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed & NM_NDISC_CONFIG_DNS_SERVERS) {
|
if (changed & NM_NDISC_CONFIG_DNS_SERVERS) {
|
||||||
|
@@ -208,7 +208,9 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
|
|||||||
rdata->routes,
|
rdata->routes,
|
||||||
rdata->routes_n,
|
rdata->routes_n,
|
||||||
RT_TABLE_MAIN,
|
RT_TABLE_MAIN,
|
||||||
global_opt.priority_v6);
|
global_opt.priority_v6,
|
||||||
|
nm_platform_check_kernel_support (NM_PLATFORM_GET,
|
||||||
|
NM_PLATFORM_KERNEL_SUPPORT_RTA_PREF));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed & NM_NDISC_CONFIG_DHCP_LEVEL) {
|
if (changed & NM_NDISC_CONFIG_DHCP_LEVEL) {
|
||||||
|
@@ -1769,7 +1769,8 @@ nm_ip6_config_reset_routes_ndisc (NMIP6Config *self,
|
|||||||
const NMNDiscRoute *routes,
|
const NMNDiscRoute *routes,
|
||||||
guint routes_n,
|
guint routes_n,
|
||||||
guint32 route_table,
|
guint32 route_table,
|
||||||
guint32 route_metric)
|
guint32 route_metric,
|
||||||
|
gboolean kernel_support_rta_pref)
|
||||||
{
|
{
|
||||||
NMIP6ConfigPrivate *priv;
|
NMIP6ConfigPrivate *priv;
|
||||||
guint i;
|
guint i;
|
||||||
@@ -1800,6 +1801,8 @@ nm_ip6_config_reset_routes_ndisc (NMIP6Config *self,
|
|||||||
r->rt_source = NM_IP_CONFIG_SOURCE_NDISC;
|
r->rt_source = NM_IP_CONFIG_SOURCE_NDISC;
|
||||||
r->table_coerced = nm_platform_route_table_coerce (route_table);
|
r->table_coerced = nm_platform_route_table_coerce (route_table);
|
||||||
r->metric = route_metric;
|
r->metric = route_metric;
|
||||||
|
r->rt_pref = ndisc_route->preference;
|
||||||
|
nm_assert ((NMIcmpv6RouterPref) r->rt_pref == ndisc_route->preference);
|
||||||
|
|
||||||
if (_nm_ip_config_add_obj (priv->multi_idx,
|
if (_nm_ip_config_add_obj (priv->multi_idx,
|
||||||
&priv->idx_ip6_routes_,
|
&priv->idx_ip6_routes_,
|
||||||
@@ -1814,28 +1817,40 @@ nm_ip6_config_reset_routes_ndisc (NMIP6Config *self,
|
|||||||
new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, obj_new);
|
new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, obj_new);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use the first gateway as ordered in neighbor discovery cache. */
|
|
||||||
if (gateways_n) {
|
if (gateways_n) {
|
||||||
const NMPObject *obj_new;
|
const NMPObject *obj_new;
|
||||||
const NMPlatformIP6Route r = {
|
NMPlatformIP6Route r = {
|
||||||
.rt_source = NM_IP_CONFIG_SOURCE_NDISC,
|
.rt_source = NM_IP_CONFIG_SOURCE_NDISC,
|
||||||
.ifindex = priv->ifindex,
|
.ifindex = priv->ifindex,
|
||||||
.gateway = gateways[0].address,
|
|
||||||
.table_coerced = nm_platform_route_table_coerce (route_table),
|
.table_coerced = nm_platform_route_table_coerce (route_table),
|
||||||
.metric = route_metric,
|
.metric = route_metric,
|
||||||
};
|
};
|
||||||
|
const NMIcmpv6RouterPref first_pref = gateways[0].preference;
|
||||||
|
|
||||||
if (_nm_ip_config_add_obj (priv->multi_idx,
|
for (i = 0; i < gateways_n; i++) {
|
||||||
&priv->idx_ip6_routes_,
|
r.gateway = gateways[i].address;
|
||||||
priv->ifindex,
|
r.rt_pref = gateways[i].preference;
|
||||||
NULL,
|
nm_assert ((NMIcmpv6RouterPref) r.rt_pref == gateways[i].preference);
|
||||||
(const NMPlatformObject *) &r,
|
if (_nm_ip_config_add_obj (priv->multi_idx,
|
||||||
FALSE,
|
&priv->idx_ip6_routes_,
|
||||||
TRUE,
|
priv->ifindex,
|
||||||
NULL,
|
NULL,
|
||||||
&obj_new))
|
(const NMPlatformObject *) &r,
|
||||||
changed = TRUE;
|
FALSE,
|
||||||
new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, obj_new);
|
TRUE,
|
||||||
|
NULL,
|
||||||
|
&obj_new))
|
||||||
|
changed = TRUE;
|
||||||
|
new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, obj_new);
|
||||||
|
|
||||||
|
if ( first_pref != gateways[i].preference
|
||||||
|
&& !kernel_support_rta_pref) {
|
||||||
|
/* We are unable to configure a router preference. Hence, we skip all gateways
|
||||||
|
* with a different preference from the first gateway. Note, that the gateways
|
||||||
|
* are sorted in order of highest to lowest preference. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nm_dedup_multi_index_dirty_remove_idx (priv->multi_idx, &priv->idx_ip6_routes, FALSE) > 0)
|
if (nm_dedup_multi_index_dirty_remove_idx (priv->multi_idx, &priv->idx_ip6_routes, FALSE) > 0)
|
||||||
|
@@ -219,6 +219,7 @@ void nm_ip6_config_reset_routes_ndisc (NMIP6Config *self,
|
|||||||
const struct _NMNDiscRoute *routes,
|
const struct _NMNDiscRoute *routes,
|
||||||
guint routes_n,
|
guint routes_n,
|
||||||
guint32 route_table,
|
guint32 route_table,
|
||||||
guint32 route_metric);
|
guint32 route_metric,
|
||||||
|
gboolean kernel_support_rta_pref);
|
||||||
|
|
||||||
#endif /* __NETWORKMANAGER_IP6_CONFIG_H__ */
|
#endif /* __NETWORKMANAGER_IP6_CONFIG_H__ */
|
||||||
|
Reference in New Issue
Block a user