Commit f0de7d34 authored by Thomas Haller's avatar Thomas Haller
Browse files

platform: add non-exclusive routes and drop route-manager

Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because

 - when configuring routes, multiple (managed) interfaces may get
   conflicting routes (multihoming). Only one of the routes can be actually
   configured using `ip route replace`, so we need to track routes that are
   currently shadowed.

 - when configuring routes, we might replace externally configured
   routes on unmanaged interfaces. We should not interfere with such
   routes.

That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.

Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.

It practice it is a bit more complicated because:

 - when adding an IPv4 address, kernel will automatically create a device route
   for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
   IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
   addresses yet (and we don't require such a kernel yet), we still need functionality
   similar to nm_route_manager_ip4_route_register_device_route_purge_list().
   This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().

 - trying to configure an IPv6 route with a source address will be rejected
   by kernel as long as the address is tentative (see related bug rh#1457196).
   Preferably, NMDevice would keep the list of routes which should be configured,
   while kernel would have the list of what actually is configured. There is a
   feed-back loop where both affect each other (for example, when externally deleting
   a route, NMDevice must forget about it too). Previously, NMRouteManager would have
   the task of remembering all routes which we currently want to configure, but cannot
   due to conflicting routes.
   We get rid of that, because now we configure non-exclusive routes. We however still
   will need to remember IPv6 routes with a source address, that currently cannot be
   configured yet. Hence, we will need to keep track of routes that
   currently cannot be configured, but later may be.
   That is still not done yet, as NMRouteManager didn't handle this
   correctly either.
parent 974ff629
......@@ -1323,9 +1323,6 @@ src_libNetworkManagerBase_la_SOURCES = \
src/nm-ip6-config.c \
src/nm-ip6-config.h \
\
src/nm-route-manager.c \
src/nm-route-manager.h \
\
src/dhcp/nm-dhcp-client.c \
src/dhcp/nm-dhcp-client.h \
src/dhcp/nm-dhcp-client-logging.h \
......@@ -2961,8 +2958,6 @@ check_programs += \
src/tests/test-general-with-expect \
src/tests/test-ip4-config \
src/tests/test-ip6-config \
src/tests/test-route-manager-linux \
src/tests/test-route-manager-fake \
src/tests/test-dcb \
src/tests/test-systemd \
src/tests/test-resolvconf-capture \
......@@ -3010,28 +3005,6 @@ $(src_tests_test_general_with_expect_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
$(src_tests_test_wired_defname_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
$(src_tests_test_utils_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
src_tests_test_route_manager_ldflags = \
$(CODE_COVERAGE_LDFLAGS)
src_tests_test_route_manager_ldadd = \
src/libNetworkManagerTest.la \
$(GLIB_LIBS) \
$(LIBUDEV_LIBS) \
$(LIBNL_LIBS)
src_tests_test_route_manager_fake_SOURCES = src/tests/test-route-manager.c
src_tests_test_route_manager_fake_CPPFLAGS = $(src_tests_cppflags_fake)
src_tests_test_route_manager_fake_LDFLAGS = $(src_tests_test_route_manager_ldflags)
src_tests_test_route_manager_fake_LDADD = $(src_tests_test_route_manager_ldadd)
src_tests_test_route_manager_linux_SOURCES = src/tests/test-route-manager.c
src_tests_test_route_manager_linux_CPPFLAGS = $(src_tests_cppflags_linux)
src_tests_test_route_manager_linux_LDFLAGS = $(src_tests_test_route_manager_ldflags)
src_tests_test_route_manager_linux_LDADD = $(src_tests_test_route_manager_ldadd)
$(src_tests_test_route_manager_fake_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
$(src_tests_test_route_manager_linux_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
src_tests_test_systemd_CPPFLAGS = $(src_libsystemd_nm_la_cppflags)
src_tests_test_systemd_LDADD = \
src/libsystemd-nm.la \
......
......@@ -77,7 +77,7 @@ nm_dedup_multi_idx_type_init (NMDedupMultiIdxType *idx_type,
/*****************************************************************************/
static NMDedupMultiEntry *
_entry_lookup_obj (NMDedupMultiIndex *self,
_entry_lookup_obj (const NMDedupMultiIndex *self,
const NMDedupMultiIdxType *idx_type,
const NMDedupMultiObj *obj)
{
......@@ -92,7 +92,7 @@ _entry_lookup_obj (NMDedupMultiIndex *self,
}
static NMDedupMultiHeadEntry *
_entry_lookup_head (NMDedupMultiIndex *self,
_entry_lookup_head (const NMDedupMultiIndex *self,
const NMDedupMultiIdxType *idx_type,
const NMDedupMultiObj *obj)
{
......@@ -682,7 +682,7 @@ nm_dedup_multi_index_remove_idx (NMDedupMultiIndex *self,
* Returns: the cache entry or %NULL if the entry wasn't found.
*/
const NMDedupMultiEntry *
nm_dedup_multi_index_lookup_obj (NMDedupMultiIndex *self,
nm_dedup_multi_index_lookup_obj (const NMDedupMultiIndex *self,
const NMDedupMultiIdxType *idx_type,
/*const NMDedupMultiObj * */ gconstpointer obj)
{
......@@ -708,7 +708,7 @@ nm_dedup_multi_index_lookup_obj (NMDedupMultiIndex *self,
* Returns: the cache entry or %NULL if the entry wasn't found.
*/
const NMDedupMultiHeadEntry *
nm_dedup_multi_index_lookup_head (NMDedupMultiIndex *self,
nm_dedup_multi_index_lookup_head (const NMDedupMultiIndex *self,
const NMDedupMultiIdxType *idx_type,
/*const NMDedupMultiObj * */ gconstpointer obj)
{
......
......@@ -278,11 +278,11 @@ gboolean nm_dedup_multi_index_add (NMDedupMultiIndex *self,
const NMDedupMultiEntry **out_entry,
/* const NMDedupMultiObj ** */ gpointer out_obj_old);
const NMDedupMultiEntry *nm_dedup_multi_index_lookup_obj (NMDedupMultiIndex *self,
const NMDedupMultiEntry *nm_dedup_multi_index_lookup_obj (const NMDedupMultiIndex *self,
const NMDedupMultiIdxType *idx_type,
/*const NMDedupMultiObj * */ gconstpointer obj);
const NMDedupMultiHeadEntry *nm_dedup_multi_index_lookup_head (NMDedupMultiIndex *self,
const NMDedupMultiHeadEntry *nm_dedup_multi_index_lookup_head (const NMDedupMultiIndex *self,
const NMDedupMultiIdxType *idx_type,
/*const NMDedupMultiObj * */ gconstpointer obj);
......
......@@ -66,7 +66,6 @@
#include "dns/nm-dns-manager.h"
#include "nm-core-internal.h"
#include "nm-default-route-manager.h"
#include "nm-route-manager.h"
#include "systemd/nm-sd.h"
#include "nm-lldp-listener.h"
#include "nm-audit-manager.h"
......@@ -491,16 +490,14 @@ static void nm_device_set_proxy_config (NMDevice *self, const char *pac_url);
static gboolean nm_device_set_ip4_config (NMDevice *self,
NMIP4Config *config,
guint32 default_route_metric,
gboolean commit,
gboolean routes_full_sync);
gboolean commit);
static gboolean ip4_config_merge_and_apply (NMDevice *self,
NMIP4Config *config,
gboolean commit);
static gboolean nm_device_set_ip6_config (NMDevice *self,
NMIP6Config *config,
gboolean commit,
gboolean routes_full_sync);
gboolean commit);
static gboolean ip6_config_merge_and_apply (NMDevice *self,
gboolean commit);
......@@ -2767,6 +2764,99 @@ link_changed_cb (NMPlatform *platform,
}
}
/*****************************************************************************/
typedef struct {
in_addr_t network;
guint8 plen;
} IP4RPFilterData;
static guint
_v4_has_shadowed_routes_detect_hash (const IP4RPFilterData *d)
{
guint h = 0;
h = NM_HASH_COMBINE (h, d->network);
h = NM_HASH_COMBINE (h, d->plen);
return h;
}
static gboolean
_v4_has_shadowed_routes_detect_equal (const IP4RPFilterData *d1, const IP4RPFilterData *d2)
{
return d1->network == d2->network && d1->plen == d2->plen;
}
static gboolean
_v4_has_shadowed_routes_detect (NMDevice *self)
{
NMPlatform *platform;
int ifindex;
NMPLookup lookup;
const NMDedupMultiHeadEntry *head_entry;
NMDedupMultiIter iter;
const NMPObject *o;
guint data_len;
gs_unref_hashtable GHashTable *data_hash = NULL;
gs_free IP4RPFilterData *data_arr = NULL;
ifindex = nm_device_get_ip_ifindex (self);
if (ifindex <= 0)
return FALSE;
platform = nm_device_get_platform (self);
head_entry = nm_platform_lookup (platform,
nmp_lookup_init_addrroute (&lookup,
NMP_OBJECT_TYPE_IP4_ROUTE,
ifindex));
if (!head_entry)
return FALSE;
/* first, create a lookup index @data_hash for all network/plen pairs. */
data_len = 0;
data_arr = g_new (IP4RPFilterData, head_entry->len);
data_hash = g_hash_table_new ((GHashFunc) _v4_has_shadowed_routes_detect_hash,
(GEqualFunc) _v4_has_shadowed_routes_detect_equal);
nmp_cache_iter_for_each (&iter, head_entry, &o) {
const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE (o);
IP4RPFilterData *d;
nm_assert (r->ifindex == ifindex);
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r))
continue;
d = &data_arr[data_len++];
d->network = nm_utils_ip4_address_clear_host_address (r->network, r->plen);
d->plen = r->plen;
g_hash_table_add (data_hash, d);
}
/* then, search if there is any route on another interface with the same
* network/plen destination. If yes, we consider this a multihoming
* setup. */
head_entry = nm_platform_lookup (platform,
nmp_lookup_init_obj_type (&lookup,
NMP_OBJECT_TYPE_IP4_ROUTE));
nmp_cache_iter_for_each (&iter, head_entry, &o) {
const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE (o);
IP4RPFilterData d;
if ( r->ifindex == ifindex
|| NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r))
continue;
d.network = nm_utils_ip4_address_clear_host_address (r->network, r->plen);
d.plen = r->plen;
if (g_hash_table_contains (data_hash, &d))
return TRUE;
}
return FALSE;
}
static void
ip4_rp_filter_update (NMDevice *self)
{
......@@ -2792,20 +2882,6 @@ ip4_rp_filter_update (NMDevice *self)
}
}
static void
ip4_routes_changed_changed_cb (NMRouteManager *route_manager, NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
int ifindex = nm_device_get_ip_ifindex (self);
if (nm_device_sys_iface_state_is_external_or_assume (self))
return;
priv->v4_has_shadowed_routes = nm_route_manager_ip4_routes_shadowed (route_manager,
ifindex);
ip4_rp_filter_update (self);
}
static void
link_changed (NMDevice *self, const NMPlatformLink *pllink)
{
......@@ -3846,8 +3922,8 @@ nm_device_removed (NMDevice *self, gboolean unconfigure_ip_config)
_update_default_route (self, AF_INET6, priv->default_route.v6_has, TRUE);
_update_default_route (self, AF_INET, FALSE, TRUE);
_update_default_route (self, AF_INET6, FALSE, TRUE);
nm_device_set_ip4_config (self, NULL, 0, FALSE, FALSE);
nm_device_set_ip6_config (self, NULL, FALSE, FALSE);
nm_device_set_ip4_config (self, NULL, 0, FALSE);
nm_device_set_ip6_config (self, NULL, FALSE);
}
static gboolean
......@@ -5582,7 +5658,6 @@ ip4_config_merge_and_apply (NMDevice *self,
const guint32 default_route_metric = nm_device_get_ip4_route_metric (self);
guint32 gateway;
gboolean connection_has_default_route, connection_is_never_default;
gboolean routes_full_sync;
gboolean ignore_auto_routes = FALSE;
gboolean ignore_auto_dns = FALSE;
gboolean auto_method = FALSE;
......@@ -5749,11 +5824,7 @@ END_ADD_DEFAULT_ROUTE:
NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, composite);
}
routes_full_sync = commit
&& priv->v4_commit_first_time
&& !nm_device_sys_iface_state_is_external_or_assume (self);
success = nm_device_set_ip4_config (self, composite, default_route_metric, commit, routes_full_sync);
success = nm_device_set_ip4_config (self, composite, default_route_metric, commit);
g_object_unref (composite);
if (commit)
......@@ -6308,7 +6379,6 @@ ip6_config_merge_and_apply (NMDevice *self,
gboolean has_direct_route;
const struct in6_addr *gateway;
gboolean connection_has_default_route, connection_is_never_default;
gboolean routes_full_sync;
gboolean ignore_auto_routes = FALSE;
gboolean ignore_auto_dns = FALSE;
gboolean auto_method = FALSE;
......@@ -6497,11 +6567,7 @@ END_ADD_DEFAULT_ROUTE:
}
}
routes_full_sync = commit
&& priv->v6_commit_first_time
&& !nm_device_sys_iface_state_is_external_or_assume (self);
success = nm_device_set_ip6_config (self, composite, commit, routes_full_sync);
success = nm_device_set_ip6_config (self, composite, commit);
g_object_unref (composite);
if (commit)
priv->v6_commit_first_time = FALSE;
......@@ -9853,46 +9919,35 @@ static gboolean
nm_device_set_ip4_config (NMDevice *self,
NMIP4Config *new_config,
guint32 default_route_metric,
gboolean commit,
gboolean routes_full_sync)
gboolean commit)
{
NMDevicePrivate *priv;
NMIP4Config *old_config = NULL;
gboolean has_changes = FALSE;
gboolean success = TRUE;
gboolean def_route_changed;
int ip_ifindex, config_ifindex;
int ip_ifindex = 0;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
_LOGD (LOGD_IP4, "ip4-config: update (commit=%d, routes-full-sync=%d, new-config=%p)",
commit, routes_full_sync, new_config);
_LOGD (LOGD_IP4, "ip4-config: update (commit=%d, new-config=%p)",
commit, new_config);
priv = NM_DEVICE_GET_PRIVATE (self);
ip_ifindex = nm_device_get_ip_ifindex (self);
nm_assert ( !new_config
|| ( new_config
&& ((ip_ifindex = nm_device_get_ip_ifindex (self)) > 0)
&& ip_ifindex == nm_ip4_config_get_ifindex (new_config)));
if (new_config) {
config_ifindex = nm_ip4_config_get_ifindex (new_config);
if (config_ifindex > 0)
g_return_val_if_fail (ip_ifindex == config_ifindex, FALSE);
}
priv = NM_DEVICE_GET_PRIVATE (self);
old_config = priv->ip4_config;
/* Always commit to nm-platform to update lifetimes */
if (commit && new_config) {
gboolean assumed = nm_device_sys_iface_state_is_external_or_assume (self);
_commit_mtu (self, new_config);
/* For assumed devices we must not touch the kernel-routes, such as the device-route.
* FIXME: this is wrong in case where "assumed" means "take-over-seamlessly". In this
* case, we should manage the device route, for example on new DHCP lease. */
success = nm_ip4_config_commit (new_config,
nm_device_get_platform (self),
nm_netns_get_route_manager (priv->netns),
ip_ifindex,
routes_full_sync,
assumed ? (gint64) -1 : (gint64) default_route_metric);
default_route_metric);
}
if (new_config) {
......@@ -10031,29 +10086,26 @@ nm_device_set_wwan_ip4_config (NMDevice *self, NMIP4Config *config)
static gboolean
nm_device_set_ip6_config (NMDevice *self,
NMIP6Config *new_config,
gboolean commit,
gboolean routes_full_sync)
gboolean commit)
{
NMDevicePrivate *priv;
NMIP6Config *old_config = NULL;
gboolean has_changes = FALSE;
gboolean success = TRUE;
gboolean def_route_changed;
int ip_ifindex, config_ifindex;
int ip_ifindex = 0;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
_LOGD (LOGD_IP6, "ip6-config: update (commit=%d, routes-full-sync=%d, new-config=%p)",
commit, routes_full_sync, new_config);
_LOGD (LOGD_IP6, "ip6-config: update (commit=%d, new-config=%p)",
commit, new_config);
priv = NM_DEVICE_GET_PRIVATE (self);
ip_ifindex = nm_device_get_ip_ifindex (self);
nm_assert ( !new_config
|| ( new_config
&& ((ip_ifindex = nm_device_get_ip_ifindex (self)) > 0)
&& ip_ifindex == nm_ip6_config_get_ifindex (new_config)));
if (new_config) {
config_ifindex = nm_ip6_config_get_ifindex (new_config);
if (config_ifindex > 0)
g_return_val_if_fail (ip_ifindex == config_ifindex, FALSE);
}
priv = NM_DEVICE_GET_PRIVATE (self);
old_config = priv->ip6_config;
......@@ -10061,10 +10113,7 @@ nm_device_set_ip6_config (NMDevice *self,
if (commit && new_config) {
_commit_mtu (self, priv->ip4_config);
success = nm_ip6_config_commit (new_config,
nm_device_get_platform (self),
nm_netns_get_route_manager (priv->netns),
ip_ifindex,
routes_full_sync);
nm_device_get_platform (self));
}
if (new_config) {
......@@ -10900,6 +10949,11 @@ queued_ip4_config_change (gpointer user_data)
set_unmanaged_external_down (self, TRUE);
if (!nm_device_sys_iface_state_is_external_or_assume (self)) {
priv->v4_has_shadowed_routes = _v4_has_shadowed_routes_detect (self);;
ip4_rp_filter_update (self);
}
return FALSE;
}
......@@ -12105,8 +12159,8 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type)
/* Clean up IP configs; this does not actually deconfigure the
* interface; the caller must flush routes and addresses explicitly.
*/
nm_device_set_ip4_config (self, NULL, 0, TRUE, TRUE);
nm_device_set_ip6_config (self, NULL, TRUE, TRUE);
nm_device_set_ip4_config (self, NULL, 0, TRUE);
nm_device_set_ip6_config (self, NULL, TRUE);
g_clear_object (&priv->proxy_config);
g_clear_object (&priv->con_ip4_config);
g_clear_object (&priv->dev_ip4_config);
......@@ -12194,18 +12248,24 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean
if (NM_DEVICE_GET_CLASS (self)->deactivate)
NM_DEVICE_GET_CLASS (self)->deactivate (self);
ifindex = nm_device_get_ip_ifindex (self);
if (cleanup_type == CLEANUP_TYPE_DECONFIGURE) {
/* master: release slaves */
nm_device_master_release_slaves (self);
/* Take out any entries in the routing table and any IP address the device had. */
ifindex = nm_device_get_ip_ifindex (self);
if (ifindex > 0) {
nm_route_manager_route_flush (nm_netns_get_route_manager (priv->netns), ifindex);
nm_platform_ip_address_flush (nm_device_get_platform (self), AF_UNSPEC, ifindex);
NMPlatform *platform = nm_device_get_platform (self);
nm_platform_ip_route_flush (platform, AF_UNSPEC, ifindex);
nm_platform_ip_address_flush (platform, AF_UNSPEC, ifindex);
}
}
if (ifindex > 0)
nm_platform_ip4_dev_route_blacklist_set (nm_device_get_platform (self), ifindex, NULL);
/* slave: mark no longer enslaved */
if ( priv->master
&& nm_platform_link_get_master (nm_device_get_platform (self), priv->ifindex) <= 0)
......@@ -13851,9 +13911,6 @@ constructed (GObject *object)
g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, G_CALLBACK (device_ipx_changed), self);
g_signal_connect (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (link_changed_cb), self);
g_signal_connect (nm_netns_get_route_manager (priv->netns), NM_ROUTE_MANAGER_IP4_ROUTES_CHANGED,
G_CALLBACK (ip4_routes_changed_changed_cb), self);
priv->settings = g_object_ref (NM_SETTINGS_GET);
g_assert (priv->settings);
......@@ -13894,9 +13951,6 @@ dispose (GObject *object)
g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (device_ipx_changed), self);
g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (link_changed_cb), self);
g_signal_handlers_disconnect_by_func (nm_netns_get_route_manager (priv->netns),
G_CALLBACK (ip4_routes_changed_changed_cb), self);
g_slist_free_full (priv->arping.dad_list, (GDestroyNotify) nm_arping_manager_destroy);
priv->arping.dad_list = NULL;
......
......@@ -32,7 +32,6 @@
#include "nm-setting-connection.h"
#include "NetworkManagerUtils.h"
#include "devices/nm-device-private.h"
#include "nm-route-manager.h"
#include "nm-netns.h"
#include "nm-act-request.h"
#include "nm-ip4-config.h"
......@@ -1066,10 +1065,11 @@ deactivate_cleanup (NMModem *self, NMDevice *device)
priv->ip6_method == NM_MODEM_IP_METHOD_AUTO) {
ifindex = nm_device_get_ip_ifindex (device);
if (ifindex > 0) {
nm_route_manager_route_flush (nm_netns_get_route_manager (nm_device_get_netns (device)),
ifindex);
nm_platform_ip_address_flush (nm_device_get_platform (device), AF_UNSPEC, ifindex);
nm_platform_link_set_down (nm_device_get_platform (device), ifindex);
NMPlatform *platform = nm_device_get_platform (device);
nm_platform_ip_route_flush (platform, AF_UNSPEC, ifindex);
nm_platform_ip_address_flush (platform, AF_UNSPEC, ifindex);
nm_platform_link_set_down (platform, ifindex);
}
}
}
......
......@@ -42,7 +42,6 @@
#include "nm-utils.h"
#include "nm-setting-ip6-config.h"
#include "systemd/nm-sd.h"
#include "nm-route-manager.h"
#if !defined(NM_DIST_VERSION)
# define NM_DIST_VERSION VERSION
......@@ -98,12 +97,6 @@ static struct {
/*****************************************************************************/
NMRouteManager *route_manager_get (void);
NM_DEFINE_SINGLETON_GETTER (NMRouteManager, route_manager_get, NM_TYPE_ROUTE_MANAGER);
/*****************************************************************************/
static void
dhcp4_state_changed (NMDhcpClient *client,
NMDhcpState state,
......@@ -122,13 +115,17 @@ dhcp4_state_changed (NMDhcpClient *client,
switch (state) {
case NM_DHCP_STATE_BOUND:
g_assert (ip4_config);
g_assert (nm_ip4_config_get_ifindex (ip4_config) == gl.ifindex);
existing = nm_ip4_config_capture (nm_platform_get_multi_idx (NM_PLATFORM_GET),
NM_PLATFORM_GET, gl.ifindex, FALSE);
if (last_config)
nm_ip4_config_subtract (existing, last_config);
nm_ip4_config_merge (existing, ip4_config, NM_IP_CONFIG_MERGE_DEFAULT);
if (!nm_ip4_config_commit (existing, NM_PLATFORM_GET, route_manager_get (), gl.ifindex, TRUE, global_opt.priority_v4))
if (!nm_ip4_config_commit (existing,
NM_PLATFORM_GET,
global_opt.priority_v4))
_LOGW (LOGD_DHCP4, "failed to apply DHCPv4 config");
if (last_config)
......@@ -257,7 +254,7 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
}
nm_ip6_config_merge (existing, ndisc_config, NM_IP_CONFIG_MERGE_DEFAULT);
if (!nm_ip6_config_commit (existing, NM_PLATFORM_GET, route_manager_get (), gl.ifindex, TRUE))
if (!nm_ip6_config_commit (existing, NM_PLATFORM_GET))
_LOGW (LOGD_IP6, "failed to apply IPv6 config");
}
......
......@@ -33,7 +33,6 @@
#include "platform/nm-platform.h"
#include "platform/nm-platform-utils.h"
#include "NetworkManagerUtils.h"
#include "nm-route-manager.h"
#include "nm-core-internal.h"
#include "introspection/org.freedesktop.NetworkManager.IP4Config.h"
......@@ -284,6 +283,48 @@ append_force_and_out:
return FALSE;
}
/**
* _nm_ip_config_lookup_ip_route:
* @multi_idx:
* @idx_type:
* @needle:
* @cmp_type: after lookup, filter the result by comparing with @cmp_type. Only
* return the result, if it compares equal to @needle according to this @cmp_type.
* Note that the index uses %NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST type, so passing
* that compare-type means not to filter any further.
*
* Returns: the found entry or %NULL.
*/
const NMDedupMultiEntry *
_nm_ip_config_lookup_ip_route (const NMDedupMultiIndex *multi_idx,
const NMIPConfigDedupMultiIdxType *idx_type,
const NMPObject *needle,
NMPlatformIPRouteCmpType cmp_type)
{
const NMDedupMultiEntry *entry;
nm_assert (multi_idx);
nm_assert (idx_type);
nm_assert (NM_IN_SET (idx_type->obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
nm_assert (NMP_OBJECT_GET_TYPE (needle) == idx_type->obj_type);
entry = nm_dedup_multi_index_lookup_obj (multi_idx,
&idx_type->parent,
needle);
if (!entry)
return NULL;
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST)
nm_assert (nm_platform_ip4_route_cmp (NMP_OBJECT_CAST_IP4_ROUTE (entry->obj), NMP_OBJECT_CAST_IP4_ROUTE (needle), cmp_type) == 0);
else {
if (nm_platform_ip4_route_cmp (NMP_OBJECT_CAST_IP4_ROUTE (entry->obj),
NMP_OBJECT_CAST_IP4_ROUTE (needle),
cmp_type) != 0)
return NULL;
}
return entry;
}
/*****************************************************************************/
NM_GOBJECT_PROPERTIES_DEFINE (NMIP4Config,
......@@ -352,6 +393,9 @@ G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, NM_TYPE_EXPORTED_OBJECT)
static void _add_address (NMIP4Config *self, const NMPObject *obj_new, const NMPlatformIP4Address *new);
static void _add_route (NMIP4Config *self, const NMPObject *obj_new, const NMPlatformIP4Route *new);
static const NMDedupMultiEntry *_lookup_route (const NMIP4Config *self,
const NMPObject *needle,
NMPlatformIPRouteCmpType cmp_type);
/*****************************************************************************/
......@@ -669,37 +713,41 @@ nm_ip4_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
}
gboolean
nm_ip4_config_commit (const NMIP4Config *self, NMPlatform *platform, NMRouteManager *route_manager, int ifindex, gboolean routes_full_sync, gint64 default_route_metric)
nm_ip4_config_commit (const NMIP4Config *self,
NMPlatform *platform,
guint32 default_route_metric)