summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/nm-l3cfg.c107
-rw-r--r--src/core/nm-l3cfg.h14
2 files changed, 106 insertions, 15 deletions
diff --git a/src/core/nm-l3cfg.c b/src/core/nm-l3cfg.c
index dfb80c7cb9..e7aee79a04 100644
--- a/src/core/nm-l3cfg.c
+++ b/src/core/nm-l3cfg.c
@@ -12,6 +12,7 @@
#include "libnm-glib-aux/nm-time-utils.h"
#include "libnm-platform/nm-platform.h"
#include "libnm-platform/nmp-object.h"
+#include "libnm-platform/nmp-route-manager.h"
#include "nm-netns.h"
#include "n-acd/src/n-acd.h"
#include "nm-l3-ipv4ll.h"
@@ -410,6 +411,25 @@ static NM_UTILS_LOOKUP_DEFINE(_l3_acd_addr_state_to_string,
"external-removed"),
NM_UTILS_LOOKUP_ITEM(NM_L3_ACD_ADDR_STATE_USED, "used"), );
+static gboolean
+_obj_is_route_nodev(const NMPObject *obj)
+{
+ gboolean has_ifindex;
+
+ nm_assert(obj);
+
+ has_ifindex = (NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(obj)->ifindex > 0);
+
+ nm_assert(has_ifindex
+ == !(NM_IN_SET(NMP_OBJECT_GET_TYPE(obj),
+ NMP_OBJECT_TYPE_IP4_ROUTE,
+ NMP_OBJECT_TYPE_IP6_ROUTE)
+ && nm_platform_route_type_is_nodev(nm_platform_route_type_uncoerce(
+ NMP_OBJECT_CAST_IP_ROUTE(obj)->type_coerced))));
+
+ return !has_ifindex;
+}
+
/*****************************************************************************/
NMIPConfig *
@@ -952,6 +972,11 @@ _obj_states_update_all(NML3Cfg *self)
self->priv.p->combined_l3cd_commited,
&obj,
obj_type) {
+ if (_obj_is_route_nodev(obj)) {
+ /* this is a nodev route. We don't track an obj-state for this. */
+ continue;
+ }
+
obj_state = g_hash_table_lookup(self->priv.p->obj_state_hash, &obj);
if (!obj_state) {
obj_state =
@@ -1081,13 +1106,15 @@ static void
_commit_collect_routes(NML3Cfg *self,
int addr_family,
NML3CfgCommitType commit_type,
- GPtrArray **routes)
+ GPtrArray **routes,
+ GPtrArray **routes_nodev)
{
const int IS_IPv4 = NM_IS_IPv4(addr_family);
const NMDedupMultiHeadEntry *head_entry;
const NMDedupMultiEntry *entry;
nm_assert(routes && !*routes);
+ nm_assert(routes_nodev && !*routes_nodev);
head_entry = nm_l3_config_data_lookup_objs(self->priv.p->combined_l3cd_commited,
NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4));
@@ -1097,16 +1124,20 @@ _commit_collect_routes(NML3Cfg *self,
c_list_for_each_entry (entry, &head_entry->lst_entries_head, lst_entries) {
const NMPObject *obj = entry->obj;
+ GPtrArray **r;
- if (!_obj_states_sync_filter(self, obj, commit_type))
- continue;
-
- if (!*routes) {
- *routes =
- g_ptr_array_new_full(head_entry->len, (GDestroyNotify) nm_dedup_multi_obj_unref);
+ if (_obj_is_route_nodev(obj))
+ r = routes_nodev;
+ else {
+ if (!_obj_states_sync_filter(self, obj, commit_type))
+ continue;
+ r = routes;
}
- g_ptr_array_add(*routes, (gpointer) nmp_object_ref(obj));
+ if (!*r)
+ *r = g_ptr_array_new_full(head_entry->len, (GDestroyNotify) nm_dedup_multi_obj_unref);
+
+ g_ptr_array_add(*r, (gpointer) nmp_object_ref(obj));
}
}
@@ -3403,6 +3434,53 @@ nm_l3cfg_remove_config_all_dirty(NML3Cfg *self, gconstpointer tag)
/*****************************************************************************/
+#define _NODEV_ROUTES_TAG(self, IS_IPv4) ((gconstpointer) (&(&(self)->priv.route_manager)[IS_IPv4]))
+
+static gboolean
+_nodev_routes_untrack(NML3Cfg *self, int addr_family)
+{
+ return nmp_route_manager_untrack_all(self->priv.route_manager,
+ _NODEV_ROUTES_TAG(self, NM_IS_IPv4(addr_family)),
+ FALSE,
+ TRUE);
+}
+
+static void
+_nodev_routes_sync(NML3Cfg *self,
+ int addr_family,
+ NML3CfgCommitType commit_type,
+ GPtrArray *routes_nodev)
+{
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ const NMPObjectType obj_type = NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4);
+ guint i;
+ gboolean changed = FALSE;
+
+ if (!routes_nodev)
+ goto out_clear;
+
+ for (i = 0; i < routes_nodev->len; i++) {
+ const NMPObject *obj = routes_nodev->pdata[i];
+
+ if (nmp_route_manager_track(self->priv.route_manager,
+ obj_type,
+ NMP_OBJECT_CAST_IP_ROUTE(obj),
+ 1,
+ _NODEV_ROUTES_TAG(self, IS_IPv4),
+ NULL))
+ changed = TRUE;
+ }
+
+out_clear:
+ if (_nodev_routes_untrack(self, addr_family))
+ changed = TRUE;
+
+ if (changed || commit_type >= NM_L3_CFG_COMMIT_TYPE_REAPPLY)
+ nmp_route_manager_sync(self->priv.route_manager, NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4), FALSE);
+}
+
+/*****************************************************************************/
+
typedef struct {
NML3Cfg *self;
gconstpointer tag;
@@ -4102,6 +4180,7 @@ _l3_commit_one(NML3Cfg *self,
const int IS_IPv4 = NM_IS_IPv4(addr_family);
gs_unref_ptrarray GPtrArray *addresses = NULL;
gs_unref_ptrarray GPtrArray *routes = NULL;
+ gs_unref_ptrarray GPtrArray *routes_nodev = NULL;
gs_unref_ptrarray GPtrArray *addresses_prune = NULL;
gs_unref_ptrarray GPtrArray *routes_prune = NULL;
gs_unref_ptrarray GPtrArray *routes_temporary_not_available_arr = NULL;
@@ -4125,7 +4204,7 @@ _l3_commit_one(NML3Cfg *self,
if (self->priv.p->combined_l3cd_commited) {
addresses = _commit_collect_addresses(self, addr_family, commit_type);
- _commit_collect_routes(self, addr_family, commit_type, &routes);
+ _commit_collect_routes(self, addr_family, commit_type, &routes, &routes_nodev);
route_table_sync =
nm_l3_config_data_get_route_table_sync(self->priv.p->combined_l3cd_commited,
@@ -4163,6 +4242,8 @@ _l3_commit_one(NML3Cfg *self,
addresses,
addresses_prune);
+ _nodev_routes_sync(self, addr_family, commit_type, routes_nodev);
+
if (!nm_platform_ip_route_sync(self->priv.platform,
addr_family,
self->priv.ifindex,
@@ -4597,6 +4678,8 @@ constructed(GObject *object)
self->priv.platform = g_object_ref(nm_netns_get_platform(self->priv.netns));
nm_assert(NM_IS_PLATFORM(self->priv.platform));
+ self->priv.route_manager = nmp_route_manager_ref(nm_netns_get_route_manager(self->priv.netns));
+
_LOGT("created (netns=" NM_HASH_OBFUSCATE_PTR_FMT ")", NM_HASH_OBFUSCATE_PTR(self->priv.netns));
G_OBJECT_CLASS(nm_l3cfg_parent_class)->constructed(object);
@@ -4647,8 +4730,14 @@ finalize(GObject *object)
nm_assert(c_list_is_empty(&self->priv.p->obj_state_temporary_not_available_lst_head));
nm_assert(c_list_is_empty(&self->priv.p->obj_state_zombie_lst_head));
+ if (_nodev_routes_untrack(self, AF_INET))
+ nmp_route_manager_sync(self->priv.route_manager, NMP_OBJECT_TYPE_IP4_ROUTE, FALSE);
+ if (_nodev_routes_untrack(self, AF_INET6))
+ nmp_route_manager_sync(self->priv.route_manager, NMP_OBJECT_TYPE_IP6_ROUTE, FALSE);
+
g_clear_object(&self->priv.netns);
g_clear_object(&self->priv.platform);
+ nm_clear_pointer(&self->priv.route_manager, nmp_route_manager_unref);
nm_clear_l3cd(&self->priv.p->combined_l3cd_merged);
nm_clear_l3cd(&self->priv.p->combined_l3cd_commited);
diff --git a/src/core/nm-l3cfg.h b/src/core/nm-l3cfg.h
index 6fd8f9de80..7dc9faccfe 100644
--- a/src/core/nm-l3cfg.h
+++ b/src/core/nm-l3cfg.h
@@ -195,16 +195,18 @@ typedef struct {
} NML3ConfigNotifyData;
struct _NML3CfgPrivate;
+struct _NMPRouteManager;
struct _NML3Cfg {
GObject parent;
struct {
- struct _NML3CfgPrivate *p;
- NMNetns *netns;
- NMPlatform *platform;
- const NMPObject *plobj;
- const NMPObject *plobj_next;
- int ifindex;
+ struct _NML3CfgPrivate *p;
+ NMNetns *netns;
+ NMPlatform *platform;
+ struct _NMPRouteManager *route_manager;
+ const NMPObject *plobj;
+ const NMPObject *plobj_next;
+ int ifindex;
} priv;
};