Commit 68a4bb9a authored by Jaroslava Fiedlerova's avatar Jaroslava Fiedlerova

Merge remote-tracking branch 'origin/mplane-v16.01' into integration_2025_w48 (!3616)

[FHI72 M-plane] Update the M-plane support to v16.01

- retrieve the additional hardware states (oper-state, admin-state,
  availability-state) and update according to the received notifications
- properly configure MIMO mode if a RU supports
- update the yang models to v16.01
- tested with Benetel v1.4.1, and added an example run in the M-plane doc

Note: backwards compatible with M-plane v05.00

Also, memory leakages fixed cause by ru_session_list_t, and xml functions
xmlReadMemory() and xmlNodeGetContent().
parents c8b4aa2a 19bb4630
This diff is collapsed.
...@@ -59,24 +59,7 @@ bool connect_mplane(ru_session_t *ru_session) ...@@ -59,24 +59,7 @@ bool connect_mplane(ru_session_t *ru_session)
void disconnect_mplane(void *rus_disconnect) void disconnect_mplane(void *rus_disconnect)
{ {
ru_session_list_t *ru_session_list = (ru_session_list_t *)rus_disconnect; ru_session_list_t *ru_session_list = (ru_session_list_t *)rus_disconnect;
free_ru_session_list(ru_session_list);
for (size_t i = 0; i <ru_session_list->num_rus; i++) {
ru_session_t *ru_session = &ru_session_list->ru_session[i];
if (ru_session->session == NULL)
continue;
MP_LOG_I("Sending PM de-activation request for RU \"%s\".\n", ru_session->ru_ip_add);
bool success = pm_conf(ru_session, "false");
if (success)
MP_LOG_I("Successfully de-activated PM for RU \"%s\".\n", ru_session->ru_ip_add);
MP_LOG_I("Disconnecting from RU \"%s\".\n", ru_session->ru_ip_add);
nc_session_free(ru_session->session, NULL);
ru_session->session = NULL;
#ifdef MPLANE_V1
ly_ctx_destroy((struct ly_ctx *)ru_session->ctx, NULL);
#elif defined MPLANE_V2
ly_ctx_destroy((struct ly_ctx *)ru_session->ctx);
#endif
}
nc_client_destroy(); nc_client_destroy();
} }
...@@ -141,6 +141,43 @@ bool init_mplane(ru_session_list_t *ru_session_list) ...@@ -141,6 +141,43 @@ bool init_mplane(ru_session_list_t *ru_session_list)
return true; return true;
} }
static void init_ru_notif(ru_session_t *ru_session, const char* buffer)
{
char* usage_state = get_ru_xml_node(buffer, "usage-state");
if (usage_state != NULL && strcmp(usage_state, "busy") == 0) {
ru_session->ru_notif.rx_carrier_state = BUSY_CARRIER;
ru_session->ru_notif.tx_carrier_state = BUSY_CARRIER;
ru_session->ru_notif.config_change = true;
} else if (usage_state != NULL && strcmp(usage_state, "active") == 0) {
ru_session->ru_notif.rx_carrier_state = READY_CARRIER;
ru_session->ru_notif.tx_carrier_state = READY_CARRIER;
ru_session->ru_notif.config_change = true;
} else { // "idle" or NULL
ru_session->ru_notif.rx_carrier_state = DISABLED_CARRIER;
ru_session->ru_notif.tx_carrier_state = DISABLED_CARRIER;
ru_session->ru_notif.config_change = false;
}
char *oper_state = get_ru_xml_node(buffer, "oper-state");
ru_session->ru_notif.hardware.oper_state = (str_to_enum_oper(oper_state) != OPER_COUNT) ? str_to_enum_oper(oper_state) : ENABLED_OPER;
char *admin_state = get_ru_xml_node(buffer, "admin-state");
ru_session->ru_notif.hardware.admin_state = (str_to_enum_admin(admin_state) != ADMIN_COUNT) ? str_to_enum_admin(admin_state) : UNLOCKED_ADMIN;
char *avail_state = get_ru_xml_node(buffer, "availability-state");
ru_session->ru_notif.hardware.avail_state = (str_to_enum_avail(avail_state) != AVAIL_COUNT) ? str_to_enum_avail(avail_state) : NORMAL_AVAIL;
char *ptp_state = get_ru_xml_node(buffer, "sync-state");
ru_session->ru_notif.ptp_state = str_to_enum_ptp(ptp_state);
MP_LOG_I("RU is in \"%s\" sync state.\n", ptp_state);
free(usage_state);
free(oper_state);
free(admin_state);
free(avail_state);
free(ptp_state);
}
bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus) bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus)
{ {
bool success = false; bool success = false;
...@@ -149,12 +186,8 @@ bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const siz ...@@ -149,12 +186,8 @@ bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const siz
success = get_mplane(ru_session, &operational_ds); success = get_mplane(ru_session, &operational_ds);
AssertError(success, return false, "[MPLANE] Unable to continue: could not get RU answer via get_mplane().\n"); AssertError(success, return false, "[MPLANE] Unable to continue: could not get RU answer via get_mplane().\n");
bool ptp_state = false; // init RU notifications
const char *sync_state = get_ru_xml_node(operational_ds, "sync-state"); init_ru_notif(ru_session, operational_ds);
if (strcmp(sync_state, "LOCKED") == 0) {
MP_LOG_I("RU is already PTP synchronized.\n");
ptp_state = true;
}
/* 1) as per M-plane spec, RU must be in supervised mode, /* 1) as per M-plane spec, RU must be in supervised mode,
where stream = NULL && filter = "/o-ran-supervision:supervision-notification"; where stream = NULL && filter = "/o-ran-supervision:supervision-notification";
...@@ -163,7 +196,6 @@ bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const siz ...@@ -163,7 +196,6 @@ bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const siz
=> since more than one subscription at the time within one session is not possible, we will subscribe to all notifications */ => since more than one subscription at the time within one session is not possible, we will subscribe to all notifications */
const char *stream = "NETCONF"; const char *stream = "NETCONF";
const char *filter = NULL; const char *filter = NULL;
ru_session->ru_notif.ptp_state = ptp_state;
success = subscribe_mplane(ru_session, stream, filter, (void *)&ru_session->ru_notif); success = subscribe_mplane(ru_session, stream, filter, (void *)&ru_session->ru_notif);
AssertError(success, return false, "[MPLANE] Unable to continue: could not get RU answer via subscribe_mplane().\n"); AssertError(success, return false, "[MPLANE] Unable to continue: could not get RU answer via subscribe_mplane().\n");
...@@ -189,26 +221,18 @@ bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const siz ...@@ -189,26 +221,18 @@ bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const siz
success = load_yang_models(ru_session, operational_ds); success = load_yang_models(ru_session, operational_ds);
AssertError(success, return false, "[MPLANE] Unable to load yang models.\n"); AssertError(success, return false, "[MPLANE] Unable to load yang models.\n");
if (ru_session->ru_notif.ptp_state) { while (1) {
char *content = NULL; sleep(5);
success = configure_ru_from_yang(ru_session, oai, num_rus, &content); if (!ru_session->ru_notif.ptp_state && !ru_session->ru_notif.hardware.oper_state && !ru_session->ru_notif.hardware.admin_state && !ru_session->ru_notif.hardware.avail_state) {
AssertError(success, return false, "[MPLANE] Unable to create content for <edit-config> RPC for start-up procedure.\n"); char *content = NULL;
success = configure_ru_from_yang(ru_session, oai, num_rus, &content);
success = edit_val_commmit_rpc(ru_session, content); AssertError(success, return false, "[MPLANE] Unable to create content for <edit-config> RPC for start-up procedure.\n");
AssertError(success, return false, "[MPLANE] Unable to continue.\n");
free(content);
}
const char *usage_state = get_ru_xml_node(operational_ds, "usage-state"); success = edit_val_commmit_rpc(ru_session, content);
MP_LOG_I("Usage state = \"%s\" for RU \"%s\".\n", usage_state, ru_session->ru_ip_add); AssertError(success, return false, "[MPLANE] Unable to continue.\n");
if (strcmp(usage_state, "busy") == 0) { // carriers are already activated free(content);
ru_session->ru_notif.rx_carrier_state = true; break;
ru_session->ru_notif.tx_carrier_state = true; }
ru_session->ru_notif.config_change = true;
} else {
ru_session->ru_notif.rx_carrier_state = false;
ru_session->ru_notif.tx_carrier_state = false;
ru_session->ru_notif.config_change = false;
} }
free(operational_ds); free(operational_ds);
......
...@@ -20,11 +20,145 @@ ...@@ -20,11 +20,145 @@
*/ */
#include "ru-mplane-api.h" #include "ru-mplane-api.h"
#include "init-mplane.h"
#include "xml/get-xml.h" #include "xml/get-xml.h"
#include "common/utils/assertions.h" #include "common/utils/assertions.h"
#include <string.h> #include <string.h>
#include <libyang/libyang.h>
#include <nc_client.h>
static void free_pm_stats(pm_stats_t *src)
{
// free Rx window measurements
for (size_t i = 0; i < src->rx_num; i++) {
free(src->rx_window_meas[i]);
}
free(src->rx_window_meas);
// free Tx measurements
for (size_t i = 0; i < src->tx_num; i++) {
free(src->tx_meas[i]);
}
free(src->tx_meas);
}
static void free_uplane_info(uplane_info_t *src)
{
for (size_t i = 0; i < src->num; i++) {
free(src->name[i]);
}
free(src->name);
}
static void free_ru_mplane_config(ru_mplane_config_t *src)
{
// free DU MAC address(es) and VLAN tag(s)
for (size_t i = 0; i < src->num_cu_planes; i++) {
free(src->du_mac_addr[i]);
}
free(src->du_mac_addr);
free(src->vlan_tag);
// free interface name
free(src->interface_name);
// free endpoints and carriers
free_uplane_info(&src->tx_endpoints);
free_uplane_info(&src->rx_endpoints);
free_uplane_info(&src->tx_carriers);
free_uplane_info(&src->rx_carriers);
}
static void free_ru_session(ru_session_t *src)
{
// username
free(src->username);
// if no RU connected to, free only the initialized RU IP address
if (src->session == NULL) {
free(src->ru_ip_add);
return;
}
// disconnect from the RU
MP_LOG_I("Sending PM de-activation request for RU \"%s\".\n", src->ru_ip_add);
bool success = pm_conf(src, "false");
if (success)
MP_LOG_I("Successfully de-activated PM for RU \"%s\".\n", src->ru_ip_add);
MP_LOG_I("Disconnecting from RU \"%s\".\n", src->ru_ip_add);
// free RU IP address
free(src->ru_ip_add);
// free RU M-plane config
free_ru_mplane_config(&src->ru_mplane_config);
// free NETCONF session
nc_session_free(src->session, NULL);
src->session = NULL;
// free libyang context
#ifdef MPLANE_V1
ly_ctx_destroy((struct ly_ctx *)src->ctx, NULL);
#elif defined MPLANE_V2
ly_ctx_destroy((struct ly_ctx *)src->ctx);
#endif
// free only the RU MAC addressin xran M-plane info
free(src->xran_mplane.ru_mac_addr);
// nothing to free in ru_notif
// free PM stats
free_pm_stats(&src->pm_stats);
}
void free_ru_session_list(ru_session_list_t *src)
{
// DU key pair
for (size_t i = 0; i < 2; i++) {
free(src->du_key_pair[i]);
}
free(src->du_key_pair);
// RU session
for (size_t i = 0; i < src->num_rus; i++) {
free_ru_session(&src->ru_session[i]);
}
free(src->ru_session);
}
oper_state_e str_to_enum_oper(const char* value) {
#define X(name, str) if (value != NULL && strcmp(value, str) == 0) return name;
OPER_STATE
#undef X
return OPER_COUNT;
};
admin_state_e str_to_enum_admin(const char* value) {
#define X(name, str) if (value != NULL && strcmp(value, str) == 0) return name;
ADMIN_STATE
#undef X
return ADMIN_COUNT;
};
avail_state_e str_to_enum_avail(const char* value) {
#define X(name, str) if (value != NULL && strcmp(value, str) == 0) return name;
AVAIL_STATE
#undef X
return AVAIL_COUNT;
};
ptp_state_e str_to_enum_ptp(const char* value) {
#define X(name, str) if (value != NULL && strcmp(value, str) == 0) return name;
PTP_STATE
#undef X
return PTP_COUNT;
};
carrier_state_e str_to_enum_carrier(const char* value) {
#define X(name, str) if (value != NULL && strcmp(value, str) == 0) return name;
CARRIER_STATE
#undef X
return CARRIER_COUNT;
};
static void free_match_list(char **match_list, size_t count) static void free_match_list(char **match_list, size_t count)
{ {
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
...@@ -63,13 +197,15 @@ static void fix_benetel_setting(xran_mplane_t *xran_mplane, const uint32_t inter ...@@ -63,13 +197,15 @@ static void fix_benetel_setting(xran_mplane_t *xran_mplane, const uint32_t inter
bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_t *xran_mplane) bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_t *xran_mplane)
{ {
/* some O-RU vendors are not fully compliant as per M-plane specifications */ /* some O-RU vendors are not fully compliant as per M-plane specifications */
const char *ru_vendor = get_ru_xml_node(buffer, "mfg-name"); char *ru_vendor = get_ru_xml_node(buffer, "mfg-name");
// RU MAC // RU MAC
xran_mplane->ru_mac_addr = get_ru_xml_node(buffer, "mac-address"); // TODO: support for VVDN, as it defines multiple MAC addresses xran_mplane->ru_mac_addr = get_ru_xml_node(buffer, "mac-address"); // TODO: support for VVDN, as it defines multiple MAC addresses
// MTU // MTU
const uint32_t interface_mtu = (uint32_t)atoi(get_ru_xml_node(buffer, "l2-mtu")); char *int_mtu_str = get_ru_xml_node(buffer, "l2-mtu");
const uint32_t interface_mtu = (uint32_t)atoi(int_mtu_str);
free(int_mtu_str);
// IQ bitwidth // IQ bitwidth
char **match_list = NULL; char **match_list = NULL;
...@@ -107,14 +243,17 @@ bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_ ...@@ -107,14 +243,17 @@ bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_
free_match_list(match_list, count); free_match_list(match_list, count);
// Managed delay support // Managed delay support
const char *managed_delay = get_ru_xml_node(buffer, "managed-delay-support"); char *managed_delay = get_ru_xml_node(buffer, "managed-delay-support");
xran_mplane->managed_delay = (strcasecmp(managed_delay, "NON_MANAGED") == 0) ? false : true; xran_mplane->managed_delay = (strcasecmp(managed_delay, "NON_MANAGED") == 0) ? false : true;
free(managed_delay);
// Store the max gain // Store the max gain
xran_mplane->max_tx_gain = (double)atof(get_ru_xml_node(buffer, "max-gain")); char *max_tx_gain_str = get_ru_xml_node(buffer, "max-gain");
xran_mplane->max_tx_gain = (double)atof(max_tx_gain_str);
free(max_tx_gain_str);
// Model name // Model name
const char *model_name = get_ru_xml_node(buffer, "model-name"); char *model_name = get_ru_xml_node(buffer, "model-name");
if (strcasecmp(ru_vendor, "BENETEL") == 0 /* || strcmp(ru_vendor, "VVDN-LPRU") == 0 || strcmp(ru_vendor, "Metanoia") == 0 */) { if (strcasecmp(ru_vendor, "BENETEL") == 0 /* || strcmp(ru_vendor, "VVDN-LPRU") == 0 || strcmp(ru_vendor, "Metanoia") == 0 */) {
fix_benetel_setting(xran_mplane, interface_mtu, first_iq_width, max_num_ant, model_name); fix_benetel_setting(xran_mplane, interface_mtu, first_iq_width, max_num_ant, model_name);
...@@ -150,6 +289,9 @@ bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_ ...@@ -150,6 +289,9 @@ bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_
xran_mplane->ru_port, xran_mplane->ru_port,
xran_mplane->max_tx_gain); xran_mplane->max_tx_gain);
free(ru_vendor);
free(model_name);
return true; return true;
} }
...@@ -185,7 +327,7 @@ bool get_uplane_info(const char *buffer, ru_mplane_config_t *ru_mplane_config) ...@@ -185,7 +327,7 @@ bool get_uplane_info(const char *buffer, ru_mplane_config_t *ru_mplane_config)
bool get_pm_object_list(const char *buffer, pm_stats_t *pm_stats) bool get_pm_object_list(const char *buffer, pm_stats_t *pm_stats)
{ {
const char *ru_vendor = get_ru_xml_node(buffer, "mfg-name"); char *ru_vendor = get_ru_xml_node(buffer, "mfg-name");
if (strcasecmp(ru_vendor, "BENETEL") == 0) { if (strcasecmp(ru_vendor, "BENETEL") == 0) {
pm_stats->start_up_timing = false; pm_stats->start_up_timing = false;
} else { } else {
...@@ -200,5 +342,7 @@ bool get_pm_object_list(const char *buffer, pm_stats_t *pm_stats) ...@@ -200,5 +342,7 @@ bool get_pm_object_list(const char *buffer, pm_stats_t *pm_stats)
MP_LOG_I("Successfully retreived all performance measurement names.\n"); MP_LOG_I("Successfully retreived all performance measurement names.\n");
free(ru_vendor);
return true; return true;
} }
...@@ -31,10 +31,86 @@ ...@@ -31,10 +31,86 @@
#define MP_LOG_I(x, args...) LOG_I(HW, "[MPLANE] " x, ##args) #define MP_LOG_I(x, args...) LOG_I(HW, "[MPLANE] " x, ##args)
#define MP_LOG_W(x, args...) LOG_W(HW, "[MPLANE] " x, ##args) #define MP_LOG_W(x, args...) LOG_W(HW, "[MPLANE] " x, ##args)
#define OPER_STATE \
X(ENABLED_OPER, "enabled") \
X(DISABLED_OPER, "disabled")
typedef enum {
#define X(name, str) name,
OPER_STATE
#undef X
OPER_COUNT
} oper_state_e;
oper_state_e str_to_enum_oper(const char* value);
#define ADMIN_STATE \
X(UNLOCKED_ADMIN, "unlocked") \
X(SHUTTING_DOWN_ADMIN, "shutting-down") \
X(LOCKED_ADMIN, "locked")
typedef enum {
#define X(name, str) name,
ADMIN_STATE
#undef X
ADMIN_COUNT
} admin_state_e;
admin_state_e str_to_enum_admin(const char* value);
#define AVAIL_STATE \
X(NORMAL_AVAIL, "NORMAL") \
X(DEGRADED_AVAIL, "DEGRADED") \
X(FAULTY_AVAIL, "FAULTY")
typedef enum {
#define X(name, str) name,
AVAIL_STATE
#undef X
AVAIL_COUNT
} avail_state_e;
avail_state_e str_to_enum_avail(const char* value);
typedef struct {
oper_state_e oper_state; // "enabled", "disabled"
admin_state_e admin_state; // "unlocked", "shutting-down", "locked"
avail_state_e avail_state; // "NORMAL", "DEGRADED", "FAULTY"
} hardware_notif_t;
#define PTP_STATE \
X(LOCKED_PTP, "LOCKED") \
X(FREERUN_PTP, "FREERUN") \
X(HOLDOVER_PTP, "HOLDOVER")
typedef enum {
#define X(name, str) name,
PTP_STATE
#undef X
PTP_COUNT
} ptp_state_e;
ptp_state_e str_to_enum_ptp(const char* value);
#define CARRIER_STATE \
X(READY_CARRIER, "READY") \
X(DISABLED_CARRIER, "DISABLED") \
X(BUSY_CARRIER, "BUSY")
typedef enum {
#define X(name, str) name,
CARRIER_STATE
#undef X
CARRIER_COUNT
} carrier_state_e;
carrier_state_e str_to_enum_carrier(const char* value);
typedef struct { typedef struct {
bool ptp_state; hardware_notif_t hardware;
bool rx_carrier_state; ptp_state_e ptp_state; // "LOCKED", "FREERUN", "HOLDOVER"
bool tx_carrier_state; carrier_state_e rx_carrier_state; // "READY", "DISABLED", "BUSY"
carrier_state_e tx_carrier_state; // "READY", "DISABLED", "BUSY"
bool config_change; bool config_change;
// to be extended with any notification callback // to be extended with any notification callback
...@@ -112,6 +188,8 @@ typedef struct { ...@@ -112,6 +188,8 @@ typedef struct {
} ru_session_list_t; } ru_session_list_t;
void free_ru_session_list(ru_session_list_t *src);
bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_t *xran_mplane); bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_t *xran_mplane);
bool get_uplane_info(const char *buffer, ru_mplane_config_t *ru_mplane_config); bool get_uplane_info(const char *buffer, ru_mplane_config_t *ru_mplane_config);
......
...@@ -30,13 +30,8 @@ ...@@ -30,13 +30,8 @@
static void recv_notif_v1(const struct nc_notif *notif, ru_notif_t *answer) static void recv_notif_v1(const struct nc_notif *notif, ru_notif_t *answer)
{ {
const char *node_name = notif->tree->child->attr->name; const char *node_name = notif->tree->child->attr->name;
const char *value = notif->tree->child->attr->value_str;
if (strcmp(node_name, "sync-state")) { if (strcmp(node_name, "sync-state")) {
if (strcmp(value, "LOCKED") == 0) { answer->ptp_state = str_to_enum_ptp(notif->tree->child->attr->value_str);
answer->ptp_state = true;
} else {
answer->ptp_state = false;
}
} }
// carriers state - to be filled // carriers state - to be filled
...@@ -52,6 +47,8 @@ static void notif_clb_v1(struct nc_session *session, const struct nc_notif *noti ...@@ -52,6 +47,8 @@ static void notif_clb_v1(struct nc_session *session, const struct nc_notif *noti
MP_LOG_I("\nReceived notification at (%s)\n%s\n", notif->datetime, subs_reply); MP_LOG_I("\nReceived notification at (%s)\n%s\n", notif->datetime, subs_reply);
recv_notif_v1(notif, answer); recv_notif_v1(notif, answer);
free(subs_reply);
} }
#elif MPLANE_V2 #elif MPLANE_V2
static void log_v2_pm_info(const char *ru_ip_add, struct lyd_node_inner *stats) static void log_v2_pm_info(const char *ru_ip_add, struct lyd_node_inner *stats)
...@@ -85,33 +82,36 @@ static void log_v2_pm_info(const char *ru_ip_add, struct lyd_node_inner *stats) ...@@ -85,33 +82,36 @@ static void log_v2_pm_info(const char *ru_ip_add, struct lyd_node_inner *stats)
meas_list[7], count_list[7]); meas_list[7], count_list[7]);
} }
static void get_hardware_states(struct lyd_node_inner *op, ru_notif_t *answer)
{
struct lyd_node *child = NULL;
LY_LIST_FOR(op->child, child) {
if (strcmp(child->schema->name, "admin-state") == 0) {
answer->hardware.admin_state = str_to_enum_admin(lyd_get_value(child));
} else if (strcmp(child->schema->name, "availability-state") == 0) {
answer->hardware.avail_state = str_to_enum_avail(lyd_get_value(child));
}
}
}
static void recv_notif_v2(struct lyd_node_inner *op, ru_notif_t *answer) static void recv_notif_v2(struct lyd_node_inner *op, ru_notif_t *answer)
{ {
const char *notif = op->schema->name; const char *notif = op->schema->name;
if (strcmp(notif, "synchronization-state-change") == 0) { if (strcmp(notif, "synchronization-state-change") == 0) {
const char *value = lyd_get_value(op->child); answer->ptp_state = str_to_enum_ptp(lyd_get_value(op->child));
if (strcmp(value, "LOCKED") == 0) {
answer->ptp_state = true;
} else { // "FREERUN" or "HOLDOVER"
answer->ptp_state = false;
}
} else if (strcmp(notif, "rx-array-carriers-state-change") == 0) { } else if (strcmp(notif, "rx-array-carriers-state-change") == 0) {
const char *value = lyd_get_value(lyd_child(op->child)->next); answer->rx_carrier_state = str_to_enum_carrier(lyd_get_value(lyd_child(op->child)->next));
if (strcmp(value, "READY") == 0) {
answer->rx_carrier_state = true;
} else { // "DISABLED" or "BUSY"
answer->rx_carrier_state = false;
}
} else if (strcmp(notif, "tx-array-carriers-state-change") == 0) { } else if (strcmp(notif, "tx-array-carriers-state-change") == 0) {
const char *value = lyd_get_value(lyd_child(op->child)->next); answer->tx_carrier_state = str_to_enum_carrier(lyd_get_value(lyd_child(op->child)->next));
if (strcmp(value, "READY") == 0) {
answer->tx_carrier_state = true;
} else { // "DISABLED" or "BUSY"
answer->tx_carrier_state = false;
}
} else if (strcmp(notif, "netconf-config-change") == 0) { } else if (strcmp(notif, "netconf-config-change") == 0) {
answer->config_change = true; answer->config_change = true;
} else if (strcmp(notif, "hardware-state-oper-enabled") == 0) {
answer->hardware.oper_state = ENABLED_OPER;
get_hardware_states(op, answer);
} else if (strcmp(notif, "hardware-state-oper-disabled") == 0) {
answer->hardware.oper_state = DISABLED_OPER;
get_hardware_states(op, answer);
} }
} }
...@@ -126,11 +126,14 @@ static void notif_clb_v2(struct nc_session *session, const struct lyd_node *envp ...@@ -126,11 +126,14 @@ static void notif_clb_v2(struct nc_session *session, const struct lyd_node *envp
struct lyd_node_inner *op_inner = (struct lyd_node_inner *)op; struct lyd_node_inner *op_inner = (struct lyd_node_inner *)op;
if (strcmp(op_inner->schema->name, "measurement-result-stats") == 0) { if (strcmp(op_inner->schema->name, "measurement-result-stats") == 0) {
log_v2_pm_info(ru_ip_add, op_inner); log_v2_pm_info(ru_ip_add, op_inner);
free(subs_reply);
return; return;
} }
MP_LOG_I("Received notification from RU \"%s\" at (%s)\n%s\n", ru_ip_add, ((struct lyd_node_opaq *)lyd_child(envp))->value, subs_reply); MP_LOG_I("Received notification from RU \"%s\" at (%s)\n%s\n", ru_ip_add, ((struct lyd_node_opaq *)lyd_child(envp))->value, subs_reply);
recv_notif_v2(op_inner, answer); recv_notif_v2(op_inner, answer);
free(subs_reply);
} }
#endif #endif
......
...@@ -23,8 +23,9 @@ ...@@ -23,8 +23,9 @@
#include <libxml/parser.h> #include <libxml/parser.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
static char *find_ru_xml_node(xmlNode *node, const char *filter) static xmlChar *find_ru_xml_node(xmlNode *node, const char *filter)
{ {
for (xmlNode *cur_node = node; cur_node; cur_node = cur_node->next) { for (xmlNode *cur_node = node; cur_node; cur_node = cur_node->next) {
if (cur_node->type != XML_ELEMENT_NODE) if (cur_node->type != XML_ELEMENT_NODE)
...@@ -39,9 +40,9 @@ static char *find_ru_xml_node(xmlNode *node, const char *filter) ...@@ -39,9 +40,9 @@ static char *find_ru_xml_node(xmlNode *node, const char *filter)
break; break;
} }
} }
return (char *)xmlNodeGetContent(target_node); return xmlNodeGetContent(target_node);
} }
char *answer = find_ru_xml_node(cur_node->children, filter); xmlChar *answer = find_ru_xml_node(cur_node->children, filter);
if (answer != NULL) { if (answer != NULL) {
return answer; return answer;
} }
...@@ -56,7 +57,13 @@ char *get_ru_xml_node(const char *buffer, const char *filter) ...@@ -56,7 +57,13 @@ char *get_ru_xml_node(const char *buffer, const char *filter)
xmlDoc *doc = xmlReadMemory(buffer, len, NULL, NULL, 0); xmlDoc *doc = xmlReadMemory(buffer, len, NULL, NULL, 0);
xmlNode *root_element = xmlDocGetRootElement(doc); xmlNode *root_element = xmlDocGetRootElement(doc);
return find_ru_xml_node(root_element->children, filter); xmlChar *content = find_ru_xml_node(root_element->children, filter);
char *value = strdup((char *)content);
xmlFree(content);
xmlFreeDoc(doc);
return value;
} }
static void find_ru_xml_list(xmlNode *node, const char *filter, char ***match_list, size_t *count) static void find_ru_xml_list(xmlNode *node, const char *filter, char ***match_list, size_t *count)
...@@ -74,11 +81,12 @@ static void find_ru_xml_list(xmlNode *node, const char *filter, char ***match_li ...@@ -74,11 +81,12 @@ static void find_ru_xml_list(xmlNode *node, const char *filter, char ***match_li
break; break;
} }
} }
const char *content = (const char *)xmlNodeGetContent(name_node ? name_node : cur_node); xmlChar *content = xmlNodeGetContent(name_node ? name_node : cur_node);
if (content) { if (content) {
*match_list = realloc(*match_list, (*count + 1) * sizeof(char *)); *match_list = realloc(*match_list, (*count + 1) * sizeof(char *));
(*match_list)[*count] = strdup(content); (*match_list)[*count] = strdup((char *)content);
(*count)++; (*count)++;
xmlFree(content);
} }
} }
find_ru_xml_list(cur_node->children, filter, match_list, count); find_ru_xml_list(cur_node->children, filter, match_list, count);
...@@ -93,4 +101,6 @@ void get_ru_xml_list(const char *buffer, const char *filter, char ***match_list, ...@@ -93,4 +101,6 @@ void get_ru_xml_list(const char *buffer, const char *filter, char ***match_list,
xmlNode *root_element = xmlDocGetRootElement(doc); xmlNode *root_element = xmlDocGetRootElement(doc);
find_ru_xml_list(root_element->children, filter, match_list, count); find_ru_xml_list(root_element->children, filter, match_list, count);
xmlFreeDoc(doc);
} }
...@@ -42,20 +42,30 @@ static bool store_schemas(xmlNode *node, ru_session_t *ru_session, struct ly_ctx ...@@ -42,20 +42,30 @@ static bool store_schemas(xmlNode *node, ru_session_t *ru_session, struct ly_ctx
if (strcmp((const char *)cur_node->name, "schema") == 0) { if (strcmp((const char *)cur_node->name, "schema") == 0) {
xmlNode *name_node = xmlFirstElementChild(cur_node); xmlNode *name_node = xmlFirstElementChild(cur_node);
char *module_name = (char *)xmlNodeGetContent(name_node); xmlChar *module_name = xmlNodeGetContent(name_node);
xmlNode *revision_node = xmlNextElementSibling(name_node); xmlNode *revision_node = xmlNextElementSibling(name_node);
char *module_revision = (char *)xmlNodeGetContent(revision_node); xmlChar *module_revision = xmlNodeGetContent(revision_node);
xmlNode *format_node = xmlNextElementSibling(revision_node); xmlNode *format_node = xmlNextElementSibling(revision_node);
char *module_format = (char *)xmlNodeGetContent(format_node); xmlChar *module_format = xmlNodeGetContent(format_node);
if (strcmp(module_format, "yang") != 0) if (strcmp((char*)module_format, "yang") != 0) {
xmlFree(module_name);
xmlFree(module_revision);
xmlFree(module_format);
continue; continue;
}
MP_LOG_I("RPC request to RU \"%s\" = <get-schema> for module \"%s\".\n", ru_session->ru_ip_add, module_name); MP_LOG_I("RPC request to RU \"%s\" = <get-schema> for module \"%s\".\n", ru_session->ru_ip_add, module_name);
struct nc_rpc *get_schema_rpc = nc_rpc_getschema(module_name, module_revision, "yang", param); struct nc_rpc *get_schema_rpc = nc_rpc_getschema((char*)module_name, (char*)module_revision, "yang", param);
char *schema_data = NULL; char *schema_data = NULL;
bool success = rpc_send_recv((struct nc_session *)ru_session->session, get_schema_rpc, wd, timeout, &schema_data); bool success = rpc_send_recv((struct nc_session *)ru_session->session, get_schema_rpc, wd, timeout, &schema_data);
AssertError(success, return false, "[MPLANE] Unable to get schema for module \"%s\" from RU \"%s\".\n", module_name, ru_session->ru_ip_add); if (!success) {
MP_LOG_W("[MPLANE] Unable to get schema for module \"%s\" from RU \"%s\".\n", module_name, ru_session->ru_ip_add);
xmlFree(module_name);
xmlFree(module_revision);
xmlFree(module_format);
return false;
}
if (schema_data) { if (schema_data) {
#ifdef MPLANE_V1 #ifdef MPLANE_V1
...@@ -68,11 +78,21 @@ static bool store_schemas(xmlNode *node, ru_session_t *ru_session, struct ly_ctx ...@@ -68,11 +78,21 @@ static bool store_schemas(xmlNode *node, ru_session_t *ru_session, struct ly_ctx
if (!mod) { if (!mod) {
MP_LOG_W("Unable to load module \"%s\" from RU \"%s\".\n", module_name, ru_session->ru_ip_add); MP_LOG_W("Unable to load module \"%s\" from RU \"%s\".\n", module_name, ru_session->ru_ip_add);
nc_rpc_free(get_schema_rpc); nc_rpc_free(get_schema_rpc);
#ifdef MPLANE_V1
ly_ctx_destroy(*ctx, NULL);
#elif defined MPLANE_V2
ly_ctx_destroy(*ctx); ly_ctx_destroy(*ctx);
return false; #endif
} xmlFree(module_name);
xmlFree(module_revision);
xmlFree(module_format);
return false;
}
} }
nc_rpc_free(get_schema_rpc); nc_rpc_free(get_schema_rpc);
xmlFree(module_name);
xmlFree(module_revision);
xmlFree(module_format);
} }
} }
...@@ -105,6 +125,7 @@ bool load_yang_models(ru_session_t *ru_session, const char *buffer) ...@@ -105,6 +125,7 @@ bool load_yang_models(ru_session_t *ru_session, const char *buffer)
xmlNode *root_element = xmlDocGetRootElement(doc); xmlNode *root_element = xmlDocGetRootElement(doc);
bool success = load_from_operational_ds(root_element->children, ru_session, ctx); bool success = load_from_operational_ds(root_element->children, ru_session, ctx);
xmlFreeDoc(doc);
if (success) { if (success) {
MP_LOG_I("Successfully loaded all yang modules from operational datastore for RU \"%s\".\n", ru_session->ru_ip_add); MP_LOG_I("Successfully loaded all yang modules from operational datastore for RU \"%s\".\n", ru_session->ru_ip_add);
return true; return true;
...@@ -116,7 +137,7 @@ bool load_yang_models(ru_session_t *ru_session, const char *buffer) ...@@ -116,7 +137,7 @@ bool load_yang_models(ru_session_t *ru_session, const char *buffer)
1) the yang models order is not good - the dependancy models have to be loaded first 1) the yang models order is not good - the dependancy models have to be loaded first
2) earlier O-RAN yang versions (e.g. v4) is not properly defined (i.e. optional parameters should not be included by default) */ 2) earlier O-RAN yang versions (e.g. v4) is not properly defined (i.e. optional parameters should not be included by default) */
const char *yang_dir = YANG_MODELS; const char *yang_dir = YANG_MODELS;
const char *yang_models[] = {"ietf-interfaces", "iana-if-type", "ietf-ip", "iana-hardware", "ietf-hardware", "o-ran-interfaces", "o-ran-module-cap", "o-ran-compression-factors", "o-ran-processing-element", "o-ran-uplane-conf", "ietf-netconf-acm", "ietf-crypto-types", "o-ran-file-management", "o-ran-performance-management"}; const char *yang_models[] = {"ietf-interfaces", "iana-if-type", "ietf-ip", "iana-hardware", "ietf-hardware", "o-ran-wg4-features", "o-ran-interfaces", "o-ran-module-cap", "o-ran-compression-factors", "ietf-crypto-types", "o-ran-usermgmt", "o-ran-processing-element", "o-ran-hardware", "o-ran-common-yang-types", "o-ran-delay-management", "o-ran-uplane-conf", "ietf-netconf-acm", "o-ran-file-management", "o-ran-performance-management"};
#ifdef MPLANE_V1 #ifdef MPLANE_V1
*ctx = ly_ctx_new(yang_dir, 0); *ctx = ly_ctx_new(yang_dir, 0);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -86,6 +86,7 @@ int trx_oran_stop(openair0_device *device) ...@@ -86,6 +86,7 @@ int trx_oran_stop(openair0_device *device)
#ifdef OAI_MPLANE #ifdef OAI_MPLANE
printf("[MPLANE] Stopping M-plane.\n"); printf("[MPLANE] Stopping M-plane.\n");
disconnect_mplane(s->mplane_priv); disconnect_mplane(s->mplane_priv);
free(s->mplane_priv);
#endif #endif
return (0); return (0);
} }
...@@ -312,41 +313,42 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device *d ...@@ -312,41 +313,42 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device *d
bool success = false; bool success = false;
#ifdef OAI_MPLANE #ifdef OAI_MPLANE
ru_session_list_t ru_session_list = {0}; ru_session_list_t *ru_session_list = calloc(1, sizeof(*ru_session_list));
success = init_mplane(&ru_session_list); assert(ru_session_list != NULL && "Memory exhausted");
success = init_mplane(ru_session_list);
AssertFatal(success, "[MPLANE] Cannot initialize M-plane.\n"); AssertFatal(success, "[MPLANE] Cannot initialize M-plane.\n");
bool ru_configured[ru_session_list.num_rus]; bool ru_configured[ru_session_list->num_rus];
for (size_t i = 0; i < ru_session_list.num_rus; i++) { for (size_t i = 0; i < ru_session_list->num_rus; i++) {
ru_session_t *ru_session = &ru_session_list.ru_session[i]; ru_session_t *ru_session = &ru_session_list->ru_session[i];
ru_configured[i] = connect_mplane(ru_session); ru_configured[i] = connect_mplane(ru_session);
if (!ru_configured[i]) { if (!ru_configured[i]) {
continue; continue;
} }
ru_configured[i] = manage_ru(ru_session, openair0_cfg, ru_session_list.num_rus); ru_configured[i] = manage_ru(ru_session, openair0_cfg, ru_session_list->num_rus);
} }
bool all_ok = true; bool all_ok = true;
bool ru_ready[ru_session_list.num_rus]; bool ru_ready[ru_session_list->num_rus];
for (size_t i = 0; i < ru_session_list.num_rus; i++) { for (size_t i = 0; i < ru_session_list->num_rus; i++) {
if (!ru_configured[i]) { if (!ru_configured[i]) {
MP_LOG_I("RU with IP %s couldn't be configured.\n", ru_session_list.ru_session[i].ru_ip_add); MP_LOG_I("RU with IP %s couldn't be configured.\n", ru_session_list->ru_session[i].ru_ip_add);
all_ok = false; all_ok = false;
} }
ru_ready[i] = false; ru_ready[i] = false;
} }
if (!all_ok) { if (!all_ok) {
disconnect_mplane((void *)&ru_session_list); disconnect_mplane(ru_session_list);
AssertFatal(false, "[MPLANE] Stopping M-plane.\n"); AssertFatal(false, "[MPLANE] Stopping M-plane.\n");
} }
while (true) { while (true) {
sleep(1); sleep(1);
bool all_rus_ready = true; bool all_rus_ready = true;
for (int i = 0; i < ru_session_list.num_rus; i++) { for (int i = 0; i < ru_session_list->num_rus; i++) {
ru_session_t *ru_session = &ru_session_list.ru_session[i]; ru_session_t *ru_session = &ru_session_list->ru_session[i];
if (!ru_ready[i] && ru_session->ru_notif.config_change && ru_session->ru_notif.rx_carrier_state && ru_session->ru_notif.tx_carrier_state) { if (!ru_ready[i] && ru_session->ru_notif.config_change && !ru_session->ru_notif.rx_carrier_state && !ru_session->ru_notif.tx_carrier_state) {
MP_LOG_I("RU \"%s\" is now ready.\n", ru_session->ru_ip_add); MP_LOG_I("RU \"%s\" is now ready.\n", ru_session->ru_ip_add);
ru_ready[i] = true; ru_ready[i] = true;
if (!ru_session->pm_stats.start_up_timing) { if (!ru_session->pm_stats.start_up_timing) {
...@@ -364,9 +366,9 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device *d ...@@ -364,9 +366,9 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device *d
} }
} }
eth->mplane_priv = (void *)&ru_session_list; eth->mplane_priv = ru_session_list;
success = get_xran_config((void *)&ru_session_list, openair0_cfg, &fh_init, fh_config); success = get_xran_config(ru_session_list, openair0_cfg, &fh_init, fh_config);
AssertFatal(success, "[MPLANE] Cannot configure xran with M-plane info.\n"); AssertFatal(success, "[MPLANE] Cannot configure xran with M-plane info.\n");
#else #else
success = get_xran_config(NULL, openair0_cfg, &fh_init, fh_config); success = get_xran_config(NULL, openair0_cfg, &fh_init, fh_config);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment