Properly free the memory
1. Create a free_ru_session_list() function to free the memory allocated for the connected RUs before closing the nr-softmodem. 2. xmlReadMemory() and xmlNodeGetContent() were causing serious memory leakages, and now all is properly freed using xmlFreeDoc() and xmlFree().
This commit is contained in:
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,110 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#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) {
|
oper_state_e str_to_enum_oper(const char* value) {
|
||||||
#define X(name, str) if (value != NULL && strcmp(value, str) == 0) return name;
|
#define X(name, str) if (value != NULL && strcmp(value, str) == 0) return name;
|
||||||
OPER_STATE
|
OPER_STATE
|
||||||
@@ -98,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;
|
||||||
@@ -142,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);
|
||||||
@@ -185,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,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 {
|
||||||
@@ -235,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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -188,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);
|
||||||
|
|||||||
@@ -47,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)
|
||||||
@@ -124,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
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.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)
|
||||||
@@ -40,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;
|
||||||
}
|
}
|
||||||
@@ -57,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)
|
||||||
@@ -75,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);
|
||||||
@@ -94,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
|
|||||||
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
|
||||||
@@ -73,10 +83,16 @@ static bool store_schemas(xmlNode *node, ru_session_t *ru_session, struct ly_ctx
|
|||||||
#elif defined MPLANE_V2
|
#elif defined MPLANE_V2
|
||||||
ly_ctx_destroy(*ctx);
|
ly_ctx_destroy(*ctx);
|
||||||
#endif
|
#endif
|
||||||
return false;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,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;
|
||||||
|
|||||||
Reference in New Issue
Block a user