Reapply "cloud-setup: parse OCI metadata related to VLAN config"

Baremetal instances in Oracle Cloud require special VLAN config. Parse
the metadata related to it.

This reverts commit 5eefd2d59c.

(cherry picked from commit 5c3efeef15)
This commit is contained in:
Lubomir Rintel
2025-02-10 02:46:49 +01:00
parent b7114d00ed
commit fd6f4f86e4
3 changed files with 90 additions and 2 deletions

View File

@@ -92,6 +92,9 @@ _get_config_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
gs_unref_bytes GBytes *response = NULL;
gs_free_error GError *error = NULL;
nm_auto_decref_json json_t *vnics = NULL;
gboolean is_baremetal;
gs_unref_ptrarray GPtrArray *phys_nic_macs = NULL;
GHashTableIter h_iter;
size_t i;
nm_http_client_poll_req_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
@@ -112,12 +115,24 @@ _get_config_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
goto out;
}
if (json_array_size(vnics) > 0) {
is_baremetal = NULL != json_object_get(json_array_get(vnics, 0), "nicIndex");
_LOGI("get-config: detected %s instance", is_baremetal ? "baremetal" : "VM");
} else {
is_baremetal = FALSE;
_LOGI("get-config: empty VNICs metadata, cannot detect instance type");
}
if (is_baremetal)
phys_nic_macs = g_ptr_array_sized_new(16);
for (i = 0; i < json_array_size(vnics); i++) {
json_t *vnic, *field;
const char *vnic_id = "", *val;
gs_free char *mac = NULL;
in_addr_t addr;
int prefix;
json_int_t nic_index = -1, vlan_tag = -1;
vnic = json_array_get(vnics, i);
if (!json_is_object(vnic)) {
@@ -130,12 +145,28 @@ _get_config_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
field = json_object_get(vnic, "macAddr");
val = field && json_is_string(field) ? json_string_value(field) : NULL;
if (!val) {
mac = val ? nmcs_utils_hwaddr_normalize(val, json_string_length(field)) : NULL;
if (!mac) {
_VNIC_WARN("missing or invalid 'macAddr', ignoring VNIC");
continue;
}
mac = nmcs_utils_hwaddr_normalize(val, json_string_length(field));
if (is_baremetal) {
field = json_object_get(vnic, "nicIndex");
nic_index = field && json_is_integer(field) ? json_integer_value(field) : -1;
if (nic_index < 0 || nic_index >= 1024) { /* 1024 = random limit to prevent abuse*/
_VNIC_WARN("missing or invalid 'nicIndex', ignoring VNIC");
continue;
}
field = json_object_get(vnic, "vlanTag");
vlan_tag = field && json_is_integer(field) ? json_integer_value(field) : -1;
if (vlan_tag < 0) {
_VNIC_WARN("missing or invalid 'vlanTag', ignoring VNIC");
continue;
}
}
config_iface_data = nmcs_provider_get_config_iface_data_create(get_config_data, FALSE, mac);
config_iface_data->iface_idx = i;
@@ -168,6 +199,48 @@ _get_config_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
} else {
_VNIC_WARN("missing or invalid 'subnetCidrBlock'");
}
if (is_baremetal) {
gboolean is_phys_nic = vlan_tag == 0;
/* In baremetal instances, configure VNICs' VLAN (physical NICs don't need it) */
if (is_phys_nic) {
config_iface_data->priv.oci.vlan_tag = 0;
config_iface_data->priv.oci.parent_hwaddr = NULL;
if (nic_index >= phys_nic_macs->len)
g_ptr_array_set_size(phys_nic_macs,
NM_MAX((guint) (nic_index + 1), phys_nic_macs->len * 2));
phys_nic_macs->pdata[nic_index] = (gpointer) config_iface_data->hwaddr;
} else {
/* We might not have all the physical NICs' MACs yet, save nicIndex for later */
config_iface_data->priv.oci.parent_hwaddr = GINT_TO_POINTER((int) nic_index);
config_iface_data->priv.oci.vlan_tag = vlan_tag;
}
}
}
if (is_baremetal) {
g_hash_table_iter_init(&h_iter, get_config_data->result_dict);
/* Now that all the metadata is processed we should have all the physical NICs' MACs */
while (g_hash_table_iter_next(&h_iter, NULL, (gpointer *) &config_iface_data)) {
bool is_phys_nic = config_iface_data->priv.oci.vlan_tag == 0;
int nic_index = GPOINTER_TO_INT(config_iface_data->priv.oci.parent_hwaddr);
if (is_phys_nic)
continue;
if (nic_index >= phys_nic_macs->len || phys_nic_macs->pdata[nic_index] == NULL) {
_LOGW("get-config: physical NIC for nicIndex=%d not found, ignoring VNIC "
"(VNIC macAddr=%s)",
nic_index,
config_iface_data->hwaddr);
g_hash_table_iter_remove(&h_iter);
continue;
}
config_iface_data->priv.oci.parent_hwaddr = g_strdup(phys_nic_macs->pdata[nic_index]);
}
}
out:

View File

@@ -188,6 +188,7 @@ nmcs_provider_get_config_iface_data_create(NMCSProviderGetConfigTaskData *get_co
iface_data = g_slice_new(NMCSProviderGetConfigIfaceData);
*iface_data = (NMCSProviderGetConfigIfaceData) {
.provider = g_object_ref(get_config_data->self),
.get_config_data = get_config_data,
.hwaddr = g_strdup(hwaddr),
.iface_idx = -1,
@@ -203,6 +204,11 @@ nmcs_provider_get_config_iface_data_create(NMCSProviderGetConfigTaskData *get_co
iface_data->priv.aliyun = (typeof(iface_data->priv.aliyun)) {
.has_primary_ip_address = FALSE,
};
} else if (G_OBJECT_TYPE(get_config_data->self) == nmcs_provider_oci_get_type()) {
iface_data->priv.oci = (typeof(iface_data->priv.oci)) {
.vlan_tag = 0,
.parent_hwaddr = NULL,
};
}
/* the has does not own the key (iface_datta->hwaddr), the lifetime of the
@@ -220,6 +226,9 @@ _iface_data_free(gpointer data)
g_free(iface_data->ipv4s_arr);
nm_g_ptr_array_unref(iface_data->iproutes);
g_free((char *) iface_data->hwaddr);
if (G_OBJECT_TYPE(iface_data->provider) == nmcs_provider_oci_get_type())
g_free((char *) iface_data->priv.oci.parent_hwaddr);
g_clear_object(&iface_data->provider);
nm_g_slice_free(iface_data);
}

View File

@@ -17,6 +17,8 @@ typedef struct {
* dictionary. */
const char *hwaddr;
struct _NMCSProvider *provider;
struct _NMCSProviderGetConfigTaskData *get_config_data;
in_addr_t *ipv4s_arr;
@@ -51,6 +53,10 @@ typedef struct {
bool has_primary_ip_address : 1;
bool ipv4s_arr_ordered : 1;
} aliyun;
struct {
guint32 vlan_tag; /* 0 if no VLAN is needed */
const char *parent_hwaddr;
} oci;
} priv;
} NMCSProviderGetConfigIfaceData;