mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-25 08:20:43 +01:00
core: add nexthop id reservation function in the netns
When an IP configuration method (e.g. NDisc) wants to use a nexthop, it needs to allocate a free id. Add functions to keep track of the used ids in the namespace so that we avoid collisions.
This commit is contained in:
parent
ce2078dd4f
commit
13f83149e1
2 changed files with 86 additions and 0 deletions
|
|
@ -83,6 +83,11 @@ typedef struct {
|
|||
* by IP address. */
|
||||
GHashTable *watcher_ip_data_idx;
|
||||
|
||||
/* Tracks reserved nexthop IDs. Maps guint32 id -> gconstpointer tag.
|
||||
* This is used to avoid nexthop ID collisions across different
|
||||
* interfaces/ndisc instances within the same network namespace. */
|
||||
GHashTable *nexthop_id_reserved;
|
||||
|
||||
CList l3cfg_signal_pending_lst_head;
|
||||
GSource *signal_pending_idle_source;
|
||||
} NMNetnsPrivate;
|
||||
|
|
@ -1521,6 +1526,76 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean
|
||||
nm_netns_nexthop_id_is_reserved(NMNetns *self, guint32 id)
|
||||
{
|
||||
NMNetnsPrivate *priv;
|
||||
|
||||
g_return_val_if_fail(NM_IS_NETNS(self), FALSE);
|
||||
nm_assert(id != 0);
|
||||
|
||||
priv = NM_NETNS_GET_PRIVATE(self);
|
||||
return g_hash_table_contains(priv->nexthop_id_reserved, GUINT_TO_POINTER(id));
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_netns_nexthop_id_reserve(NMNetns *self, guint32 id, gconstpointer tag)
|
||||
{
|
||||
NMNetnsPrivate *priv;
|
||||
gpointer existing_tag;
|
||||
|
||||
g_return_val_if_fail(NM_IS_NETNS(self), FALSE);
|
||||
nm_assert(id != 0);
|
||||
nm_assert(tag);
|
||||
|
||||
priv = NM_NETNS_GET_PRIVATE(self);
|
||||
|
||||
if (g_hash_table_lookup_extended(priv->nexthop_id_reserved,
|
||||
GUINT_TO_POINTER(id),
|
||||
NULL,
|
||||
&existing_tag)) {
|
||||
/* The ID is already reserved. If it's by the same tag, it's
|
||||
* idempotent; otherwise it's a collision. */
|
||||
return existing_tag == tag;
|
||||
}
|
||||
|
||||
g_hash_table_insert(priv->nexthop_id_reserved, GUINT_TO_POINTER(id), (gpointer) tag);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nm_netns_nexthop_id_release(NMNetns *self, guint32 id)
|
||||
{
|
||||
NMNetnsPrivate *priv;
|
||||
|
||||
g_return_if_fail(NM_IS_NETNS(self));
|
||||
nm_assert(id != 0);
|
||||
|
||||
priv = NM_NETNS_GET_PRIVATE(self);
|
||||
g_hash_table_remove(priv->nexthop_id_reserved, GUINT_TO_POINTER(id));
|
||||
}
|
||||
|
||||
void
|
||||
nm_netns_nexthop_id_release_all(NMNetns *self, gconstpointer tag)
|
||||
{
|
||||
NMNetnsPrivate *priv;
|
||||
GHashTableIter iter;
|
||||
gpointer value;
|
||||
|
||||
g_return_if_fail(NM_IS_NETNS(self));
|
||||
nm_assert(tag);
|
||||
|
||||
priv = NM_NETNS_GET_PRIVATE(self);
|
||||
|
||||
g_hash_table_iter_init(&iter, priv->nexthop_id_reserved);
|
||||
while (g_hash_table_iter_next(&iter, NULL, &value)) {
|
||||
if (value == tag)
|
||||
g_hash_table_iter_remove(&iter);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
nm_netns_init(NMNetns *self)
|
||||
{
|
||||
|
|
@ -1545,6 +1620,8 @@ nm_netns_init(NMNetns *self)
|
|||
(GDestroyNotify) _watcher_by_tag_destroy,
|
||||
NULL);
|
||||
priv->watcher_ip_data_idx = g_hash_table_new(_watcher_ip_data_hash, _watcher_ip_data_equal);
|
||||
|
||||
priv->nexthop_id_reserved = g_hash_table_new(nm_direct_hash, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1637,6 +1714,8 @@ dispose(GObject *object)
|
|||
nm_clear_pointer(&priv->watcher_by_tag_idx, g_hash_table_destroy);
|
||||
nm_clear_pointer(&priv->watcher_ip_data_idx, g_hash_table_destroy);
|
||||
|
||||
nm_clear_pointer(&priv->nexthop_id_reserved, g_hash_table_destroy);
|
||||
|
||||
nm_clear_g_source_inst(&priv->signal_pending_idle_source);
|
||||
|
||||
if (priv->platform)
|
||||
|
|
|
|||
|
|
@ -109,4 +109,11 @@ void nm_netns_watcher_add(NMNetns *self,
|
|||
void nm_netns_watcher_remove_all(NMNetns *self, gconstpointer tag);
|
||||
void nm_netns_watcher_remove_dirty(NMNetns *self, gconstpointer tag);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean nm_netns_nexthop_id_is_reserved(NMNetns *self, guint32 id);
|
||||
gboolean nm_netns_nexthop_id_reserve(NMNetns *self, guint32 id, gconstpointer tag);
|
||||
void nm_netns_nexthop_id_release(NMNetns *self, guint32 id);
|
||||
void nm_netns_nexthop_id_release_all(NMNetns *self, gconstpointer tag);
|
||||
|
||||
#endif /* __NM_NETNS_H__ */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue