aliyun: reuse ipv4 gateway address returned by metadata server

The default ipv4 gateway address of the VPC in Aliyun cloud is not the
first IP address in the CIDR subnet block, we should instead use the
ipv4 gateway address retrieved from the metadata server in
`_nmc_mangle_connection()`.

https://bugzilla.redhat.com/show_bug.cgi?id=1823315

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/958

Signed-off-by: Wen Liang <liangwen12year@gmail.com>
This commit is contained in:
Wen Liang 2021-08-05 07:44:05 -04:00
parent f43bee77d6
commit 778e1f8493
4 changed files with 53 additions and 9 deletions

View file

@ -410,8 +410,8 @@ ln -s /etc/systemd/system/timers.target.wants/nm-cloud-setup.timer /usr/lib/syst
<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 first IP address in the CIDR subnet block. For
example, we might get a route <literal>"0.0.0.0/0 10.0.0.1 10 table=30400"</literal>.</para>
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
@ -419,7 +419,7 @@ ln -s /etc/systemd/system/timers.target.wants/nm-cloud-setup.timer /usr/lib/syst
</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.150/24" ipv4.routes "0.0.0.0/0 10.0.0.1 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>.
<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.

View file

@ -340,11 +340,13 @@ _nmc_mangle_connection(NMDevice * device,
if (entry)
g_ptr_array_add(addrs_new, entry);
}
gateway = nm_utils_ip4_address_clear_host_address(config_data->cidr_addr,
config_data->cidr_prefix);
((guint8 *) &gateway)[3] += 1;
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;
}
rt_metric = 10;
rt_table = 30400 + config_data->iface_idx;

View file

@ -123,7 +123,8 @@ 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_NETMASK
GET_CONFIG_FETCH_DONE_TYPE_NETMASK,
GET_CONFIG_FETCH_DONE_TYPE_GATEWAY,
} GetConfigFetchDoneType;
static void
@ -140,6 +141,7 @@ _get_config_fetch_done_cb(NMHttpClient * http_client,
in_addr_t tmp_addr;
int tmp_prefix;
in_addr_t netmask_bin;
in_addr_t gateway_bin;
gs_free const char ** s_addrs = NULL;
gsize i;
gsize len;
@ -200,6 +202,17 @@ _get_config_fetch_done_cb(NMHttpClient * http_client,
config_iface_data->cidr_prefix = nm_utils_ip4_netmask_to_prefix(netmask_bin);
};
break;
case GET_CONFIG_FETCH_DONE_TYPE_GATEWAY:
if (nm_utils_parse_inaddr_bin(AF_INET,
g_bytes_get_data(response, NULL),
NULL,
&gateway_bin)) {
config_iface_data->has_gateway = TRUE;
config_iface_data->gateway = gateway_bin;
};
break;
}
out:
@ -234,6 +247,15 @@ _get_config_fetch_done_cb_netmask(GObject *source, GAsyncResult *result, gpointe
GET_CONFIG_FETCH_DONE_TYPE_NETMASK);
}
static void
_get_config_fetch_done_cb_gateway(GObject *source, GAsyncResult *result, gpointer user_data)
{
_get_config_fetch_done_cb(NM_HTTP_CLIENT(source),
result,
user_data,
GET_CONFIG_FETCH_DONE_TYPE_GATEWAY);
}
typedef struct {
gssize iface_idx;
char path[0];
@ -277,6 +299,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
gs_free char * uri1 = NULL;
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,
@ -354,6 +377,23 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
NULL,
_get_config_fetch_done_cb_netmask,
nm_utils_user_data_pack(get_config_data, hwaddr));
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, "/") ? "" : "/",
"gateway")),
HTTP_TIMEOUT_MS,
512 * 1024,
10000,
1000,
NULL,
get_config_data->intern_cancellable,
NULL,
NULL,
_get_config_fetch_done_cb_gateway,
nm_utils_user_data_pack(get_config_data, hwaddr));
}
_nmcs_provider_get_config_task_maybe_return(get_config_data, NULL);

View file

@ -19,9 +19,11 @@ typedef struct {
gssize iface_idx;
in_addr_t cidr_addr;
in_addr_t gateway;
guint8 cidr_prefix;
bool has_ipv4s : 1;
bool has_cidr : 1;
bool has_gateway : 1;
NMIPRoute **iproutes_arr;
gsize iproutes_len;