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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user