diff options
author | Thomas Haller <thaller@redhat.com> | 2022-02-02 17:39:14 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2022-02-09 19:13:04 +0100 |
commit | 7c27c63bece5488a71950ce32178432d523c7ac3 (patch) | |
tree | e134f157c26d72c76ec57cb72fb92b44cc118763 | |
parent | 2e04d64232a589e0c7934d970dc8e079122b5951 (diff) |
platform: extend NMPRouteManager to work for routes
-rw-r--r-- | src/core/devices/nm-device.c | 4 | ||||
-rw-r--r-- | src/core/platform/tests/test-route.c | 8 | ||||
-rw-r--r-- | src/libnm-platform/nmp-route-manager.c | 136 | ||||
-rw-r--r-- | src/libnm-platform/nmp-route-manager.h | 43 |
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); /*****************************************************************************/ |