Commit dd8a6eaa authored by Teodora's avatar Teodora

Load yang models

Ideally, we should load the yang models from the RU operational datastore, but the issues are following:
  1) the yang models order is not good - 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)

Added support in both cases, loading from RU with <get-schema> RPC, and loading statically from "radio/fhi_72/mplane/yang/models" folder.
parent e0ffba49
......@@ -32,6 +32,7 @@ target_sources(oran_fhlib_5g_mplane PRIVATE
subscribe-mplane.c
ru-mplane-api.c
xml/get-xml.c
yang/get-yang.c
)
pkg_check_modules(libyang REQUIRED libyang)
......
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "get-yang.h"
#include "../rpc-send-recv.h"
#include "common/utils/assertions.h"
#include <libxml/parser.h>
static bool store_schemas(xmlNode *node, ru_session_t *ru_session, struct ly_ctx **ctx)
{
int timeout = CLI_RPC_REPLY_TIMEOUT;
NC_WD_MODE wd = NC_WD_ALL;
NC_PARAMTYPE param = NC_PARAMTYPE_CONST;
LYS_INFORMAT ly_format = LYS_IN_YANG;
#ifdef MPLANE_V1
*ctx = ly_ctx_new(NULL, 0);
#elif defined MPLANE_V2
ly_ctx_new(NULL, 0, ctx);
#endif
for (xmlNode *cur_node = node; cur_node; cur_node = cur_node->next) {
if (strcmp((const char *)cur_node->name, "schema") == 0) {
xmlNode *name_node = xmlFirstElementChild(cur_node);
char *module_name = (char *)xmlNodeGetContent(name_node);
xmlNode *revision_node = xmlNextElementSibling(name_node);
char *module_revision = (char *)xmlNodeGetContent(revision_node);
xmlNode *format_node = xmlNextElementSibling(revision_node);
char *module_format = (char *)xmlNodeGetContent(format_node);
if (strcmp(module_format, "yang") != 0)
continue;
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);
char *schema_data = NULL;
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 (schema_data) {
#ifdef MPLANE_V1
const struct lys_module *mod = lys_parse_mem(*ctx, schema_data, ly_format);
#elif defined MPLANE_V2
struct lys_module *mod = NULL;
lys_parse_mem(*ctx, schema_data, ly_format, &mod);
#endif
free(schema_data);
if (!mod) {
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);
ly_ctx_destroy(*ctx);
return false;
}
}
nc_rpc_free(get_schema_rpc);
}
}
return true;
}
static bool load_from_operational_ds(xmlNode *node, ru_session_t *ru_session, struct ly_ctx **ctx)
{
for (xmlNode *schemas_node = node; schemas_node; schemas_node = schemas_node->next) {
if(schemas_node->type != XML_ELEMENT_NODE)
continue;
if (strcmp((const char *)schemas_node->name, "schemas") == 0) {
return store_schemas(schemas_node->children, ru_session, ctx);
} else {
bool success = load_from_operational_ds(schemas_node->children, ru_session, ctx);
if (success)
return true;
}
}
return false;
}
bool load_yang_models(ru_session_t *ru_session, const char *buffer, struct ly_ctx **ctx)
{
// Initialize the xml file
size_t len = strlen(buffer) + 1;
xmlDoc *doc = xmlReadMemory(buffer, len, NULL, NULL, 0);
xmlNode *root_element = xmlDocGetRootElement(doc);
bool success = load_from_operational_ds(root_element->children, ru_session, ctx);
if (success) {
MP_LOG_I("Successfully loaded all yang modules from operational datastore for RU \"%s\".\n", ru_session->ru_ip_add);
return true;
} else {
MP_LOG_W("Unable to load all yang modules from operational datastore for RU \"%s\". Using yang models present in \"models\" subfolder.\n", ru_session->ru_ip_add);
}
/* ideally, we should load the yang models from the operational datastore, but the issues are following:
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) */
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"};
#ifdef MPLANE_V1
*ctx = ly_ctx_new(yang_dir, 0);
AssertError(*ctx != NULL, return false, "[MPLANE] Unable to create libyang context: %s.\n", ly_errmsg(*ctx));
#elif defined MPLANE_V2
LY_ERR ret = ly_ctx_new(yang_dir, 0, ctx);
AssertError(ret == LY_SUCCESS, return false, "[MPLANE] Unable to create libyang context: %s.\n", ly_errmsg(*ctx));
#endif
const size_t num_models = sizeof(yang_models) / sizeof(yang_models[0]);
for (size_t i = 0; i < num_models; ++i) {
#ifdef MPLANE_V1
const struct lys_module *mod = ly_ctx_load_module(*ctx, yang_models[i], NULL);
AssertError(mod != NULL, return false, "[MPLANE] Failed to load yang model %s.\n", yang_models[i]);
#elif defined MPLANE_V2
const struct lys_module *mod = ly_ctx_load_module(*ctx, yang_models[i], NULL, NULL);
AssertError(mod != NULL, return false, "[MPLANE] Failed to load yang model %s.\n", yang_models[i]);
#endif
}
MP_LOG_I("Successfully loaded all yang modules for RU \"%s\".\n", ru_session->ru_ip_add);
return true;
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#ifndef GET_MPLANE_YANG_MODELS_H
#define GET_MPLANE_YANG_MODELS_H
#include "../ru-mplane-api.h"
#include <libyang/libyang.h>
bool load_yang_models(ru_session_t *ru_session, const char *buffer, struct ly_ctx **ctx);
#endif /* GET_MPLANE_YANG_MODELS_H */
module iana-hardware {
yang-version 1.1;
namespace "urn:ietf:params:xml:ns:yang:iana-hardware";
prefix ianahw;
organization "IANA";
contact
" Internet Assigned Numbers Authority
Postal: ICANN
12025 Waterfront Drive, Suite 300
Los Angeles, CA 90094-2536
United States of America
Tel: +1 310 301 5800
E-Mail: iana@iana.org>";
description
"IANA-defined identities for hardware class.
The latest revision of this YANG module can be obtained from
the IANA website.
Requests for new values should be made to IANA via
email (iana@iana.org).
Copyright (c) 2018 IETF Trust and the persons identified as
authors of the code. All rights reserved.
Redistribution and use in source and binary forms, with or
without modification, is permitted pursuant to, and subject
to the license terms contained in, the Simplified BSD License
set forth in Section 4.c of the IETF Trust's Legal Provisions
Relating to IETF Documents
(https://trustee.ietf.org/license-info).
The initial version of this YANG module is part of RFC 8348;
see the RFC itself for full legal notices.";
reference
"https://www.iana.org/assignments/yang-parameters";
revision 2018-03-13 {
description
"Initial revision.";
reference
"RFC 8348: A YANG Data Model for Hardware Management";
}
/*
* Identities
*/
identity hardware-class {
description
"This identity is the base for all hardware class
identifiers.";
}
identity unknown {
base ianahw:hardware-class;
description
"This identity is applicable if the hardware class is unknown
to the server.";
}
identity chassis {
base ianahw:hardware-class;
description
"This identity is applicable if the hardware class is an
overall container for networking equipment. Any class of
physical component, except a stack, may be contained within a
chassis; a chassis may only be contained within a stack.";
}
identity backplane {
base ianahw:hardware-class;
description
"This identity is applicable if the hardware class is some sort
of device for aggregating and forwarding networking traffic,
such as a shared backplane in a modular ethernet switch. Note
that an implementation may model a backplane as a single
physical component, which is actually implemented as multiple
discrete physical components (within a chassis or stack).";
}
identity container {
base ianahw:hardware-class;
description
"This identity is applicable if the hardware class is capable
of containing one or more removable physical entities,
possibly of different types. For example, each (empty or
full) slot in a chassis will be modeled as a container. Note
that all removable physical components should be modeled
within a container component, such as field-replaceable
modules, fans, or power supplies. Note that all known
containers should be modeled by the agent, including empty
containers.";
}
identity power-supply {
base ianahw:hardware-class;
description
"This identity is applicable if the hardware class is a
power-supplying component.";
}
identity fan {
base ianahw:hardware-class;
description
"This identity is applicable if the hardware class is a fan or
other heat-reduction component.";
}
identity sensor {
base ianahw:hardware-class;
description
"This identity is applicable if the hardware class is some sort
of sensor, such as a temperature sensor within a router
chassis.";
}
identity module {
base ianahw:hardware-class;
description
"This identity is applicable if the hardware class is some sort
of self-contained sub-system. If a module component is
removable, then it should be modeled within a container
component; otherwise, it should be modeled directly within
another physical component (e.g., a chassis or another
module).";
}
identity port {
base ianahw:hardware-class;
description
"This identity is applicable if the hardware class is some sort
of networking port capable of receiving and/or transmitting
networking traffic.";
}
identity stack {
base ianahw:hardware-class;
description
"This identity is applicable if the hardware class is some sort
of super-container (possibly virtual) intended to group
together multiple chassis entities. A stack may be realized
by a virtual cable, a real interconnect cable attached to
multiple chassis, or multiple interconnect cables. A stack
should not be modeled within any other physical components,
but a stack may be contained within another stack. Only
chassis components should be contained within a stack.";
}
identity cpu {
base ianahw:hardware-class;
description
"This identity is applicable if the hardware class is some sort
of central processing unit.";
}
identity energy-object {
base ianahw:hardware-class;
description
"This identity is applicable if the hardware class is some sort
of energy object, i.e., it is a piece of equipment that is
part of or attached to a communications network that is
monitored, it is controlled, or it aids in the management of
another device for Energy Management.";
}
identity battery {
base ianahw:hardware-class;
description
"This identity is applicable if the hardware class is some sort
of battery.";
}
identity storage-drive {
base ianahw:hardware-class;
description
"This identity is applicable if the hardware class is some sort
of component with data storage capability as its main
functionality, e.g., hard disk drive (HDD), solid-state device
(SSD), solid-state hybrid drive (SSHD), object storage device
(OSD), or other.";
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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