diff options
author | Thomas Haller <thaller@redhat.com> | 2020-09-14 15:07:18 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2020-09-14 17:28:10 +0200 |
commit | 3fcfb53c4b8d9c8c84008a01d0cc8e7cd7eff2e8 (patch) | |
tree | 85c5c5ce6b0d736649ef2a294a3a10303f5d04c5 | |
parent | 991999489a300fb623e0fc4b5b6e465f94c79352 (diff) | |
download | NetworkManager-3fcfb53c4b8d9c8c84008a01d0cc8e7cd7eff2e8.tar.gz |
core: add nm_netns_shared_ip_reserve() API
Add a better way of tracking the shared IP addresses that are in use.
This will replace NMDevice's usage of a global hash table. For one, the
API is more formalized with reserve() and release() functions.
Also, it ties the used IP addresses to the netns, which would be more
correct (in the future when we may support more netns).
-rw-r--r-- | src/nm-netns.c | 108 | ||||
-rw-r--r-- | src/nm-netns.h | 12 |
2 files changed, 120 insertions, 0 deletions
diff --git a/src/nm-netns.c b/src/nm-netns.c index cf0e5f0b6b..a9596eaf00 100644 --- a/src/nm-netns.c +++ b/src/nm-netns.c @@ -28,6 +28,7 @@ typedef struct { NMPNetns *platform_netns; NMPRulesManager *rules_manager; GHashTable *l3cfgs; + GHashTable *shared_ips; CList l3cfg_signal_pending_lst_head; guint signal_pending_idle_id; } NMNetnsPrivate; @@ -218,6 +219,112 @@ _platform_signal_cb (NMPlatform *platform, /*****************************************************************************/ +NMNetnsSharedIPHandle * +nm_netns_shared_ip_reserve (NMNetns *self) +{ + NMNetnsPrivate *priv; + NMNetnsSharedIPHandle *handle; + const in_addr_t addr_start = ntohl (0x0a2a0001u); /* 10.42.0.1 */ + in_addr_t addr; + char sbuf_addr[NM_UTILS_INET_ADDRSTRLEN]; + + /* Find an unused address in the 10.42.x.x range */ + + g_return_val_if_fail (NM_IS_NETNS (self), NULL); + + priv = NM_NETNS_GET_PRIVATE (self); + + if (!priv->shared_ips) { + addr = addr_start; + priv->shared_ips = g_hash_table_new (nm_puint32_hash, nm_puint32_equals); + g_object_ref (self); + } else { + guint32 count; + + nm_assert (g_hash_table_size (priv->shared_ips) > 0); + + count = 0u; + for (;;) { + addr = addr_start + htonl (count << 8u); + + handle = g_hash_table_lookup (priv->shared_ips, &addr); + if (!handle) + break; + + count++; + + if (count > 0xFFu) { + if (handle->_ref_count == 1) { + _LOGE ("shared-ip4: ran out of shared IP addresses. Reuse %s/24", + _nm_utils_inet4_ntop (handle->addr, sbuf_addr)); + } else { + _LOGD ("shared-ip4: reserved IP address range %s/24 (duplicate)", + _nm_utils_inet4_ntop (handle->addr, sbuf_addr)); + } + handle->_ref_count++; + return handle; + } + } + } + + handle = g_slice_new (NMNetnsSharedIPHandle); + *handle = (NMNetnsSharedIPHandle) { + .addr = addr, + ._ref_count = 1, + ._self = self, + }; + + g_hash_table_add (priv->shared_ips, handle); + + _LOGD ("shared-ip4: reserved IP address range %s/24", + _nm_utils_inet4_ntop (handle->addr, sbuf_addr)); + return handle; +} + +void +nm_netns_shared_ip_release (NMNetnsSharedIPHandle *handle) +{ + NMNetns *self; + NMNetnsPrivate *priv; + char sbuf_addr[NM_UTILS_INET_ADDRSTRLEN]; + + g_return_if_fail (handle); + + self = handle->_self; + + g_return_if_fail (NM_IS_NETNS (self)); + + priv = NM_NETNS_GET_PRIVATE (self); + + nm_assert (handle->_ref_count > 0); + nm_assert (handle == nm_g_hash_table_lookup (priv->shared_ips, handle)); + + if (handle->_ref_count > 1) { + nm_assert (handle->addr == ntohl (0x0A2AFF01u)); /* 10.42.255.1 */ + handle->_ref_count--; + _LOGD ("shared-ip4: release IP address range %s/24 (%d more references held)", + _nm_utils_inet4_ntop (handle->addr, sbuf_addr), + handle->_ref_count); + return; + } + + if (!g_hash_table_remove (priv->shared_ips, handle)) + nm_assert_not_reached (); + + if (g_hash_table_size (priv->shared_ips) == 0) { + nm_clear_pointer (&priv->shared_ips, g_hash_table_unref); + g_object_unref (self); + } + + _LOGD ("shared-ip4: release IP address range %s/24", + _nm_utils_inet4_ntop (handle->addr, sbuf_addr)); + + handle->_self = NULL; + nm_g_slice_free (handle); +} + +/*****************************************************************************/ + static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) @@ -312,6 +419,7 @@ dispose (GObject *object) nm_assert (nm_g_hash_table_size (priv->l3cfgs) == 0); nm_assert (c_list_is_empty (&priv->l3cfg_signal_pending_lst_head)); + nm_assert (!priv->shared_ips); nm_clear_g_source (&priv->signal_pending_idle_id); diff --git a/src/nm-netns.h b/src/nm-netns.h index 2af0242b8d..080caa30e3 100644 --- a/src/nm-netns.h +++ b/src/nm-netns.h @@ -34,4 +34,16 @@ struct _NMDedupMultiIndex *nm_netns_get_multi_idx (NMNetns *self); NML3Cfg *nm_netns_access_l3cfg (NMNetns *netns, int ifindex); +/*****************************************************************************/ + +typedef struct { + in_addr_t addr; + int _ref_count; + NMNetns *_self; +} NMNetnsSharedIPHandle; + +NMNetnsSharedIPHandle *nm_netns_shared_ip_reserve (NMNetns *self); + +void nm_netns_shared_ip_release (NMNetnsSharedIPHandle *handle); + #endif /* __NM_NETNS_H__ */ |