1621 lines
73 KiB
Diff
1621 lines
73 KiB
Diff
From f79d5a903b769f45f084d81a732ec9b3dcc3f2a9 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Wed, 1 Sep 2021 09:30:29 +0200
|
|
Subject: [PATCH 01/10] cloud-setup: return structure for get_config() result
|
|
instead of generic hash table
|
|
|
|
Returning a struct seems easier to understand, because then the result
|
|
is typed.
|
|
|
|
Also, we might return additional results, which are system wide and not
|
|
per-interface.
|
|
|
|
(cherry picked from commit 323e18276894591712a5e29f6e907562c79c5216)
|
|
(cherry picked from commit c94b1c43d4b5c5b88d67d7966d23a005028e78d8)
|
|
---
|
|
src/nm-cloud-setup/main.c | 54 ++++++++++++++++--------------
|
|
src/nm-cloud-setup/nmcs-provider.c | 28 ++++++++++++++--
|
|
src/nm-cloud-setup/nmcs-provider.h | 20 ++++++++++-
|
|
3 files changed, 72 insertions(+), 30 deletions(-)
|
|
|
|
diff --git a/src/nm-cloud-setup/main.c b/src/nm-cloud-setup/main.c
|
|
index 8dc67851794c..04b29f8a4b74 100644
|
|
--- a/src/nm-cloud-setup/main.c
|
|
+++ b/src/nm-cloud-setup/main.c
|
|
@@ -200,30 +200,30 @@ _nmc_get_device_by_hwaddr(NMClient *nmc, const char *hwaddr)
|
|
/*****************************************************************************/
|
|
|
|
typedef struct {
|
|
- GMainLoop * main_loop;
|
|
- GHashTable *config_dict;
|
|
+ GMainLoop * main_loop;
|
|
+ NMCSProviderGetConfigResult *result;
|
|
} GetConfigData;
|
|
|
|
static void
|
|
-_get_config_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
|
+_get_config_cb(GObject *source, GAsyncResult *res, gpointer user_data)
|
|
{
|
|
- GetConfigData * data = user_data;
|
|
- gs_unref_hashtable GHashTable *config_dict = NULL;
|
|
- gs_free_error GError *error = NULL;
|
|
+ GetConfigData * data = user_data;
|
|
+ nm_auto_free_nmcs_provider_get_config_result NMCSProviderGetConfigResult *result = NULL;
|
|
+ gs_free_error GError *error = NULL;
|
|
|
|
- config_dict = nmcs_provider_get_config_finish(NMCS_PROVIDER(source), result, &error);
|
|
+ result = nmcs_provider_get_config_finish(NMCS_PROVIDER(source), res, &error);
|
|
|
|
- if (!config_dict) {
|
|
+ if (!result) {
|
|
if (!nm_utils_error_is_cancelled(error))
|
|
_LOGI("failure to get meta data: %s", error->message);
|
|
} else
|
|
_LOGD("meta data received");
|
|
|
|
- data->config_dict = g_steal_pointer(&config_dict);
|
|
+ data->result = g_steal_pointer(&result);
|
|
g_main_loop_quit(data->main_loop);
|
|
}
|
|
|
|
-static GHashTable *
|
|
+static NMCSProviderGetConfigResult *
|
|
_get_config(GCancellable *sigterm_cancellable, NMCSProvider *provider, NMClient *nmc)
|
|
{
|
|
nm_auto_unref_gmainloop GMainLoop *main_loop = g_main_loop_new(NULL, FALSE);
|
|
@@ -243,7 +243,7 @@ _get_config(GCancellable *sigterm_cancellable, NMCSProvider *provider, NMClient
|
|
|
|
g_main_loop_run(main_loop);
|
|
|
|
- return data.config_dict;
|
|
+ return data.result;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
@@ -396,13 +396,13 @@ _nmc_mangle_connection(NMDevice * device,
|
|
/*****************************************************************************/
|
|
|
|
static guint
|
|
-_config_data_get_num_valid(GHashTable *config_dict)
|
|
+_config_data_get_num_valid(const NMCSProviderGetConfigResult *result)
|
|
{
|
|
const NMCSProviderGetConfigIfaceData *config_data;
|
|
GHashTableIter h_iter;
|
|
guint n = 0;
|
|
|
|
- g_hash_table_iter_init(&h_iter, config_dict);
|
|
+ g_hash_table_iter_init(&h_iter, result->iface_datas);
|
|
while (g_hash_table_iter_next(&h_iter, NULL, (gpointer *) &config_data)) {
|
|
if (nmcs_provider_get_config_iface_data_is_valid(config_data))
|
|
n++;
|
|
@@ -525,7 +525,9 @@ try_again:
|
|
}
|
|
|
|
static gboolean
|
|
-_config_all(GCancellable *sigterm_cancellable, NMClient *nmc, GHashTable *config_dict)
|
|
+_config_all(GCancellable * sigterm_cancellable,
|
|
+ NMClient * nmc,
|
|
+ const NMCSProviderGetConfigResult *result)
|
|
{
|
|
GHashTableIter h_iter;
|
|
const NMCSProviderGetConfigIfaceData *c_config_data;
|
|
@@ -533,9 +535,9 @@ _config_all(GCancellable *sigterm_cancellable, NMClient *nmc, GHashTable *config
|
|
gboolean is_single_nic;
|
|
gboolean any_changes = FALSE;
|
|
|
|
- is_single_nic = (_config_data_get_num_valid(config_dict) <= 1);
|
|
+ is_single_nic = (_config_data_get_num_valid(result) <= 1);
|
|
|
|
- g_hash_table_iter_init(&h_iter, config_dict);
|
|
+ g_hash_table_iter_init(&h_iter, result->iface_datas);
|
|
while (g_hash_table_iter_next(&h_iter, (gpointer *) &c_hwaddr, (gpointer *) &c_config_data)) {
|
|
if (_config_one(sigterm_cancellable, nmc, is_single_nic, c_hwaddr, c_config_data))
|
|
any_changes = TRUE;
|
|
@@ -564,12 +566,12 @@ sigterm_handler(gpointer user_data)
|
|
int
|
|
main(int argc, const char *const *argv)
|
|
{
|
|
- gs_unref_object GCancellable * sigterm_cancellable = NULL;
|
|
- nm_auto_destroy_and_unref_gsource GSource *sigterm_source = NULL;
|
|
- gs_unref_object NMCSProvider *provider = NULL;
|
|
- gs_unref_object NMClient *nmc = NULL;
|
|
- gs_unref_hashtable GHashTable *config_dict = NULL;
|
|
- gs_free_error GError *error = NULL;
|
|
+ gs_unref_object GCancellable * sigterm_cancellable = NULL;
|
|
+ nm_auto_destroy_and_unref_gsource GSource *sigterm_source = NULL;
|
|
+ gs_unref_object NMCSProvider *provider = NULL;
|
|
+ gs_unref_object NMClient * nmc = NULL;
|
|
+ nm_auto_free_nmcs_provider_get_config_result NMCSProviderGetConfigResult *result = NULL;
|
|
+ gs_free_error GError *error = NULL;
|
|
|
|
_nm_logging_enabled_init(g_getenv(NMCS_ENV_VARIABLE("NM_CLOUD_SETUP_LOG")));
|
|
|
|
@@ -614,17 +616,17 @@ main(int argc, const char *const *argv)
|
|
goto done;
|
|
}
|
|
|
|
- config_dict = _get_config(sigterm_cancellable, provider, nmc);
|
|
- if (!config_dict)
|
|
+ result = _get_config(sigterm_cancellable, provider, nmc);
|
|
+ if (!result)
|
|
goto done;
|
|
|
|
- if (_config_all(sigterm_cancellable, nmc, config_dict))
|
|
+ if (_config_all(sigterm_cancellable, nmc, result))
|
|
_LOGI("some changes were applied for provider %s", nmcs_provider_get_name(provider));
|
|
else
|
|
_LOGD("no changes were applied for provider %s", nmcs_provider_get_name(provider));
|
|
|
|
done:
|
|
- nm_clear_pointer(&config_dict, g_hash_table_unref);
|
|
+ nm_clear_pointer(&result, nmcs_provider_get_config_result_free);
|
|
g_clear_object(&nmc);
|
|
g_clear_object(&provider);
|
|
|
|
diff --git a/src/nm-cloud-setup/nmcs-provider.c b/src/nm-cloud-setup/nmcs-provider.c
|
|
index 678152aa95e0..77f8090a8225 100644
|
|
--- a/src/nm-cloud-setup/nmcs-provider.c
|
|
+++ b/src/nm-cloud-setup/nmcs-provider.c
|
|
@@ -49,6 +49,28 @@ nmcs_provider_get_main_context(NMCSProvider *self)
|
|
|
|
return nm_http_client_get_main_context(NMCS_PROVIDER_GET_PRIVATE(self)->http_client);
|
|
}
|
|
+/*****************************************************************************/
|
|
+
|
|
+static NMCSProviderGetConfigResult *
|
|
+nmcs_provider_get_config_result_new(GHashTable *iface_datas)
|
|
+{
|
|
+ NMCSProviderGetConfigResult *result;
|
|
+
|
|
+ result = g_new(NMCSProviderGetConfigResult, 1);
|
|
+ *result = (NMCSProviderGetConfigResult){
|
|
+ .iface_datas = g_hash_table_ref(iface_datas),
|
|
+ };
|
|
+ return result;
|
|
+}
|
|
+
|
|
+void
|
|
+nmcs_provider_get_config_result_free(NMCSProviderGetConfigResult *result)
|
|
+{
|
|
+ if (result) {
|
|
+ nm_g_hash_table_unref(result->iface_datas);
|
|
+ g_free(result);
|
|
+ }
|
|
+}
|
|
|
|
/*****************************************************************************/
|
|
|
|
@@ -137,8 +159,8 @@ _get_config_task_maybe_return(NMCSProviderGetConfigTaskData *get_config_data, GE
|
|
} else {
|
|
_LOGD("get-config: success");
|
|
g_task_return_pointer(get_config_data->task,
|
|
- g_hash_table_ref(get_config_data->result_dict),
|
|
- (GDestroyNotify) g_hash_table_unref);
|
|
+ nmcs_provider_get_config_result_new(get_config_data->result_dict),
|
|
+ (GDestroyNotify) nmcs_provider_get_config_result_free);
|
|
}
|
|
|
|
nm_clear_g_signal_handler(g_task_get_cancellable(get_config_data->task),
|
|
@@ -217,7 +239,7 @@ nmcs_provider_get_config(NMCSProvider * self,
|
|
NMCS_PROVIDER_GET_CLASS(self)->get_config(self, get_config_data);
|
|
}
|
|
|
|
-GHashTable *
|
|
+NMCSProviderGetConfigResult *
|
|
nmcs_provider_get_config_finish(NMCSProvider *self, GAsyncResult *result, GError **error)
|
|
{
|
|
g_return_val_if_fail(NMCS_IS_PROVIDER(self), FALSE);
|
|
diff --git a/src/nm-cloud-setup/nmcs-provider.h b/src/nm-cloud-setup/nmcs-provider.h
|
|
index 13212b8e4cb4..730ddc9d8f09 100644
|
|
--- a/src/nm-cloud-setup/nmcs-provider.h
|
|
+++ b/src/nm-cloud-setup/nmcs-provider.h
|
|
@@ -43,6 +43,24 @@ nmcs_provider_get_config_iface_data_is_valid(const NMCSProviderGetConfigIfaceDat
|
|
|
|
NMCSProviderGetConfigIfaceData *nmcs_provider_get_config_iface_data_new(gboolean was_requested);
|
|
|
|
+/*****************************************************************************/
|
|
+
|
|
+typedef struct {
|
|
+ /* A dictionary of (const char *) -> (NMCSProviderGetConfigIfaceData *).
|
|
+ * This is the per-interface result of get_config(). */
|
|
+ GHashTable *iface_datas;
|
|
+} NMCSProviderGetConfigResult;
|
|
+
|
|
+void nmcs_provider_get_config_result_free(NMCSProviderGetConfigResult *result);
|
|
+
|
|
+NM_AUTO_DEFINE_FCN0(NMCSProviderGetConfigResult *,
|
|
+ _nm_auto_free_nmcs_provider_get_config_result,
|
|
+ nmcs_provider_get_config_result_free);
|
|
+#define nm_auto_free_nmcs_provider_get_config_result \
|
|
+ nm_auto(_nm_auto_free_nmcs_provider_get_config_result)
|
|
+
|
|
+/*****************************************************************************/
|
|
+
|
|
typedef struct {
|
|
GTask *task;
|
|
|
|
@@ -124,7 +142,7 @@ void nmcs_provider_get_config(NMCSProvider * provider,
|
|
GAsyncReadyCallback callback,
|
|
gpointer user_data);
|
|
|
|
-GHashTable *
|
|
+NMCSProviderGetConfigResult *
|
|
nmcs_provider_get_config_finish(NMCSProvider *provider, GAsyncResult *result, GError **error);
|
|
|
|
#endif /* __NMCS_PROVIDER_H__ */
|
|
--
|
|
2.31.1
|
|
|
|
|
|
From 165dd652446673c826ef0da33b865da359aa22ee Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Wed, 1 Sep 2021 09:42:37 +0200
|
|
Subject: [PATCH 02/10] cloud-setup: cache number of valid interfaces in
|
|
get-config result
|
|
|
|
Now that we return a struct from get_config(), we can have system-wide
|
|
properties returned.
|
|
|
|
Let it count and cache the number of valid iface_datas.
|
|
|
|
Currently that is not yet used, but it will be.
|
|
|
|
(cherry picked from commit a3cd66d3fadcecab9b186cc7f634f6ec6a5a92ee)
|
|
(cherry picked from commit e74375fc3b68b07d1ed5f6ebca40cbe5b20ed47b)
|
|
---
|
|
src/nm-cloud-setup/main.c | 22 +---------------------
|
|
src/nm-cloud-setup/nmcs-provider.c | 15 +++++++++++++--
|
|
src/nm-cloud-setup/nmcs-provider.h | 3 +++
|
|
3 files changed, 17 insertions(+), 23 deletions(-)
|
|
|
|
diff --git a/src/nm-cloud-setup/main.c b/src/nm-cloud-setup/main.c
|
|
index 04b29f8a4b74..686cd2fc0c84 100644
|
|
--- a/src/nm-cloud-setup/main.c
|
|
+++ b/src/nm-cloud-setup/main.c
|
|
@@ -395,26 +395,9 @@ _nmc_mangle_connection(NMDevice * device,
|
|
|
|
/*****************************************************************************/
|
|
|
|
-static guint
|
|
-_config_data_get_num_valid(const NMCSProviderGetConfigResult *result)
|
|
-{
|
|
- const NMCSProviderGetConfigIfaceData *config_data;
|
|
- GHashTableIter h_iter;
|
|
- guint n = 0;
|
|
-
|
|
- g_hash_table_iter_init(&h_iter, result->iface_datas);
|
|
- while (g_hash_table_iter_next(&h_iter, NULL, (gpointer *) &config_data)) {
|
|
- if (nmcs_provider_get_config_iface_data_is_valid(config_data))
|
|
- n++;
|
|
- }
|
|
-
|
|
- return n;
|
|
-}
|
|
-
|
|
static gboolean
|
|
_config_one(GCancellable * sigterm_cancellable,
|
|
NMClient * nmc,
|
|
- gboolean is_single_nic,
|
|
const char * hwaddr,
|
|
const NMCSProviderGetConfigIfaceData *config_data)
|
|
{
|
|
@@ -532,14 +515,11 @@ _config_all(GCancellable * sigterm_cancellable,
|
|
GHashTableIter h_iter;
|
|
const NMCSProviderGetConfigIfaceData *c_config_data;
|
|
const char * c_hwaddr;
|
|
- gboolean is_single_nic;
|
|
gboolean any_changes = FALSE;
|
|
|
|
- is_single_nic = (_config_data_get_num_valid(result) <= 1);
|
|
-
|
|
g_hash_table_iter_init(&h_iter, result->iface_datas);
|
|
while (g_hash_table_iter_next(&h_iter, (gpointer *) &c_hwaddr, (gpointer *) &c_config_data)) {
|
|
- if (_config_one(sigterm_cancellable, nmc, is_single_nic, c_hwaddr, c_config_data))
|
|
+ if (_config_one(sigterm_cancellable, nmc, c_hwaddr, c_config_data))
|
|
any_changes = TRUE;
|
|
}
|
|
|
|
diff --git a/src/nm-cloud-setup/nmcs-provider.c b/src/nm-cloud-setup/nmcs-provider.c
|
|
index 77f8090a8225..8f82ddb493ea 100644
|
|
--- a/src/nm-cloud-setup/nmcs-provider.c
|
|
+++ b/src/nm-cloud-setup/nmcs-provider.c
|
|
@@ -54,12 +54,23 @@ nmcs_provider_get_main_context(NMCSProvider *self)
|
|
static NMCSProviderGetConfigResult *
|
|
nmcs_provider_get_config_result_new(GHashTable *iface_datas)
|
|
{
|
|
- NMCSProviderGetConfigResult *result;
|
|
+ const NMCSProviderGetConfigIfaceData *iface_data;
|
|
+ NMCSProviderGetConfigResult * result;
|
|
+ GHashTableIter h_iter;
|
|
+ guint num_valid_ifaces = 0;
|
|
+
|
|
+ g_hash_table_iter_init(&h_iter, iface_datas);
|
|
+ while (g_hash_table_iter_next(&h_iter, NULL, (gpointer *) &iface_data)) {
|
|
+ if (nmcs_provider_get_config_iface_data_is_valid(iface_data))
|
|
+ num_valid_ifaces++;
|
|
+ }
|
|
|
|
result = g_new(NMCSProviderGetConfigResult, 1);
|
|
*result = (NMCSProviderGetConfigResult){
|
|
- .iface_datas = g_hash_table_ref(iface_datas),
|
|
+ .iface_datas = g_hash_table_ref(iface_datas),
|
|
+ .num_valid_ifaces = num_valid_ifaces,
|
|
};
|
|
+
|
|
return result;
|
|
}
|
|
|
|
diff --git a/src/nm-cloud-setup/nmcs-provider.h b/src/nm-cloud-setup/nmcs-provider.h
|
|
index 730ddc9d8f09..2e4c8d167a73 100644
|
|
--- a/src/nm-cloud-setup/nmcs-provider.h
|
|
+++ b/src/nm-cloud-setup/nmcs-provider.h
|
|
@@ -49,6 +49,9 @@ typedef struct {
|
|
/* A dictionary of (const char *) -> (NMCSProviderGetConfigIfaceData *).
|
|
* This is the per-interface result of get_config(). */
|
|
GHashTable *iface_datas;
|
|
+
|
|
+ /* The number of iface_datas that are nmcs_provider_get_config_iface_data_is_valid(). */
|
|
+ guint num_valid_ifaces;
|
|
} NMCSProviderGetConfigResult;
|
|
|
|
void nmcs_provider_get_config_result_free(NMCSProviderGetConfigResult *result);
|
|
--
|
|
2.31.1
|
|
|
|
|
|
From 2e6d23ef2496b7a26f6406fab1d274eee66467af Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Wed, 1 Sep 2021 10:11:31 +0200
|
|
Subject: [PATCH 03/10] cloud-setup: count numbers of valid IPv4 addresses in
|
|
get-config result
|
|
|
|
Will be used next.
|
|
|
|
(cherry picked from commit 7969ae1a82b90c3a9dbe33875d138c7b55cf6ac8)
|
|
(cherry picked from commit ae504433f11480fde2436d3a5acba026db6c47bd)
|
|
---
|
|
src/nm-cloud-setup/nmcs-provider.c | 6 +++++-
|
|
src/nm-cloud-setup/nmcs-provider.h | 3 +++
|
|
2 files changed, 8 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/nm-cloud-setup/nmcs-provider.c b/src/nm-cloud-setup/nmcs-provider.c
|
|
index 8f82ddb493ea..8901100378d0 100644
|
|
--- a/src/nm-cloud-setup/nmcs-provider.c
|
|
+++ b/src/nm-cloud-setup/nmcs-provider.c
|
|
@@ -58,17 +58,21 @@ nmcs_provider_get_config_result_new(GHashTable *iface_datas)
|
|
NMCSProviderGetConfigResult * result;
|
|
GHashTableIter h_iter;
|
|
guint num_valid_ifaces = 0;
|
|
+ guint num_ipv4s = 0;
|
|
|
|
g_hash_table_iter_init(&h_iter, iface_datas);
|
|
while (g_hash_table_iter_next(&h_iter, NULL, (gpointer *) &iface_data)) {
|
|
- if (nmcs_provider_get_config_iface_data_is_valid(iface_data))
|
|
+ if (nmcs_provider_get_config_iface_data_is_valid(iface_data)) {
|
|
num_valid_ifaces++;
|
|
+ num_ipv4s += iface_data->ipv4s_len;
|
|
+ }
|
|
}
|
|
|
|
result = g_new(NMCSProviderGetConfigResult, 1);
|
|
*result = (NMCSProviderGetConfigResult){
|
|
.iface_datas = g_hash_table_ref(iface_datas),
|
|
.num_valid_ifaces = num_valid_ifaces,
|
|
+ .num_ipv4s = num_ipv4s,
|
|
};
|
|
|
|
return result;
|
|
diff --git a/src/nm-cloud-setup/nmcs-provider.h b/src/nm-cloud-setup/nmcs-provider.h
|
|
index 2e4c8d167a73..31fec4449f9e 100644
|
|
--- a/src/nm-cloud-setup/nmcs-provider.h
|
|
+++ b/src/nm-cloud-setup/nmcs-provider.h
|
|
@@ -52,6 +52,9 @@ typedef struct {
|
|
|
|
/* The number of iface_datas that are nmcs_provider_get_config_iface_data_is_valid(). */
|
|
guint num_valid_ifaces;
|
|
+
|
|
+ /* the number of IPv4 addresses over all valid iface_datas. */
|
|
+ guint num_ipv4s;
|
|
} NMCSProviderGetConfigResult;
|
|
|
|
void nmcs_provider_get_config_result_free(NMCSProviderGetConfigResult *result);
|
|
--
|
|
2.31.1
|
|
|
|
|
|
From d80ef34f9390eb2baecb863cbbeded3dbffa1d8e Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Wed, 1 Sep 2021 10:15:37 +0200
|
|
Subject: [PATCH 04/10] cloud-setup: skip configuring policy routing if there
|
|
is only one interface/address
|
|
|
|
nm-cloud-setup automatically configures the network. That may conflict
|
|
with what the user wants. In case the user configures some specific
|
|
setup, they are encouraged to disable nm-cloud-setup (and its
|
|
automatism).
|
|
|
|
Still, what we do by default matters, and should play as well with
|
|
user's expectations. Configuring policy routing and a higher priority
|
|
table (30400+) that hijacks the traffic can cause problems.
|
|
|
|
If the system only has one IPv4 address and one interface, then there
|
|
is no point in configuring policy routing at all. Detect that, and skip
|
|
the change in that case.
|
|
|
|
Note that of course we need to handle the case where previously multiple
|
|
IP addresses were configured and an update gives only one address. In
|
|
that case we need to clear the previously configured rules/routes. The
|
|
patch achieves this.
|
|
|
|
(cherry picked from commit 5f047968d7a48999d20001f83e2005caa43c80ce)
|
|
(cherry picked from commit 8bc8a0f56b97c28cf26fd678a549db41399adcb7)
|
|
---
|
|
src/nm-cloud-setup/main.c | 41 +++++++++++++++++++++++++++++++--------
|
|
1 file changed, 33 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/src/nm-cloud-setup/main.c b/src/nm-cloud-setup/main.c
|
|
index 686cd2fc0c84..bb5c0d5ded9d 100644
|
|
--- a/src/nm-cloud-setup/main.c
|
|
+++ b/src/nm-cloud-setup/main.c
|
|
@@ -269,7 +269,9 @@ _nmc_skip_connection(NMConnection *connection)
|
|
static gboolean
|
|
_nmc_mangle_connection(NMDevice * device,
|
|
NMConnection * connection,
|
|
+ const NMCSProviderGetConfigResult * result,
|
|
const NMCSProviderGetConfigIfaceData *config_data,
|
|
+ gboolean * out_skipped_single_addr,
|
|
gboolean * out_changed)
|
|
{
|
|
NMSettingIPConfig * s_ip;
|
|
@@ -288,6 +290,9 @@ _nmc_mangle_connection(NMDevice * device,
|
|
gs_unref_ptrarray GPtrArray *rules_new = NULL;
|
|
gs_unref_ptrarray GPtrArray *routes_new = NULL;
|
|
|
|
+ NM_SET_OUT(out_skipped_single_addr, FALSE);
|
|
+ NM_SET_OUT(out_changed, FALSE);
|
|
+
|
|
if (!nm_streq0(nm_connection_get_connection_type(connection), NM_SETTING_WIRED_SETTING_NAME))
|
|
return FALSE;
|
|
|
|
@@ -329,7 +334,11 @@ _nmc_mangle_connection(NMDevice * device,
|
|
}
|
|
}
|
|
|
|
- if (config_data->has_ipv4s && config_data->has_cidr) {
|
|
+ if (result->num_valid_ifaces <= 1 && result->num_ipv4s <= 1) {
|
|
+ /* this setup only has one interface and one IPv4 address (or less).
|
|
+ * We don't need to configure policy routing in this case. */
|
|
+ NM_SET_OUT(out_skipped_single_addr, TRUE);
|
|
+ } else if (config_data->has_ipv4s && config_data->has_cidr) {
|
|
for (i = 0; i < config_data->ipv4s_len; i++) {
|
|
NMIPAddress *entry;
|
|
|
|
@@ -398,6 +407,7 @@ _nmc_mangle_connection(NMDevice * device,
|
|
static gboolean
|
|
_config_one(GCancellable * sigterm_cancellable,
|
|
NMClient * nmc,
|
|
+ const NMCSProviderGetConfigResult * result,
|
|
const char * hwaddr,
|
|
const NMCSProviderGetConfigIfaceData *config_data)
|
|
{
|
|
@@ -406,6 +416,7 @@ _config_one(GCancellable * sigterm_cancellable,
|
|
guint64 applied_version_id;
|
|
gs_free_error GError *error = NULL;
|
|
gboolean changed;
|
|
+ gboolean skipped_single_addr;
|
|
gboolean version_id_changed;
|
|
guint try_count;
|
|
gboolean any_changes = FALSE;
|
|
@@ -454,16 +465,30 @@ try_again:
|
|
return any_changes;
|
|
}
|
|
|
|
- if (!_nmc_mangle_connection(device, applied_connection, config_data, &changed)) {
|
|
+ if (!_nmc_mangle_connection(device,
|
|
+ applied_connection,
|
|
+ result,
|
|
+ config_data,
|
|
+ &skipped_single_addr,
|
|
+ &changed)) {
|
|
_LOGD("config device %s: device has no suitable applied connection. Skip", hwaddr);
|
|
return any_changes;
|
|
}
|
|
|
|
if (!changed) {
|
|
- _LOGD("config device %s: device needs no update to applied connection \"%s\" (%s). Skip",
|
|
- hwaddr,
|
|
- nm_connection_get_id(applied_connection),
|
|
- nm_connection_get_uuid(applied_connection));
|
|
+ if (skipped_single_addr) {
|
|
+ _LOGD("config device %s: device needs no update to applied connection \"%s\" (%s) "
|
|
+ "because there are not multiple IP addresses. Skip",
|
|
+ hwaddr,
|
|
+ nm_connection_get_id(applied_connection),
|
|
+ nm_connection_get_uuid(applied_connection));
|
|
+ } else {
|
|
+ _LOGD(
|
|
+ "config device %s: device needs no update to applied connection \"%s\" (%s). Skip",
|
|
+ hwaddr,
|
|
+ nm_connection_get_id(applied_connection),
|
|
+ nm_connection_get_uuid(applied_connection));
|
|
+ }
|
|
return any_changes;
|
|
}
|
|
|
|
@@ -472,7 +497,7 @@ try_again:
|
|
nm_connection_get_id(applied_connection),
|
|
nm_connection_get_uuid(applied_connection));
|
|
|
|
- /* we are about to call Reapply(). If if that fails, it counts as if we changed something. */
|
|
+ /* we are about to call Reapply(). Even if that fails, it counts as if we changed something. */
|
|
any_changes = TRUE;
|
|
|
|
if (!nmcs_device_reapply(device,
|
|
@@ -519,7 +544,7 @@ _config_all(GCancellable * sigterm_cancellable,
|
|
|
|
g_hash_table_iter_init(&h_iter, result->iface_datas);
|
|
while (g_hash_table_iter_next(&h_iter, (gpointer *) &c_hwaddr, (gpointer *) &c_config_data)) {
|
|
- if (_config_one(sigterm_cancellable, nmc, c_hwaddr, c_config_data))
|
|
+ if (_config_one(sigterm_cancellable, nmc, result, c_hwaddr, c_config_data))
|
|
any_changes = TRUE;
|
|
}
|
|
|
|
--
|
|
2.31.1
|
|
|
|
|
|
From 0042bff5e16e71f548dcb8d046a5dbd3f694de8f Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Wed, 1 Sep 2021 14:34:51 +0200
|
|
Subject: [PATCH 05/10] cloud-setup: add "hwaddr" to
|
|
NMCSProviderGetConfigIfaceData struct
|
|
|
|
get-config() gives a NMCSProviderGetConfigResult structure, and the
|
|
main part of data is the GHashTable of MAC addresses and
|
|
NMCSProviderGetConfigIfaceData instances.
|
|
|
|
Let NMCSProviderGetConfigIfaceData also have a reference to the MAC
|
|
address. This way, I'll be able to create a (sorted) list of interface
|
|
datas, that also contain the MAC address.
|
|
|
|
(cherry picked from commit ec56fe60fbf31768d0d1cae8bb325c1fdf7dbf07)
|
|
(cherry picked from commit cc289e53699872a3617aef321453ef6a885d0148)
|
|
---
|
|
src/nm-cloud-setup/nmcs-provider-aliyun.c | 32 ++++++++++-------------
|
|
src/nm-cloud-setup/nmcs-provider-azure.c | 21 +++++++--------
|
|
src/nm-cloud-setup/nmcs-provider-ec2.c | 27 ++++++++-----------
|
|
src/nm-cloud-setup/nmcs-provider-gcp.c | 20 +++++++-------
|
|
src/nm-cloud-setup/nmcs-provider.c | 22 +++++++++++-----
|
|
src/nm-cloud-setup/nmcs-provider.h | 12 +++++++--
|
|
6 files changed, 68 insertions(+), 66 deletions(-)
|
|
|
|
diff --git a/src/nm-cloud-setup/nmcs-provider-aliyun.c b/src/nm-cloud-setup/nmcs-provider-aliyun.c
|
|
index 01a4af0ff5b8..126980fdfe44 100644
|
|
--- a/src/nm-cloud-setup/nmcs-provider-aliyun.c
|
|
+++ b/src/nm-cloud-setup/nmcs-provider-aliyun.c
|
|
@@ -134,7 +134,6 @@ _get_config_fetch_done_cb(NMHttpClient * http_client,
|
|
GetConfigFetchDoneType fetch_type)
|
|
{
|
|
NMCSProviderGetConfigTaskData *get_config_data;
|
|
- const char * hwaddr = NULL;
|
|
gs_unref_bytes GBytes *response = NULL;
|
|
gs_free_error GError * error = NULL;
|
|
NMCSProviderGetConfigIfaceData *config_iface_data;
|
|
@@ -146,7 +145,7 @@ _get_config_fetch_done_cb(NMHttpClient * http_client,
|
|
gsize i;
|
|
gsize len;
|
|
|
|
- nm_utils_user_data_unpack(user_data, &get_config_data, &hwaddr);
|
|
+ nm_utils_user_data_unpack(user_data, &get_config_data, &config_iface_data);
|
|
|
|
nm_http_client_poll_get_finish(http_client, result, NULL, &response, &error);
|
|
|
|
@@ -156,8 +155,6 @@ _get_config_fetch_done_cb(NMHttpClient * http_client,
|
|
if (error)
|
|
goto out;
|
|
|
|
- config_iface_data = g_hash_table_lookup(get_config_data->result_dict, hwaddr);
|
|
-
|
|
switch (fetch_type) {
|
|
case GET_CONFIG_FETCH_DONE_TYPE_PRIVATE_IPV4S:
|
|
|
|
@@ -300,22 +297,21 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
|
|
gs_free char * uri2 = NULL;
|
|
gs_free char * uri3 = NULL;
|
|
gs_free char * uri4 = NULL;
|
|
- const char * hwaddr;
|
|
|
|
- if (!g_hash_table_lookup_extended(get_config_data->result_dict,
|
|
- v_hwaddr,
|
|
- (gpointer *) &hwaddr,
|
|
- (gpointer *) &config_iface_data)) {
|
|
+ config_iface_data = g_hash_table_lookup(get_config_data->result_dict, v_hwaddr);
|
|
+
|
|
+ if (!config_iface_data) {
|
|
if (!get_config_data->any) {
|
|
_LOGD("get-config: skip fetching meta data for %s (%s)",
|
|
v_hwaddr,
|
|
v_mac_data->path);
|
|
continue;
|
|
}
|
|
- config_iface_data = nmcs_provider_get_config_iface_data_new(FALSE);
|
|
- g_hash_table_insert(get_config_data->result_dict,
|
|
- (char *) (hwaddr = g_strdup(v_hwaddr)),
|
|
- config_iface_data);
|
|
+
|
|
+ config_iface_data =
|
|
+ nmcs_provider_get_config_iface_data_create(get_config_data->result_dict,
|
|
+ FALSE,
|
|
+ v_hwaddr);
|
|
}
|
|
|
|
nm_assert(config_iface_data->iface_idx == -1);
|
|
@@ -324,7 +320,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
|
|
|
|
_LOGD("get-config: start fetching meta data for #%" G_GSSIZE_FORMAT ", %s (%s)",
|
|
config_iface_data->iface_idx,
|
|
- hwaddr,
|
|
+ config_iface_data->hwaddr,
|
|
v_mac_data->path);
|
|
|
|
get_config_data->n_pending++;
|
|
@@ -342,7 +338,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
|
|
NULL,
|
|
NULL,
|
|
_get_config_fetch_done_cb_vpc_cidr_block,
|
|
- nm_utils_user_data_pack(get_config_data, hwaddr));
|
|
+ nm_utils_user_data_pack(get_config_data, config_iface_data));
|
|
|
|
get_config_data->n_pending++;
|
|
nm_http_client_poll_get(
|
|
@@ -359,7 +355,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
|
|
NULL,
|
|
NULL,
|
|
_get_config_fetch_done_cb_private_ipv4s,
|
|
- nm_utils_user_data_pack(get_config_data, hwaddr));
|
|
+ nm_utils_user_data_pack(get_config_data, config_iface_data));
|
|
|
|
get_config_data->n_pending++;
|
|
nm_http_client_poll_get(
|
|
@@ -376,7 +372,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
|
|
NULL,
|
|
NULL,
|
|
_get_config_fetch_done_cb_netmask,
|
|
- nm_utils_user_data_pack(get_config_data, hwaddr));
|
|
+ nm_utils_user_data_pack(get_config_data, config_iface_data));
|
|
|
|
get_config_data->n_pending++;
|
|
nm_http_client_poll_get(
|
|
@@ -393,7 +389,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
|
|
NULL,
|
|
NULL,
|
|
_get_config_fetch_done_cb_gateway,
|
|
- nm_utils_user_data_pack(get_config_data, hwaddr));
|
|
+ nm_utils_user_data_pack(get_config_data, config_iface_data));
|
|
}
|
|
|
|
_nmcs_provider_get_config_task_maybe_return(get_config_data, NULL);
|
|
diff --git a/src/nm-cloud-setup/nmcs-provider-azure.c b/src/nm-cloud-setup/nmcs-provider-azure.c
|
|
index 69785d64a8ac..b3f0c68ba666 100644
|
|
--- a/src/nm-cloud-setup/nmcs-provider-azure.c
|
|
+++ b/src/nm-cloud-setup/nmcs-provider-azure.c
|
|
@@ -97,7 +97,6 @@ typedef struct {
|
|
gssize intern_iface_idx;
|
|
gssize extern_iface_idx;
|
|
guint n_iface_data_pending;
|
|
- const char * hwaddr;
|
|
} AzureIfaceData;
|
|
|
|
static void
|
|
@@ -378,25 +377,24 @@ _get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
|
goto out_done;
|
|
}
|
|
|
|
- if (!g_hash_table_lookup_extended(get_config_data->result_dict,
|
|
- v_hwaddr,
|
|
- (gpointer *) &iface_data->hwaddr,
|
|
- (gpointer *) &iface_data->iface_get_config)) {
|
|
+ iface_data->iface_get_config = g_hash_table_lookup(get_config_data->result_dict, v_hwaddr);
|
|
+
|
|
+ if (!iface_data->iface_get_config) {
|
|
if (!get_config_data->any) {
|
|
_LOGD("get-config: skip fetching meta data for %s (%" G_GSSIZE_FORMAT ")",
|
|
v_hwaddr,
|
|
iface_data->intern_iface_idx);
|
|
goto out_done;
|
|
}
|
|
- iface_data->iface_get_config = nmcs_provider_get_config_iface_data_new(FALSE);
|
|
- g_hash_table_insert(get_config_data->result_dict,
|
|
- (char *) (iface_data->hwaddr = g_steal_pointer(&v_hwaddr)),
|
|
- iface_data->iface_get_config);
|
|
+ iface_data->iface_get_config =
|
|
+ nmcs_provider_get_config_iface_data_create(get_config_data->result_dict,
|
|
+ FALSE,
|
|
+ v_hwaddr);
|
|
} else {
|
|
if (iface_data->iface_get_config->iface_idx >= 0) {
|
|
_LOGI("interface[%" G_GSSIZE_FORMAT "]: duplicate MAC address %s returned",
|
|
iface_data->intern_iface_idx,
|
|
- iface_data->hwaddr);
|
|
+ iface_data->iface_get_config->hwaddr);
|
|
error = nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN,
|
|
"duplicate MAC address for index %" G_GSSIZE_FORMAT,
|
|
iface_data->intern_iface_idx);
|
|
@@ -408,7 +406,7 @@ _get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
|
|
|
_LOGD("interface[%" G_GSSIZE_FORMAT "]: found a matching device with hwaddr %s",
|
|
iface_data->intern_iface_idx,
|
|
- iface_data->hwaddr);
|
|
+ iface_data->iface_get_config->hwaddr);
|
|
|
|
nm_sprintf_buf(buf, "%" G_GSSIZE_FORMAT "/ipv4/ipAddress/", iface_data->intern_iface_idx);
|
|
|
|
@@ -488,7 +486,6 @@ _get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
|
|
.intern_iface_idx = intern_iface_idx,
|
|
.extern_iface_idx = extern_iface_idx_cnt++,
|
|
.n_iface_data_pending = 0,
|
|
- .hwaddr = NULL,
|
|
};
|
|
g_ptr_array_add(ifaces_arr, iface_data);
|
|
}
|
|
diff --git a/src/nm-cloud-setup/nmcs-provider-ec2.c b/src/nm-cloud-setup/nmcs-provider-ec2.c
|
|
index 6f83238d6871..9fe625182c35 100644
|
|
--- a/src/nm-cloud-setup/nmcs-provider-ec2.c
|
|
+++ b/src/nm-cloud-setup/nmcs-provider-ec2.c
|
|
@@ -122,14 +122,13 @@ _get_config_fetch_done_cb(NMHttpClient *http_client,
|
|
gboolean is_local_ipv4)
|
|
{
|
|
NMCSProviderGetConfigTaskData *get_config_data;
|
|
- const char * hwaddr = NULL;
|
|
gs_unref_bytes GBytes *response = NULL;
|
|
gs_free_error GError * error = NULL;
|
|
NMCSProviderGetConfigIfaceData *config_iface_data;
|
|
in_addr_t tmp_addr;
|
|
int tmp_prefix;
|
|
|
|
- nm_utils_user_data_unpack(user_data, &get_config_data, &hwaddr);
|
|
+ nm_utils_user_data_unpack(user_data, &get_config_data, &config_iface_data);
|
|
|
|
nm_http_client_poll_get_finish(http_client, result, NULL, &response, &error);
|
|
|
|
@@ -139,8 +138,6 @@ _get_config_fetch_done_cb(NMHttpClient *http_client,
|
|
if (error)
|
|
goto out;
|
|
|
|
- config_iface_data = g_hash_table_lookup(get_config_data->result_dict, hwaddr);
|
|
-
|
|
if (is_local_ipv4) {
|
|
gs_free const char **s_addrs = NULL;
|
|
gsize i, len;
|
|
@@ -236,22 +233,20 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
|
|
NMCSProviderGetConfigIfaceData *config_iface_data;
|
|
gs_free char * uri1 = NULL;
|
|
gs_free char * uri2 = NULL;
|
|
- const char * hwaddr;
|
|
|
|
- if (!g_hash_table_lookup_extended(get_config_data->result_dict,
|
|
- v_hwaddr,
|
|
- (gpointer *) &hwaddr,
|
|
- (gpointer *) &config_iface_data)) {
|
|
+ config_iface_data = g_hash_table_lookup(get_config_data->result_dict, v_hwaddr);
|
|
+
|
|
+ if (!config_iface_data) {
|
|
if (!get_config_data->any) {
|
|
_LOGD("get-config: skip fetching meta data for %s (%s)",
|
|
v_hwaddr,
|
|
v_mac_data->path);
|
|
continue;
|
|
}
|
|
- config_iface_data = nmcs_provider_get_config_iface_data_new(FALSE);
|
|
- g_hash_table_insert(get_config_data->result_dict,
|
|
- (char *) (hwaddr = g_strdup(v_hwaddr)),
|
|
- config_iface_data);
|
|
+ config_iface_data =
|
|
+ nmcs_provider_get_config_iface_data_create(get_config_data->result_dict,
|
|
+ FALSE,
|
|
+ v_hwaddr);
|
|
}
|
|
|
|
nm_assert(config_iface_data->iface_idx == -1);
|
|
@@ -260,7 +255,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
|
|
|
|
_LOGD("get-config: start fetching meta data for #%" G_GSSIZE_FORMAT ", %s (%s)",
|
|
config_iface_data->iface_idx,
|
|
- hwaddr,
|
|
+ config_iface_data->hwaddr,
|
|
v_mac_data->path);
|
|
|
|
get_config_data->n_pending++;
|
|
@@ -278,7 +273,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
|
|
NULL,
|
|
NULL,
|
|
_get_config_fetch_done_cb_subnet_ipv4_cidr_block,
|
|
- nm_utils_user_data_pack(get_config_data, hwaddr));
|
|
+ nm_utils_user_data_pack(get_config_data, config_iface_data));
|
|
|
|
get_config_data->n_pending++;
|
|
nm_http_client_poll_get(
|
|
@@ -295,7 +290,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
|
|
NULL,
|
|
NULL,
|
|
_get_config_fetch_done_cb_local_ipv4s,
|
|
- nm_utils_user_data_pack(get_config_data, hwaddr));
|
|
+ nm_utils_user_data_pack(get_config_data, config_iface_data));
|
|
}
|
|
|
|
_nmcs_provider_get_config_task_maybe_return(get_config_data, NULL);
|
|
diff --git a/src/nm-cloud-setup/nmcs-provider-gcp.c b/src/nm-cloud-setup/nmcs-provider-gcp.c
|
|
index eacfd5e24805..60425ad97868 100644
|
|
--- a/src/nm-cloud-setup/nmcs-provider-gcp.c
|
|
+++ b/src/nm-cloud-setup/nmcs-provider-gcp.c
|
|
@@ -247,7 +247,6 @@ _get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
|
GCPIfaceData * iface_data = user_data;
|
|
gs_free_error GError * error = NULL;
|
|
gs_free char * v_hwaddr = NULL;
|
|
- const char * hwaddr = NULL;
|
|
gs_free const char * uri = NULL;
|
|
char sbuf[100];
|
|
NMCSProviderGetConfigTaskData *get_config_data;
|
|
@@ -273,26 +272,25 @@ _get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
|
goto out_done;
|
|
}
|
|
|
|
- if (!g_hash_table_lookup_extended(get_config_data->result_dict,
|
|
- v_hwaddr,
|
|
- (gpointer *) &hwaddr,
|
|
- (gpointer *) &iface_data->iface_get_config)) {
|
|
+ iface_data->iface_get_config = g_hash_table_lookup(get_config_data->result_dict, v_hwaddr);
|
|
+
|
|
+ if (!iface_data->iface_get_config) {
|
|
if (!get_config_data->any) {
|
|
_LOGD("get-config: skip fetching meta data for %s (%" G_GSSIZE_FORMAT ")",
|
|
v_hwaddr,
|
|
iface_data->intern_iface_idx);
|
|
goto out_done;
|
|
}
|
|
- iface_data->iface_get_config = nmcs_provider_get_config_iface_data_new(FALSE);
|
|
- g_hash_table_insert(get_config_data->result_dict,
|
|
- (char *) (hwaddr = g_steal_pointer(&v_hwaddr)),
|
|
- iface_data->iface_get_config);
|
|
+ iface_data->iface_get_config =
|
|
+ nmcs_provider_get_config_iface_data_create(get_config_data->result_dict,
|
|
+ FALSE,
|
|
+ v_hwaddr);
|
|
is_requested = FALSE;
|
|
} else {
|
|
if (iface_data->iface_get_config->iface_idx >= 0) {
|
|
_LOGI("GCP interface[%" G_GSSIZE_FORMAT "]: duplicate MAC address %s returned",
|
|
iface_data->intern_iface_idx,
|
|
- hwaddr);
|
|
+ iface_data->iface_get_config->hwaddr);
|
|
error = nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN,
|
|
"duplicate MAC address for index %" G_GSSIZE_FORMAT,
|
|
iface_data->intern_iface_idx);
|
|
@@ -306,7 +304,7 @@ _get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
|
_LOGI("GCP interface[%" G_GSSIZE_FORMAT "]: found a %sdevice with hwaddr %s",
|
|
iface_data->intern_iface_idx,
|
|
is_requested ? "requested " : "",
|
|
- hwaddr);
|
|
+ iface_data->iface_get_config->hwaddr);
|
|
|
|
nm_sprintf_buf(sbuf, "%" G_GSSIZE_FORMAT "/forwarded-ips/", iface_data->intern_iface_idx);
|
|
|
|
diff --git a/src/nm-cloud-setup/nmcs-provider.c b/src/nm-cloud-setup/nmcs-provider.c
|
|
index 8901100378d0..56f36646bb8a 100644
|
|
--- a/src/nm-cloud-setup/nmcs-provider.c
|
|
+++ b/src/nm-cloud-setup/nmcs-provider.c
|
|
@@ -127,15 +127,25 @@ nmcs_provider_detect_finish(NMCSProvider *self, GAsyncResult *result, GError **e
|
|
/*****************************************************************************/
|
|
|
|
NMCSProviderGetConfigIfaceData *
|
|
-nmcs_provider_get_config_iface_data_new(gboolean was_requested)
|
|
+nmcs_provider_get_config_iface_data_create(GHashTable *iface_datas,
|
|
+ gboolean was_requested,
|
|
+ const char *hwaddr)
|
|
{
|
|
NMCSProviderGetConfigIfaceData *iface_data;
|
|
|
|
+ nm_assert(hwaddr);
|
|
+
|
|
iface_data = g_slice_new(NMCSProviderGetConfigIfaceData);
|
|
*iface_data = (NMCSProviderGetConfigIfaceData){
|
|
+ .hwaddr = g_strdup(hwaddr),
|
|
.iface_idx = -1,
|
|
.was_requested = was_requested,
|
|
};
|
|
+
|
|
+ /* the has does not own the key (iface_datta->hwaddr), the lifetime of the
|
|
+ * key is associated with the iface_data instance. */
|
|
+ g_hash_table_replace(iface_datas, (char *) iface_data->hwaddr, iface_data);
|
|
+
|
|
return iface_data;
|
|
}
|
|
|
|
@@ -146,6 +156,7 @@ _iface_data_free(gpointer data)
|
|
|
|
g_free(iface_data->ipv4s_arr);
|
|
g_free(iface_data->iproutes_arr);
|
|
+ g_free((char *) iface_data->hwaddr);
|
|
|
|
nm_g_slice_free(iface_data);
|
|
}
|
|
@@ -224,16 +235,13 @@ nmcs_provider_get_config(NMCSProvider * self,
|
|
*get_config_data = (NMCSProviderGetConfigTaskData){
|
|
.task = nm_g_task_new(self, cancellable, nmcs_provider_get_config, callback, user_data),
|
|
.any = any,
|
|
- .result_dict = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, _iface_data_free),
|
|
+ .result_dict = g_hash_table_new_full(nm_str_hash, g_str_equal, NULL, _iface_data_free),
|
|
};
|
|
|
|
nmcs_wait_for_objects_register(get_config_data->task);
|
|
|
|
- for (; hwaddrs && hwaddrs[0]; hwaddrs++) {
|
|
- g_hash_table_insert(get_config_data->result_dict,
|
|
- g_strdup(hwaddrs[0]),
|
|
- nmcs_provider_get_config_iface_data_new(TRUE));
|
|
- }
|
|
+ for (; hwaddrs && hwaddrs[0]; hwaddrs++)
|
|
+ nmcs_provider_get_config_iface_data_create(get_config_data->result_dict, TRUE, hwaddrs[0]);
|
|
|
|
if (cancellable) {
|
|
gulong cancelled_id;
|
|
diff --git a/src/nm-cloud-setup/nmcs-provider.h b/src/nm-cloud-setup/nmcs-provider.h
|
|
index 31fec4449f9e..c67184679949 100644
|
|
--- a/src/nm-cloud-setup/nmcs-provider.h
|
|
+++ b/src/nm-cloud-setup/nmcs-provider.h
|
|
@@ -10,6 +10,10 @@
|
|
/*****************************************************************************/
|
|
|
|
typedef struct {
|
|
+ /* And it's exactly the same pointer that is also the key for the iface_datas
|
|
+ * dictionary. */
|
|
+ const char *hwaddr;
|
|
+
|
|
in_addr_t *ipv4s_arr;
|
|
gsize ipv4s_len;
|
|
|
|
@@ -41,13 +45,17 @@ nmcs_provider_get_config_iface_data_is_valid(const NMCSProviderGetConfigIfaceDat
|
|
&& ((config_data->has_ipv4s && config_data->has_cidr) || config_data->iproutes_len);
|
|
}
|
|
|
|
-NMCSProviderGetConfigIfaceData *nmcs_provider_get_config_iface_data_new(gboolean was_requested);
|
|
+NMCSProviderGetConfigIfaceData *nmcs_provider_get_config_iface_data_create(GHashTable *iface_datas,
|
|
+ gboolean was_requested,
|
|
+ const char *hwaddr);
|
|
|
|
/*****************************************************************************/
|
|
|
|
typedef struct {
|
|
/* A dictionary of (const char *) -> (NMCSProviderGetConfigIfaceData *).
|
|
- * This is the per-interface result of get_config(). */
|
|
+ * This is the per-interface result of get_config().
|
|
+ *
|
|
+ * The key is the same pointer as NMCSProviderGetConfigIfaceData's hwaddr. */
|
|
GHashTable *iface_datas;
|
|
|
|
/* The number of iface_datas that are nmcs_provider_get_config_iface_data_is_valid(). */
|
|
--
|
|
2.31.1
|
|
|
|
|
|
From 351ff60c9fb34ac6010fd895ad290db536a756a7 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Wed, 1 Sep 2021 16:59:19 +0200
|
|
Subject: [PATCH 06/10] cloud-setup: track sorted list of
|
|
NMCSProviderGetConfigIfaceData
|
|
|
|
Sorted by iface_idx. The iface_idx is probably something useful and
|
|
stable, provided by the provider. E.g. it's the order in which
|
|
interfaces are exposed on the meta data.
|
|
|
|
(cherry picked from commit 1c5cb9d3c2be5addd3b011873cfc6b99204955d1)
|
|
(cherry picked from commit 0a2ed627038349d838add8f3fd72e2d282e74693)
|
|
---
|
|
src/nm-cloud-setup/nmcs-provider.c | 49 +++++++++++++++++++++++++++++-
|
|
src/nm-cloud-setup/nmcs-provider.h | 8 +++++
|
|
2 files changed, 56 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/nm-cloud-setup/nmcs-provider.c b/src/nm-cloud-setup/nmcs-provider.c
|
|
index 56f36646bb8a..138e78d41b56 100644
|
|
--- a/src/nm-cloud-setup/nmcs-provider.c
|
|
+++ b/src/nm-cloud-setup/nmcs-provider.c
|
|
@@ -51,6 +51,19 @@ nmcs_provider_get_main_context(NMCSProvider *self)
|
|
}
|
|
/*****************************************************************************/
|
|
|
|
+static int
|
|
+_result_new_sort_iface_data(gconstpointer pa, gconstpointer pb)
|
|
+{
|
|
+ const NMCSProviderGetConfigIfaceData *a = *((const NMCSProviderGetConfigIfaceData *const *) pa);
|
|
+ const NMCSProviderGetConfigIfaceData *b = *((const NMCSProviderGetConfigIfaceData *const *) pb);
|
|
+
|
|
+ /* negative iface_idx are sorted to the end. */
|
|
+ NM_CMP_DIRECT((a->iface_idx < 0), (b->iface_idx < 0));
|
|
+
|
|
+ NM_CMP_FIELD(a, b, iface_idx);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static NMCSProviderGetConfigResult *
|
|
nmcs_provider_get_config_result_new(GHashTable *iface_datas)
|
|
{
|
|
@@ -59,6 +72,12 @@ nmcs_provider_get_config_result_new(GHashTable *iface_datas)
|
|
GHashTableIter h_iter;
|
|
guint num_valid_ifaces = 0;
|
|
guint num_ipv4s = 0;
|
|
+ GPtrArray * ptrarr;
|
|
+ guint n_iface_datas;
|
|
+
|
|
+ n_iface_datas = g_hash_table_size(iface_datas);
|
|
+
|
|
+ ptrarr = g_ptr_array_sized_new(n_iface_datas + 1u);
|
|
|
|
g_hash_table_iter_init(&h_iter, iface_datas);
|
|
while (g_hash_table_iter_next(&h_iter, NULL, (gpointer *) &iface_data)) {
|
|
@@ -66,15 +85,42 @@ nmcs_provider_get_config_result_new(GHashTable *iface_datas)
|
|
num_valid_ifaces++;
|
|
num_ipv4s += iface_data->ipv4s_len;
|
|
}
|
|
+ g_ptr_array_add(ptrarr, (gpointer) iface_data);
|
|
}
|
|
|
|
+ g_ptr_array_sort(ptrarr, _result_new_sort_iface_data);
|
|
+
|
|
+ nm_assert(n_iface_datas == ptrarr->len);
|
|
+
|
|
+ g_ptr_array_add(ptrarr, NULL);
|
|
+
|
|
result = g_new(NMCSProviderGetConfigResult, 1);
|
|
*result = (NMCSProviderGetConfigResult){
|
|
- .iface_datas = g_hash_table_ref(iface_datas),
|
|
+ .iface_datas = g_hash_table_ref(iface_datas),
|
|
+ .n_iface_datas = n_iface_datas,
|
|
+ .iface_datas_arr =
|
|
+ (const NMCSProviderGetConfigIfaceData **) g_ptr_array_free(ptrarr, FALSE),
|
|
.num_valid_ifaces = num_valid_ifaces,
|
|
.num_ipv4s = num_ipv4s,
|
|
};
|
|
|
|
+#if NM_MORE_ASSERTS > 5
|
|
+ {
|
|
+ gsize iface_idx_expected = 0;
|
|
+ guint i;
|
|
+
|
|
+ for (i = 0; i < result->n_iface_datas; i++) {
|
|
+ if (result->iface_datas_arr[i]->iface_idx < 0) {
|
|
+ nm_assert(result->iface_datas_arr[i]->iface_idx == -1);
|
|
+ iface_idx_expected = -1;
|
|
+ continue;
|
|
+ }
|
|
+ nm_assert(result->iface_datas_arr[i]->iface_idx == iface_idx_expected);
|
|
+ iface_idx_expected++;
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+
|
|
return result;
|
|
}
|
|
|
|
@@ -83,6 +129,7 @@ nmcs_provider_get_config_result_free(NMCSProviderGetConfigResult *result)
|
|
{
|
|
if (result) {
|
|
nm_g_hash_table_unref(result->iface_datas);
|
|
+ g_free((gpointer) result->iface_datas_arr);
|
|
g_free(result);
|
|
}
|
|
}
|
|
diff --git a/src/nm-cloud-setup/nmcs-provider.h b/src/nm-cloud-setup/nmcs-provider.h
|
|
index c67184679949..366320596492 100644
|
|
--- a/src/nm-cloud-setup/nmcs-provider.h
|
|
+++ b/src/nm-cloud-setup/nmcs-provider.h
|
|
@@ -63,6 +63,14 @@ typedef struct {
|
|
|
|
/* the number of IPv4 addresses over all valid iface_datas. */
|
|
guint num_ipv4s;
|
|
+
|
|
+ guint n_iface_datas;
|
|
+
|
|
+ /* The sorted value of @iface_datas, sorted by iface_idx.
|
|
+ *
|
|
+ * Not found entries (iface_idx == -1) are sorted at the end. */
|
|
+ const NMCSProviderGetConfigIfaceData *const *iface_datas_arr;
|
|
+
|
|
} NMCSProviderGetConfigResult;
|
|
|
|
void nmcs_provider_get_config_result_free(NMCSProviderGetConfigResult *result);
|
|
--
|
|
2.31.1
|
|
|
|
|
|
From d6832b24cfdb07b3acd2d92dd1ca47df46eeaba4 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Wed, 1 Sep 2021 17:23:09 +0200
|
|
Subject: [PATCH 07/10] cloud-setup: process iface-datas in sorted order
|
|
|
|
The routes/rules that are configured are independent of the
|
|
order in which we process the devices. That is, because they
|
|
use the "iface_idx" for cases where there is ambiguity.
|
|
|
|
Still, it feels nicer to always process them in a defined order.
|
|
|
|
(cherry picked from commit a95ea0eb294d646f17b5e1cf4f17cb1540f8af3a)
|
|
(cherry picked from commit 6302cd416d92a8c2f5b4a6be9dded71af4cf7ced)
|
|
---
|
|
src/nm-cloud-setup/main.c | 28 +++++++++++++---------------
|
|
1 file changed, 13 insertions(+), 15 deletions(-)
|
|
|
|
diff --git a/src/nm-cloud-setup/main.c b/src/nm-cloud-setup/main.c
|
|
index bb5c0d5ded9d..403c8d759794 100644
|
|
--- a/src/nm-cloud-setup/main.c
|
|
+++ b/src/nm-cloud-setup/main.c
|
|
@@ -405,14 +405,15 @@ _nmc_mangle_connection(NMDevice * device,
|
|
/*****************************************************************************/
|
|
|
|
static gboolean
|
|
-_config_one(GCancellable * sigterm_cancellable,
|
|
- NMClient * nmc,
|
|
- const NMCSProviderGetConfigResult * result,
|
|
- const char * hwaddr,
|
|
- const NMCSProviderGetConfigIfaceData *config_data)
|
|
+_config_one(GCancellable * sigterm_cancellable,
|
|
+ NMClient * nmc,
|
|
+ const NMCSProviderGetConfigResult *result,
|
|
+ guint idx)
|
|
{
|
|
- gs_unref_object NMDevice *device = NULL;
|
|
- gs_unref_object NMConnection *applied_connection = NULL;
|
|
+ const NMCSProviderGetConfigIfaceData *config_data = result->iface_datas_arr[idx];
|
|
+ const char * hwaddr = config_data->hwaddr;
|
|
+ gs_unref_object NMDevice *device = NULL;
|
|
+ gs_unref_object NMConnection *applied_connection = NULL;
|
|
guint64 applied_version_id;
|
|
gs_free_error GError *error = NULL;
|
|
gboolean changed;
|
|
@@ -537,14 +538,11 @@ _config_all(GCancellable * sigterm_cancellable,
|
|
NMClient * nmc,
|
|
const NMCSProviderGetConfigResult *result)
|
|
{
|
|
- GHashTableIter h_iter;
|
|
- const NMCSProviderGetConfigIfaceData *c_config_data;
|
|
- const char * c_hwaddr;
|
|
- gboolean any_changes = FALSE;
|
|
-
|
|
- g_hash_table_iter_init(&h_iter, result->iface_datas);
|
|
- while (g_hash_table_iter_next(&h_iter, (gpointer *) &c_hwaddr, (gpointer *) &c_config_data)) {
|
|
- if (_config_one(sigterm_cancellable, nmc, result, c_hwaddr, c_config_data))
|
|
+ gboolean any_changes = FALSE;
|
|
+ guint i;
|
|
+
|
|
+ for (i = 0; i < result->n_iface_datas; i++) {
|
|
+ if (_config_one(sigterm_cancellable, nmc, result, i))
|
|
any_changes = TRUE;
|
|
}
|
|
|
|
--
|
|
2.31.1
|
|
|
|
|
|
From 167faa59d23ab8b2db471169860c4387da625d21 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Wed, 1 Sep 2021 19:23:46 +0200
|
|
Subject: [PATCH 08/10] cloud-setup: limit number of supported interfaces to
|
|
avoid overlapping table numbers
|
|
|
|
The table number is chosen as 30400 + iface_idx. That is, the range is
|
|
limited and we shouldn't handle more than 100 devices. Add a check for
|
|
that and error out.
|
|
|
|
(cherry picked from commit b68d694b78fd9b4b63b0592a2518f387aaa35f87)
|
|
(cherry picked from commit 292233e16ed1f60499c2676611d59c271352e2c3)
|
|
---
|
|
src/nm-cloud-setup/main.c | 8 ++++++++
|
|
1 file changed, 8 insertions(+)
|
|
|
|
diff --git a/src/nm-cloud-setup/main.c b/src/nm-cloud-setup/main.c
|
|
index 403c8d759794..6be8c145f3c9 100644
|
|
--- a/src/nm-cloud-setup/main.c
|
|
+++ b/src/nm-cloud-setup/main.c
|
|
@@ -438,6 +438,14 @@ _config_one(GCancellable * sigterm_cancellable,
|
|
return FALSE;
|
|
}
|
|
|
|
+ if (config_data->iface_idx >= 100) {
|
|
+ /* since we use the iface_idx to select a table number, the range is limited from
|
|
+ * 0 to 99. Note that the providers are required to provide increasing numbers,
|
|
+ * so this means we bail out after the first 100 devices. */
|
|
+ _LOGD("config device %s: skip because number of supported interfaces reached", hwaddr);
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
_LOGD("config device %s: configuring \"%s\" (%s)...",
|
|
hwaddr,
|
|
nm_device_get_iface(device) ?: "/unknown/",
|
|
--
|
|
2.31.1
|
|
|
|
|
|
From 5d8ac7f10fd9b4a467e8afd7e082acb4b2d33eed Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Mon, 6 Sep 2021 10:35:36 +0200
|
|
Subject: [PATCH 09/10] cloud-setup: cleanup configuring addresses/routes/rules
|
|
in _nmc_mangle_connection()
|
|
|
|
(cherry picked from commit 0978be5e43f142ec5c6062dcfe1c2f4aa834464b)
|
|
(cherry picked from commit ce24b4bca5d3fbad65d4065325cfa80ac05fbfdb)
|
|
---
|
|
src/nm-cloud-setup/main.c | 52 +++++++++++++++++----------------------
|
|
1 file changed, 23 insertions(+), 29 deletions(-)
|
|
|
|
diff --git a/src/nm-cloud-setup/main.c b/src/nm-cloud-setup/main.c
|
|
index 6be8c145f3c9..260d111205f5 100644
|
|
--- a/src/nm-cloud-setup/main.c
|
|
+++ b/src/nm-cloud-setup/main.c
|
|
@@ -279,10 +279,6 @@ _nmc_mangle_connection(NMDevice * device,
|
|
NMConnection * remote_connection;
|
|
NMSettingIPConfig * remote_s_ip = NULL;
|
|
gsize i;
|
|
- in_addr_t gateway;
|
|
- gint64 rt_metric;
|
|
- guint32 rt_table;
|
|
- NMIPRoute * route_entry;
|
|
gboolean addrs_changed = FALSE;
|
|
gboolean rules_changed = FALSE;
|
|
gboolean routes_changed = FALSE;
|
|
@@ -339,47 +335,45 @@ _nmc_mangle_connection(NMDevice * device,
|
|
* We don't need to configure policy routing in this case. */
|
|
NM_SET_OUT(out_skipped_single_addr, TRUE);
|
|
} else if (config_data->has_ipv4s && config_data->has_cidr) {
|
|
+ NMIPAddress * addr_entry;
|
|
+ NMIPRoute * route_entry;
|
|
+ NMIPRoutingRule *rule_entry;
|
|
+ in_addr_t gateway;
|
|
+ char sbuf[NM_UTILS_INET_ADDRSTRLEN];
|
|
+
|
|
for (i = 0; i < config_data->ipv4s_len; i++) {
|
|
- NMIPAddress *entry;
|
|
-
|
|
- entry = nm_ip_address_new_binary(AF_INET,
|
|
- &config_data->ipv4s_arr[i],
|
|
- config_data->cidr_prefix,
|
|
- NULL);
|
|
- if (entry)
|
|
- g_ptr_array_add(addrs_new, entry);
|
|
+ addr_entry = nm_ip_address_new_binary(AF_INET,
|
|
+ &config_data->ipv4s_arr[i],
|
|
+ config_data->cidr_prefix,
|
|
+ NULL);
|
|
+ nm_assert(addr_entry);
|
|
+ g_ptr_array_add(addrs_new, addr_entry);
|
|
}
|
|
+
|
|
if (config_data->has_gateway && config_data->gateway) {
|
|
gateway = config_data->gateway;
|
|
} else {
|
|
gateway = nm_utils_ip4_address_clear_host_address(config_data->cidr_addr,
|
|
config_data->cidr_prefix);
|
|
- ((guint8 *) &gateway)[3] += 1;
|
|
+ if (config_data->cidr_prefix < 32)
|
|
+ ((guint8 *) &gateway)[3] += 1;
|
|
}
|
|
- rt_metric = 10;
|
|
- rt_table = 30400 + config_data->iface_idx;
|
|
|
|
- route_entry =
|
|
- nm_ip_route_new_binary(AF_INET, &nm_ip_addr_zero, 0, &gateway, rt_metric, NULL);
|
|
+ route_entry = nm_ip_route_new_binary(AF_INET, &nm_ip_addr_zero, 0, &gateway, 10, NULL);
|
|
nm_ip_route_set_attribute(route_entry,
|
|
NM_IP_ROUTE_ATTRIBUTE_TABLE,
|
|
- g_variant_new_uint32(rt_table));
|
|
+ g_variant_new_uint32(30400 + config_data->iface_idx));
|
|
g_ptr_array_add(routes_new, route_entry);
|
|
|
|
for (i = 0; i < config_data->ipv4s_len; i++) {
|
|
- NMIPRoutingRule *entry;
|
|
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
|
|
-
|
|
- entry = nm_ip_routing_rule_new(AF_INET);
|
|
- nm_ip_routing_rule_set_priority(entry, rt_table);
|
|
- nm_ip_routing_rule_set_from(entry,
|
|
+ rule_entry = nm_ip_routing_rule_new(AF_INET);
|
|
+ nm_ip_routing_rule_set_priority(rule_entry, 30400 + config_data->iface_idx);
|
|
+ nm_ip_routing_rule_set_from(rule_entry,
|
|
_nm_utils_inet4_ntop(config_data->ipv4s_arr[i], sbuf),
|
|
32);
|
|
- nm_ip_routing_rule_set_table(entry, rt_table);
|
|
-
|
|
- nm_assert(nm_ip_routing_rule_validate(entry, NULL));
|
|
-
|
|
- g_ptr_array_add(rules_new, entry);
|
|
+ nm_ip_routing_rule_set_table(rule_entry, 30400 + config_data->iface_idx);
|
|
+ nm_assert(nm_ip_routing_rule_validate(rule_entry, NULL));
|
|
+ g_ptr_array_add(rules_new, rule_entry);
|
|
}
|
|
}
|
|
|
|
--
|
|
2.31.1
|
|
|
|
|
|
From c2402be45e2dec931690aef555de43292b015422 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Wed, 1 Sep 2021 10:31:55 +0200
|
|
Subject: [PATCH 10/10] cloud-setup: use suppress_prefixlength rule to honor
|
|
non-default-routes in the main table
|
|
|
|
Background
|
|
==========
|
|
|
|
Imagine you run a container on your machine. Then the routing table
|
|
might look like:
|
|
|
|
default via 10.0.10.1 dev eth0 proto dhcp metric 100
|
|
10.0.10.0/28 dev eth0 proto kernel scope link src 10.0.10.5 metric 100
|
|
[...]
|
|
10.42.0.0/24 via 10.42.0.0 dev flannel.1 onlink
|
|
10.42.1.2 dev cali02ad7e68ce1 scope link
|
|
10.42.1.3 dev cali8fcecf5aaff scope link
|
|
10.42.2.0/24 via 10.42.2.0 dev flannel.1 onlink
|
|
10.42.3.0/24 via 10.42.3.0 dev flannel.1 onlink
|
|
|
|
That is, there are another interfaces with subnets and specific routes.
|
|
|
|
If nm-cloud-setup now configures rules:
|
|
|
|
0: from all lookup local
|
|
30400: from 10.0.10.5 lookup 30400
|
|
32766: from all lookup main
|
|
32767: from all lookup default
|
|
|
|
and
|
|
|
|
default via 10.0.10.1 dev eth0 table 30400 proto static metric 10
|
|
10.0.10.1 dev eth0 table 30400 proto static scope link metric 10
|
|
|
|
then these other subnets will also be reached via the default route.
|
|
|
|
This container example is just one case where this is a problem. In
|
|
general, if you have specific routes on another interface, then the
|
|
default route in the 30400+ table will interfere badly.
|
|
|
|
The idea of nm-cloud-setup is to automatically configure the network for
|
|
secondary IP addresses. When the user has special requirements, then
|
|
they should disable nm-cloud-setup and configure whatever they want.
|
|
But the container use case is popular and important. It is not something
|
|
where the user actively configures the network. This case needs to work better,
|
|
out of the box. In general, nm-cloud-setup should work better with the
|
|
existing network configuration.
|
|
|
|
Change
|
|
======
|
|
|
|
Add new routing tables 30200+ with the individual subnets of the
|
|
interface:
|
|
|
|
10.0.10.0/24 dev eth0 table 30200 proto static metric 10
|
|
[...]
|
|
default via 10.0.10.1 dev eth0 table 30400 proto static metric 10
|
|
10.0.10.1 dev eth0 table 30400 proto static scope link metric 10
|
|
|
|
Also add more important routing rules with priority 30200+, which select
|
|
these tables based on the source address:
|
|
|
|
30200: from 10.0.10.5 lookup 30200
|
|
|
|
These will do source based routing for the subnets on these
|
|
interfaces.
|
|
|
|
Then, add a rule with priority 30350
|
|
|
|
30350: lookup main suppress_prefixlength 0
|
|
|
|
which processes the routes from the main table, but ignores the default
|
|
routes. 30350 was chosen, because it's in between the rules 30200+ and
|
|
30400+, leaving a range for the user to configure their own rules.
|
|
|
|
Then, as before, the rules 30400+ again look at the corresponding 30400+
|
|
table, to find a default route.
|
|
|
|
Finally, process the main table again, this time honoring the default
|
|
route. That is for packets that have a different source address.
|
|
|
|
This change means that the source based routing is used for the
|
|
subnets that are configured on the interface and for the default route.
|
|
Whereas, if there are any more specific routes in the main table, they will
|
|
be preferred over the default route.
|
|
|
|
Apparently Amazon Linux solves this differently, by not configuring a
|
|
routing table for addresses on interface "eth0". That might be an
|
|
alternative, but it's not clear to me what is special about eth0 to
|
|
warrant this treatment. It also would imply that we somehow recognize
|
|
this primary interface. In practise that would be doable by selecting
|
|
the interface with "iface_idx" zero.
|
|
|
|
Instead choose this approach. This is remotely similar to what WireGuard does
|
|
for configuring the default route ([1]), however WireGuard uses fwmark to match
|
|
the packets instead of the source address.
|
|
|
|
[1] https://www.wireguard.com/netns/#improved-rule-based-routing
|
|
|
|
(cherry picked from commit fe80b2d1ecd94639573a944633a5d960db316f60)
|
|
(cherry picked from commit 58e58361bd1666e5af822a4bc970bebb8a44bd6e)
|
|
---
|
|
man/nm-cloud-setup.xml | 66 +++++++++++++++------------------------
|
|
src/nm-cloud-setup/main.c | 36 +++++++++++++++++++++
|
|
2 files changed, 62 insertions(+), 40 deletions(-)
|
|
|
|
diff --git a/man/nm-cloud-setup.xml b/man/nm-cloud-setup.xml
|
|
index 7493cc1d7f26..976fc6472464 100644
|
|
--- a/man/nm-cloud-setup.xml
|
|
+++ b/man/nm-cloud-setup.xml
|
|
@@ -256,7 +256,9 @@ ln -s /etc/systemd/system/timers.target.wants/nm-cloud-setup.timer /usr/lib/syst
|
|
Also, if the device is currently not activated in NetworkManager or if the currently
|
|
activated profile has a user-data <literal>org.freedesktop.nm-cloud-setup.skip=yes</literal>,
|
|
it is skipped.</para>
|
|
- <para>Then, the tool will change the runtime configuration of the device.
|
|
+ <para>If only one interface and one address is configured, then the tool does nothing
|
|
+ and leaves the automatic configuration that was obtained via DHCP.</para>
|
|
+ <para>Otherwise, the tool will change the runtime configuration of the device.
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Add static IPv4 addresses for all the configured addresses from <literal>local-ipv4s</literal> with
|
|
@@ -267,15 +269,25 @@ ln -s /etc/systemd/system/timers.target.wants/nm-cloud-setup.timer /usr/lib/syst
|
|
<para>Choose a route table 30400 + the index of the interface and
|
|
add a default route <literal>0.0.0.0/0</literal>. The gateway
|
|
is the first IP address in the CIDR subnet block. For
|
|
- example, we might get a route <literal>"0.0.0.0/0 172.16.5.1 10 table=30401"</literal>.</para>
|
|
+ example, we might get a route <literal>"0.0.0.0/0 172.16.5.1 10 table=30400"</literal>.</para>
|
|
+ <para>Also choose a route table 30200 + the interface index. This
|
|
+ contains a direct routes to the subnets of this interface.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Finally, add a policy routing rule for each address. For example
|
|
- <literal>"priority 30401 from 172.16.5.3/32 table 30401, priority 30401 from 172.16.5.4/32 table 30401"</literal>.</para>
|
|
+ <literal>"priority 30200 from 172.16.5.3/32 table 30200, priority 30200 from 172.16.5.4/32 table 30200"</literal>.
|
|
+ and
|
|
+ <literal>"priority 30400 from 172.16.5.3/32 table 30400, priority 30400 from 172.16.5.4/32 table 30400"</literal>
|
|
+ The 30200+ rules select the table to reach the subnet directly, while the 30400+ rules use the
|
|
+ default route. Also add a rule
|
|
+ <literal>"priority 30350 table main suppress_prefixlength 0"</literal>. This has a priority between
|
|
+ the two previous rules and causes a lookup of routes in the main table while ignoring the default
|
|
+ route. The purpose of this is so that other specific routes in the main table are honored over
|
|
+ the default route in table 30400+.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
With above example, this roughly corresponds for interface <literal>eth0</literal> to
|
|
- <command>nmcli device modify "eth0" ipv4.addresses "172.16.5.3/24,172.16.5.4/24" ipv4.routes "0.0.0.0/0 172.16.5.1 10 table=30401" ipv4.routing-rules "priority 30401 from 172.16.5.3/32 table 30401, priority 30401 from 172.16.5.4/32 table 30401"</command>.
|
|
+ <command>nmcli device modify "eth0" ipv4.addresses "172.16.5.3/24,172.16.5.4/24" ipv4.routes "172.16.5.0/24 0.0.0.0 10 table=30200, 0.0.0.0/0 172.16.5.1 10 table=30400" ipv4.routing-rules "priority 30200 from 172.16.5.3/32 table 30200, priority 30200 from 172.16.5.4/32 table 30200, priority 20350 table main suppress_prefixlength 0, priority 30400 from 172.16.5.3/32 table 30400, priority 30400 from 172.16.5.4/32 table 30400"</command>.
|
|
Note that this replaces the previous addresses, routes and rules with the new information.
|
|
But also note that this only changes the run time configuration of the device. The
|
|
connection profile on disk is not affected.
|
|
@@ -360,14 +372,8 @@ ln -s /etc/systemd/system/timers.target.wants/nm-cloud-setup.timer /usr/lib/syst
|
|
</listitem>
|
|
<listitem>
|
|
<para>At this point, we have a list of all interfaces (by MAC address) and their configured IPv4 addresses.</para>
|
|
- <para>For each device, we lookup the currently applied connection in NetworkManager. That implies, that the device is currently activated
|
|
- in NetworkManager. If no such device was in NetworkManager, or if the profile has user-data <literal>org.freedesktop.nm-cloud-setup.skip=yes</literal>,
|
|
- we skip the device. Now for each found IP address we add a static address "$ADDR/$SUBNET_PREFIX". Also we configure policy routing
|
|
- by adding a static route "$ADDR/$SUBNET_PREFIX $GATEWAY 10, table=$TABLE" where $GATEWAY is the first IP address in the subnet and table
|
|
- is 30400 plus the interface index. Also we add a policy routing rule "priority $TABLE from $ADDR/32 table $TABLE".</para>
|
|
- <para>The effect is not unlike calling
|
|
- <command>nmcli device modify "$DEVICE" ipv4.addresses "$ADDR/$SUBNET [,...]" ipv4.routes "$ADDR/32 $GATEWAY 10 table=$TABLE" ipv4.routing-rules "priority $TABLE from $ADDR/32 table $TABLE"</command>
|
|
- for all relevant devices and all found addresses.</para>
|
|
+ <para>Then the tool configures the system like doing for AWS environment. That is, using source based policy routing
|
|
+ with the tables/rules 30200/30400.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</refsect2>
|
|
@@ -389,9 +395,10 @@ ln -s /etc/systemd/system/timers.target.wants/nm-cloud-setup.timer /usr/lib/syst
|
|
of available interface. Interfaces are identified by their MAC address.</para>
|
|
</listitem>
|
|
<listitem>
|
|
- <para>Then for each interface fetch <literal>http://100.100.100.200/2016-01-01/meta-data/network/interfaces/macs/$MAC/vpc-cidr-block</literal>
|
|
- , <literal>http://100.100.100.200/2016-01-01/meta-data/network/interfaces/macs/$MAC/private-ipv4s</literal> and
|
|
- <literal>http://100.100.100.200/2016-01-01/meta-data/network/interfaces/macs/$MAC/netmask</literal>.
|
|
+ <para>Then for each interface fetch <literal>http://100.100.100.200/2016-01-01/meta-data/network/interfaces/macs/$MAC/vpc-cidr-block</literal>,
|
|
+ <literal>http://100.100.100.200/2016-01-01/meta-data/network/interfaces/macs/$MAC/private-ipv4s</literal>,
|
|
+ <literal>http://100.100.100.200/2016-01-01/meta-data/network/interfaces/macs/$MAC/netmask</literal> and
|
|
+ <literal>http://100.100.100.200/2016-01-01/meta-data/network/interfaces/macs/$MAC/gateway</literal>.
|
|
Thereby we get a list of private IPv4 addresses, one CIDR subnet block and private IPv4 addresses prefix.</para>
|
|
</listitem>
|
|
<listitem>
|
|
@@ -399,31 +406,10 @@ ln -s /etc/systemd/system/timers.target.wants/nm-cloud-setup.timer /usr/lib/syst
|
|
If no ethernet device for the respective MAC address is found, it is skipped.
|
|
Also, if the device is currently not activated in NetworkManager or if the currently
|
|
activated profile has a user-data <literal>org.freedesktop.nm-cloud-setup.skip=yes</literal>,
|
|
- it is skipped.</para>
|
|
- <para>Then, the tool will change the runtime configuration of the device.
|
|
- <itemizedlist>
|
|
- <listitem>
|
|
- <para>Add static IPv4 addresses for all the configured addresses from <literal>private-ipv4s</literal> with
|
|
- prefix length according to <literal>netmask</literal>. For example,
|
|
- we might have here 2 IP addresses like <literal>"10.0.0.150/24,10.0.0.152/24"</literal>.</para>
|
|
- </listitem>
|
|
- <listitem>
|
|
- <para>Choose a route table 30400 + the index of the interface and
|
|
- add a default route <literal>0.0.0.0/0</literal>. The gateway
|
|
- is the default gateway retrieved from metadata server. For
|
|
- example, we might get a route <literal>"0.0.0.0/0 10.0.0.253 10 table=30400"</literal>.</para>
|
|
- </listitem>
|
|
- <listitem>
|
|
- <para>Finally, add a policy routing rule for each address. For example
|
|
- <literal>"priority 30400 from 10.0.0.150/32 table 30400, priority 30400 from 10.0.0.152/32 table 30400"</literal>.</para>
|
|
- </listitem>
|
|
- </itemizedlist>
|
|
- With above example, this roughly corresponds for interface <literal>eth0</literal> to
|
|
- <command>nmcli device modify "eth0" ipv4.addresses "10.0.0.150/24,10.0.0.152/24" ipv4.routes "0.0.0.0/0 10.0.0.253 10 table=30400" ipv4.routing-rules "priority 30400 from 10.0.0.150/32 table 30400, priority 30400 from 10.0.0.152/32 table 30400"</command>.
|
|
- Note that this replaces the previous addresses, routes and rules with the new information.
|
|
- But also note that this only changes the run time configuration of the device. The
|
|
- connection profile on disk is not affected.
|
|
- </para>
|
|
+ it is skipped. Also, there is only one interface and one IP address, the tool does nothing.</para>
|
|
+ <para>Then the tool configures the system like doing for AWS environment. That is, using source based policy routing
|
|
+ with the tables/rules 30200/30400. One difference to AWS is that the gateway is also fetched via metadata instead
|
|
+ of using the first IP address in the subnet.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</refsect2>
|
|
diff --git a/src/nm-cloud-setup/main.c b/src/nm-cloud-setup/main.c
|
|
index 260d111205f5..916f41da91d3 100644
|
|
--- a/src/nm-cloud-setup/main.c
|
|
+++ b/src/nm-cloud-setup/main.c
|
|
@@ -4,6 +4,8 @@
|
|
|
|
#include "libnm-client-aux-extern/nm-libnm-aux.h"
|
|
|
|
+#include <linux/rtnetlink.h>
|
|
+
|
|
#include "nm-cloud-setup-utils.h"
|
|
#include "nmcs-provider-ec2.h"
|
|
#include "nmcs-provider-gcp.h"
|
|
@@ -335,6 +337,8 @@ _nmc_mangle_connection(NMDevice * device,
|
|
* We don't need to configure policy routing in this case. */
|
|
NM_SET_OUT(out_skipped_single_addr, TRUE);
|
|
} else if (config_data->has_ipv4s && config_data->has_cidr) {
|
|
+ gs_unref_hashtable GHashTable *unique_subnets =
|
|
+ g_hash_table_new(nm_direct_hash, g_direct_equal);
|
|
NMIPAddress * addr_entry;
|
|
NMIPRoute * route_entry;
|
|
NMIPRoutingRule *rule_entry;
|
|
@@ -359,6 +363,38 @@ _nmc_mangle_connection(NMDevice * device,
|
|
((guint8 *) &gateway)[3] += 1;
|
|
}
|
|
|
|
+ for (i = 0; i < config_data->ipv4s_len; i++) {
|
|
+ in_addr_t a = config_data->ipv4s_arr[i];
|
|
+
|
|
+ a = nm_utils_ip4_address_clear_host_address(a, config_data->cidr_prefix);
|
|
+
|
|
+ G_STATIC_ASSERT_EXPR(sizeof(gsize) >= sizeof(in_addr_t));
|
|
+ if (g_hash_table_add(unique_subnets, GSIZE_TO_POINTER(a))) {
|
|
+ route_entry =
|
|
+ nm_ip_route_new_binary(AF_INET, &a, config_data->cidr_prefix, NULL, 10, NULL);
|
|
+ nm_ip_route_set_attribute(route_entry,
|
|
+ NM_IP_ROUTE_ATTRIBUTE_TABLE,
|
|
+ g_variant_new_uint32(30200 + config_data->iface_idx));
|
|
+ g_ptr_array_add(routes_new, route_entry);
|
|
+ }
|
|
+
|
|
+ rule_entry = nm_ip_routing_rule_new(AF_INET);
|
|
+ nm_ip_routing_rule_set_priority(rule_entry, 30200 + config_data->iface_idx);
|
|
+ nm_ip_routing_rule_set_from(rule_entry,
|
|
+ _nm_utils_inet4_ntop(config_data->ipv4s_arr[i], sbuf),
|
|
+ 32);
|
|
+ nm_ip_routing_rule_set_table(rule_entry, 30200 + config_data->iface_idx);
|
|
+ nm_assert(nm_ip_routing_rule_validate(rule_entry, NULL));
|
|
+ g_ptr_array_add(rules_new, rule_entry);
|
|
+ }
|
|
+
|
|
+ rule_entry = nm_ip_routing_rule_new(AF_INET);
|
|
+ nm_ip_routing_rule_set_priority(rule_entry, 30350);
|
|
+ nm_ip_routing_rule_set_table(rule_entry, RT_TABLE_MAIN);
|
|
+ nm_ip_routing_rule_set_suppress_prefixlength(rule_entry, 0);
|
|
+ nm_assert(nm_ip_routing_rule_validate(rule_entry, NULL));
|
|
+ g_ptr_array_add(rules_new, rule_entry);
|
|
+
|
|
route_entry = nm_ip_route_new_binary(AF_INET, &nm_ip_addr_zero, 0, &gateway, 10, NULL);
|
|
nm_ip_route_set_attribute(route_entry,
|
|
NM_IP_ROUTE_ATTRIBUTE_TABLE,
|
|
--
|
|
2.31.1
|
|
|