mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-09 14:40:21 +01:00
cloud-setup: reorder addresses to honor "primary_ip_address"
The order of IPv4 addresses matters, in particular if they are in
the same subnet. Kernel will mark all but the first one as "secondary".
In NetworkManager's ipv4.addresses, the first address is the primary.
It seems that on aliyun cloud, "private-ipv4s" URL may give the
addresses in arbitrary order. The primary can be fetched from
"primary-ip-address".
Fix that by also fetching "primary-ip-address". Then, resort the array
so that the primary is the first one in the list.
https://bugzilla.redhat.com/show_bug.cgi?id=2079849
(cherry picked from commit 191baf84e2)
This commit is contained in:
parent
a845a3425f
commit
3a9ec3c5a3
2 changed files with 73 additions and 1 deletions
|
|
@ -123,6 +123,7 @@ detect(NMCSProvider *provider, GTask *task)
|
|||
typedef enum {
|
||||
GET_CONFIG_FETCH_DONE_TYPE_SUBNET_VPC_CIDR_BLOCK,
|
||||
GET_CONFIG_FETCH_DONE_TYPE_PRIVATE_IPV4S,
|
||||
GET_CONFIG_FETCH_DONE_TYPE_PRIMARY_IP_ADDRESS,
|
||||
GET_CONFIG_FETCH_DONE_TYPE_NETMASK,
|
||||
GET_CONFIG_FETCH_DONE_TYPE_GATEWAY,
|
||||
} GetConfigFetchDoneType;
|
||||
|
|
@ -177,6 +178,16 @@ _get_config_fetch_done_cb(NMHttpClient *http_client,
|
|||
}
|
||||
break;
|
||||
|
||||
case GET_CONFIG_FETCH_DONE_TYPE_PRIMARY_IP_ADDRESS:
|
||||
|
||||
if (nm_utils_parse_inaddr_bin(AF_INET, g_bytes_get_data(response, NULL), NULL, &tmp_addr)) {
|
||||
nm_assert(config_iface_data->priv.aliyun.primary_ip_address == 0);
|
||||
nm_assert(!config_iface_data->priv.aliyun.has_primary_ip_address);
|
||||
config_iface_data->priv.aliyun.primary_ip_address = tmp_addr;
|
||||
config_iface_data->priv.aliyun.has_primary_ip_address = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_CONFIG_FETCH_DONE_TYPE_SUBNET_VPC_CIDR_BLOCK:
|
||||
|
||||
if (nm_utils_parse_inaddr_prefix_bin(AF_INET,
|
||||
|
|
@ -212,6 +223,26 @@ _get_config_fetch_done_cb(NMHttpClient *http_client,
|
|||
break;
|
||||
}
|
||||
|
||||
if (!config_iface_data->priv.aliyun.ipv4s_arr_ordered
|
||||
&& config_iface_data->priv.aliyun.has_primary_ip_address
|
||||
&& config_iface_data->ipv4s_len > 0) {
|
||||
for (i = 0; i < config_iface_data->ipv4s_len; i++) {
|
||||
if (config_iface_data->ipv4s_arr[i]
|
||||
!= config_iface_data->priv.aliyun.primary_ip_address)
|
||||
continue;
|
||||
if (i > 0) {
|
||||
/* OK, at position [i] we found the primary address.
|
||||
* Move the elements from [0..(i-1)] to [1..i] and then set [0]. */
|
||||
memmove(&config_iface_data->ipv4s_arr[1],
|
||||
&config_iface_data->ipv4s_arr[0],
|
||||
i * sizeof(in_addr_t));
|
||||
config_iface_data->ipv4s_arr[0] = config_iface_data->priv.aliyun.primary_ip_address;
|
||||
}
|
||||
break;
|
||||
}
|
||||
config_iface_data->priv.aliyun.ipv4s_arr_ordered = TRUE;
|
||||
}
|
||||
|
||||
out:
|
||||
get_config_data->n_pending--;
|
||||
_nmcs_provider_get_config_task_maybe_return(get_config_data, g_steal_pointer(&error));
|
||||
|
|
@ -235,6 +266,17 @@ _get_config_fetch_done_cb_private_ipv4s(GObject *source, GAsyncResult *result, g
|
|||
GET_CONFIG_FETCH_DONE_TYPE_PRIVATE_IPV4S);
|
||||
}
|
||||
|
||||
static void
|
||||
_get_config_fetch_done_cb_primary_ip_address(GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
_get_config_fetch_done_cb(NM_HTTP_CLIENT(source),
|
||||
result,
|
||||
user_data,
|
||||
GET_CONFIG_FETCH_DONE_TYPE_PRIMARY_IP_ADDRESS);
|
||||
}
|
||||
|
||||
static void
|
||||
_get_config_fetch_done_cb_netmask(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
|
|
@ -297,6 +339,7 @@ _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;
|
||||
gs_free char *uri5 = NULL;
|
||||
|
||||
config_iface_data = g_hash_table_lookup(get_config_data->result_dict, v_hwaddr);
|
||||
|
||||
|
|
@ -361,6 +404,23 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
|
|||
nm_http_client_poll_get(
|
||||
http_client,
|
||||
(uri3 = _aliyun_uri_interfaces(v_mac_data->path,
|
||||
NM_STR_HAS_SUFFIX(v_mac_data->path, "/") ? "" : "/",
|
||||
"primary-ip-address")),
|
||||
HTTP_TIMEOUT_MS,
|
||||
512 * 1024,
|
||||
10000,
|
||||
1000,
|
||||
NULL,
|
||||
get_config_data->intern_cancellable,
|
||||
NULL,
|
||||
NULL,
|
||||
_get_config_fetch_done_cb_primary_ip_address,
|
||||
nm_utils_user_data_pack(get_config_data, config_iface_data));
|
||||
|
||||
get_config_data->n_pending++;
|
||||
nm_http_client_poll_get(
|
||||
http_client,
|
||||
(uri4 = _aliyun_uri_interfaces(v_mac_data->path,
|
||||
NM_STR_HAS_SUFFIX(v_mac_data->path, "/") ? "" : "/",
|
||||
"netmask")),
|
||||
HTTP_TIMEOUT_MS,
|
||||
|
|
@ -377,7 +437,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
|
|||
get_config_data->n_pending++;
|
||||
nm_http_client_poll_get(
|
||||
http_client,
|
||||
(uri4 = _aliyun_uri_interfaces(v_mac_data->path,
|
||||
(uri5 = _aliyun_uri_interfaces(v_mac_data->path,
|
||||
NM_STR_HAS_SUFFIX(v_mac_data->path, "/") ? "" : "/",
|
||||
"gateway")),
|
||||
HTTP_TIMEOUT_MS,
|
||||
|
|
|
|||
|
|
@ -36,6 +36,18 @@ typedef struct {
|
|||
* nmcs_provider_get_config(). */
|
||||
bool was_requested : 1;
|
||||
|
||||
/* Usually we would want that the parent class NMCSProvider is not aware about
|
||||
* the implementations. However, it's convenient to track implementation specific data
|
||||
* here, thus we violate such separation. In practice, all subclasses are known
|
||||
* at compile time, and it will be simpler this way. */
|
||||
struct {
|
||||
struct {
|
||||
in_addr_t primary_ip_address;
|
||||
bool has_primary_ip_address : 1;
|
||||
bool ipv4s_arr_ordered : 1;
|
||||
} aliyun;
|
||||
} priv;
|
||||
|
||||
} NMCSProviderGetConfigIfaceData;
|
||||
|
||||
static inline gboolean
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue