diff options
| author | Thomas Haller <thaller@redhat.com> | 2014-08-29 00:03:47 +0200 |
|---|---|---|
| committer | Thomas Haller <thaller@redhat.com> | 2014-10-12 22:31:39 +0200 |
| commit | 3f69af3d08b8da490dae72df960ce2c4b756a350 (patch) | |
| tree | 428f3d6fb471c38c37ccdf3b727efc4f3af29fcf | |
| parent | b27e3a378371540b7f729522f44cf4452511a722 (diff) | |
| download | NetworkManager-th/bgo735512_route_metric-1.tar.gz | |
WIP: core: always add default routes on a device just as non-default routesth/bgo735512_route_metric-1
I will add a NMDefaultRouteManager instance. Devices will call
update(manager, device), and the manager will handle all the default
routes.
that is needed, to remove duplicate default routes with the same
metric.
NMPolicy also can check there, who has the default route. signals,
properties, all the great stuff is yet to come...
This class is needed, to move functionality (handling of default routes)
our of NMPolicy (which is overcrowded already).
Signed-off-by: Thomas Haller <thaller@redhat.com>
| -rw-r--r-- | src/Makefile.am | 2 | ||||
| -rw-r--r-- | src/devices/nm-device.c | 64 | ||||
| -rw-r--r-- | src/nm-default-route-manager.c | 330 | ||||
| -rw-r--r-- | src/nm-default-route-manager.h | 56 | ||||
| -rw-r--r-- | src/nm-ip4-config.c | 8 | ||||
| -rw-r--r-- | src/nm-ip6-config.c | 11 | ||||
| -rw-r--r-- | src/nm-policy.c | 31 | ||||
| -rw-r--r-- | src/nm-types.h | 1 |
8 files changed, 494 insertions, 9 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 95df89be74..d97a626f83 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -216,6 +216,8 @@ nm_sources = \ nm-dbus-manager.h \ nm-dcb.c \ nm-dcb.h \ + nm-default-route-manager.c \ + nm-default-route-manager.h \ nm-dhcp4-config.c \ nm-dhcp4-config.h \ nm-dhcp6-config.c \ diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 823bd60dad..58e16dcedd 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -2661,9 +2661,41 @@ ip4_config_merge_and_apply (NMDevice *self, /* Merge user overrides into the composite config */ connection = nm_device_get_connection (self); if (connection) { + NMSettingIP4Config *s_ip4; + guint32 route_metric, mss; + guint32 gw_addr; + NMPlatformIP4Route route; + nm_ip4_config_merge_setting (composite, nm_connection_get_setting_ip4_config (connection), nm_device_get_ip4_route_priority (self)); + + /* add the default route */ + if ( !nm_active_connection_get_assumed (NM_ACTIVE_CONNECTION (nm_device_get_act_request (self))) + && (s_ip4 = nm_connection_get_setting_ip4_config (connection)) + && !nm_setting_ip4_config_get_never_default (s_ip4)) { + + route_metric = nm_device_get_ip4_route_priority (self); + gw_addr = nm_ip4_config_get_gateway (composite); + mss = nm_ip4_config_get_mss (composite); + + memset (&route, 0, sizeof (route)); + route.source = NM_PLATFORM_SOURCE_USER; + route.network = 0; + route.plen = 0; + route.gateway = gw_addr; + route.metric = route_metric; + route.mss = mss; + + nm_ip4_config_add_route (composite, &route); + if ( gw_addr + && !nm_ip4_config_get_direct_route_for_host (composite, gw_addr)) { + route.network = gw_addr; + route.plen = 32; + route.gateway = 0; + nm_ip4_config_add_route (composite, &route); + } + } } /* Allow setting MTU etc */ @@ -3086,9 +3118,41 @@ ip6_config_merge_and_apply (NMDevice *self, /* Merge user overrides into the composite config */ connection = nm_device_get_connection (self); if (connection) { + NMSettingIP6Config *s_ip6; + guint32 route_metric, mss; + const struct in6_addr *gw_addr; + NMPlatformIP6Route route; + nm_ip6_config_merge_setting (composite, nm_connection_get_setting_ip6_config (connection), nm_device_get_ip6_route_priority (self)); + + /* add the default route */ + if ( !nm_active_connection_get_assumed (NM_ACTIVE_CONNECTION (nm_device_get_act_request (self))) + && (s_ip6 = nm_connection_get_setting_ip6_config (connection)) + && !nm_setting_ip6_config_get_never_default (s_ip6)) { + + route_metric = nm_device_get_ip6_route_priority (self); + gw_addr = nm_ip6_config_get_gateway (composite); + mss = nm_ip6_config_get_mss (composite); + + memset (&route, 0, sizeof (route)); + route.source = NM_PLATFORM_SOURCE_USER; + route.network = in6addr_any; + route.plen = 0; + route.gateway = gw_addr ? *gw_addr : in6addr_any; + route.metric = route_metric; + route.mss = mss; + + nm_ip6_config_add_route (composite, &route); + if ( gw_addr + && !nm_ip6_config_get_direct_route_for_host (composite, gw_addr)) { + route.network = *gw_addr; + route.plen = 128; + route.gateway = in6addr_any; + nm_ip6_config_add_route (composite, &route); + } + } } nm_ip6_config_addresses_sort (composite, diff --git a/src/nm-default-route-manager.c b/src/nm-default-route-manager.c new file mode 100644 index 0000000000..fcdc892210 --- /dev/null +++ b/src/nm-default-route-manager.c @@ -0,0 +1,330 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2014 Red Hat, Inc. + */ + + +#include "nm-default-route-manager.h" + +#include "config.h" + +#include "string.h" + +#include "nm-logging.h" +#include "nm-device.h" +#include "nm-platform.h" +#include "nm-ip4-config.h" + +typedef struct { + GPtrArray *entries_ip4; + GPtrArray *entries_ip6; +} NMDefaultRouteManagerPrivate; + +#define NM_DEFAULT_ROUTE_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEFAULT_ROUTE_MANAGER, NMDefaultRouteManagerPrivate)) + +G_DEFINE_TYPE (NMDefaultRouteManager, nm_default_route_manager, G_TYPE_OBJECT) + +enum { + SIGNAL_CHANGED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +/***********************************************************************************/ + +typedef struct { + NMDevice *device; + gulong signal_removed_id; + union { + NMPlatformIPRoute route; + NMPlatformIP4Route route4; + NMPlatformIP6Route route6; + }; + gboolean gw_route_added; +} Entry; + +static void +_entry_free (Entry *entry) +{ + g_signal_handler_disconnect (entry->device, entry->signal_removed_id); + g_object_unref (entry->device); + g_free (entry); +} + +static Entry * +_entry_find_by_device (GPtrArray *entries, NMDevice *device, int *out_idx) +{ + guint i; + + for (i = 0; i < entries->len; i++) { + Entry *e = g_ptr_array_index (entries, i); + + if (e->device == device) { + if (out_idx) + *out_idx = i; + return e; + } + } + if (out_idx) + *out_idx = -1; + return NULL; +} + +static int +_sort_entries_cmp (gconstpointer a, gconstpointer b, gpointer user_data) +{ + const Entry *e_a, *e_b; + guint32 m_a, m_b; + gboolean is_v4 = GPOINTER_TO_INT (user_data); + + e_a = *((const Entry **) a); + e_b = *((const Entry **) b); + + m_a = e_a->route.metric; + m_b = e_b->route.metric; + + if (!is_v4) { + m_a = nm_utils_ip6_route_metric_normalize (m_a); + m_b = nm_utils_ip6_route_metric_normalize (m_b); + } + + if (m_a < m_b) + return -1; + if (m_a > m_b) + return 1; + return 0; +} + +static gboolean +_sort_entries (GPtrArray *entries, gboolean is_v4, gboolean *out_first_entry_changed) +{ + void **original; + gboolean changed = FALSE; + gboolean first_entry_changed = FALSE; + + if (entries->len <= 1) + goto EXIT; + + original = g_new (void *, entries->len); + memcpy (original, entries->pdata, entries->len); + + g_ptr_array_sort_with_data (entries, _sort_entries_cmp, GINT_TO_POINTER (is_v4)); + + if (memcmp (original, entries->pdata, entries->len) == 0) + goto EXIT; + + changed = TRUE; + g_free (original); + + first_entry_changed = original[0] != entries->pdata[0]; + +EXIT: + if (out_first_entry_changed) + *out_first_entry_changed = first_entry_changed; + return changed; +} + +static void +_update_update4 (NMDefaultRouteManager *self, NMDevice *device, const Entry *old_entry, gboolean sync_one) +{ + NMDefaultRouteManagerPrivate *priv = NM_DEFAULT_ROUTE_MANAGER_GET_PRIVATE (self); + Entry *entry; + int idx; + gboolean first_entry_changed, entries_resorted; + + entry = _entry_find_by_device (priv->entries_ip4, device, &idx); + g_return_if_fail (entry); + + nm_log_dbg (LOGD_IP4, "default-route: %s entry %s", old_entry ? "update" : "add", nm_platform_ip4_route_to_string (&entry->route4)); + + entries_resorted = _sort_entries (priv->entries_ip4, TRUE, &first_entry_changed); + + if (sync_one) { + NMIP4Config *ip4_config; + guint32 mss; + + ip4_config = nm_device_get_ip4_config (device); + mss = ip4_config ? nm_ip4_config_get_mss (ip4_config) : 0; + + if (!nm_platform_ip4_route_add (entry->route4.ifindex, NM_PLATFORM_SOURCE_USER, + 0, 0, entry->route4.gateway, + entry->route4.metric, mss)) { + + if (old_entry) { + if (old_entry->gw_route_added) { + + } + } + } + + g_signal_emit (self, signals[SIGNAL_CHANGED], 0, (gboolean) idx == 0); +} + +static void +_update_remove4 (NMDefaultRouteManager *self, NMDevice *device, gboolean sync_one) +{ + NMDefaultRouteManagerPrivate *priv = NM_DEFAULT_ROUTE_MANAGER_GET_PRIVATE (self); + Entry *entry; + int idx; + + entry = _entry_find_by_device (priv->entries_ip4, device, &idx); + g_return_if_fail (entry); + + nm_log_dbg (LOGD_IP4, "default-route: remove entry %s", nm_platform_ip4_route_to_string (&entry->route4)); + + if (sync_one) { + if (entry->gw_route_added) + nm_platform_ip4_route_delete (entry->route.ifindex, entry->route4.gateway, 32, entry->route.metric); + nm_platform_ip4_route_delete (entry->route.ifindex, 0, 0, entry->route.metric); + } + + g_ptr_array_remove_index (priv->entries_ip4, idx); + + g_signal_emit (self, signals[SIGNAL_CHANGED], 0, (gboolean) idx == 0); +} + +static void +device_removed_cb (NMDevice *device, NMDefaultRouteManager *self) +{ + _update_remove4 (self, device, TRUE); +} + +void +nm_default_route_manager_update_ip4_default_route (NMDefaultRouteManager *self, NMDevice *device) +{ + NMDefaultRouteManagerPrivate *priv; + Entry *entry; + NMIP4Config *ip4_config; + const NMPlatformIP4Route *default_route = NULL; + + g_return_if_fail (NM_IS_DEFAULT_ROUTE_MANAGER (self)); + g_return_if_fail (NM_IS_DEVICE (device)); + + priv = NM_DEFAULT_ROUTE_MANAGER_GET_PRIVATE (self); + + entry = _entry_find_by_device (priv->entries_ip4, device, NULL); + ip4_config = nm_device_get_ip4_config (device); + if ( ip4_config + && nm_ip4_config_get_gateway (ip4_config) + && nm_device_get_device_type (device) != NM_DEVICE_TYPE_MODEM + && !nm_ip4_config_get_never_default (ip4_config)) { + default_route = nm_ip4_config_get_default_route (ip4_config); + g_assert (!default_route || default_route->plen == 0); + } + + if (!entry && !default_route) + /* nothing to do */; + else if (!entry) { + /* add new */ + entry = g_new0 (Entry, 1); + entry->device = g_object_ref (device); + + entry->signal_removed_id = g_signal_connect (device, NM_DEVICE_REMOVED, G_CALLBACK (device_removed_cb), self); + entry->route4 = *default_route; + entry->route4.ifindex = nm_device_get_ip_ifindex (device); + entry->route4.network = 0; + + g_ptr_array_add (priv->entries_ip4, entry); + _update_update4 (self, device, NULL, TRUE); + } else if (default_route) { + /* update */ + Entry old_entry, new_entry; + + new_entry = *entry; + new_entry.route4 = *default_route; + new_entry.route4.ifindex = nm_device_get_ip_ifindex (device); + new_entry.route4.network = 0; + + if (memcmp (entry, &new_entry, sizeof (new_entry)) == 0) + return; + + old_entry = *entry; + new_entry.gw_route_added = FALSE; + *entry = new_entry; + _update_update4 (self, device, &old_entry, TRUE); + } else + _update_remove4 (self, device, TRUE); +} + +/***********************************************************************************/ + +static NMDefaultRouteManager *singleton; + +NMDefaultRouteManager * +nm_default_route_manager_get () +{ + if (G_UNLIKELY (!singleton)) { + singleton = NM_DEFAULT_ROUTE_MANAGER (g_object_new (NM_TYPE_DEFAULT_ROUTE_MANAGER, NULL)); + g_object_add_weak_pointer (G_OBJECT (singleton), (gpointer *) &singleton); + } + return singleton; +} + +/***********************************************************************************/ + +static void +nm_default_route_manager_init (NMDefaultRouteManager *self) +{ + NMDefaultRouteManagerPrivate *priv = NM_DEFAULT_ROUTE_MANAGER_GET_PRIVATE (self); + + priv->entries_ip4 = g_ptr_array_new_full (0, (GDestroyNotify) _entry_free); + priv->entries_ip6 = g_ptr_array_new_full (0, (GDestroyNotify) _entry_free); +} + +static void +dispose (GObject *object) +{ + NMDefaultRouteManager *self = NM_DEFAULT_ROUTE_MANAGER (object); + NMDefaultRouteManagerPrivate *priv = NM_DEFAULT_ROUTE_MANAGER_GET_PRIVATE (self); + + if (priv->entries_ip4) { + g_ptr_array_free (priv->entries_ip4, TRUE); + priv->entries_ip4 = NULL; + } + if (priv->entries_ip6) { + g_ptr_array_free (priv->entries_ip6, TRUE); + priv->entries_ip6 = NULL; + } + + G_OBJECT_CLASS (nm_default_route_manager_parent_class)->dispose (object); +} + +static void +nm_default_route_manager_class_init (NMDefaultRouteManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMDefaultRouteManagerPrivate)); + + /* virtual methods */ + object_class->dispose = dispose; + + /* Signals */ + + /* has a boolean parameter to indicate, that the most preferred device changed */ + signals[SIGNAL_CHANGED] = + g_signal_new (NM_DEFAULT_ROUTE_MANAGER_CHANGED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 1, + G_TYPE_BOOLEAN); +} + diff --git a/src/nm-default-route-manager.h b/src/nm-default-route-manager.h new file mode 100644 index 0000000000..dad3eab09b --- /dev/null +++ b/src/nm-default-route-manager.h @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2014 Red Hat, Inc. + */ + +#include <glib-object.h> + +#include "nm-types.h" + +#ifndef __NETWORKMANAGER_DEFAULT_ROUTE_MANAGER_H__ +#define __NETWORKMANAGER_DEFAULT_ROUTE_MANAGER_H__ + + +#define NM_TYPE_DEFAULT_ROUTE_MANAGER (nm_default_route_manager_get_type ()) +#define NM_DEFAULT_ROUTE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEFAULT_ROUTE_MANAGER, NMDefaultRouteManager)) +#define NM_DEFAULT_ROUTE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEFAULT_ROUTE_MANAGER, NMDefaultRouteManagerClass)) +#define NM_IS_DEFAULT_ROUTE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEFAULT_ROUTE_MANAGER)) +#define NM_IS_DEFAULT_ROUTE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEFAULT_ROUTE_MANAGER)) +#define NM_DEFAULT_ROUTE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEFAULT_ROUTE_MANAGER, NMDefaultRouteManagerClass)) + + +#define NM_DEFAULT_ROUTE_MANAGER_CHANGED "changed" + + +struct _NMDefaultRouteManager { + GObject parent; +}; + +typedef struct { + GObjectClass parent; +} NMDefaultRouteManagerClass; + +GType nm_default_route_manager_get_type (void); + +NMDefaultRouteManager *nm_default_route_manager_get (void); + +void nm_default_route_manager_update_ip4_default_route (NMDefaultRouteManager *manager, NMDevice *device); +void nm_default_route_manager_update_ip6_default_route (NMDefaultRouteManager *manager, NMDevice *device); + +#endif /* NM_DEFAULT_ROUTE_MANAGER_H */ + diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 1e1ca1e85c..622f324473 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -1749,8 +1749,14 @@ get_property (GObject *object, guint prop_id, for (i = 0; i < nroutes; i++) { const NMPlatformIP4Route *route = nm_ip4_config_get_route (config, i); - GArray *array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 4); + GArray *array; + /* libnm NMIP4Config object does not allow plen of zero. Skip + * default routes. */ + if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) + continue; + + array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 4); g_array_append_val (array, route->network); g_array_append_val (array, route->plen); g_array_append_val (array, route->gateway); diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 2d89681300..c9c31d3e5e 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -1659,12 +1659,19 @@ get_property (GObject *object, guint prop_id, int i; for (i = 0; i < nroutes; i++) { + GValueArray *array; const NMPlatformIP6Route *route = nm_ip6_config_get_route (config, i); - - GValueArray *array = g_value_array_new (4); GByteArray *ba; GValue element = G_VALUE_INIT; + /* libnm NMIP4Config object does not allow plen of zero. + * The same restriction does not apply to NMIP6Config, but + * for consistency, also skip default routes for IPv6. */ + if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) + continue; + + array = g_value_array_new (4); + g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY); ba = g_byte_array_new (); g_byte_array_append (ba, (guint8 *) &route->network, sizeof (route->network)); diff --git a/src/nm-policy.c b/src/nm-policy.c index 964a2e6608..e8975cb99d 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -102,7 +102,7 @@ get_best_ip4_device (NMPolicy *self, gboolean fully_activated) NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const GSList *iter; NMDevice *best = NULL; - int best_prio = G_MAXINT; + guint32 best_prio = G_MAXUINT32; for (iter = nm_manager_get_devices (priv->manager); iter; iter = g_slist_next (iter)) { NMDevice *dev = NM_DEVICE (iter->data); @@ -111,7 +111,7 @@ get_best_ip4_device (NMPolicy *self, gboolean fully_activated) NMActRequest *req; NMConnection *connection; NMSettingIP4Config *s_ip4; - int prio; + gint64 prio = -1; const char *method = NULL; if ( state <= NM_DEVICE_STATE_DISCONNECTED @@ -123,6 +123,7 @@ get_best_ip4_device (NMPolicy *self, gboolean fully_activated) if (fully_activated) { NMIP4Config *ip4_config; + const NMPlatformIP4Route *default_route; ip4_config = nm_device_get_ip4_config (dev); if (!ip4_config) @@ -135,6 +136,12 @@ get_best_ip4_device (NMPolicy *self, gboolean fully_activated) /* 'never-default' devices can't ever be the default */ if (nm_ip4_config_get_never_default (ip4_config)) continue; + + default_route = nm_ip4_config_get_default_route (ip4_config); + if (!default_route) + continue; + + prio = default_route->metric; } req = nm_device_get_act_request (dev); @@ -154,7 +161,8 @@ get_best_ip4_device (NMPolicy *self, gboolean fully_activated) if (nm_setting_ip4_config_get_never_default (s_ip4)) continue; - prio = nm_device_get_priority (dev); + if (prio < 0) + prio = nm_device_get_ip4_route_priority (dev); if ( prio < best_prio || (priv->default_device4 == dev && prio == best_prio) || !best) { @@ -186,7 +194,7 @@ get_best_ip6_device (NMPolicy *self, gboolean fully_activated) NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const GSList *iter; NMDevice *best = NULL; - int best_prio = G_MAXINT; + guint32 best_prio = G_MAXUINT32; for (iter = nm_manager_get_devices (priv->manager); iter; iter = g_slist_next (iter)) { NMDevice *dev = NM_DEVICE (iter->data); @@ -195,7 +203,7 @@ get_best_ip6_device (NMPolicy *self, gboolean fully_activated) NMActRequest *req; NMConnection *connection; NMSettingIP6Config *s_ip6; - int prio; + gint64 prio = -1; const char *method = NULL; if ( state <= NM_DEVICE_STATE_DISCONNECTED @@ -207,6 +215,7 @@ get_best_ip6_device (NMPolicy *self, gboolean fully_activated) if (fully_activated) { NMIP6Config *ip6_config; + const NMPlatformIP6Route *default_route; ip6_config = nm_device_get_ip6_config (dev); if (!ip6_config) @@ -217,6 +226,12 @@ get_best_ip6_device (NMPolicy *self, gboolean fully_activated) if (nm_ip6_config_get_never_default (ip6_config)) continue; + + default_route = nm_ip6_config_get_default_route (ip6_config); + if (!default_route) + continue; + + prio = default_route->metric; } req = nm_device_get_act_request (dev); @@ -234,7 +249,11 @@ get_best_ip6_device (NMPolicy *self, gboolean fully_activated) if (nm_setting_ip6_config_get_never_default (s_ip6)) continue; - prio = nm_device_get_priority (dev); + if (prio < 0) + prio = nm_device_get_ip6_route_priority (dev); + + prio = nm_utils_ip6_route_metric_normalize (prio); + if ( prio < best_prio || (priv->default_device6 == dev && prio == best_prio) || !best) { diff --git a/src/nm-types.h b/src/nm-types.h index 4119d490d5..4e087bec00 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -28,6 +28,7 @@ typedef struct _NMAuthSubject NMAuthSubject; typedef struct _NMConnectionProvider NMConnectionProvider; typedef struct _NMConnectivity NMConnectivity; typedef struct _NMDBusManager NMDBusManager; +typedef struct _NMDefaultRouteManager NMDefaultRouteManager; typedef struct _NMDevice NMDevice; typedef struct _NMDhcp4Config NMDhcp4Config; typedef struct _NMDhcp6Config NMDhcp6Config; |
