summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-09-14 15:07:18 +0200
committerThomas Haller <thaller@redhat.com>2020-09-14 17:28:10 +0200
commit3fcfb53c4b8d9c8c84008a01d0cc8e7cd7eff2e8 (patch)
tree85c5c5ce6b0d736649ef2a294a3a10303f5d04c5
parent991999489a300fb623e0fc4b5b6e465f94c79352 (diff)
downloadNetworkManager-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.c108
-rw-r--r--src/nm-netns.h12
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__ */