device: merge branch 'th/device-track-shared-ips'

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/625
This commit is contained in:
Thomas Haller 2020-09-15 12:01:52 +02:00
commit 88425e569f
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
3 changed files with 133 additions and 37 deletions

View file

@ -327,6 +327,8 @@ typedef struct _NMDevicePrivate {
const NML3ConfigData *l3cds[_L3_CONFIG_DATA_TYPE_NUM];
NMNetnsSharedIPHandle *shared_ip_handle;
int parent_ifindex;
int auth_retries;
@ -9649,21 +9651,11 @@ nm_device_dhcp4_renew (NMDevice *self, gboolean release)
/*****************************************************************************/
static GHashTable *shared_ips = NULL;
static void
shared_ip_release (gpointer data)
{
g_hash_table_remove (shared_ips, data);
if (!g_hash_table_size (shared_ips))
nm_clear_pointer (&shared_ips, g_hash_table_unref);
}
static NMIP4Config *
shared4_new_config (NMDevice *self, NMConnection *connection)
{
NMIP4Config *config = NULL;
gboolean is_generated = FALSE;
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMIP4Config *config;
NMSettingIPConfig *s_ip4;
NMPlatformIP4Address address = {
.addr_source = NM_IP_CONFIG_SOURCE_SHARED,
@ -9673,42 +9665,24 @@ shared4_new_config (NMDevice *self, NMConnection *connection)
g_return_val_if_fail (connection, NULL);
s_ip4 = nm_connection_get_setting_ip4_config (connection);
if (s_ip4 && nm_setting_ip_config_get_num_addresses (s_ip4)) {
if ( s_ip4
&& nm_setting_ip_config_get_num_addresses (s_ip4) > 0) {
/* Use the first user-supplied address */
NMIPAddress *user = nm_setting_ip_config_get_address (s_ip4, 0);
in_addr_t a;
nm_ip_address_get_address_binary (user, &a);
nm_platform_ip4_address_set_addr (&address, a, nm_ip_address_get_prefix (user));
nm_clear_pointer (&priv->shared_ip_handle, nm_netns_shared_ip_release);
} else {
/* Find an unused address in the 10.42.x.x range */
guint32 start = (guint32) ntohl (0x0a2a0001); /* 10.42.0.1 */
guint32 count = 0;
if (G_UNLIKELY (!shared_ips))
shared_ips = g_hash_table_new (nm_direct_hash, NULL);
else {
while (g_hash_table_lookup (shared_ips, GUINT_TO_POINTER (start + count))) {
count += ntohl (0x100);
if (count > ntohl (0xFE00)) {
_LOGE (LOGD_SHARING, "ran out of shared IP addresses!");
return FALSE;
}
}
}
nm_platform_ip4_address_set_addr (&address, start + count, 24);
g_hash_table_add (shared_ips, GUINT_TO_POINTER (address.address));
is_generated = TRUE;
if (!priv->shared_ip_handle)
priv->shared_ip_handle = nm_netns_shared_ip_reserve (nm_device_get_netns (self));
nm_platform_ip4_address_set_addr (&address, priv->shared_ip_handle->addr, 24);
}
config = nm_device_ip4_config_new (self);
nm_ip4_config_add_address (config, &address);
if (is_generated) {
/* Remove the address lock when the object gets disposed */
g_object_set_qdata_full (G_OBJECT (config), NM_CACHED_QUARK ("shared-ip"),
GUINT_TO_POINTER (address.address),
shared_ip_release);
}
return config;
}
@ -15936,6 +15910,8 @@ _cleanup_generic_pre (NMDevice *self, CleanupType cleanup_type)
queued_state_clear (self);
nm_clear_pointer (&priv->shared_ip_handle, nm_netns_shared_ip_release);
_cleanup_ip_pre (self, AF_INET, cleanup_type);
_cleanup_ip_pre (self, AF_INET6, cleanup_type);
}

View file

@ -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);

View file

@ -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__ */