summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2022-02-02 17:39:14 +0100
committerThomas Haller <thaller@redhat.com>2022-02-09 19:13:04 +0100
commit7c27c63bece5488a71950ce32178432d523c7ac3 (patch)
treee134f157c26d72c76ec57cb72fb92b44cc118763
parent2e04d64232a589e0c7934d970dc8e079122b5951 (diff)
platform: extend NMPRouteManager to work for routes
-rw-r--r--src/core/devices/nm-device.c4
-rw-r--r--src/core/platform/tests/test-route.c8
-rw-r--r--src/libnm-platform/nmp-route-manager.c136
-rw-r--r--src/libnm-platform/nmp-route-manager.h43
4 files changed, 126 insertions, 65 deletions
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index f7836567a0..30e0fe8fef 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -9357,7 +9357,7 @@ _routing_rules_sync(NMDevice *self, NMTernary set_mode)
keep_deleted_rules = FALSE;
if (set_mode == NM_TERNARY_DEFAULT) {
/* when exiting NM, we leave the device up and the rules configured.
- * We just all nmp_route_manager_sync_rules() to forget about the synced rules,
+ * We just call nmp_route_manager_sync() to forget about the synced rules,
* but we don't actually delete them.
*
* FIXME: that is a problem after restart of NetworkManager, because these
@@ -9371,7 +9371,7 @@ _routing_rules_sync(NMDevice *self, NMTernary set_mode)
* file and track them after restart again. */
keep_deleted_rules = TRUE;
}
- nmp_route_manager_sync_rules(route_manager, keep_deleted_rules);
+ nmp_route_manager_sync(route_manager, NMP_OBJECT_TYPE_ROUTING_RULE, keep_deleted_rules);
}
static gboolean
diff --git a/src/core/platform/tests/test-route.c b/src/core/platform/tests/test-route.c
index fb6ca72d32..cf0236e0e6 100644
--- a/src/core/platform/tests/test-route.c
+++ b/src/core/platform/tests/test-route.c
@@ -1675,14 +1675,14 @@ again:
NULL);
}
if (nmtst_get_rand_uint32() % objs_sync->len == 0) {
- nmp_route_manager_sync_rules(route_manager, FALSE);
+ nmp_route_manager_sync(route_manager, NMP_OBJECT_TYPE_ROUTING_RULE, FALSE);
g_assert_cmpint(nmtstp_platform_routing_rules_get_count(platform, AF_UNSPEC),
==,
i + 1);
}
}
- nmp_route_manager_sync_rules(route_manager, FALSE);
+ nmp_route_manager_sync(route_manager, NMP_OBJECT_TYPE_ROUTING_RULE, FALSE);
g_assert_cmpint(nmtstp_platform_routing_rules_get_count(platform, AF_UNSPEC),
==,
objs_sync->len);
@@ -1713,14 +1713,14 @@ again:
break;
}
if (nmtst_get_rand_uint32() % objs_sync->len == 0) {
- nmp_route_manager_sync_rules(route_manager, FALSE);
+ nmp_route_manager_sync(route_manager, NMP_OBJECT_TYPE_ROUTING_RULE, FALSE);
g_assert_cmpint(nmtstp_platform_routing_rules_get_count(platform, AF_UNSPEC),
==,
objs_sync->len - i - 1);
}
}
- nmp_route_manager_sync_rules(route_manager, FALSE);
+ nmp_route_manager_sync(route_manager, NMP_OBJECT_TYPE_ROUTING_RULE, FALSE);
} else {
for (i = 0; i < objs->len;) {
diff --git a/src/libnm-platform/nmp-route-manager.c b/src/libnm-platform/nmp-route-manager.c
index 583e9bdf9d..c2a83de70a 100644
--- a/src/libnm-platform/nmp-route-manager.c
+++ b/src/libnm-platform/nmp-route-manager.c
@@ -116,7 +116,10 @@ static void
_track_data_assert(const TrackData *track_data, gboolean linked)
{
nm_assert(track_data);
- nm_assert(NMP_OBJECT_GET_TYPE(track_data->obj) == NMP_OBJECT_TYPE_ROUTING_RULE);
+ nm_assert(NM_IN_SET(NMP_OBJECT_GET_TYPE(track_data->obj),
+ NMP_OBJECT_TYPE_IP4_ROUTE,
+ NMP_OBJECT_TYPE_IP6_ROUTE,
+ NMP_OBJECT_TYPE_ROUTING_RULE));
nm_assert(nmp_object_is_visible(track_data->obj));
nm_assert(track_data->user_tag);
nm_assert(!linked || !c_list_is_empty(&track_data->obj_lst));
@@ -132,9 +135,7 @@ _track_data_hash(gconstpointer data)
_track_data_assert(track_data, FALSE);
nm_hash_init(&h, 269297543u);
- nm_platform_routing_rule_hash_update(NMP_OBJECT_CAST_ROUTING_RULE(track_data->obj),
- NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID,
- &h);
+ nmp_object_id_hash_update(track_data->obj, &h);
nm_hash_update_val(&h, track_data->user_tag);
return nm_hash_complete(&h);
}
@@ -149,10 +150,7 @@ _track_data_equal(gconstpointer data_a, gconstpointer data_b)
_track_data_assert(track_data_b, FALSE);
return track_data_a->user_tag == track_data_b->user_tag
- && (nm_platform_routing_rule_cmp(NMP_OBJECT_CAST_ROUTING_RULE(track_data_a->obj),
- NMP_OBJECT_CAST_ROUTING_RULE(track_data_b->obj),
- NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID)
- == 0);
+ && nmp_object_id_equal(track_data_a->obj, track_data_b->obj);
}
static void
@@ -199,13 +197,8 @@ static guint
_track_obj_data_hash(gconstpointer data)
{
const TrackObjData *obj_data = data;
- NMHashState h;
- nm_hash_init(&h, 432817559u);
- nm_platform_routing_rule_hash_update(NMP_OBJECT_CAST_ROUTING_RULE(obj_data->obj),
- NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID,
- &h);
- return nm_hash_complete(&h);
+ return nmp_object_id_hash(obj_data->obj);
}
static gboolean
@@ -214,10 +207,7 @@ _track_obj_data_equal(gconstpointer data_a, gconstpointer data_b)
const TrackObjData *obj_data_a = data_a;
const TrackObjData *obj_data_b = data_b;
- return (nm_platform_routing_rule_cmp(NMP_OBJECT_CAST_ROUTING_RULE(obj_data_a->obj),
- NMP_OBJECT_CAST_ROUTING_RULE(obj_data_b->obj),
- NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID)
- == 0);
+ return nmp_object_id_equal(obj_data_a->obj, obj_data_b->obj);
}
static void
@@ -250,10 +240,15 @@ _track_data_lookup(GHashTable *by_data, const NMPObject *obj, gconstpointer user
return g_hash_table_lookup(by_data, &track_data_needle);
}
+/*****************************************************************************/
+
/**
- * nmp_route_manager_track_rule:
+ * nmp_route_manager_track:
* @self: the #NMPRouteManager instance
- * @routing_rule: the #NMPlatformRoutingRule to track or untrack
+ * @obj_type: the NMPObjectType of @obj that we are tracking.
+ * @obj: the NMPlatformObject (of type NMPObjectType) to track. Usually
+ * a #NMPlatformRoutingRule, #NMPlatformIP4Route or #NMPlatformIP6Route
+ * pointer.
* @track_priority: the priority for tracking the rule. Note that
* negative values indicate a forced absence of the rule. Priorities
* are compared with their absolute values (with higher absolute
@@ -270,11 +265,12 @@ _track_data_lookup(GHashTable *by_data, const NMPObject *obj, gconstpointer user
* The purpose here is to set this to %NMP_ROUTE_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG.
*/
void
-nmp_route_manager_track_rule(NMPRouteManager *self,
- const NMPlatformRoutingRule *routing_rule,
- gint32 track_priority,
- gconstpointer user_tag,
- gconstpointer user_tag_untrack)
+nmp_route_manager_track(NMPRouteManager *self,
+ NMPObjectType obj_type,
+ gconstpointer obj,
+ gint32 track_priority,
+ gconstpointer user_tag,
+ gconstpointer user_tag_untrack)
{
NMPObject obj_stack;
const NMPObject *p_obj_stack;
@@ -286,11 +282,18 @@ nmp_route_manager_track_rule(NMPRouteManager *self,
gboolean track_priority_present;
g_return_if_fail(NMP_IS_ROUTE_MANAGER(self));
- g_return_if_fail(routing_rule);
+ g_return_if_fail(obj);
g_return_if_fail(user_tag);
+
+ /* The route must not be tied to an interface. We can only handle here
+ * blackhole/unreachable/prohibit route types. */
+ g_return_if_fail(obj_type == NMP_OBJECT_TYPE_ROUTING_RULE
+ || (NM_IN_SET(obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)
+ && ((const NMPlatformIPRoute *) obj)->ifindex == 0));
+
nm_assert(track_priority != G_MININT32);
- p_obj_stack = nmp_object_stackinit(&obj_stack, NMP_OBJECT_TYPE_ROUTING_RULE, routing_rule);
+ p_obj_stack = nmp_object_stackinit(&obj_stack, obj_type, obj);
nm_assert(nmp_object_is_visible(p_obj_stack));
@@ -363,12 +366,13 @@ nmp_route_manager_track_rule(NMPRouteManager *self,
_track_data_assert(track_data, TRUE);
if (changed) {
- _LOGD("routing-rule: track [" NM_HASH_OBFUSCATE_PTR_FMT ",%s%u] \"%s\")",
+ _LOGD("track [" NM_HASH_OBFUSCATE_PTR_FMT ",%s%u] %s \"%s\"",
NM_HASH_OBFUSCATE_PTR(track_data->user_tag),
(track_data->track_priority_val == 0
? ""
: (track_data->track_priority_present ? "+" : "-")),
(guint) track_data->track_priority_val,
+ NMP_OBJECT_GET_CLASS(track_data->obj)->obj_type_name,
nmp_object_to_string(track_data->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
}
}
@@ -386,8 +390,9 @@ _track_data_untrack(NMPRouteManager *self,
nm_assert(self->by_data);
nm_assert(g_hash_table_lookup(self->by_data, track_data) == track_data);
- _LOGD("routing-rule: untrack [" NM_HASH_OBFUSCATE_PTR_FMT "] \"%s\"",
+ _LOGD("untrack [" NM_HASH_OBFUSCATE_PTR_FMT "] %s \"%s\"",
NM_HASH_OBFUSCATE_PTR(track_data->user_tag),
+ NMP_OBJECT_GET_CLASS(track_data->obj)->obj_type_name,
nmp_object_to_string(track_data->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
#if NM_MORE_ASSERTS
@@ -425,19 +430,24 @@ _track_data_untrack(NMPRouteManager *self,
}
void
-nmp_route_manager_untrack_rule(NMPRouteManager *self,
- const NMPlatformRoutingRule *routing_rule,
- gconstpointer user_tag)
+nmp_route_manager_untrack(NMPRouteManager *self,
+ NMPObjectType obj_type,
+ gconstpointer obj,
+ gconstpointer user_tag)
{
NMPObject obj_stack;
const NMPObject *p_obj_stack;
TrackData *track_data;
g_return_if_fail(NMP_IS_ROUTE_MANAGER(self));
- g_return_if_fail(routing_rule);
+ nm_assert(NM_IN_SET(obj_type,
+ NMP_OBJECT_TYPE_IP4_ROUTE,
+ NMP_OBJECT_TYPE_IP6_ROUTE,
+ NMP_OBJECT_TYPE_ROUTING_RULE));
+ g_return_if_fail(obj);
g_return_if_fail(user_tag);
- p_obj_stack = nmp_object_stackinit(&obj_stack, NMP_OBJECT_TYPE_ROUTING_RULE, routing_rule);
+ p_obj_stack = nmp_object_stackinit(&obj_stack, obj_type, obj);
nm_assert(nmp_object_is_visible(p_obj_stack));
@@ -490,29 +500,41 @@ nmp_route_manager_untrack_all(NMPRouteManager *self,
g_hash_table_remove(self->by_user_tag, user_tag_data);
}
+/*****************************************************************************/
+
void
-nmp_route_manager_sync_rules(NMPRouteManager *self, gboolean keep_deleted_rules)
+nmp_route_manager_sync(NMPRouteManager *self, NMPObjectType obj_type, gboolean keep_deleted)
{
const NMDedupMultiHeadEntry *pl_head_entry;
NMDedupMultiIter pl_iter;
const NMPObject *plobj;
- gs_unref_ptrarray GPtrArray *rules_to_delete = NULL;
+ gs_unref_ptrarray GPtrArray *objs_to_delete = NULL;
TrackObjData *obj_data;
GHashTableIter h_iter;
guint i;
const TrackData *td_best;
g_return_if_fail(NMP_IS_ROUTE_MANAGER(self));
+ g_return_if_fail(NM_IN_SET(obj_type,
+ NMP_OBJECT_TYPE_IP4_ROUTE,
+ NMP_OBJECT_TYPE_IP6_ROUTE,
+ NMP_OBJECT_TYPE_ROUTING_RULE));
+
+ _LOGD("sync %s%s",
+ nmp_class_from_type(obj_type)->obj_type_name,
+ keep_deleted ? " (don't remove any)" : "");
- _LOGD("sync%s", keep_deleted_rules ? " (don't remove any rules)" : "");
+ if (obj_type == NMP_OBJECT_TYPE_ROUTING_RULE)
+ pl_head_entry = nm_platform_lookup_obj_type(self->platform, obj_type);
+ else
+ pl_head_entry = nm_platform_lookup_object(self->platform, obj_type, 0);
- pl_head_entry = nm_platform_lookup_obj_type(self->platform, NMP_OBJECT_TYPE_ROUTING_RULE);
if (pl_head_entry) {
nmp_cache_iter_for_each (&pl_iter, pl_head_entry, &plobj) {
obj_data = g_hash_table_lookup(self->by_obj, &plobj);
if (!obj_data) {
- /* this rule is not tracked. It was externally added, hence we
+ /* this obj is not tracked. It was externally added, hence we
* ignore it. */
continue;
}
@@ -535,28 +557,36 @@ nmp_route_manager_sync_rules(NMPRouteManager *self, gboolean keep_deleted_rules)
}
}
- if (keep_deleted_rules) {
- _LOGD("forget/leak rule added by us: %s",
+ if (keep_deleted) {
+ _LOGD("forget/leak object added by us: %s \"%s\"",
+ NMP_OBJECT_GET_CLASS(plobj)->obj_type_name,
nmp_object_to_string(plobj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
continue;
}
- if (!rules_to_delete)
- rules_to_delete = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref);
+ if (!objs_to_delete)
+ objs_to_delete = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref);
- g_ptr_array_add(rules_to_delete, (gpointer) nmp_object_ref(plobj));
+ g_ptr_array_add(objs_to_delete, (gpointer) nmp_object_ref(plobj));
obj_data->config_state = CONFIG_STATE_REMOVED_BY_US;
}
}
- if (rules_to_delete) {
- for (i = 0; i < rules_to_delete->len; i++)
- nm_platform_object_delete(self->platform, rules_to_delete->pdata[i]);
+ if (objs_to_delete) {
+ for (i = 0; i < objs_to_delete->len; i++)
+ nm_platform_object_delete(self->platform, objs_to_delete->pdata[i]);
}
g_hash_table_iter_init(&h_iter, self->by_obj);
while (g_hash_table_iter_next(&h_iter, (gpointer *) &obj_data, NULL)) {
+ if (NMP_OBJECT_GET_TYPE(obj_data->obj) != obj_type) {
+ /* Here we need to iterate over all objects (rules and ip4/ip6 routes)
+ * and skip over the non-interesting ones. It might be better to
+ * track 3 separate CList by object type. */
+ continue;
+ }
+
td_best = _track_obj_data_get_best_data(obj_data);
if (!td_best) {
@@ -585,12 +615,18 @@ nmp_route_manager_sync_rules(NMPRouteManager *self, gboolean keep_deleted_rules)
continue;
obj_data->config_state = CONFIG_STATE_ADDED_BY_US;
- nm_platform_routing_rule_add(self->platform,
- NMP_NLM_FLAG_ADD,
- NMP_OBJECT_CAST_ROUTING_RULE(obj_data->obj));
+
+ if (obj_type == NMP_OBJECT_TYPE_ROUTING_RULE) {
+ nm_platform_routing_rule_add(self->platform,
+ NMP_NLM_FLAG_ADD,
+ NMP_OBJECT_CAST_ROUTING_RULE(obj_data->obj));
+ } else
+ nm_platform_ip_route_add(self->platform, NMP_NLM_FLAG_APPEND, obj_data->obj);
}
}
+/*****************************************************************************/
+
void
nmp_route_manager_track_rule_from_platform(NMPRouteManager *self,
NMPlatform *platform,
diff --git a/src/libnm-platform/nmp-route-manager.h b/src/libnm-platform/nmp-route-manager.h
index 3bc4a49301..17af8ee0c5 100644
--- a/src/libnm-platform/nmp-route-manager.h
+++ b/src/libnm-platform/nmp-route-manager.h
@@ -19,11 +19,27 @@ void nmp_route_manager_unref(NMPRouteManager *self);
#define nm_auto_unref_route_manager nm_auto(_nmp_route_manager_unref)
NM_AUTO_DEFINE_FCN0(NMPRouteManager *, _nmp_route_manager_unref, nmp_route_manager_unref);
-void nmp_route_manager_track_rule(NMPRouteManager *self,
- const NMPlatformRoutingRule *routing_rule,
- gint32 track_priority,
- gconstpointer user_tag,
- gconstpointer user_tag_untrack);
+void nmp_route_manager_track(NMPRouteManager *self,
+ NMPObjectType obj_type,
+ gconstpointer obj,
+ gint32 track_priority,
+ gconstpointer user_tag,
+ gconstpointer user_tag_untrack);
+
+static inline void
+nmp_route_manager_track_rule(NMPRouteManager *self,
+ const NMPlatformRoutingRule *routing_rule,
+ gint32 track_priority,
+ gconstpointer user_tag,
+ gconstpointer user_tag_untrack)
+{
+ nmp_route_manager_track(self,
+ NMP_OBJECT_TYPE_ROUTING_RULE,
+ routing_rule,
+ track_priority,
+ user_tag,
+ user_tag_untrack);
+}
void nmp_route_manager_track_rule_default(NMPRouteManager *self,
int addr_family,
@@ -36,9 +52,18 @@ void nmp_route_manager_track_rule_from_platform(NMPRouteManager *self,
gint32 tracking_priority,
gconstpointer user_tag);
-void nmp_route_manager_untrack_rule(NMPRouteManager *self,
- const NMPlatformRoutingRule *routing_rule,
- gconstpointer user_tag);
+void nmp_route_manager_untrack(NMPRouteManager *self,
+ NMPObjectType obj_type,
+ gconstpointer obj,
+ gconstpointer user_tag);
+
+static inline void
+nmp_route_manager_untrack_rule(NMPRouteManager *self,
+ const NMPlatformRoutingRule *routing_rule,
+ gconstpointer user_tag)
+{
+ nmp_route_manager_untrack(self, NMP_OBJECT_TYPE_ROUTING_RULE, routing_rule, user_tag);
+}
void nmp_route_manager_set_dirty(NMPRouteManager *self, gconstpointer user_tag);
@@ -46,7 +71,7 @@ void nmp_route_manager_untrack_all(NMPRouteManager *self,
gconstpointer user_tag,
gboolean all /* or only dirty */);
-void nmp_route_manager_sync_rules(NMPRouteManager *self, gboolean keep_deleted_rules);
+void nmp_route_manager_sync(NMPRouteManager *self, NMPObjectType obj_type, gboolean keep_deleted);
/*****************************************************************************/