Performance Management implementation

Introduced a parameter start_up_timing which indicates if PM activation is supported during the start-up
procedure. We initialize this parameter, based on the vendor.

Notification interval is set to 10s.
This commit is contained in:
Teodora
2025-08-26 15:17:38 +02:00
parent 625b4b0cde
commit 0367881ba9
15 changed files with 3791 additions and 3 deletions
+5
View File
@@ -20,6 +20,7 @@
*/
#include "connect-mplane.h"
#include "init-mplane.h"
#include "common/utils/assertions.h"
#include <libyang/libyang.h>
@@ -63,6 +64,10 @@ void disconnect_mplane(void *rus_disconnect)
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;
+16
View File
@@ -182,6 +182,10 @@ bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const siz
success = get_uplane_info(operational_ds, &ru_session->ru_mplane_config);
AssertError(success, return false, "[MPLANE] Unable to get U-plane info from RU operational datastore.\n");
// Performance Management
success = get_pm_object_list(operational_ds, &ru_session->pm_stats);
AssertError(success, return false, "[MPLANE] Unable to retrieve performance measurement names from RU \"%s\".\n", ru_session->ru_ip_add);
success = load_yang_models(ru_session, operational_ds);
AssertError(success, return false, "[MPLANE] Unable to load yang models.\n");
@@ -212,3 +216,15 @@ bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const siz
return true;
}
bool pm_conf(ru_session_t *ru_session, const char *active)
{
char *content = get_pm_content(ru_session, active);
bool success = edit_val_commmit_rpc(ru_session, content);
AssertError(success, return false, "[MPLANE] Cannot continue.\n");
free(content);
return true;
}
+2
View File
@@ -29,4 +29,6 @@ bool init_mplane(ru_session_list_t *ru_session_list);
bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus);
bool pm_conf(ru_session_t *ru_session, const char *active);
#endif /* OAI_MPLANE_H */
+20
View File
@@ -182,3 +182,23 @@ bool get_uplane_info(const char *buffer, ru_mplane_config_t *ru_mplane_config)
return true;
}
bool get_pm_object_list(const char *buffer, pm_stats_t *pm_stats)
{
const char *ru_vendor = get_ru_xml_node(buffer, "mfg-name");
if (strcasecmp(ru_vendor, "BENETEL") == 0) {
pm_stats->start_up_timing = false;
} else {
pm_stats->start_up_timing = true;
}
// Rx window
get_ru_xml_list(buffer, "rx-window-objects", &pm_stats->rx_window_meas, &pm_stats->rx_num);
// Tx
get_ru_xml_list(buffer, "tx-stats-objects", &pm_stats->tx_meas, &pm_stats->tx_num);
MP_LOG_I("Successfully retreived all performance measurement names.\n");
return true;
}
+15
View File
@@ -81,6 +81,18 @@ typedef struct {
} ru_mplane_config_t;
typedef struct {
// activation if required at start-up timing
bool start_up_timing;
size_t rx_num;
char **rx_window_meas;
size_t tx_num;
char **tx_meas;
} pm_stats_t;
typedef struct {
char *username;
char *ru_ip_add;
@@ -89,6 +101,7 @@ typedef struct {
void *ctx;
xran_mplane_t xran_mplane;
ru_notif_t ru_notif;
pm_stats_t pm_stats;
} ru_session_t;
@@ -103,4 +116,6 @@ bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_
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);
#endif /* RU_MPLANE_API_H */
+37 -1
View File
@@ -54,6 +54,37 @@ static void notif_clb_v1(struct nc_session *session, const struct nc_notif *noti
recv_notif_v1(notif, answer);
}
#elif MPLANE_V2
static void log_v2_pm_info(const char *ru_ip_add, struct lyd_node_inner *stats)
{
struct lyd_node *child, *field = NULL;
size_t len = 0;
char *meas_list[8], *count_list[8] = {};
LY_LIST_FOR(stats->child, child) {
// const char *type = child->schema->name; // e.g. "rx-window-stats", "tx-stats"
struct lyd_node_inner *stats_inner = (struct lyd_node_inner *)child;
LY_LIST_FOR(stats_inner->child, field) {
if (strcmp(field->schema->name, "measurement-object") == 0) {
meas_list[len] = (char *)lyd_get_value(field);
} else if (strcmp(field->schema->name, "count") == 0) {
count_list[len] = (char *)lyd_get_value(field);
len++;
}
}
}
MP_LOG_I("[PM: \"%s\"][%s %7s][%s %7s][%s %7s][%s %7s][%s %7s][%s %7s][%s %7s][%s %7s]\n",
ru_ip_add,
meas_list[0], count_list[0],
meas_list[1], count_list[1],
meas_list[2], count_list[2],
meas_list[3], count_list[3],
meas_list[4], count_list[4],
meas_list[5], count_list[5],
meas_list[6], count_list[6],
meas_list[7], count_list[7]);
}
static void recv_notif_v2(struct lyd_node_inner *op, ru_notif_t *answer)
{
const char *notif = op->schema->name;
@@ -92,9 +123,14 @@ static void notif_clb_v2(struct nc_session *session, const struct lyd_node *envp
char *subs_reply = NULL;
lyd_print_mem(&subs_reply, op, output_format, LYD_PRINT_WITHSIBLINGS);
const char *ru_ip_add = nc_session_get_host(session);
struct lyd_node_inner *op_inner = (struct lyd_node_inner *)op;
if (strcmp(op_inner->schema->name, "measurement-result-stats") == 0) {
log_v2_pm_info(ru_ip_add, op_inner);
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);
recv_notif_v2((struct lyd_node_inner *)op, answer);
recv_notif_v2(op_inner, answer);
}
#endif
+2 -1
View File
@@ -68,7 +68,8 @@ static void find_ru_xml_list(xmlNode *node, const char *filter, char ***match_li
xmlNode *name_node = NULL;
for (xmlNode *cur_node2 = cur_node->children; cur_node2; cur_node2 = cur_node2->next) {
if (cur_node2->type == XML_ELEMENT_NODE && strcmp((const char *)cur_node2->name, "name") == 0) {
const char *name_node_str = (const char *)cur_node2->name;
if (cur_node2->type == XML_ELEMENT_NODE && (strcmp(name_node_str, "name") == 0 || strcmp(name_node_str, "measurement-object") == 0)) {
name_node = cur_node2;
break;
}
@@ -396,6 +396,56 @@ static bool create_uplane_conf_v2(const ru_session_t *ru_session, const openair0
return true;
}
static
bool create_pm_conf_v2(const ru_session_t *ru_session, const char *active, struct lyd_node **root)
{
LY_ERR ret = LY_SUCCESS;
ret = lyd_new_path(NULL, (struct ly_ctx *)ru_session->ctx, "/o-ran-performance-management:performance-measurement-objects", NULL, 0, root);
VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create root \"performance-measurement-objects\" node.\n");
ret = lyd_new_term(*root, NULL, "notification-interval", "10", 0, NULL);
VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"notification-interval\" node.\n");
ret = lyd_new_term(*root, NULL, "rx-window-measurement-interval", "10", 0, NULL);
VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"rx-window-measurement-interval\" node.\n");
ret = lyd_new_term(*root, NULL, "tx-measurement-interval", "10", 0, NULL);
VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"tx-measurement-interval\" node.\n");
for (size_t i = 0; i < ru_session->pm_stats.rx_num; i++) {
struct lyd_node *rx_window_meas_objects = NULL;
ret = lyd_new_list(*root, NULL, "rx-window-measurement-objects", 0, &rx_window_meas_objects, ru_session->pm_stats.rx_window_meas[i]);
VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"rx-window-measurement-objects\" node.\n");
ret = lyd_new_term(rx_window_meas_objects, NULL, "active", active, 0, NULL);
VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"active\" node.\n");
ret = lyd_new_term(rx_window_meas_objects, NULL, "object-unit", "RU", 0, NULL);
VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"object-unit\" node.\n");
ret = lyd_new_term(rx_window_meas_objects, NULL, "report-info", "COUNT", 0, NULL);
VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"report-info\" node.\n");
}
for (size_t i = 0; i < ru_session->pm_stats.tx_num; i++) {
struct lyd_node *tx_meas_objects = NULL;
ret = lyd_new_list(*root, NULL, "tx-measurement-objects", 0, &tx_meas_objects, ru_session->pm_stats.tx_meas[i]);
VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"tx-measurement-objects\" node.\n");
ret = lyd_new_term(tx_meas_objects, NULL, "active", active, 0, NULL);
VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"active\" node.\n");
ret = lyd_new_term(tx_meas_objects, NULL, "object-unit", "RU", 0, NULL);
VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"object-unit\" node.\n");
ret = lyd_new_term(tx_meas_objects, NULL, "report-info", "COUNT", 0, NULL);
VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"report-info\" node.\n");
}
return true;
}
#endif
bool configure_ru_from_yang(const ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus, char **result)
@@ -445,11 +495,43 @@ bool configure_ru_from_yang(const ru_session_t *ru_session, const openair0_confi
ret = lyd_merge_siblings(&all_merge, uplane_conf, 0);
VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Cannot merge CU-plane interface, processing element and U-plane configuration.\n");
// <o-ran-pm>
struct lyd_node *pm_conf = NULL;
if (ru_session->pm_stats.start_up_timing) {
success = create_pm_conf_v2(ru_session, "true", &pm_conf);
VERIFY_SUCCESS(success, "[MPLANE] Cannot create PM activation.\n");
} else {
success = create_pm_conf_v2(ru_session, "false", &pm_conf);
VERIFY_SUCCESS(success, "[MPLANE] Cannot create PM deactivation.\n");
}
ret = lyd_merge_siblings(&all_merge, pm_conf, 0);
VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Cannot merge CU-plane interface, processing element, U-plane configuration and PM configuration.\n");
lyd_print_mem(result, all_merge, LYD_XML, LYD_PRINT_WITHSIBLINGS);
lyd_free_siblings(all_merge);
lyd_free_siblings(uplane_conf);
lyd_free_siblings(pm_conf);
#endif
return true;
}
char *get_pm_content(const ru_session_t *ru_session, const char *active)
{
bool success = false;
char *content = NULL;
#ifdef MPLANE_V1
VERIFY_SUCCESS(success, "[MPLANE] To be implemented and tested.\n");
#elif defined MPLANE_V2
struct lyd_node *pm_conf = NULL;
success = create_pm_conf_v2(ru_session, active, &pm_conf);
AssertError(success, return false, "[MPLANE] Cannot create PM configuration.\n");
lyd_print_mem(&content, pm_conf, LYD_XML, LYD_PRINT_WITHSIBLINGS);
lyd_free_siblings(pm_conf);
#endif
return content;
}
@@ -29,4 +29,6 @@
bool configure_ru_from_yang(const ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus, char **result);
char *get_pm_content(const ru_session_t *ru_session, const char *active);
#endif /* CREATE_MPLANE_YANG_CONFIG_H */
+1 -1
View File
@@ -116,7 +116,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
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"};
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"};
#ifdef MPLANE_V1
*ctx = ly_ctx_new(yang_dir, 0);
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,440 @@
module ietf-netconf-acm {
namespace "urn:ietf:params:xml:ns:yang:ietf-netconf-acm";
prefix nacm;
import ietf-yang-types {
prefix yang;
}
organization
"IETF NETCONF (Network Configuration) Working Group";
contact
"WG Web: <https://datatracker.ietf.org/wg/netconf/>
WG List: <mailto:netconf@ietf.org>
Author: Andy Bierman
<mailto:andy@yumaworks.com>
Author: Martin Bjorklund
<mailto:mbj@tail-f.com>";
description
"Network Configuration Access Control Model.
Copyright (c) 2012 - 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).
This version of this YANG module is part of RFC 8341; see
the RFC itself for full legal notices.";
revision "2018-02-14" {
description
"Added support for YANG 1.1 actions and notifications tied to
data nodes. Clarified how NACM extensions can be used by
other data models.";
reference
"RFC 8341: Network Configuration Access Control Model";
}
revision "2012-02-22" {
description
"Initial version.";
reference
"RFC 6536: Network Configuration Protocol (NETCONF)
Access Control Model";
}
/*
* Extension statements
*/
extension default-deny-write {
description
"Used to indicate that the data model node
represents a sensitive security system parameter.
If present, the NETCONF server will only allow the designated
'recovery session' to have write access to the node. An
explicit access control rule is required for all other users.
If the NACM module is used, then it must be enabled (i.e.,
/nacm/enable-nacm object equals 'true'), or this extension
is ignored.
The 'default-deny-write' extension MAY appear within a data
definition statement. It is ignored otherwise.";
}
extension default-deny-all {
description
"Used to indicate that the data model node
controls a very sensitive security system parameter.
If present, the NETCONF server will only allow the designated
'recovery session' to have read, write, or execute access to
the node. An explicit access control rule is required for all
other users.
If the NACM module is used, then it must be enabled (i.e.,
/nacm/enable-nacm object equals 'true'), or this extension
is ignored.
The 'default-deny-all' extension MAY appear within a data
definition statement, 'rpc' statement, or 'notification'
statement. It is ignored otherwise.";
}
/*
* Derived types
*/
typedef user-name-type {
type string {
length "1..max";
}
description
"General-purpose username string.";
}
typedef matchall-string-type {
type string {
pattern '\*';
}
description
"The string containing a single asterisk '*' is used
to conceptually represent all possible values
for the particular leaf using this data type.";
}
typedef access-operations-type {
type bits {
bit create {
description
"Any protocol operation that creates a
new data node.";
}
bit read {
description
"Any protocol operation or notification that
returns the value of a data node.";
}
bit update {
description
"Any protocol operation that alters an existing
data node.";
}
bit delete {
description
"Any protocol operation that removes a data node.";
}
bit exec {
description
"Execution access to the specified protocol operation.";
}
}
description
"Access operation.";
}
typedef group-name-type {
type string {
length "1..max";
pattern '[^\*].*';
}
description
"Name of administrative group to which
users can be assigned.";
}
typedef action-type {
type enumeration {
enum permit {
description
"Requested action is permitted.";
}
enum deny {
description
"Requested action is denied.";
}
}
description
"Action taken by the server when a particular
rule matches.";
}
typedef node-instance-identifier {
type yang:xpath1.0;
description
"Path expression used to represent a special
data node, action, or notification instance-identifier
string.
A node-instance-identifier value is an
unrestricted YANG instance-identifier expression.
All the same rules as an instance-identifier apply,
except that predicates for keys are optional. If a key
predicate is missing, then the node-instance-identifier
represents all possible server instances for that key.
This XML Path Language (XPath) expression is evaluated in the
following context:
o The set of namespace declarations are those in scope on
the leaf element where this type is used.
o The set of variable bindings contains one variable,
'USER', which contains the name of the user of the
current session.
o The function library is the core function library, but
note that due to the syntax restrictions of an
instance-identifier, no functions are allowed.
o The context node is the root node in the data tree.
The accessible tree includes actions and notifications tied
to data nodes.";
}
/*
* Data definition statements
*/
container nacm {
nacm:default-deny-all;
description
"Parameters for NETCONF access control model.";
leaf enable-nacm {
type boolean;
default "true";
description
"Enables or disables all NETCONF access control
enforcement. If 'true', then enforcement
is enabled. If 'false', then enforcement
is disabled.";
}
leaf read-default {
type action-type;
default "permit";
description
"Controls whether read access is granted if
no appropriate rule is found for a
particular read request.";
}
leaf write-default {
type action-type;
default "deny";
description
"Controls whether create, update, or delete access
is granted if no appropriate rule is found for a
particular write request.";
}
leaf exec-default {
type action-type;
default "permit";
description
"Controls whether exec access is granted if no appropriate
rule is found for a particular protocol operation request.";
}
leaf enable-external-groups {
type boolean;
default "true";
description
"Controls whether the server uses the groups reported by the
NETCONF transport layer when it assigns the user to a set of
NACM groups. If this leaf has the value 'false', any group
names reported by the transport layer are ignored by the
server.";
}
leaf denied-operations {
type yang:zero-based-counter32;
config false;
mandatory true;
description
"Number of times since the server last restarted that a
protocol operation request was denied.";
}
leaf denied-data-writes {
type yang:zero-based-counter32;
config false;
mandatory true;
description
"Number of times since the server last restarted that a
protocol operation request to alter
a configuration datastore was denied.";
}
leaf denied-notifications {
type yang:zero-based-counter32;
config false;
mandatory true;
description
"Number of times since the server last restarted that
a notification was dropped for a subscription because
access to the event type was denied.";
}
container groups {
description
"NETCONF access control groups.";
list group {
key name;
description
"One NACM group entry. This list will only contain
configured entries, not any entries learned from
any transport protocols.";
leaf name {
type group-name-type;
description
"Group name associated with this entry.";
}
leaf-list user-name {
type user-name-type;
description
"Each entry identifies the username of
a member of the group associated with
this entry.";
}
}
}
list rule-list {
key name;
ordered-by user;
description
"An ordered collection of access control rules.";
leaf name {
type string {
length "1..max";
}
description
"Arbitrary name assigned to the rule-list.";
}
leaf-list group {
type union {
type matchall-string-type;
type group-name-type;
}
description
"List of administrative groups that will be
assigned the associated access rights
defined by the 'rule' list.
The string '*' indicates that all groups apply to the
entry.";
}
list rule {
key name;
ordered-by user;
description
"One access control rule.
Rules are processed in user-defined order until a match is
found. A rule matches if 'module-name', 'rule-type', and
'access-operations' match the request. If a rule
matches, the 'action' leaf determines whether or not
access is granted.";
leaf name {
type string {
length "1..max";
}
description
"Arbitrary name assigned to the rule.";
}
leaf module-name {
type union {
type matchall-string-type;
type string;
}
default "*";
description
"Name of the module associated with this rule.
This leaf matches if it has the value '*' or if the
object being accessed is defined in the module with the
specified module name.";
}
choice rule-type {
description
"This choice matches if all leafs present in the rule
match the request. If no leafs are present, the
choice matches all requests.";
case protocol-operation {
leaf rpc-name {
type union {
type matchall-string-type;
type string;
}
description
"This leaf matches if it has the value '*' or if
its value equals the requested protocol operation
name.";
}
}
case notification {
leaf notification-name {
type union {
type matchall-string-type;
type string;
}
description
"This leaf matches if it has the value '*' or if its
value equals the requested notification name.";
}
}
case data-node {
leaf path {
type node-instance-identifier;
mandatory true;
description
"Data node instance-identifier associated with the
data node, action, or notification controlled by
this rule.
Configuration data or state data
instance-identifiers start with a top-level
data node. A complete instance-identifier is
required for this type of path value.
The special value '/' refers to all possible
datastore contents.";
}
}
}
leaf access-operations {
type union {
type matchall-string-type;
type access-operations-type;
}
default "*";
description
"Access operations associated with this rule.
This leaf matches if it has the value '*' or if the
bit corresponding to the requested operation is set.";
}
leaf action {
type action-type;
mandatory true;
description
"The access control action associated with the
rule. If a rule has been determined to match a
particular request, then this object is used
to determine whether to permit or deny the
request.";
}
leaf comment {
type string;
description
"A textual description of the access rule.";
}
}
}
}
}
@@ -0,0 +1,213 @@
module o-ran-file-management {
yang-version 1.1;
namespace "urn:o-ran:file-management:1.0";
prefix "o-ran-file-mgmt";
import ietf-crypto-types {
prefix "ct";
}
organization "O-RAN Alliance";
contact
"www.o-ran.org";
description
"This module defines the configuration and operations for handling upload.
Copyright 2019 the O-RAN Alliance.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the above disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the above disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the Members of the O-RAN Alliance nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.";
revision "2019-07-03" {
description
"version 1.1.0
1) backward compatible changes to correct sFTP Server Authentication .
2) minor fixes according to lack of descriptions
3) backward compatible changes to introduce groupings";
reference "ORAN-WG4.M.0-v01.00";
}
revision "2019-02-04" {
description
"version 1.0.0
1) imported model from xRAN
2) changed namespace and reference from xran to o-ran";
reference "ORAN-WG4.M.0-v01.00";
}
grouping file-path-grouping {
description "Complete logical path of the file to upload/download
(no wildcard is allowed) ex : /o-RAN/log/syslog.1";
leaf local-logical-file-path {
type string;
mandatory true;
description "Local logical file path";
}
leaf remote-file-path {
type string;
mandatory true;
description "URI specifying the remote-file-path on O-DU/NMS.
Format:sftp://<username>@<host>[:port]/path";
}
}
grouping output-status-grouping {
description "Status grouping";
leaf status {
type enumeration {
enum SUCCESS {
description "";}
enum FAILURE {
description "";}
}
description "Operation status";
}
leaf reject-reason {
when "../status = 'FAILURE'";
type string;
description "";
}
}
grouping credential-information {
description "Type of authentication to use for SFTP upload or download.";
choice credentials {
case password {
container password {
presence true;
leaf password {
type string;
mandatory true;
description
"password needed for O-RU authentication.";
}
description
"password for O-RU authentication method in use";
}
container server {
list keys {
key algorithm;
ordered-by user;
uses ct:public-key-grouping;
description
"List of allowed algorithms with its keys";
}
description
"Key for sFTP server authentication";
}
}
case certificate {
container certificate {
presence true;
description
"certificate authentication method in use";
}
}
description "";
}
}
grouping retrieve-input {
description "Grouping for information retrieval RPC input";
leaf logical-path {
type string;
mandatory true;
description "O-RAN unit of which the files are to be listed.
ex : O-RAN/log, o-RAN/PM, O-RAN/transceiver";
}
leaf file-name-filter {
type string;
description "Filter which are to be applied on the result list of file names (* is allowed as wild-card).";
}
}
grouping retrieve-output {
description "Grouping for information retrieval RPC output";
uses output-status-grouping;
leaf-list file-list {
when "../status = 'SUCCESS'";
type string;
description "List of files in the unit with the filter applied.";
}
}
// RPCs
rpc file-upload {
description "File upload over SFTP from equipment to NETCONF client";
input {
uses file-path-grouping;
uses credential-information;
}
output {
uses output-status-grouping;
}
}
rpc retrieve-file-list {
description "List all the files in the logical O-RAN unit (* is allowed as wild-card).";
input {
uses retrieve-input;
}
output {
uses retrieve-output;
}
}
notification file-upload-notification {
uses file-path-grouping;
uses output-status-grouping;
description "";
}
rpc file-download {
description
"Management plane triggered to generate the download file of O-RU.";
input {
uses file-path-grouping;
uses credential-information;
}
output {
uses output-status-grouping;
}
}
notification file-download-event {
uses file-path-grouping;
uses output-status-grouping;
description "";
}
}
File diff suppressed because it is too large Load Diff
+5
View File
@@ -338,6 +338,11 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device *d
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);
ru_ready[i] = true;
if (!ru_session->pm_stats.start_up_timing) {
success = pm_conf(ru_session, "true");
if (success)
MP_LOG_I("Sucessfully activated PM after start-up procedure for RU \"%s\".\n", ru_session->ru_ip_add);
}
} else {
all_rus_ready = false;
break;