mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-18 15:20:37 +01:00
cloud-setup: merge branch 'th/cloud-setup-fix-containers'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/740
https://bugzilla.redhat.com/show_bug.cgi?id=1977984#c27
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/974
(cherry picked from commit e947053c23)
This commit is contained in:
commit
df7d1f94b7
8 changed files with 347 additions and 200 deletions
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -200,30 +202,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 +245,7 @@ _get_config(GCancellable *sigterm_cancellable, NMCSProvider *provider, NMClient
|
|||
|
||||
g_main_loop_run(main_loop);
|
||||
|
||||
return data.config_dict;
|
||||
return data.result;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -269,7 +271,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;
|
||||
|
|
@ -277,10 +281,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;
|
||||
|
|
@ -288,6 +288,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,48 +332,84 @@ _nmc_mangle_connection(NMDevice * device,
|
|||
}
|
||||
}
|
||||
|
||||
if (config_data->has_ipv4s && config_data->has_cidr) {
|
||||
for (i = 0; i < config_data->ipv4s_len; i++) {
|
||||
NMIPAddress *entry;
|
||||
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) {
|
||||
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;
|
||||
in_addr_t gateway;
|
||||
char sbuf[NM_UTILS_INET_ADDRSTRLEN];
|
||||
|
||||
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);
|
||||
for (i = 0; i < config_data->ipv4s_len; i++) {
|
||||
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);
|
||||
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,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -395,34 +434,20 @@ _nmc_mangle_connection(NMDevice * device,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static guint
|
||||
_config_data_get_num_valid(GHashTable *config_dict)
|
||||
{
|
||||
const NMCSProviderGetConfigIfaceData *config_data;
|
||||
GHashTableIter h_iter;
|
||||
guint n = 0;
|
||||
|
||||
g_hash_table_iter_init(&h_iter, config_dict);
|
||||
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)
|
||||
_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;
|
||||
gboolean skipped_single_addr;
|
||||
gboolean version_id_changed;
|
||||
guint try_count;
|
||||
gboolean any_changes = FALSE;
|
||||
|
|
@ -443,6 +468,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/",
|
||||
|
|
@ -471,16 +504,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;
|
||||
}
|
||||
|
||||
|
|
@ -489,7 +536,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,
|
||||
|
|
@ -525,19 +572,15 @@ 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;
|
||||
const char * c_hwaddr;
|
||||
gboolean is_single_nic;
|
||||
gboolean any_changes = FALSE;
|
||||
gboolean any_changes = FALSE;
|
||||
guint i;
|
||||
|
||||
is_single_nic = (_config_data_get_num_valid(config_dict) <= 1);
|
||||
|
||||
g_hash_table_iter_init(&h_iter, config_dict);
|
||||
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))
|
||||
for (i = 0; i < result->n_iface_datas; i++) {
|
||||
if (_config_one(sigterm_cancellable, nmc, result, i))
|
||||
any_changes = TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -564,12 +607,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 +657,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,90 @@ nmcs_provider_get_main_context(NMCSProvider *self)
|
|||
|
||||
return nm_http_client_get_main_context(NMCS_PROVIDER_GET_PRIVATE(self)->http_client);
|
||||
}
|
||||
/*****************************************************************************/
|
||||
|
||||
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)
|
||||
{
|
||||
const NMCSProviderGetConfigIfaceData *iface_data;
|
||||
NMCSProviderGetConfigResult * result;
|
||||
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)) {
|
||||
if (nmcs_provider_get_config_iface_data_is_valid(iface_data)) {
|
||||
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),
|
||||
.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;
|
||||
}
|
||||
|
||||
void
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -90,15 +174,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;
|
||||
}
|
||||
|
||||
|
|
@ -109,6 +203,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);
|
||||
}
|
||||
|
|
@ -137,8 +232,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),
|
||||
|
|
@ -187,16 +282,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;
|
||||
|
|
@ -217,7 +309,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);
|
||||
|
|
|
|||
|
|
@ -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,7 +45,43 @@ 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().
|
||||
*
|
||||
* 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(). */
|
||||
guint num_valid_ifaces;
|
||||
|
||||
/* 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);
|
||||
|
||||
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 +164,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__ */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue