From 3bbf9d8a3c81afebcffb2b926cef219336dd53d6 Mon Sep 17 00:00:00 2001 From: Alex Stancu Date: Fri, 9 Apr 2021 15:13:00 +0300 Subject: [PATCH] Add supoprt for D release use-case. Add support for O-RU recovery use case: - add O-RU November train models support - add O-DU models support. Issue-ID: SIM-58 Issue-ID: SIM-59 Change-Id: Ic7beb6771acb2e086822323f2bb41ed9c4b4dfca Signed-off-by: Alex Stancu --- ntsimulator/.env | 22 +- ntsimulator/deploy/base/build_ntsim-ng.sh | 11 +- ntsimulator/deploy/base/client.key | 27 + ntsimulator/deploy/base/common.h.in | 1645 ++++++++++++ ntsimulator/deploy/base/ubuntu.Dockerfile | 66 +- ntsimulator/deploy/base/yang/nts-common.yang | 474 ++-- .../deploy/base/yang/nts-network-function.yang | 150 +- ntsimulator/deploy/nts-manager/Dockerfile | 38 + ntsimulator/deploy/nts-manager/config.json | 42 +- ntsimulator/deploy/nts-manager/container-tag.yaml | 2 +- ntsimulator/deploy/nts-manager/local.Dockerfile | 38 + ntsimulator/deploy/nts-manager/supervisord.conf | 22 - .../deploy/nts-manager/yang/nts-manager.yang | 459 +++- ntsimulator/deploy/o-ran-du/Dockerfile | 39 + ntsimulator/deploy/o-ran-du/config.json | 144 + ntsimulator/deploy/o-ran-du/container-tag.yaml | 2 + ntsimulator/deploy/o-ran-du/data/README.md | 2 + .../data/o-ran-sc-du-hello-world-operational.xml | 14 + .../data/o-ran-sc-du-hello-world-running.xml | 11 + .../local.Dockerfile} | 12 +- ntsimulator/deploy/o-ran-du/yang/ietf-system.yang | 802 ++++++ .../o-ran-du/yang/o-ran-sc-du-hello-world.yang | 200 ++ ntsimulator/deploy/o-ran-du/yang/onap-system.yang | 59 + ntsimulator/deploy/o-ran-ru-fh/Dockerfile | 39 + ntsimulator/deploy/o-ran-ru-fh/config.json | 163 ++ ntsimulator/deploy/o-ran-ru-fh/container-tag.yaml | 2 + ntsimulator/deploy/o-ran-ru-fh/data/README.md | 2 + .../data/ietf-hardware-operational.json | 307 +++ .../o-ran-ru-fh/data/ietf-hardware-running.json | 276 ++ .../local.Dockerfile} | 12 +- .../o-ran-ru-fh/yang/iana-hardware@2018-03-13.yang | 180 ++ .../o-ran-ru-fh/yang/iana-if-type@2017-01-19.yang | 1611 ++++++++++++ .../o-ran-ru-fh/yang/ietf-alarms@2019-09-11.yang | 1526 +++++++++++ .../yang/ietf-crypto-types@2019-10-18.yang | 2173 ++++++++++++++++ .../yang/ietf-dhcpv6-types@2018-01-30.yang | 207 ++ .../o-ran-ru-fh/yang/ietf-hardware@2018-03-13.yang | 1141 ++++++++ .../yang/ietf-inet-types@2013-07-15.yang | 429 +++ .../yang/ietf-interfaces@2018-02-20.yang | 1073 ++++++++ .../o-ran-ru-fh/yang/ietf-ip@2018-02-22.yang | 860 ++++++ .../yang/ietf-netconf-acm@2018-02-14.yang | 440 ++++ .../yang/ietf-network-instance@2019-01-21.yang | 282 ++ .../o-ran-ru-fh/yang/ietf-restconf@2017-01-26.yang | 278 ++ .../ietf-subscribed-notifications@2019-09-09.yang | 1350 ++++++++++ .../deploy/o-ran-ru-fh/yang/ietf-system.yang | 802 ++++++ .../yang/ietf-yang-schema-mount@2019-01-14.yang | 224 ++ .../yang/ietf-yang-types@2013-07-15.yang | 435 ++++ .../yang/o-ran-ald-port@2019-07-03.yang | 238 ++ .../o-ran-ru-fh/yang/o-ran-ald@2019-07-03.yang | 161 ++ .../yang/o-ran-antenna-calibration@2020-12-10.yang | 466 ++++ .../yang/o-ran-beamforming@2020-04-17.yang | 888 +++++++ .../yang/o-ran-compression-factors@2020-08-10.yang | 368 +++ .../yang/o-ran-delay-management@2020-08-10.yang | 354 +++ .../o-ran-ru-fh/yang/o-ran-dhcp@2020-12-10.yang | 331 +++ .../yang/o-ran-ecpri-delay@2019-02-04.yang | 135 + .../yang/o-ran-ethernet-forwarding@2020-04-17.yang | 126 + .../yang/o-ran-externalio@2019-07-03.yang | 183 ++ .../o-ran-ru-fh/yang/o-ran-fan@2019-07-03.yang | 125 + .../yang/o-ran-file-management@2019-07-03.yang | 213 ++ .../o-ran-ru-fh/yang/o-ran-fm@2019-02-04.yang | 166 ++ .../yang/o-ran-hardware@2020-12-10.yang | 330 +++ .../yang/o-ran-interfaces@2020-12-10.yang | 490 ++++ .../yang/o-ran-laa-operations@2019-07-03.yang | 253 ++ .../o-ran-ru-fh/yang/o-ran-laa@2019-07-03.yang | 126 + .../o-ran-ru-fh/yang/o-ran-lbm@2019-02-04.yang | 308 +++ .../yang/o-ran-module-cap@2020-12-10.yang | 857 ++++++ .../yang/o-ran-mplane-int@2019-07-03.yang | 232 ++ .../yang/o-ran-operations@2020-12-10.yang | 306 +++ .../o-ran-performance-management@2020-12-10.yang | 1200 +++++++++ .../yang/o-ran-processing-element@2020-04-17.yang | 360 +++ .../yang/o-ran-shared-cell@2020-12-10.yang | 564 ++++ .../yang/o-ran-software-management@2019-07-03.yang | 595 +++++ .../yang/o-ran-supervision@2020-12-10.yang | 228 ++ .../o-ran-ru-fh/yang/o-ran-sync@2020-08-10.yang | 988 +++++++ .../o-ran-ru-fh/yang/o-ran-trace@2019-07-03.yang | 102 + .../yang/o-ran-transceiver@2019-07-03.yang | 513 ++++ .../yang/o-ran-troubleshooting@2019-02-04.yang | 96 + .../yang/o-ran-udp-echo@2019-02-04.yang | 95 + .../yang/o-ran-uplane-conf@2020-12-10.yang | 2744 ++++++++++++++++++++ .../yang/o-ran-usermgmt@2020-12-10.yang | 206 ++ ...an-ves-subscribed-notifications@2020-12-10.yang | 87 + .../yang/o-ran-wg4-features@2020-12-10.yang | 57 + .../deploy/o-ran-ru-fh/yang/onap-system.yang | 59 + ntsimulator/deploy/o-ran/Dockerfile | 39 + ntsimulator/deploy/o-ran/config.json | 119 +- ntsimulator/deploy/o-ran/container-tag.yaml | 2 +- ntsimulator/deploy/o-ran/data/README.md | 2 + .../ubuntu.Dockerfile => o-ran/local.Dockerfile} | 17 +- ntsimulator/deploy/o-ran/supervisord.conf | 22 - ntsimulator/deploy/x-ran/Dockerfile | 39 + ntsimulator/deploy/x-ran/config.json | 37 +- ntsimulator/deploy/x-ran/container-tag.yaml | 2 +- ntsimulator/deploy/x-ran/data/README.md | 2 + ntsimulator/deploy/x-ran/local.Dockerfile | 43 + ntsimulator/deploy/x-ran/supervisord.conf | 22 - ntsimulator/docker-compose.yaml | 114 +- ntsimulator/nts-ng-docker-image-build-ubuntu.yaml | 54 +- ntsimulator/nts-start.sh | 1 + ntsimulator/nts-stop.sh | 1 + ntsimulator/nts_build.sh | 4 + ntsimulator/ntsim-ng/core/app/app_common.c | 69 + ntsimulator/ntsim-ng/core/app/app_common.h | 21 + ntsimulator/ntsim-ng/core/app/manager.c | 749 ++---- ntsimulator/ntsim-ng/core/app/manager.h | 128 +- ntsimulator/ntsim-ng/core/app/manager_actions.c | 583 +++++ ntsimulator/ntsim-ng/core/app/manager_context.c | 361 +++ ntsimulator/ntsim-ng/core/app/manager_operations.c | 556 ++-- ntsimulator/ntsim-ng/core/app/manager_sysrepo.c | 456 ++++ ntsimulator/ntsim-ng/core/app/network_function.c | 447 +++- ntsimulator/ntsim-ng/core/app/supervisor.c | 216 ++ ntsimulator/ntsim-ng/core/app/supervisor.h | 20 + ntsimulator/ntsim-ng/core/container.c | 264 ++ ntsimulator/ntsim-ng/core/container.h | 24 + ntsimulator/ntsim-ng/core/context.c | 66 +- ntsimulator/ntsim-ng/core/datastore/generate.c | 1185 +++++++++ ntsimulator/ntsim-ng/core/datastore/generate.h | 28 + ntsimulator/ntsim-ng/core/datastore/populate.c | 482 +--- ntsimulator/ntsim-ng/core/datastore/populate.h | 33 +- ntsimulator/ntsim-ng/core/datastore/populate_rec.c | 584 ----- ntsimulator/ntsim-ng/core/datastore/schema.c | 85 +- ntsimulator/ntsim-ng/core/datastore/schema.h | 6 +- ntsimulator/ntsim-ng/core/docker.c | 659 +++-- ntsimulator/ntsim-ng/core/docker.h | 43 +- ntsimulator/ntsim-ng/core/faults/faults.c | 6 +- ntsimulator/ntsim-ng/core/faults/faults_counters.c | 2 +- ntsimulator/ntsim-ng/core/faults/faults_logic.c | 4 +- .../ntsim-ng/core/faults/faults_processing.c | 50 +- ntsimulator/ntsim-ng/core/faults/faults_ves.c | 82 +- ntsimulator/ntsim-ng/core/framework.c | 1016 +++++--- ntsimulator/ntsim-ng/core/framework.h | 243 +- ntsimulator/ntsim-ng/core/nc_config.c | 273 +- ntsimulator/ntsim-ng/core/nc_config.h | 6 +- ntsimulator/ntsim-ng/core/session.c | 29 +- ntsimulator/ntsim-ng/core/test.c | 23 +- .../manual_notification/manual_notification.c | 33 +- .../manual_notification/manual_notification.h | 3 + .../features/netconf_call_home/netconf_call_home.c | 87 +- .../features/netconf_call_home/netconf_call_home.h | 1 + .../features/ves_file_ready/ves_file_ready.c | 94 +- .../features/ves_file_ready/ves_file_ready.h | 2 + .../features/ves_heartbeat/ves_heartbeat.c | 122 +- .../features/ves_heartbeat/ves_heartbeat.h | 2 + .../ves_pnf_registration/ves_pnf_registration.c | 189 +- .../ves_pnf_registration/ves_pnf_registration.h | 1 + .../features/web_cut_through/web_cut_through.c | 128 +- .../features/web_cut_through/web_cut_through.h | 2 + ntsimulator/ntsim-ng/main.c | 257 +- ntsimulator/ntsim-ng/utils/http_client.c | 34 +- ntsimulator/ntsim-ng/utils/log_utils.c | 144 +- ntsimulator/ntsim-ng/utils/log_utils.h | 12 +- ntsimulator/ntsim-ng/utils/nc_client.c | 77 +- ntsimulator/ntsim-ng/utils/nc_client.h | 2 + ntsimulator/ntsim-ng/utils/nts_utils.c | 398 ++- ntsimulator/ntsim-ng/utils/nts_utils.h | 6 +- ntsimulator/ntsim-ng/utils/rand_utils.c | 46 +- ntsimulator/ntsim-ng/utils/sys_utils.c | 12 +- ntsimulator/ntsim-ng/utils/type_utils.c | 2 +- ntsimulator/ubuntu_build.sh | 3 - 157 files changed, 39360 insertions(+), 4259 deletions(-) create mode 100644 ntsimulator/deploy/base/client.key create mode 100644 ntsimulator/deploy/base/common.h.in create mode 100644 ntsimulator/deploy/nts-manager/Dockerfile create mode 100644 ntsimulator/deploy/nts-manager/local.Dockerfile delete mode 100644 ntsimulator/deploy/nts-manager/supervisord.conf create mode 100644 ntsimulator/deploy/o-ran-du/Dockerfile create mode 100644 ntsimulator/deploy/o-ran-du/config.json create mode 100644 ntsimulator/deploy/o-ran-du/container-tag.yaml create mode 100644 ntsimulator/deploy/o-ran-du/data/README.md create mode 100644 ntsimulator/deploy/o-ran-du/data/o-ran-sc-du-hello-world-operational.xml create mode 100644 ntsimulator/deploy/o-ran-du/data/o-ran-sc-du-hello-world-running.xml rename ntsimulator/deploy/{x-ran/ubuntu.Dockerfile => o-ran-du/local.Dockerfile} (80%) create mode 100644 ntsimulator/deploy/o-ran-du/yang/ietf-system.yang create mode 100644 ntsimulator/deploy/o-ran-du/yang/o-ran-sc-du-hello-world.yang create mode 100644 ntsimulator/deploy/o-ran-du/yang/onap-system.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/Dockerfile create mode 100644 ntsimulator/deploy/o-ran-ru-fh/config.json create mode 100644 ntsimulator/deploy/o-ran-ru-fh/container-tag.yaml create mode 100644 ntsimulator/deploy/o-ran-ru-fh/data/README.md create mode 100644 ntsimulator/deploy/o-ran-ru-fh/data/ietf-hardware-operational.json create mode 100644 ntsimulator/deploy/o-ran-ru-fh/data/ietf-hardware-running.json rename ntsimulator/deploy/{o-ran/ubuntu.Dockerfile => o-ran-ru-fh/local.Dockerfile} (80%) create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/iana-hardware@2018-03-13.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/iana-if-type@2017-01-19.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/ietf-alarms@2019-09-11.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/ietf-crypto-types@2019-10-18.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/ietf-dhcpv6-types@2018-01-30.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/ietf-hardware@2018-03-13.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/ietf-inet-types@2013-07-15.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/ietf-interfaces@2018-02-20.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/ietf-ip@2018-02-22.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/ietf-netconf-acm@2018-02-14.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/ietf-network-instance@2019-01-21.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/ietf-restconf@2017-01-26.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/ietf-subscribed-notifications@2019-09-09.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/ietf-system.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/ietf-yang-schema-mount@2019-01-14.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/ietf-yang-types@2013-07-15.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ald-port@2019-07-03.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ald@2019-07-03.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-antenna-calibration@2020-12-10.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-beamforming@2020-04-17.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-compression-factors@2020-08-10.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-delay-management@2020-08-10.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-dhcp@2020-12-10.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ecpri-delay@2019-02-04.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ethernet-forwarding@2020-04-17.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-externalio@2019-07-03.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-fan@2019-07-03.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-file-management@2019-07-03.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-fm@2019-02-04.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-hardware@2020-12-10.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-interfaces@2020-12-10.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-laa-operations@2019-07-03.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-laa@2019-07-03.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-lbm@2019-02-04.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-module-cap@2020-12-10.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-mplane-int@2019-07-03.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-operations@2020-12-10.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-performance-management@2020-12-10.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-processing-element@2020-04-17.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-shared-cell@2020-12-10.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-software-management@2019-07-03.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-supervision@2020-12-10.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-sync@2020-08-10.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-trace@2019-07-03.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-transceiver@2019-07-03.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-troubleshooting@2019-02-04.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-udp-echo@2019-02-04.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-uplane-conf@2020-12-10.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-usermgmt@2020-12-10.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ves-subscribed-notifications@2020-12-10.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-wg4-features@2020-12-10.yang create mode 100644 ntsimulator/deploy/o-ran-ru-fh/yang/onap-system.yang create mode 100644 ntsimulator/deploy/o-ran/Dockerfile create mode 100644 ntsimulator/deploy/o-ran/data/README.md rename ntsimulator/deploy/{nts-manager/ubuntu.Dockerfile => o-ran/local.Dockerfile} (71%) delete mode 100644 ntsimulator/deploy/o-ran/supervisord.conf create mode 100644 ntsimulator/deploy/x-ran/Dockerfile create mode 100644 ntsimulator/deploy/x-ran/data/README.md create mode 100644 ntsimulator/deploy/x-ran/local.Dockerfile delete mode 100644 ntsimulator/deploy/x-ran/supervisord.conf create mode 100755 ntsimulator/nts-start.sh create mode 100755 ntsimulator/nts-stop.sh create mode 100755 ntsimulator/nts_build.sh create mode 100644 ntsimulator/ntsim-ng/core/app/app_common.c create mode 100644 ntsimulator/ntsim-ng/core/app/app_common.h create mode 100644 ntsimulator/ntsim-ng/core/app/manager_actions.c create mode 100644 ntsimulator/ntsim-ng/core/app/manager_context.c create mode 100644 ntsimulator/ntsim-ng/core/app/manager_sysrepo.c create mode 100644 ntsimulator/ntsim-ng/core/app/supervisor.c create mode 100644 ntsimulator/ntsim-ng/core/app/supervisor.h create mode 100644 ntsimulator/ntsim-ng/core/container.c create mode 100644 ntsimulator/ntsim-ng/core/container.h create mode 100644 ntsimulator/ntsim-ng/core/datastore/generate.c create mode 100644 ntsimulator/ntsim-ng/core/datastore/generate.h delete mode 100644 ntsimulator/ntsim-ng/core/datastore/populate_rec.c delete mode 100755 ntsimulator/ubuntu_build.sh diff --git a/ntsimulator/.env b/ntsimulator/.env index 42632ac..4104951 100644 --- a/ntsimulator/.env +++ b/ntsimulator/.env @@ -1,6 +1,22 @@ DOCKER_REPO=o-ran-sc/ +NTS_MANAGER_PORT=8300 +NTS_BUILD_VERSION=1.2.0 -# when changing BUILD_VERSION make sure you also change the version in framework.c -BUILD_VERSION=1.0.6 +IPv6_ENABLED=true +SSH_CONNECTIONS=1 +TLS_CONNECTIONS=0 -NTS_MANAGER_PORT=8300 +SDN_CONTROLLER_PROTOCOL=http +SDN_CONTROLLER_IP=2001:db8:1:1::21 +SDN_CONTROLLER_PORT=8181 +SDN_CONTROLLER_CALLHOME_PORT=6666 +SDN_CONTROLLER_USERNAME=admin +SDN_CONTROLLER_PASSWORD=admin + +VES_COMMON_HEADER_VERSION=7.1 +VES_ENDPOINT_PROTOCOL=https +VES_ENDPOINT_IP=2001:db8:1:1::90 +VES_ENDPOINT_PORT=8443 +VES_ENDPOINT_AUTH_METHOD=no-auth +VES_ENDPOINT_USERNAME=sample1 +VES_ENDPOINT_PASSWORD=sample1 diff --git a/ntsimulator/deploy/base/build_ntsim-ng.sh b/ntsimulator/deploy/base/build_ntsim-ng.sh index 49cac32..b64f071 100755 --- a/ntsimulator/deploy/base/build_ntsim-ng.sh +++ b/ntsimulator/deploy/base/build_ntsim-ng.sh @@ -18,18 +18,24 @@ # ***************************************************************************/ files=( + "core/container.c" "core/context.c" "core/docker.c" "core/framework.c" "core/test.c" "core/session.c" "core/nc_config.c" + "core/app/supervisor.c" + "core/app/app_common.c" "core/app/manager.c" + "core/app/manager_context.c" "core/app/manager_operations.c" + "core/app/manager_actions.c" + "core/app/manager_sysrepo.c" "core/app/network_function.c" "core/datastore/schema.c" + "core/datastore/generate.c" "core/datastore/populate.c" - "core/datastore/populate_rec.c" "core/faults/faults.c" "core/faults/faults_counters.c" "core/faults/faults_processing.c" @@ -77,6 +83,9 @@ done output="ntsim-ng" build="gcc -Wall -pedantic -Isource $sources $libraries -o$output" +if [[ -n "${BUILD_WITH_DEBUG}" ]]; then + build="gcc -g -Wall -pedantic -Isource $sources $libraries -o$output" +fi echo "Building with command: $build" $build diff --git a/ntsimulator/deploy/base/client.key b/ntsimulator/deploy/base/client.key new file mode 100644 index 0000000..7ccdab1 --- /dev/null +++ b/ntsimulator/deploy/base/client.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAueCQaNQWoNmFK6LKu1p8U8ZWdWg/PvDdLsJyzfzl/Qw4UA68 +SfFNaY06zZl8QB9W02nr5kWeeMY0VA3adrPgOlvfx3oWlFbkETnMaN4OT3WTQ0Wt +6jAWZDzVfopwpJPAzRPxACDftIqFGagYcF32hZlVNqqnVdbXh0S0EViweqp/dbG4 +VDUHSNVbglc+u4UbEzNIFXMdEFsJZpkynOmSiTsIATqIhb+2srkVgLwhfkC2qkuH +QwAHdubuB07ObM2z01UhyEdDvEYGHwtYAGDBL2TAcsI0oGeVkRyuOkV0QY0UN7UE +FI1yTYw+xZ42HgFx3uGwApCImxhbj69GBYWFqwIDAQABAoIBAQCZN9kR8DGu6V7y +t0Ax68asL8O5B/OKaHWKQ9LqpVrXmikZJOxkbzoGldow/CIFoU+q+Zbwu9aDa65a +0wiP7Hoa4Py3q5XNNUrOQDyU/OYC7cI0I83WS0lJ2zOJGYj8wKae5Z81IeQFKGHK +4lsy1OGPAvPRGh7RjUUgRavA2MCwe07rWRuDb/OJFe4Oh56UMEjwMiNBtMNtncog +j1vr/qgRJdf9tf0zlJmLvUJ9+HSFFV9I/97LJyFhb95gAfHkjdVroLVgT3Cho+4P +WtZaKCIGD0OwfOG2nLV4leXvRUk62/LMlB8NI9+JF7Xm+HCKbaWHNWC7mvWSLV58 +Zl4AbUWRAoGBANyJ6SFHFRHSPDY026SsdMzXR0eUxBAK7G70oSBKKhY+O1j0ocLE +jI2krHJBhHbLlnvJVyMUaCUOTS5m0uDw9hgSsAqeSL3hL38kxVZw+KNG9Ouno1Fl +KnE/xXHlPQyeGs/P8nAMzHZxQtEsQdQayJEhK2XXHTsy7Q3MxDisfVJ1AoGBANfD +34gB+OMx6pwj7zk3qWbYXSX8xjCZMR0ciko+h4xeMP2N8B0oyoqC+v1ABMAtJ3wG +sGZd0hV9gwM7OUM3SEwkn6oeg1GemWLcn4rlSmTnZc4aeVwrEWlnSNFX3s4g9l4u +k8Ugu4MVJYqH8HuDQ5Ggl6/QAwPzMSEdCW0O+jOfAoGAIBRbegC5+t6m7Yegz4Ja +dxV1g98K6f58x+MDsQu4tYWV4mmrQgaPH2dtwizvlMwmdpkh+LNWNtWuumowkJHc +akIFo3XExQIFg6wYnGtQb4e5xrGa2xMpKlIJaXjb+YLiCYqJDG2ALFZrTrvuU2kV +9a5qfqTc1qigvNolTM0iaaUCgYApmrZWhnLUdEKV2wP813PNxfioI4afxlpHD8LG +sCn48gymR6E+Lihn7vuwq5B+8fYEH1ISWxLwW+RQUjIneNhy/jjfV8TgjyFqg7or +0Sy4KjpiNI6kLBXOakELRNNMkeSPopGR2E7v5rr3bGD9oAD+aqX1G7oJH/KgPPYd +Vl7+ZwKBgQDcHyWYrimjyUgKaQD2GmoO9wdcJYQ59ke9K+OuGlp4ti5arsi7N1tP +B4f09aeELM2ASIuk8Q/Mx0jQFnm8lzRFXdewgvdPoZW/7VufM9O7dGPOc41cm2Dh +yrTcXx/VmUBb+/fnXVEgCv7gylp/wtdTGHQBQJHR81jFBz0lnLj+gg== +-----END RSA PRIVATE KEY----- diff --git a/ntsimulator/deploy/base/common.h.in b/ntsimulator/deploy/base/common.h.in new file mode 100644 index 0000000..fa0cee6 --- /dev/null +++ b/ntsimulator/deploy/base/common.h.in @@ -0,0 +1,1645 @@ +/** + * @file common.h + * @author Michal Vasko + * @brief common routines header + * + * @copyright + * Copyright 2018 Deutsche Telekom AG. + * Copyright 2018 - 2021 CESNET, z.s.p.o. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +#ifndef _COMMON_H +#define _COMMON_H + +#define _GNU_SOURCE +#define _POSIX_C_SOURCE 200809L + +#include +#include +#include +#include +#include +#include + +#include + +#include "compat.h" +#include "sysrepo.h" + +/* + * If the compiler supports attribute to mark objects as hidden, mark all + * objects as hidden and export only objects explicitly marked to be part of + * the public API. + */ +#define API __attribute__((visibility("default"))) + +/** support for pthread_mutex_timedlock */ +#cmakedefine SR_HAVE_PTHREAD_MUTEX_TIMEDLOCK +#ifndef SR_HAVE_PTHREAD_MUTEX_TIMEDLOCK +int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abstime); +#endif + +/** use access() if eaccess() is not available (it may adversely affect access control, however) */ +#cmakedefine SR_HAVE_EACCESS +#ifndef SR_HAVE_EACCESS +# define eaccess access +#endif + +/** atomic variables */ +#cmakedefine SR_HAVE_STDATOMIC +#ifdef SR_HAVE_STDATOMIC +# include + +# define ATOMIC_T atomic_uint_fast32_t +# define ATOMIC_T_MAX UINT_FAST32_MAX + +# define ATOMIC_STORE_RELAXED(var, x) atomic_store_explicit(&(var), x, memory_order_relaxed) +# define ATOMIC_LOAD_RELAXED(var) atomic_load_explicit(&(var), memory_order_relaxed) +# define ATOMIC_INC_RELAXED(var) atomic_fetch_add_explicit(&(var), 1, memory_order_relaxed) +# define ATOMIC_ADD_RELAXED(var, x) atomic_fetch_add_explicit(&(var), x, memory_order_relaxed) +# define ATOMIC_DEC_RELAXED(var) atomic_fetch_sub_explicit(&(var), 1, memory_order_relaxed) +# define ATOMIC_SUB_RELAXED(var, x) atomic_fetch_sub_explicit(&(var), x, memory_order_relaxed) +#else +# define ATOMIC_T uint32_t +# define ATOMIC_T_MAX UINT32_MAX + +# define ATOMIC_STORE_RELAXED(var, x) ((var) = (x)) +# define ATOMIC_LOAD_RELAXED(var) (var) +# define ATOMIC_INC_RELAXED(var) __sync_fetch_and_add(&(var), 1) +# define ATOMIC_ADD_RELAXED(var, x) __sync_fetch_and_add(&(var), x) +# define ATOMIC_DEC_RELAXED(var) __sync_fetch_and_sub(&(var), 1) +# define ATOMIC_SUB_RELAXED(var, x) __sync_fetch_and_sub(&(var), x) +#endif + +/** macro for mutex align check */ +#define SR_MUTEX_ALIGN_CHECK(mutex) ((uintptr_t)mutex % sizeof(void *)) + +/** macro for cond align check */ +#define SR_COND_ALIGN_CHECK(cond) ((uintptr_t)cond % sizeof(void *)) + +/** macro for checking datastore type */ +#define SR_IS_CONVENTIONAL_DS(ds) ((ds == SR_DS_STARTUP) || (ds == SR_DS_RUNNING) || (ds == SR_DS_CANDIDATE)) + +/** macro for all datastore types count */ +#define SR_DS_COUNT 4 + +/** macro for checking session type */ +#define SR_IS_EVENT_SESS(session) (session->ev != SR_SUB_EV_NONE) + +/** macro for getting a SHM module on a specific index */ +#define SR_SHM_MOD_IDX(main_shm_addr, idx) ((sr_mod_t *)(((char *)main_shm_addr) + sizeof(sr_main_shm_t) + idx * sizeof(sr_mod_t))) + +/* macro for getting aligned SHM size */ +#define SR_SHM_SIZE(size) ((size) + ((~(size) + 1) & (SR_SHM_MEM_ALIGN - 1))) + +/* macro for getting main SHM from a connection */ +#define SR_CONN_MAIN_SHM(conn) ((sr_main_shm_t *)(conn)->main_shm.addr) + +/* macro for getting ext SHM from a connection */ +#define SR_CONN_EXT_SHM(conn) ((sr_ext_shm_t *)(conn)->ext_shm.addr) + +/** name of sysrepo YANG module */ +#define SR_YANG_MOD "sysrepo" + +/** UID of the superuser that can execute sensitive functions */ +#define SR_SU_UID @SYSREPO_SUPERUSER_UID@ + +/** implemented ietf-yang-library revision */ +#define SR_YANGLIB_REVISION @YANGLIB_REVISION@ + +/** main sysrepo repository path; prefix of all other paths by default */ +#define SR_REPO_PATH "@REPO_PATH@" + +/** environment variable overriding the compiled-in value */ +#define SR_REPO_PATH_ENV "SYSREPO_REPOSITORY_PATH" + +/** if not set, defaults to "SR_REPO_PATH/data" */ +#define SR_STARTUP_PATH "@STARTUP_DATA_PATH@" + +/** if not set, defaults to "SR_REPO_PATH/data/notif" */ +#define SR_NOTIFICATION_PATH "@NOTIFICATION_PATH@" + +/** if not set, defaults to "SR_REPO_PATH/yang" */ +#define SR_YANG_PATH "@YANG_MODULE_PATH@" + +/** where SHM files are stored */ +#define SR_SHM_DIR "/dev/shm" + +/** default prefix for SHM files in /dev/shm */ +#define SR_SHM_PREFIX_DEFAULT "sr" + +/** suffix of backed-up LYB files */ +#define SR_FILE_BACKUP_SUFFIX ".bck" + +/** environment variable for setting a custom prefix for SHM files */ +#define SR_SHM_PREFIX_ENV "SYSREPO_SHM_PREFIX" + +/** maximum number of possible system-wide concurrent owners of a read lock */ +#define SR_RWLOCK_READ_LIMIT 10 + +/** all ext SHM item sizes will be aligned to this number; also represents the allocation unit (B) */ +#define SR_SHM_MEM_ALIGN 8 + +/** notification file will never exceed this size (kB) */ +#define SR_EV_NOTIF_FILE_MAX_SIZE 1024 + +/** timeout for locking subscription structure lock, should be enough for a single ::sr_process_events() call (ms) */ +#define SR_SUBSCR_LOCK_TIMEOUT 30000 + +/** timeout for locking lydmods data for access; should be enough for parsing, applying any scheduled changes, and printing (ms) */ +#define SR_LYDMODS_LOCK_TIMEOUT 5000 + +/** timeout for locking notification buffer lock, used when adding/removing notifications (ms) */ +#define SR_NOTIF_BUF_LOCK_TIMEOUT 100 + +/** timeout for locking subscription SHM; maximum time an event handling should take (ms) */ +#define SR_SUBSHM_LOCK_TIMEOUT 10000 + +/** timeout for locking ext SHM lock; time that truncating and writing into SHM may take (ms) */ +#define SR_EXT_LOCK_TIMEOUT 100 + +/** timeout for locking the local connection list; maximum time the list can be accessed (ms) */ +#define SR_CONN_LIST_LOCK_TIMEOUT 100 + +/** timeout for locking connection remap lock; maximum time it can be continuously read/written to it (ms) */ +#define SR_CONN_REMAP_LOCK_TIMEOUT 10000 + +/** timeout for locking (data of) a module; maximum time a module write lock is expected to be held (ms) */ +#define SR_MOD_LOCK_TIMEOUT 5000 + +/** timeout for locking SHM module/RPC subscriptions; maxmum time full event processing may take (ms) */ +#define SR_SHMEXT_SUB_LOCK_TIMEOUT 15000 + +/** timeout for locking module cache (ms) */ +#define SR_MOD_CACHE_LOCK_TIMEOUT 10000 + +/** default timeout for change subscription callback (ms) */ +#define SR_CHANGE_CB_TIMEOUT 60000 + +/** default timeout for operational subscription callback (ms) */ +#define SR_OPER_CB_TIMEOUT 60000 + +/** default timeout for RPC/action subscription callback (ms) */ +#define SR_RPC_CB_TIMEOUT 60000 + +/** group to own all directories/files */ +#define SR_GROUP "@SYSREPO_GROUP@" + +/** umask modifying all the permissions below */ +#define SR_UMASK @SYSREPO_UMASK@ + +/** permissions of main SHM lock file and main SHM itself */ +#define SR_MAIN_SHM_PERM 00666 + +/** permissions of connection lock files */ +#define SR_CONN_LOCKFILE_PERM 00666 + +/** permissions of all subscription SHMs */ +#define SR_SUB_SHM_PERM 00666 + +/** permissions of all event pipes (only owner read, anyone else write */ +#define SR_EVPIPE_PERM 00622 + +/** permissions of directories for sysrepo files */ +#define SR_DIR_PERM 00777 + +/** permissions of used YANG modules */ +#define SR_YANG_PERM 00644 + +/** permissions of stored notifications and data files */ +#define SR_FILE_PERM 00600 + +/** permissions of data files of internal modules */ +#define SR_INT_FILE_PERM 00664 + +/** permission of data files of sysrepo-monitoring internal module */ +#define SR_MON_INT_FILE_PERM 00600 + +/** initial length of message buffer (B) */ +#define SR_MSG_LEN_START 128 + +/** default operational origin for operational data (push/pull) */ +#define SR_OPER_ORIGIN "unknown" + +/** default operational origin for enabled running data */ +#define SR_CONFIG_ORIGIN "intended" + +/* + * Internal declarations + definitions + */ + +extern char sysrepo_yang[]; + +typedef struct sr_mod_s sr_mod_t; + +typedef struct sr_dep_s sr_dep_t; + +/** static initializer of the shared memory structure */ +#define SR_SHM_INITIALIZER {.fd = -1, .size = 0, .addr = NULL} + +/** initializer of mod_info structure */ +#define SR_MODINFO_INIT(mi, c, d, d2) mi.ds = (d); mi.ds2 = (d2); mi.diff = NULL; mi.data = NULL; \ + mi.data_cached = 0; mi.conn = (c); mi.mods = NULL; mi.mod_count = 0 + +/** + * @brief Generic shared memory information structure. + */ +typedef struct sr_shm_s { + int fd; /**< Shared memory file desriptor. */ + size_t size; /**< Shared memory mapping current size. */ + char *addr; /**< Shared memory mapping address. */ +} sr_shm_t; + +/** + * @brief Session information structure. + */ +typedef struct sr_sid_s { + uint32_t sr; /**< Sysrepo session ID. */ + uint32_t nc; /**< NETCONF session ID. */ + char *user; /**< Sysrepo user. */ +} sr_sid_t; + +/** + * @brief Connection ID. + */ +typedef uint32_t sr_cid_t; + +/** + * @brief Lock mode. + */ +typedef enum sr_lock_mode_e { + SR_LOCK_NONE = 0, /**< Not locked. */ + SR_LOCK_READ, /**< Read lock. */ + SR_LOCK_READ_UPGR, /**< Read lock with the upgrade capability. */ + SR_LOCK_WRITE /**< Write lock. */ +} sr_lock_mode_t; + +/** + * @brief Sysrepo read-write lock. + */ +typedef struct sr_rwlock_s { + pthread_mutex_t mutex; /**< Lock mutex. */ + pthread_cond_t cond; /**< Lock condition variable. */ + + pthread_mutex_t r_mutex; /**< Mutex for accessing readers, needed because of concurrent reading. */ + sr_cid_t readers[SR_RWLOCK_READ_LIMIT]; /**< CIDs of all READ lock owners (including READ-UPGR), 0s otherwise. */ + sr_cid_t upgr; /**< CID of the READ-UPGR lock owner if locked, 0 otherwise. */ + sr_cid_t writer; /**< CID of the WRITE lock owner if locked, 0 otherwise. */ +} sr_rwlock_t; + +struct modsub_changesub_s; +struct modsub_change_s; +struct modsub_opersub_s; +struct modsub_oper_s; +struct opsub_rpcsub_s; +struct opsub_rpc_s; +struct modsub_notif_s; + +#include "edit_diff.h" +#include "log.h" +#include "modinfo.h" +#include "shm.h" +#include "lyd_mods.h" +#include "replay.h" + +/* + * Private definitions of public declarations + */ + +/** + * @brief Sysrepo connection. + */ +struct sr_conn_ctx_s { + struct ly_ctx *ly_ctx; /**< Libyang context, also available to user. */ + sr_conn_options_t opts; /**< Connection options. */ + sr_diff_check_cb diff_check_cb; /**< Connection user diff check callback. */ + + pthread_mutex_t ptr_lock; /**< Session-shared lock for accessing pointers to sessions. */ + sr_session_ctx_t **sessions; /**< Array of sessions for this connection. */ + uint32_t session_count; /**< Session count. */ + sr_cid_t cid; /**< Globally unique connection ID */ + + int main_create_lock; /**< Process-shared file lock for creating main/ext SHM. */ + sr_rwlock_t ext_remap_lock; /**< Session-shared lock only for remapping ext SHM. */ + sr_shm_t main_shm; /**< Main SHM structure. */ + sr_shm_t ext_shm; /**< External SHM structure (all stored offsets point here). */ + + struct sr_mod_cache_s { + sr_rwlock_t lock; /**< Session-shared lock for accessing the module cache. */ + struct lyd_node *data; /**< Data of all cached modules, */ + + struct { + const struct lys_module *ly_mod; /**< Libyang module in the cache. */ + uint32_t ver; /**< Version of the module data in the cache, 0 is not valid */ + } *mods; /**< Array of cached modules. */ + uint32_t mod_count; /**< Cached modules count. */ + } mod_cache; /**< Module running data cache. */ +}; + +/** + * @brief Sysrepo session. + */ +struct sr_session_ctx_s { + sr_conn_ctx_t *conn; /**< Connection used for creating this session. */ + sr_datastore_t ds; /**< Datastore of the session. */ + sr_sub_event_t ev; /**< Event of a callback session. ::SR_SUB_EV_NONE for standard user sessions. */ + sr_sid_t sid; /**< Session information. */ + sr_sid_t ev_sid; /**< Event (originator) session information. Valid only if ev is not ::SR_SUB_EV_NONE. */ + sr_error_info_t *err_info; /**< Session error information. */ + + pthread_mutex_t ptr_lock; /**< Lock for accessing pointers to subscriptions. */ + sr_subscription_ctx_t **subscriptions; /**< Array of subscriptions of this session. */ + uint32_t subscription_count; /**< Subscription count. */ + + struct { + struct lyd_node *edit; /**< Prepared edit data tree. */ + struct lyd_node *diff; /**< Diff data tree, used for module change iterator. */ + } dt[SR_DS_COUNT]; /**< Session-exclusive prepared changes. */ + + struct sr_sess_notif_buf { + ATOMIC_T thread_running; /**< Flag whether the notification buffering thread of this session is running. */ + pthread_t tid; /**< Thread ID of the thread. */ + sr_rwlock_t lock; /**< Lock for accessing thread_running and the notification buffer + (READ-lock is not used). */ + struct sr_sess_notif_buf_node { + char *notif_lyb; /**< Buffered notification to be stored in LYB format. */ + time_t notif_ts; /**< Buffered notification timestamp. */ + const struct lys_module *notif_mod; /**< Buffered notification modules. */ + struct sr_sess_notif_buf_node *next; /**< Next stored notification buffer node. */ + } *first; /**< First stored notification buffer node. */ + struct sr_sess_notif_buf_node *last; /**< Last stored notification buffer node. */ + } notif_buf; /**< Notification buffering attributes. */ +}; + +/** + * @brief Sysrepo subscription. + */ +struct sr_subscription_ctx_s { + sr_conn_ctx_t *conn; /**< Connection of the subscription. */ + uint32_t evpipe_num; /**< Event pipe number of this subscription structure. */ + int evpipe; /**< Event pipe opened for reading. */ + ATOMIC_T thread_running; /**< Flag whether the thread handling this subscription is running. */ + pthread_t tid; /**< Thread ID of the handler thread. */ + sr_rwlock_t subs_lock; /**< Session-shared lock for accessing the subscriptions. */ + + struct modsub_change_s { + char *module_name; /**< Module of the subscriptions. */ + sr_datastore_t ds; /**< Datastore of the subscriptions. */ + struct modsub_changesub_s { + char *xpath; /**< Subscription XPath. */ + uint32_t priority; /**< Subscription priority. */ + sr_subscr_options_t opts; /**< Subscription options. */ + sr_module_change_cb cb; /**< Subscription callback. */ + void *private_data; /**< Subscription callback private data. */ + sr_session_ctx_t *sess; /**< Subscription session. */ + + uint32_t request_id; /**< Request ID of the last processed request. */ + sr_sub_event_t event; /**< Type of the last processed event. */ + } *subs; /**< Configuration change subscriptions for each XPath. */ + uint32_t sub_count; /**< Configuration change module XPath subscription count. */ + + sr_shm_t sub_shm; /**< Subscription SHM. */ + } *change_subs; /**< Change subscriptions for each module. */ + uint32_t change_sub_count; /**< Change module subscription count. */ + + struct modsub_oper_s { + char *module_name; /**< Module of the subscriptions. */ + struct modsub_opersub_s { + char *xpath; /**< Subscription XPath. */ + sr_oper_get_items_cb cb; /**< Subscription callback. */ + void *private_data; /**< Subscription callback private data. */ + sr_session_ctx_t *sess; /**< Subscription session. */ + + uint32_t request_id; /**< Request ID of the last processed request. */ + sr_shm_t sub_shm; /**< Subscription SHM. */ + } *subs; /**< Operational subscriptions for each XPath. */ + uint32_t sub_count; /**< Operational module XPath subscription count. */ + } *oper_subs; /**< Operational subscriptions for each module. */ + uint32_t oper_sub_count; /**< Operational module subscription count. */ + + struct modsub_notif_s { + char *module_name; /**< Module of the subscriptions. */ + struct modsub_notifsub_s { + uint32_t sub_id; /**< Unique (notification) subscription ID. */ + char *xpath; /**< Subscription XPath. */ + time_t start_time; /**< Subscription start time. */ + int replayed; /**< Flag whether the subscription replay is finished. */ + time_t stop_time; /**< Subscription stop time. */ + sr_event_notif_cb cb; /**< Subscription value callback. */ + sr_event_notif_tree_cb tree_cb; /**< Subscription tree callback. */ + void *private_data; /**< Subscription callback private data. */ + sr_session_ctx_t *sess; /**< Subscription session. */ + } *subs; /**< Notification subscriptions for each XPath. */ + uint32_t sub_count; /**< Notification module XPath subscription count. */ + + uint32_t request_id; /**< Request ID of the last processed request. */ + sr_shm_t sub_shm; /**< Subscription SHM. */ + } *notif_subs; /**< Notification subscriptions for each module. */ + uint32_t notif_sub_count; /**< Notification module subscription count. */ + + struct opsub_rpc_s { + char *path; /**< Subscription RPC/action path. */ + struct opsub_rpcsub_s { + char *xpath; /**< Subscription XPath. */ + uint32_t priority; /**< Subscription priority. */ + sr_rpc_cb cb; /**< Subscription value callback. */ + sr_rpc_tree_cb tree_cb; /**< Subscription tree callback. */ + void *private_data; /**< Subscription callback private data. */ + sr_session_ctx_t *sess; /**< Subscription session. */ + + uint32_t request_id; /**< Request ID of the last processed request. */ + sr_sub_event_t event; /**< Type of the last processed event. */ + } *subs; /**< RPC/action subscription for each XPath. */ + uint32_t sub_count; /**< RPC/action XPath subscription count. */ + + sr_shm_t sub_shm; /**< Subscription SHM. */ + } *rpc_subs; /**< RPC/action subscriptions for each operation. */ + uint32_t rpc_sub_count; /**< RPC/action operation subscription count. */ +}; + +/** + * @brief Change iterator. + */ +struct sr_change_iter_s { + struct lyd_node *diff; /**< Optional copied diff that set items point into. */ + struct ly_set *set; /**< Set of all the selected diff nodes. */ + uint32_t idx; /**< Index of the next change. */ +}; + +/* + * From sysrepo.c + */ + +/** + * @brief Start a new session. + * + * @param[in] conn Connection of the session. + * @param[in] datastore Datastore of the session. + * @param[in] event Optional event the session is handling, SR_SUB_EV_NONE for a standard session. + * @param[in] ev_sid Event originator SID. + * @param[in] ev_ncid Event originator NCID. + * @param[in] ev_user Event originator user. + * @param[out] session Created session. + * @return err_info, NULL on success. + */ +sr_error_info_t *_sr_session_start(sr_conn_ctx_t *conn, const sr_datastore_t datastore, sr_sub_event_t event, + uint32_t ev_sid, uint32_t ev_ncid, const char *ev_user, sr_session_ctx_t **session); + +/* + * Subscription functions + */ + +/** + * @brief Add a change subscription into a subscription structure. + * + * @param[in] sess Subscription session. + * @param[in] mod_name Subscription module name. + * @param[in] xpath Subscription XPath. + * @param[in] change_cb Subscription callback. + * @param[in] private_data Subscription callback private data. + * @param[in] priority Subscription priority. + * @param[in] sub_opts Subscription options. + * @param[in] has_subs_lock What kind of SUBS lock is held. + * @param[in,out] subs Subscription structure. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_sub_change_add(sr_session_ctx_t *sess, const char *mod_name, const char *xpath, sr_module_change_cb change_cb, + void *private_data, uint32_t priority, sr_subscr_options_t sub_opts, sr_lock_mode_t has_subs_lock, + sr_subscription_ctx_t *subs); + +/** + * @brief Delete a change subscription from a subscription structure. + * + * @param[in] mod_name Subscription module name. + * @param[in] xpath Subscription XPath. + * @param[in] ds Subscription datastore. + * @param[in] change_cb Subscription callback. + * @param[in] private_data Subscription callback private data. + * @param[in] priority Subscription priority. + * @param[in] sub_opts Subscription options. + * @param[in] has_subs_lock What kind of SUBS lock is held. + * @param[in,out] subs Subscription structure. + */ +void sr_sub_change_del(const char *mod_name, const char *xpath, sr_datastore_t ds, sr_module_change_cb change_cb, + void *private_data, uint32_t priority, sr_subscr_options_t sub_opts, sr_lock_mode_t has_subs_lock, + sr_subscription_ctx_t *subs); + +/** + * @brief Add an operational subscription into a subscription structure. + * + * @param[in] sess Subscription session. + * @param[in] mod_name Subscription module name. + * @param[in] xpath Subscription XPath. + * @param[in] oper_cb Subscription callback. + * @param[in] private_data Subscription callback private data. + * @param[in] has_subs_lock What kind of SUBS lock is held. + * @param[in,out] subs Subscription structure. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_sub_oper_add(sr_session_ctx_t *sess, const char *mod_name, const char *xpath, + sr_oper_get_items_cb oper_cb, void *private_data, sr_lock_mode_t has_subs_lock, sr_subscription_ctx_t *subs); + +/** + * @brief Delete an operational subscription from a subscription structure. + * + * @param[in] mod_name Subscription module name. + * @param[in] xpath Subscription XPath. + * @param[in] has_subs_lock What kind of SUBS lock is held. + * @param[in,out] subs Subscription structure. + */ +void sr_sub_oper_del(const char *mod_name, const char *xpath, sr_lock_mode_t has_subs_lock, sr_subscription_ctx_t *subs); + +/** + * @brief Add a notification subscription into a subscription structure. + * + * @param[in] sess Subscription session. + * @param[in] mod_name Subscription module name. + * @param[in] sub_id Unique notif sub ID. + * @param[in] xpath Subscription XPath. + * @param[in] start_time Subscription start time. + * @param[in] stop_time Subscription stop time. + * @param[in] notif_cb Subscription value callback. + * @param[in] notif_tree_cb Subscription tree callback. + * @param[in] private_data Subscription callback private data. + * @param[in] has_subs_lock What kind of SUBS lock is held. + * @param[in,out] subs Subscription structure. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_sub_notif_add(sr_session_ctx_t *sess, const char *mod_name, uint32_t sub_id, const char *xpath, + time_t start_time, time_t stop_time, sr_event_notif_cb notif_cb, sr_event_notif_tree_cb notif_tree_cb, + void *private_data, sr_lock_mode_t has_subs_lock, sr_subscription_ctx_t *subs); + +/** + * @brief Delete a notification subscription from a subscription structure. + * + * @param[in] mod_name Subscription module name. + * @param[in] sub_id Unique notif sub ID. + * @param[in] has_subs_lock What kind of SUBS lock is held. + * @param[in,out] subs Subscription structure. + */ +void sr_sub_notif_del(const char *mod_name, uint32_t sub_id, sr_lock_mode_t has_subs_lock, sr_subscription_ctx_t *subs); + +/** + * @brief Add an RPC subscription into a subscription structure. + * + * @param[in] sess Subscription session. + * @param[in] path Subscription RPC path. + * @param[in] xpath Subscription XPath. + * @param[in] rpc_cb Subscription value callback. + * @param[in] rpc_tree_cb Subscription tree callback. + * @param[in] private_data Subscription callback private data. + * @param[in] priority Subscription priority. + * @param[in] has_subs_lock What kind of SUBS lock is held. + * @param[in,out] subs Subscription structure. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_sub_rpc_add(sr_session_ctx_t *sess, const char *path, const char *xpath, sr_rpc_cb rpc_cb, + sr_rpc_tree_cb rpc_tree_cb, void *private_data, uint32_t priority, sr_lock_mode_t has_subs_lock, + sr_subscription_ctx_t *subs); + +/** + * @brief Delete an RPC subscription from a subscription structure. + * + * @param[in] path Subscription RPC path. + * @param[in] xpath Subscription XPath. + * @param[in] rpc_cb Subscription value callback. + * @param[in] rpc_tree_cb Subscription tree callback. + * @param[in] private_data Subscription callback private data. + * @param[in] priority Subscription priority. + * @param[in] has_subs_lock What kind of SUBS lock is held. + * @param[in,out] subs Subscription structure. + */ +void sr_sub_rpc_del(const char *path, const char *xpath, sr_rpc_cb rpc_cb, sr_rpc_tree_cb rpc_tree_cb, + void *private_data, uint32_t priority, sr_lock_mode_t has_subs_lock, sr_subscription_ctx_t *subs); + +/** + * @brief Count subscriptions of session \p sess in subscriptions structure \p subs. + * + * @param[in] sess Subscription session. + * @param[in] has_subs_lock What kind of SUBS lock is held. + * @param[in] subs Session subscription. + * @return Number of session subscriptions. + */ +int sr_subs_session_count(sr_session_ctx_t *sess, sr_lock_mode_t has_subs_lock, sr_subscription_ctx_t *subs); + +/** + * @brief Delete all subscriptions in \p subs of session \p sess. + * Main SHM read-upgr lock must be held and will be temporarily upgraded! + * + * @param[in] sess Subscription session. + * @param[in] has_subs_lock What kind of SUBS lock is held. + * @param[in] subs Session subscription. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_subs_session_del(sr_session_ctx_t *sess, sr_lock_mode_t has_subs_lock, sr_subscription_ctx_t *subs); + +/** + * @brief Delete all subscriptions in \p subs of all the sessions. + * Main SHM read-upgr lock must be held and will be temporarily upgraded! + * + * @param[in,out] subs Subscription structure. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_subs_del_all(sr_subscription_ctx_t *subs); + +/** + * @brief Find notifications subscribers for a module. + * + * @param[in] conn Connection to use. + * @param[in] mod_name Module name. + * @param[out] notif_subs Notification subscriptions. + * @param[out] notif_sub_count Number of subscribers. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_notif_find_subscriber(sr_conn_ctx_t *conn, const char *mod_name, sr_mod_notif_sub_t **notif_subs, + uint32_t *notif_sub_count); + +/** + * @brief Call notification callback for a notification. + * + * @param[in] ev_sess Event session to provide for the callback. + * @param[in] cb Value callback. + * @param[in] tree_cb Tree callback. + * @param[in] private_data Callback private data. + * @param[in] notif_type Notification type. + * @param[in] notif_op Notification node of the notification (relevant for nested notifications). + * @param[in] notif_ts Timestamp of when the notification was generated. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_notif_call_callback(sr_session_ctx_t *ev_sess, sr_event_notif_cb cb, sr_event_notif_tree_cb tree_cb, + void *private_data, const sr_ev_notif_type_t notif_type, const struct lyd_node *notif_op, time_t notif_ts); + +/* + * Utility functions + */ + +/** + * @brief Add a generic pointer to a ptr array. + * + * @param[in] ptr_lock Pointers lock. + * @param[in,out] ptrs Pointer array to enlarge. + * @param[in,out] ptr_count Pointer array count. + * @param[in] add_ptr Pointer to add. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_ptr_add(pthread_mutex_t *ptr_lock, void ***ptrs, uint32_t *ptr_count, void *add_ptr); + +/** + * @brief Delete a generic pointer from a ptr array. + * + * @param[in,out] ptrs Pointer array to delete from. + * @param[in,out] ptr_count Pointer array count. + * @param[in] del_ptr Pointer to delete. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_ptr_del(pthread_mutex_t *ptr_lock, void ***ptrs, uint32_t *ptr_count, void *del_ptr); + +/** + * @brief Wrapper for libyang ly_ctx_new(). + * + * @param[out] ly_ctx libyang context. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_ly_ctx_new(struct ly_ctx **ly_ctx); + +/** + * @brief Remove module YANG file. + * + * @param[in] name Module name. + * @param[in] revision Module revision, NULL if none. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_remove_module_file(const char *name, const char *revision); + +/** + * @brief Create (print) YANG module file and all of its submodules. + * + * @param[in] ly_mod Module to print. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_store_module_files(const struct lys_module *ly_mod); + +/** + * @brief Unlink startup, running, and candidate files of a module. + * + * @param[in] mod_name Module name. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_remove_data_files(const char *mod_name); + +/** + * @brief Check whether a module is internal libyang or sysrepo module. + * + * @param[in] ly_mod Module to check. + * @return 0 if not, non-zero if it is. + */ +int sr_module_is_internal(const struct lys_module *ly_mod); + +/** + * @brief Create startup file for a module. + * + * @param[in] ly_mod Module to create startup file for. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_create_startup_file(const struct lys_module *ly_mod); + +/** + * @brief Create all module import and include files, recursively. + * + * @param[in] ly_mod libyang module whose imports and includes to create. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_create_module_imps_incs_r(const struct lys_module *ly_mod); + +/** + * @brief Get the path the main SHM. + * + * @param[out] path Created path. Should be freed by the caller. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_path_main_shm(char **path); + +/** + * @brief Get the path the external SHM. + * + * @param[out] path Created path. Should be freed by the caller. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_path_ext_shm(char **path); + +/** + * @brief Get the path to a subscription SHM. + * + * @param[in] mod_name Module name. + * @param[in] suffix1 First suffix. + * @param[in] suffix2 Second suffix, none if equals -1. + * @param[out] path Created path. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_path_sub_shm(const char *mod_name, const char *suffix1, int64_t suffix2, char **path); + +/** + * @brief Get the path to a subscription data SHM. + * + * @param[in] mod_name Module name. + * @param[in] suffix1 First suffix. + * @param[in] suffix2 Second suffix, none if equals -1. + * @param[out] path Created path. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_path_sub_data_shm(const char *mod_name, const char *suffix1, int64_t suffix2, char **path); + +/** + * @brief Get the path to a volatile datastore SHM. + * + * @param[in] mod_name Module name. + * @param[in] ds Target datastore. + * @param[out] path Created path. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_path_ds_shm(const char *mod_name, sr_datastore_t ds, char **path); + +/** + * @brief Get the path to an event pipe. + * + * @param[in] evpipe_num Event pipe number. + * @param[out] path Created path. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_path_evpipe(uint32_t evpipe_num, char **path); + +/** + * @brief Get the path to startup files directory. + * + * @param[out] path Created path. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_path_startup_dir(char **path); + +/** + * @brief Get the path to notification files directory. + * + * @param[out] path Created path. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_path_notif_dir(char **path); + +/** + * @brief Get the path to YANG module files directory. + * + * @param[out] path Created path. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_path_yang_dir(char **path); + +/** + * @brief Get the path to a module startup file. + * + * @param[in] mod_name Module name. + * @param[out] path Created path. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_path_startup_file(const char *mod_name, char **path); + +/** + * @brief Get the path to a module notification file. + * + * @param[in] mod_name Module name. + * @param[in] from_ts Timestamp of the first stored notification. + * @param[in] to_ts Timestamp of the last stored notification. + * @param[out] path Created path. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_path_notif_file(const char *mod_name, time_t from_ts, time_t to_ts, char **path); + +/** + * @brief Get the path to a YANG module file. + * + * @param[in] mod_name Module name. + * @param[in] mod_rev Module revision. + * @param[out] path Created path. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_path_yang_file(const char *mod_name, const char *mod_rev, char **path); + +/** + * @brief Populate the lockfile path for a given Connection ID. + * When called with cid of 0 the path will be set to the lock file directory + * path. The path parameter is set to newly allocated memory. Caller is + * responsible for freeing memory. + * + * @param[in] cid Connection ID for which the lockfile path is constructed. + * @param[out] path Lockfile directory if cid is 0, path of lockfile otherwise. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_path_conn_lockfile(sr_cid_t cid, char **path); + +/** + * @brief Remove any leftover event pipes after crashed subscriptions. + * There should be none unless there was a subscription structure without subscriptions that crashed. + */ +void sr_remove_evpipes(void); + +/** + * @brief Get the UID of a user or vice versa. + * + * @param[in,out] uid UID. + * @param[in,out] user User name. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_get_pwd(uid_t *uid, char **user); + +/** + * @brief Change mode (permissions) and/or owner and group of a file. + * + * @param[in] path File path. + * @param[in] owner New owner if not NULL. + * @param[in] group New group if not NULL. + * @param[in] perm New permissions if not 0. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_chmodown(const char *path, const char *owner, const char *group, mode_t perm); + +/** + * @brief Check whether the effective user has permissions for a module. + * + * @param[in] mod_name Module to check. + * @param[in] wr Check write access if set, otherwise read. + * @param[in,out] has_access If set, it will contain the result of the access check. + * If not set, denied access returns an error. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_perm_check(const char *mod_name, int wr, int *has_access); + +/** + * @brief Get mode (permissions) and/or owner and group of a module. + * + * @param[in] mod_name Module name. + * @param[in] ds Datastore file to check, for general module access permissions, startup should always be used. + * @param[in,out] owner Module owner if not NULL. + * @param[in,out] group Module group if not NULL. + * @param[in,out] perm Module permissions if not NULL; + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_perm_get(const char *mod_name, sr_datastore_t ds, char **owner, char **group, mode_t *perm); + +/** + * @brief Check whether a file exists. + * + * @param[in] path Path to the file. + * @return 0 if file does not exist, non-zero if it exists. + */ +int sr_file_exists(const char *path); + +/** + * @brief Get current time with an offset. + * + * @param[out] ts Current time offset by \p add_ms. + * @param[in] add_ms Number os milliseconds added. + */ +void sr_time_get(struct timespec *ts, uint32_t add_ms); + +/** + * @brief Remap and possibly resize a SHM. Needs WRITE lock for resizing, + * otherwise READ lock is fine. + * + * @param[in] shm SHM structure to remap. + * @param[in] new_shm_size Resize SHM to this size, if 0 read the size of the SHM file. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_shm_remap(sr_shm_t *shm, size_t new_shm_size); + +/** + * @brief Clear a SHM structure. + * + * @param[in] shm SHM structure to clear. + */ +void sr_shm_clear(sr_shm_t *shm); + +/** + * @brief Get the next ext SHM memory hole. + * + * @param[in] last Last returned hole, NULL on first call. + * @param[in] ext_shm Ext SHM. + * @return Next ext SHM memor hole, NULL if the last was returned. + */ +sr_ext_hole_t *sr_ext_hole_next(sr_ext_hole_t *last, sr_ext_shm_t *ext_shm); + +/** + * @brief Find an existing hole. + * + * @param[in] ext_shm Ext SHM. + * @param[in] off Optional offset of the hole. + * @param[in] min_size Minimum matching hole size. + * @return First suitable hole, NULL if none found. + */ +sr_ext_hole_t *sr_ext_hole_find(sr_ext_shm_t *ext_shm, uint32_t off, uint32_t min_size); + +/** + * @brief Delete an existing hole. + * + * @param[in] ext_shm Ext SHM. + * @param[in] hole Hole to delete. + */ +void sr_ext_hole_del(sr_ext_shm_t *ext_shm, sr_ext_hole_t *hole); + +/** + * @brief Add a new hole. + * + * @param[in] ext_shm Ext SHM. + * @param[in] off Offset of the new hole. + * @param[in] size Size of the new hole. + * @return First suitable hole, NULL if none found. + */ +void sr_ext_hole_add(sr_ext_shm_t *ext_shm, uint32_t off, uint32_t size); + +/** + * @brief Copy memory into SHM. + * + * @param[in] shm_addr Mapped SHM address. + * @param[in] src Source memory. + * @param[in] size Size of source memory. + * @param[in,out] shm_end Current SHM end pointer, it is updated. + * @return Offset of the copied memory in SHM. + */ +off_t sr_shmcpy(char *shm_addr, const void *src, size_t size, char **shm_end); + +/** + * @brief Copy string into SHM. + * + * @param[in] shm_addr Mapped SHM address. + * @param[in] str Source string. + * @param[in,out] shm_end Current SHM end pointer, it is updated. + * @return Offset of the copied memory in SHM. + */ +off_t sr_shmstrcpy(char *shm_addr, const char *str, char **shm_end); + +/** + * @brief Get required memory in ext SHM for a string. + * + * @param[in] str String to be examined. + * @return Number of required bytes. + */ +size_t sr_strshmlen(const char *str); + +/** + * @brief Realloc for an array in ext SHM adding one new item. The array offset and item count is properly + * updated in the ext SHM. + * + * May remap ext SHM! + * + * @param[in] shm_ext Ext SHM structure. + * @param[in,out] shm_array_off Pointer to array offset in SHM, is updated. + * @param[in,out] shm_count Pointer to array count in SHM, is updated. + * @param[in] in_ext_shm Whether @p shm_array_off and @p shm_count themselves are stored in ext SHM or not (in main SHM). + * In case they are in ext SHM, they should not be used directly after this function as they may have been remapped! + * @param[in] item_size Array item size. + * @param[in] add_idx Index of the new item, -1 for adding at the end. + * @param[out] new_item Pointer to the new item. + * @param[in] dyn_attr_size Optional dynamic attribute size to allocate as well. + * @param[out] dyn_attr_off Optional allocated dynamic attribute offset. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_shmrealloc_add(sr_shm_t *shm_ext, off_t *shm_array_off, uint32_t *shm_count_off, int in_ext_shm, + size_t item_size, int64_t add_idx, void **new_item, size_t dyn_attr_size, off_t *dyn_attr_off); + +/** + * @brief Realloc for an array in SHM deleting one item. + * + * @param[in] shm_ext Ext SHM structure. + * @param[in,out] shm_array_off Pointer to array in SHM, set to 0 if last item was removed. + * @param[in,out] shm_count Pointer to array count in SHM, will be updated. + * @param[in] item_size Array item size. + * @param[in] del_idx Item index to delete. + * @param[in] dyn_attr_size Aligned size of dynamic attributes of the deleted item, if any. + * @param[in] dyn_attr_off Offset of the dynamic attribute, if any. + */ +void sr_shmrealloc_del(sr_shm_t *shm_ext, off_t *shm_array_off, uint32_t *shm_count, size_t item_size, uint32_t del_idx, + size_t dyn_attr_size, off_t dyn_attr_off); + +/** + * @brief Wrapper for pthread_mutex_init(). + * + * @param[in,out] lock pthread mutex to initialize. + * @param[in] shared Whether the mutex will be shared between processes or not. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_mutex_init(pthread_mutex_t *lock, int shared); + +/** + * @brief Callback called for each recovered owner of a lock. + * + * @param[in] mode Dead owner lock mode. + * @param[in] cid Dead owner connection ID. + * @param[in] data Arbitrary user data. + */ +typedef void (*sr_lock_recover_cb)(sr_lock_mode_t mode, sr_cid_t cid, void *data); + +/** + * @brief Lock a mutex. + * + * @param[in] lock Mutex to lock. + * @param[in] timeout_ms Timeout in ms for locking. + * @param[in] finc Name of the calling function for logging. + * @param[in] cb Optional callback called when recovering locks. When calling it, the lock is always held. + * Callback @p mode is set to ::SR_LOCK_WRITE and @p cid to 0. + * @param[in] cb_data Arbitrary user data for @p cb. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_mlock(pthread_mutex_t *lock, int timeout_ms, const char *func, sr_lock_recover_cb cb, void *cb_data); + +/** + * @brief Unlock a mutex. + * + * @param[in] lock Mutex to unlock. + */ +void sr_munlock(pthread_mutex_t *lock); + +/** + * @brief Initialize a sysrepo RW lock. + * + * @param[in,out] rwlock RW lock to initialize. + * @param[in] shared Whether the RW lock will be shared between processes or not. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_rwlock_init(sr_rwlock_t *rwlock, int shared); + +/** + * @brief Destroy a sysrepo RW lock. + * + * @param[in] rwlock RW lock to destroy. + */ +void sr_rwlock_destroy(sr_rwlock_t *rwlock); + +/** + * @brief Lock a sysrepo RW lock. On failure, the lock is not changed in any way. + * + * @param[in] rwlock RW lock to lock. + * @param[in] timeout_ms Timeout in ms for locking. + * @param[in] mode Lock mode to set. + * @param[in] cid Lock owner connection ID. + * @param[in] func Name of the calling function for logging. + * @param[in] cb Optional callback called when recovering locks. When calling it, WRITE lock is always held. + * @param[in] cb_data Arbitrary user data for @p cb. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_rwlock(sr_rwlock_t *rwlock, int timeout_ms, sr_lock_mode_t mode, sr_cid_t cid, const char *func, + sr_lock_recover_cb cb, void *cb_data); + +/** + * @brief Relock a sysrepo RW lock (upgrade or downgrade). On failure, the lock is not changed in any way. + * + * If @p mode is ::SR_LOCK_WRITE, the @p rwlock must be locked with ::SR_LOCK_READ_UPGR. + * If @p mode is ::SR_LOCK_READ or ::SR_LOCK_READ_UPGR, the @p rwlock must be locked with ::SR_LOCK_WRITE. + * + * @param[in] rwlock RW lock to lock. + * @param[in] timeout_ms Timeout in ms for locking. Only needed for lock upgrade (if @p mode is ::SR_LOCK_WRITE). + * @param[in] mode Lock mode to set. + * @param[in] cid Lock owner connection ID. + * @param[in] func Name of the calling function for logging. + * @param[in] cb Optional callback called when recovering locks. When calling it, WRITE lock is always held. + * @param[in] cb_data Arbitrary user data for @p cb. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_rwrelock(sr_rwlock_t *rwlock, int timeout_ms, sr_lock_mode_t mode, sr_cid_t cid, const char *func, + sr_lock_recover_cb cb, void *cb_data); + +/** + * @brief Unlock a sysrepo RW lock. On failure, whatever steps are possible are still performed. + * + * @param[in] rwlock RW lock to unlock. + * @param[in] timeout_ms Timeout in ms for locking. Only needed for read or read-upgr unlock. + * @param[in] mode Lock mode that was successfully set for the lock. + * @param[in] cid Lock owner connection ID. + * @param[in] func Name of the calling function for logging. + */ +void sr_rwunlock(sr_rwlock_t *rwlock, int timeout_ms, sr_lock_mode_t mode, sr_cid_t cid, const char *func); + +/** + * @brief Check whether a connection is alive. + * + * @param[in] cid Connection CID. + * @return 0 if it is dead, non-zero if it alive. + */ +int sr_conn_is_alive(sr_cid_t cid); + +/** + * @brief Wrapper to realloc() that frees memory on failure. + * + * @param[in] ptr Pointer to the current memory. + * @param[in] size New size of the memory. + * @return Resized memory, NULL on error. + */ +void *sr_realloc(void *ptr, size_t size); + +/** + * @brief Copy file contents to another file. + * + * @param[in] to Destination file path. + * @param[in] from Source file path. + * @param[in] file_mode Permissions of \p to file, if being created. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_cp_path(const char *to, const char *from, mode_t file_mode); + +/** + * @brief Wrapper for open(2). + * + * Additionally sets umask. + * + * @param[in] pathname Path of the file to open. + * @param[in] flags Flags to use. + * @param[in] mode Permissions for the file in case it is created. + * @return Opened file descriptor. + * @return -1 on error, errno set. + */ +int sr_open(const char *pathname, int flags, mode_t mode); + +/** + * @brief Create all directories in the path, wrapper for mkdir(2). + * + * Additionally sets umask. + * + * @param[in] path Full path, is temporarily modified. + * @param[in] mode Mode (permissions) of the directories. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_mkpath(char *path, mode_t mode); + +/** + * @brief Get first namespace (module name) from an XPath expression. + * + * @param[in] expr Expression to inspect. + * @return First module name, NULL on error. + */ +char *sr_get_first_ns(const char *expr); + +/** + * @brief Get XPath expression without any predicates. + * + * @param[in] expr Expression to transform. + * @param[out] expr2 Expression without predicates. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_get_trim_predicates(const char *expr, char **expr2); + +/** + * @brief Get datastore string name. + * + * @param[in] ds Datastore to transform. + * @return Datastore string name. + */ +const char *sr_ds2str(sr_datastore_t ds); + +/** + * @brief Get datastore identity name from ietf-datastores. + * + * @param[in] ds Datastore to transform. + * @return Datastore identity name. + */ +const char *sr_ds2ident(sr_datastore_t ds); + +/** + * @brief Sleep for specified milliseconds. + * + * @param[in] msec Number of ms to sleep for. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_msleep(uint32_t msec); + +/** + * @brief Print a message into a newly allocated buffer. + * + * @param[in,out] str Buffer for the message. + * @param[in,out] str_len Current buffer length. + * @param[in] offset Print into buffer with an offset. + * @param[in] format Format of the message. + * @param[in] ap Format argument list. + * @return Number of printed characters, -1 on error. + */ +int sr_vsprintf(char **str, int *str_len, int offset, const char *format, va_list ap); + +/** + * @brief Print a message into a newly allocated buffer. + * + * @param[in,out] str Buffer for the message. + * @param[in,out] str_len Current buffer length. + * @param[in] offset Print into buffer with an offset. + * @param[in] format Format of the message. + * @param[in] ... Format arguments. + * @return Number of printed characters, -1 on error. + */ +int sr_sprintf(char **str, int *str_len, int offset, const char *format, ...); + +/** + * @brief Get a file descriptor size. + * + * @param[in] fd File descriptor to inspect. + * @param[out] size Size of \p fd. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_file_get_size(int fd, size_t *size); + +/** + * @brief Get string value of a libyang leaf(-list). + * + * @param[in] leaf Node to inspect. + * @return String value of the node. + */ +const char *sr_ly_leaf_value_str(const struct lyd_node *leaf); + +/** + * @brief Get event string name. + * + * @param[in] ev Event to transform. + * @return Event string name. + */ +const char *sr_ev2str(sr_sub_event_t ev); + +/** + * @brief Transform internal event type into a public API event type. + * + * @param[in] ev Internal event. + * @return Public API event. + */ +sr_event_t sr_ev2api(sr_sub_event_t ev); + +/** + * @brief Transform a libyang node into sysrepo value. + * + * @param[in] node libyang node to transform. + * @param[out] sr_val sysrepo value. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_val_ly2sr(const struct lyd_node *node, sr_val_t *sr_val); + +/** + * @brief Transform a sysrepo value into libyang string value. + * + * @param[in] ctx libyang context. + * @param[in] sr_val sysrepo value to transform. + * @param[in] xpath XPath of the sysrepo value. + * @param[in] buf Function buffer, must be of size at least 22 bytes. + * @param[in] output Whether to look for output nodes instead of input. + * @return String value. + */ +char *sr_val_sr2ly_str(struct ly_ctx *ctx, const sr_val_t *sr_val, const char *xpath, char *buf, int output); + +/** + * @brief Transform a sysrepo value into libyang node. + * + * @param[in] ctx libyang context. + * @param[in] xpath XPath of the sysrepo value. + * @param[in] val_str String value of the sysrepo value. + * @param[in] dflt Dflt flag if the sysrepo value. + * @param[in] output Whether the sysrepo value is from an output. + * @param[in,out] root Transformed sysrepo value, appended if set. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_val_sr2ly(struct ly_ctx *ctx, const char *xpath, const char *val_str, int dflt, int output, + struct lyd_node **root); + +/** + * @brief Split this sibling with following siblings and its preceding siblings. + * Works only for top-level nodes! + * + * @param[in] sibling Specific sibling where to split the siblings. + */ +void sr_ly_split(struct lyd_node *sibling); + +/** + * @brief Link together split siblings. Works only for top-level nodes! + * + * @param[in] first First sibling of the preceding siblings. + * @param[in] sibling First sibling of the following siblings. + */ +void sr_ly_link(struct lyd_node *first, struct lyd_node *sibling); + +/** + * @brief Duplicate nodes to the specified depth. + * + * @param[in] src_parent Source parent. + * @param[in] depth Depth to duplicate. + * @param[in,out] trg_parent Target parent to add children to. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_lyd_dup(const struct lyd_node *src_parent, uint32_t depth, struct lyd_node *trg_parent); + +/** + * @brief Get pointer to data node children. + * + * @param[in] node Node to get children of. + * @param[in] skip_keys Whether to return first non-key child in case of lists. + * @return Node children, NULL if has none. + */ +struct lyd_node *sr_lyd_child(const struct lyd_node *node, int skip_keys); + +/** + * @brief Create any missing config/state NP containers in the siblings, recursively. + * + * @param[in,out] first First sibling to add NP containers into, set if @p parent is NULL. + * Only @p ly_mod data are considered. + * @param[in] parent Parent of any added NP containers, set if @p first is NULL. + * @param[in] ly_mod Module to consider, set if @p parent is NULL. + * @param[in,out] diff Optional diff to append any performed changes to. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_lyd_create_sibling_np_cont_r(struct lyd_node **first, struct lyd_node *parent, + const struct lys_module *ly_mod, struct lyd_node **diff); + +/** + * @brief Duplicate only config NP containers of a module from a data tree. Also optionally create state NP containers. + * + * @param[in] data Data tree to duplicate from. + * @param[in] ly_mod Module whose data to duplicate. + * @param[in] add_state_np_conts Whether to also add state NP containers. + * @param[in,out] new_data Data with appended duplicated nodes. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_lyd_dup_module_np_cont(const struct lyd_node *data, const struct lys_module *ly_mod, + int add_state_np_conts, struct lyd_node **new_data); + +/** + * @brief Duplicate all data of a module from a data tree. Also properly handles config NP containers + * and optionally even state NP containers. + * + * @param[in] data Data tree to duplicate from. + * @param[in] ly_mod Module whose data to duplicate. + * @param[in] add_state_np_conts Whether to also add state NP containers. + * @param[in,out] new_data Data with appended duplicated nodes. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_lyd_dup_module_data(const struct lyd_node *data, const struct lys_module *ly_mod, + int add_state_np_conts, struct lyd_node **new_data); + +/** + * @brief Duplicate selected nodes from a data tree. Also properly handles config/state NP containers. + * Works well even for XPaths with intersections. + * + * @param[in] data Data tree to duplicate from. + * @param[in] xpaths Array of XPaths that will select the duplicated nodes. + * @param[in] xp_count XPath count. + * @param[in,out] new_data Data with appended duplicated selected nodes. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_lyd_dup_enabled_xpath(const struct lyd_node *data, char **xpaths, uint16_t xp_count, + struct lyd_node **new_data); + +/** + * @brief Remove all nodes selected by XPath. + * + * @param[in,out] data Data to filter. + * @param[in] xpath XPath selecting the nodes that will be freed. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_lyd_xpath_complement(struct lyd_node **data, const char *xpath); + +/** + * @brief Learn whether a node is user-ordered (leaf-)list. + * + * @param[in] node (Leaf-)list instance. + * @return 0 if not, non-zero if it is. + */ +int sr_ly_is_userord(const struct lyd_node *node); + +/** + * @brief Learn whether 2 anydata/anyxml nodes are equal or not. + * + * @param[in] any1 First anydata/anyxml node. + * @param[in] any2 Second anydata/anyxml node. + * @param[out] equal 1 if equal, 0 otherwise. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_lyd_anydata_equal(const struct lyd_node *any1, const struct lyd_node *any2, int *equal); + +/** + * @brief Free anydata/anyxml value. + * + * @param[in] any Node with value to free. + */ +void sr_lyd_anydata_free(struct lyd_node *any); + +/** + * @brief Copy anydata/anyxml value from src to trg. + * + * @param[in] trg Target to copy to. + * @param[in] src Source to copy from. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_lyd_anydata_copy(struct lyd_node *trg, const struct lyd_node *src); + +/** + * @brief Get string value of an anydata/anyxml node. + * + * @param[in] any Anydata/anyxml to get the value from. + * @param[out] value_str String value. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_ly_anydata_value_str(const struct lyd_node *any, char **value_str); + +/** + * @brief Get a hash of a string value. + * + * @param[in] str String to hash. + * @return String hash. + */ +uint32_t sr_str_hash(const char *str); + +/** + * @brief Trim last node from an XPath. + * + * @param[in] xpath Full XPath. + * @param[out] trim_xpath XPath without the last node (and its predicates, if any). + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_xpath_trim_last_node(const char *xpath, char **trim_xpath); + +/** + * @brief Get the first node (with predicates if any) from an XPath. + * + * @param[in] xpath Full XPath. + * @return First XPath node path. + */ +char *sr_xpath_first_node_with_predicates(const char *xpath); + +/** + * @brief Get pointers to the next node name in an XPath. + * + * @param[in] xpath Current position in the XPath (`/` expected at the beginning). + * @param[out] mod Module name, if any. + * @param[out] mod_len Moduel name length. + * @param[out] name Node name. + * @param[out] len Node name length, + * @param[out] double_slash Whether the node starts with '//'. + * @param[out] has_predicate Whether a predicate follows. + * @return Pointer to the next XPath part (node name or predicate). + */ +const char *sr_xpath_next_name(const char *xpath, const char **mod, int *mod_len, const char **name, int *len, + int *double_slash, int *has_predicate); + +/** + * @brief Get pointers to the next predicate in an XPath. + * + * @param[in] xpath Current position in the XPath (`[` expected at the beginning). + * @param[out] pred Predicate content. + * @param[out] len Predicate content length, + * @param[out] has_predicate Whether another predicate follows. + * @return Pointer to the next XPath part (node name or predicate). + */ +const char *sr_xpath_next_predicate(const char *xpath, const char **pred, int *len, int *has_predicate); + +/** + * @brief Learn length of an XPath withtout any predicates. + * + * @param[in] xpath Full XPath. + * @return XPath length. + */ +size_t sr_xpath_len_no_predicates(const char *xpath); + +/** + * @brief Find last (most nested) parent (node with possible children) in a data tree. + * + * @param[in,out] parent Any subtree node, will be moved to the last parent. + * @param[in] nodetype Whether to stop when a specific node type is found or not. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_ly_find_last_parent(struct lyd_node **parent, int nodetype); + +/** + * @brief Unlink data of a specific module from a data tree. + * + * @param[in,out] data Data tree. + * @param[in] ly_mod libyang module of interest. + * @return Unlinked data tree. + */ +struct lyd_node *sr_module_data_unlink(struct lyd_node **data, const struct lys_module *ly_mod); + +/** + * @brief Append data loaded from a file/SHM for a specific module. Do not use for operational datastore. + * + * @param[in] ly_mod Module to process. + * @param[in] ds Datastore. + * @param[in,out] data Data tree to append to. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_module_file_data_append(const struct lys_module *ly_mod, sr_datastore_t ds, struct lyd_node **data); + +/** + * @brief Load operational data (diff) loaded from a SHM for a specific module. + * + * @param[in] mod Mod info mod. + * @param[out] diff Loaded diff to return. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_module_file_oper_data_load(struct sr_mod_info_mod_s *mod, struct lyd_node **diff); + +/** + * @brief Set (replace) data in file/SHM for a specific module. + * + * @param[in] mod_name Module name. + * @param[in] ds Target datastore + * @param[in] mod_data Module data. + * @param[in] create_flags Additional flags that will be used for opening the file, + * any of O_CREATE and O_EXCL are expected. + * @param[in] file_mode Permissions (mode) of the file, must always be correctly set because of the backup. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_module_file_data_set(const char *mod_name, sr_datastore_t ds, struct lyd_node *mod_data, + int create_flags, mode_t file_mode); + +/** + * @brief Update sysrepo stored operational diff of a module. + * + * @param[in] conn Connection to use. + * @param[in] mod_name Module name. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_module_update_oper_diff(sr_conn_ctx_t *conn, const char *mod_name); + +/** + * @brief Get next feature of a module. + * + * @param[in] last Last returned feature, NULL on first call, + * @param[in] ly_mod Module with the features. + * @param[in,out] idx Internal index fo the feature, arbitrary value can be passed but must not be changed in between calls. + * @return Next found feature, NULL if last was previously returned. + */ +struct lys_feature *sr_lys_next_feature(struct lys_feature *last, const struct lys_module *ly_mod, uint32_t *idx); + +/** + * @brief Learn CIDs and PIDs of all the live connections. + * + * @param[out] cids Optional array of CIDs. + * @param[out] pids Optional array of PIDs. + * @param[out] count Connection count, length of both @p cids and @p pids. + * @param[out] dead_cids Optional array of dead CIDs. + * @param[out] dead_count Length of @p dead_cids. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_conn_info(sr_cid_t **cids, pid_t **pids, uint32_t *count, sr_cid_t **dead_cids, uint32_t *dead_count); + +/** + * @brief Transform given time_t (seconds since the epoch) into the RFC 3339 format (YANG date-and-time). + * + * @param[in] time Time to convert. + * @param[in] tz Timezone name for the result. See tzselect(1) for list of + * correct values. If not specified (NULL) or unknown/invalid, the result is provided in UTC (Zulu). + * @param[in,out] buf Buffer to print the datetime into, must be at least 26 characters long. If not set, @p buf2 is used. + * @param[in,out] buf2 Pointer to a buffer to allocate for the datetime. + * @return err_info, NULL on success. + */ +sr_error_info_t *sr_time2datetime(time_t time, const char *tz, char *buf, char **buf2); + +#endif diff --git a/ntsimulator/deploy/base/ubuntu.Dockerfile b/ntsimulator/deploy/base/ubuntu.Dockerfile index 21439db..69d69ce 100644 --- a/ntsimulator/deploy/base/ubuntu.Dockerfile +++ b/ntsimulator/deploy/base/ubuntu.Dockerfile @@ -19,19 +19,22 @@ FROM ubuntu:20.04 as builder LABEL maintainer="alexandru.stancu@highstreet-technologies.com / adrian.lita@highstreet-technologies.com" + +RUN apt-get clean RUN apt-get update RUN DEBIAN_FRONTEND="noninteractive" apt-get install -y \ # basic tools - tzdata build-essential git cmake pkg-config supervisor \ + tzdata build-essential git cmake pkg-config \ # libyang dependencies libpcre3-dev \ # libssh dependencies - zlib1g-dev libssl-dev + zlib1g-dev libssl-dev \ + && rm -rf /var/lib/apt/lists/* # add netconf user and configure access RUN \ adduser --system netconf && \ - echo "netconf:netconf" | chpasswd + echo "netconf:netconf!" | chpasswd # use /opt/dev as working directory RUN mkdir /opt/dev @@ -40,12 +43,12 @@ WORKDIR /opt/dev # get required build libs from git RUN \ git config --global advice.detachedHead false && \ - git clone --single-branch --branch v1.7.13 https://github.com/DaveGamble/cJSON.git && \ - git clone --single-branch --branch v1.0.184 https://github.com/CESNET/libyang.git && \ - git clone --single-branch --branch v1.4.70 https://github.com/sysrepo/sysrepo.git && \ + git clone --single-branch --branch v1.7.14 https://github.com/DaveGamble/cJSON.git && \ + git clone --single-branch --branch v1.0.225 https://github.com/CESNET/libyang.git && \ + git clone --single-branch --branch v1.4.122 https://github.com/sysrepo/sysrepo.git && \ git clone --single-branch --branch libssh-0.9.2 https://git.libssh.org/projects/libssh.git && \ - git clone --single-branch --branch v1.1.26 https://github.com/CESNET/libnetconf2.git && \ - git clone --single-branch --branch v1.1.39 https://github.com/CESNET/netopeer2.git && \ + git clone --single-branch --branch v1.1.43 https://github.com/CESNET/libnetconf2.git && \ + git clone --single-branch --branch v1.1.70 https://github.com/CESNET/netopeer2.git && \ git clone --single-branch --branch curl-7_72_0 https://github.com/curl/curl.git # build and install cJSON @@ -53,7 +56,7 @@ RUN \ cd cJSON && \ mkdir build && cd build && \ cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_CJSON_TEST=Off && \ - make -j2 && \ + make -j4 && \ make install && \ ldconfig @@ -61,17 +64,18 @@ RUN \ RUN \ cd libyang && \ mkdir build && cd build && \ - cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_BUILD_TESTS=OFF .. && \ - make -j2 && \ + cmake -DCMAKE_BUILD_TYPE:String="Release" -DGEN_LANGUAGE_BINDINGS=ON -DGEN_CPP_BINDINGS=ON -DGEN_PYTHON_BINDINGS=OFF -DENABLE_BUILD_TESTS=OFF .. && \ + make -j4 && \ make install && \ ldconfig # build and install sysrepo +COPY ./deploy/base/common.h.in /opt/dev/sysrepo/src/common.h.in RUN \ cd sysrepo && \ mkdir build && cd build && \ - cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_TESTS=OFF -DREPOSITORY_LOC:PATH=/etc/sysrepo -DREQUEST_TIMEOUT=60 -DOPER_DATA_PROVIDE_TIMEOUT=60 .. && \ - make -j2 && \ + cmake -DCMAKE_BUILD_TYPE:String="Release" -DGEN_LANGUAGE_BINDINGS=ON -DGEN_CPP_BINDINGS=ON -DGEN_PYTHON_BINDINGS=OFF -DENABLE_TESTS=OFF -DREPOSITORY_LOC:PATH=/etc/sysrepo -DREQUEST_TIMEOUT=60 -DOPER_DATA_PROVIDE_TIMEOUT=60 .. && \ + make -j4 && \ make install && \ ldconfig @@ -80,17 +84,16 @@ RUN \ cd libssh && \ mkdir build && cd build && \ cmake -DWITH_EXAMPLES=OFF .. && \ - make -j2 && \ + make -j4 && \ make install && \ ldconfig - # build and install libnetconf2 RUN \ cd libnetconf2 && \ mkdir build && cd build && \ cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_BUILD_TESTS=OFF .. && \ - make -j2 && \ + make -j4 && \ make install && \ ldconfig @@ -99,7 +102,7 @@ RUN \ cd netopeer2 && \ mkdir build && cd build && \ cmake -DCMAKE_BUILD_TYPE:String="Release" -DGENERATE_HOSTKEY=OFF -DMERGE_LISTEN_CONFIG=OFF .. && \ - make -j2 && \ + make -j4 && \ make install # build and install cURL @@ -107,7 +110,7 @@ RUN \ cd curl && \ mkdir build && cd build && \ cmake -DBUILD_TESTING=OFF .. && \ - make -j2 && \ + make -j4 && \ make install && \ ldconfig @@ -122,6 +125,9 @@ RUN \ cd .. # ntsim-ng copy and build +ARG BUILD_WITH_DEBUG +ENV BUILD_WITH_DEBUG=${BUILD_WITH_DEBUG} + RUN \ mkdir /opt/dev/ntsim-ng && \ mkdir /opt/dev/ntsim-ng/config && \ @@ -137,26 +143,36 @@ RUN \ COPY ./deploy/base/ca.key /home/netconf/.ssh/ca.key COPY ./deploy/base/ca.pem /home/netconf/.ssh/ca.pem COPY ./deploy/base/client.crt /home/netconf/.ssh/client.crt +COPY ./deploy/base/client.key /home/netconf/.ssh/client.key COPY ./deploy/base/generate-ssh-keys.sh /home/netconf/.ssh/generate-ssh-keys.sh ############################# #### Lightweight Base #### ############################# + FROM ubuntu:20.04 LABEL maintainer="alexandru.stancu@highstreet-technologies.com / adrian.lita@highstreet-technologies.com" +RUN apt-get clean RUN apt-get update -RUN apt-get install -y \ - supervisor \ + +ARG BUILD_WITH_DEBUG +ENV BUILD_WITH_DEBUG=${BUILD_WITH_DEBUG} +RUN if [ -n "${BUILD_WITH_DEBUG}" ]; then DEBIAN_FRONTEND="noninteractive" apt-get install -y gdb valgrind ; fi + +RUN apt-get install -y --no-install-recommends \ + psmisc \ openssl \ openssh-client \ vsftpd \ - openssh-server + openssh-server \ + && rm -rf /var/lib/apt/lists/* \ + && unset BUILD_WITH_DEBUG # add netconf user and configure access RUN \ adduser netconf && \ - echo "netconf:netconf" | chpasswd && \ + echo "netconf:netconf!" | chpasswd && \ mkdir -p /home/netconf/.ssh COPY --from=builder /usr/local/bin /usr/local/bin @@ -198,3 +214,9 @@ WORKDIR /opt/dev/workspace ENV SSH_CONNECTIONS=1 ENV TLS_CONNECTIONS=0 ENV IPv6_ENABLED=false + +ARG NTS_BUILD_VERSION +ENV NTS_BUILD_VERSION=${NTS_BUILD_VERSION} + +ARG NTS_BUILD_DATE +ENV NTS_BUILD_DATE=${NTS_BUILD_DATE} diff --git a/ntsimulator/deploy/base/yang/nts-common.yang b/ntsimulator/deploy/base/yang/nts-common.yang index ea7e60b..86d7b3e 100644 --- a/ntsimulator/deploy/base/yang/nts-common.yang +++ b/ntsimulator/deploy/base/yang/nts-common.yang @@ -11,34 +11,43 @@ module nts-common { "O-RAN-SC"; contact " Web: - Editors: + Editors: Alex Stancu Adrian Lita Martin Skorupski "; description "This module contains common yang definitions YANG definitions for the Network Topology Simulator."; + revision 2021-03-26 { + description + "Added controller-protocol."; + reference + "O-RAN-SC SIM project"; + } + revision 2021-02-15 { + description + "Added presence to configuration containers."; + reference + "O-RAN-SC SIM project"; + } revision 2020-11-20 { description "Add feature-type for the Web cut through feature."; reference "O-RAN-SC SIM project"; } - revision 2020-10-22 { description "Add feature-type for the NETCONF Call Home feature."; reference "O-RAN-SC SIM project"; } - revision 2020-10-13 { description "Add feature-type typedef containing the features that can be activated in the Network Function."; reference "O-RAN-SC SIM project"; } - revision 2020-09-07 { description "Initial revision for the Network Topology Simulator - Next Generation common types."; @@ -47,8 +56,13 @@ module nts-common { } feature faults-status { - description - "This means that the server supports reporting back the number of faults that were generated"; + description + "This means that the server supports reporting back the number of faults that were generated"; + } + + identity NTS_FUNCTION_TYPE_BASE { + description + "The reference of each identity represents the name of the associated docker image."; } typedef authentication-method-type { @@ -76,279 +90,291 @@ module nts-common { typedef feature-type { type bits { - bit ves-file-ready { - position 0; - description - "Controls the ves-file-ready feature."; - } - bit ves-heartbeat { - position 1; - description - "Controls the ves-heartbeat feature."; - } - bit ves-pnf-registration { - position 2; - description - "Controls the ves-pnf-registration feature."; - } - bit manual-notification-generation { - position 3; - description - "Controls the manual notification generation feature."; - } - bit netconf-call-home { - position 4; - description - "Controls the NETCONF Call Home feature."; - } - bit web-cut-through { - position 5; - description - "Controls the Web Cut Through feature."; - } + bit ves-file-ready { + position 0; + description + "Controls the ves-file-ready feature."; + } + bit ves-heartbeat { + position 1; + description + "Controls the ves-heartbeat feature."; + } + bit ves-pnf-registration { + position 2; + description + "Controls the ves-pnf-registration feature."; + } + bit manual-notification-generation { + position 3; + description + "Controls the manual notification generation feature."; + } + bit netconf-call-home { + position 4; + description + "Controls the NETCONF Call Home feature."; + } + bit web-cut-through { + position 5; + description + "Controls the Web Cut Through feature."; + } } description - "Describes the features that can be enabled/disabled in the Network Function."; - } - - identity NTS_FUNCTION_TYPE_BASE { - description - "The reference of each identity represents the name of the associated docker image."; + "Describes the features that can be enabled/disabled in the Network Function."; } grouping mount-point-details-g { - leaf mount-point-addressing-method { - type enumeration { - enum host-mapping { - description - "Uses IP and port mapped to the host machine to address the nework function."; - } - enum docker-mapping { - description - "Uses Docker IP and port to address the nework function."; - } + description + "Groups details about mount point"; + leaf mount-point-addressing-method { + type enumeration { + enum host-mapping { + description + "Uses IP and port mapped to the host machine to address the nework function."; } - default docker-mapping; - description - "Specifies how to address the simulated network function: via the host machine or via docker."; - } + enum docker-mapping { + description + "Uses Docker IP and port to address the nework function."; + } + } + default "docker-mapping"; description - "Groups details about mount point"; + "Specifies how to address the simulated network function: via the host machine or via docker."; + } } grouping fault-delay-period-g { - list fault-delay-list { - key index; - ordered-by user; - leaf index { - type uint16; - description - "The index of the list."; - } - leaf delay-period { - type uint16; - units s; - description - "The amount of seconds before the next event."; - } - description - "The list defining the pattern for generating events."; - } + description + "For reusing the same fault-delay-period."; + list fault-delay-list { + key "index"; + ordered-by user; description - "For reusing the same fault-delay-period."; + "The list defining the pattern for generating events."; + leaf index { + type uint16; + description + "The index of the list."; + } + leaf delay-period { + type uint16; + units "s"; + description + "The amount of seconds before the next event."; + } + } } grouping fault-count-g { - container fault-count { - if-feature faults-status; - config false; - leaf normal { - type uint32; - description - "Number of normal (non-alarmed) events."; - } - leaf warning { - type uint32; - description - "Number of warning events."; - } - leaf minor { - type uint32; - description - "Number of minor events."; - } - leaf major { - type uint32; - description - "Number of major events."; - } - leaf critical { - type uint32; - description - "Number of critical events."; - } - description - "Container which groups the number of fault events, by severity."; - } + description + "Grouping for counting the fault events, grouped by severity."; + container fault-count { + if-feature "faults-status"; + config false; description - "Grouping for counting the fault events, grouped by severity."; + "Container which groups the number of fault events, by severity."; + leaf normal { + type uint32; + description + "Number of normal (non-alarmed) events."; + } + leaf warning { + type uint32; + description + "Number of warning events."; + } + leaf minor { + type uint32; + description + "Number of minor events."; + } + leaf major { + type uint32; + description + "Number of major events."; + } + leaf critical { + type uint32; + description + "Number of critical events."; + } + } } grouping faults-g { + description + "Grouping for fault generation"; container fault-generation { - uses fault-delay-period-g; - uses fault-count-g; + presence "Enables fault generation configuration."; description "Groups the fault generation configuration and status."; + uses fault-delay-period-g; + uses fault-count-g; } - description - "Grouping for fault generation"; } grouping faults-enabled-g { - leaf faults-enabled { - type boolean; - description - "For enabling the fault generation."; - } description "Groups the enabling of faults."; + leaf faults-enabled { + type boolean; + description + "For enabling the fault generation."; + } } grouping netconf-config-g { + description + "Groups the configuration and status of NETCONF Fault notifications."; container netconf { - uses faults-enabled-g; - leaf call-home { - type boolean; - description - "For enabling the NETCONF Call Home feature. If set to 'true', each simulated device, when booting up, will try to Call Home to the SDN Controller."; - } - description + presence "Enables NETCONF configuration."; + description "Container for describing the NETCONF details."; + uses faults-enabled-g; + leaf call-home { + type boolean; + description + "For enabling the NETCONF Call Home feature. If set to 'true', each simulated device, when booting up, will try to Call Home to the SDN Controller."; + } } - description - "Groups the configuration and status of NETCONF Fault notifications."; } grouping ves-config-g { - container ves { - uses faults-enabled-g; - leaf pnf-registration { - type boolean; - description - "For enabling the PNF Registration messages. If set to 'true', each simulated device, when booting up, will send a PNF Registration message to the VES Collector."; - } - leaf heartbeat-period { - type uint16; - description - "The number of seconds between VES heartbeat messages."; - } - description - "Container for describing the VES details."; - } description "Groups the configuration and status of VES Fault notifications."; + container ves { + presence "Enables VES configuration."; + description + "Container for describing the VES details."; + uses faults-enabled-g; + leaf pnf-registration { + type boolean; + description + "For enabling the PNF Registration messages. If set to 'true', each simulated device, when booting up, will send a PNF Registration message to the VES Collector."; + } + leaf heartbeat-period { + type uint16; + description + "The number of seconds between VES heartbeat messages."; + } + } } grouping controller-g { - leaf controller-ip { - type inet:ip-address; - description - "The IP address of the SDN Controller."; - } - leaf controller-port { - type inet:port-number; - description - "The port exposed by the SDN Controller."; - } - leaf controller-netconf-call-home-port { - type inet:port-number; - description - "The port exposed by the SDN Controller for NETCONF Call Home."; - } - leaf controller-username { - type string; + description + "Groups information about the SDN Controller."; + leaf controller-protocol { + type enumeration { + enum http { description - "The username for accessing the SDN Controller."; - } - leaf controller-password { - type string; + "HTTP protocol will be used to connect to the VES Collector."; + } + enum https { description - "The password for accessing the SDN Controller."; + "HTTPS protocol will be used to connect to the VES Collector."; + } } + default "https"; + description + "The protocol used for communication with the SDN Controller."; + } + leaf controller-ip { + type inet:ip-address; + description + "The IP address of the SDN Controller."; + } + leaf controller-port { + type inet:port-number; + description + "The port exposed by the SDN Controller."; + } + leaf controller-netconf-call-home-port { + type inet:port-number; description - "Groups information about the SDN Controller."; + "The port exposed by the SDN Controller for NETCONF Call Home."; + } + leaf controller-username { + type string; + description + "The username for accessing the SDN Controller."; + } + leaf controller-password { + type string; + description + "The password for accessing the SDN Controller."; + } } grouping ves-endpoint-g { - leaf ves-endpoint-protocol { - type enumeration { - enum http { - description - "HTTP protocol will be used to connect to the VES Collector."; - } - enum https { - description - "HTTPS protocol will be used to connect to the VES Collector."; - } - } - default https; - description - "The protocol (HTTP / HTTPS) to be used to address the VES Collector."; - } - leaf ves-endpoint-ip { - type inet:ip-address; - description - "The IP address of the VES Collector."; - } - leaf ves-endpoint-port { - type inet:port-number; - description - "The port exposed by the VES Collector."; - } - leaf ves-endpoint-auth-method { - type authentication-method-type; - default "no-auth"; - description - "The type of the authentication to be used with the VES Collector."; - } - leaf ves-endpoint-username { - type string; + description + "Groups information about the VES Collector."; + leaf ves-endpoint-protocol { + type enumeration { + enum http { description - "The username for accessing the VES Collector."; - } - leaf ves-endpoint-password { - type string; + "HTTP protocol will be used to connect to the VES Collector."; + } + enum https { description - "The password for accessing the VES Collector."; - } - leaf ves-endpoint-certificate { - type string; - description - "The Certificate to be used to authenticate to the VES Collector."; + "HTTPS protocol will be used to connect to the VES Collector."; + } } + default "https"; + description + "The protocol (HTTP / HTTPS) to be used to address the VES Collector."; + } + leaf ves-endpoint-ip { + type inet:ip-address; + description + "The IP address of the VES Collector."; + } + leaf ves-endpoint-port { + type inet:port-number; + description + "The port exposed by the VES Collector."; + } + leaf ves-endpoint-auth-method { + type authentication-method-type; + default "no-auth"; + description + "The type of the authentication to be used with the VES Collector."; + } + leaf ves-endpoint-username { + type string; + description + "The username for accessing the VES Collector."; + } + leaf ves-endpoint-password { + type string; + description + "The password for accessing the VES Collector."; + } + leaf ves-endpoint-certificate { + type string; description - "Groups information about the VES Collector."; + "The Certificate to be used to authenticate to the VES Collector."; + } } grouping rpc-status-g { - leaf status { - type enumeration { - enum SUCCESS { - description - "The RPC was successfully invoked."; - } - enum ERROR { - description - "An error was encountered when invoking the RPC."; - } - } - mandatory true; - description - "The status of the RPC."; + description + "RPC output grouping."; + leaf status { + type enumeration { + enum SUCCESS { + description + "The RPC was successfully invoked."; + } + enum ERROR { + description + "An error was encountered when invoking the RPC."; + } } + mandatory true; description - "RPC output grouping."; + "The status of the RPC."; + } } - -} //end module \ No newline at end of file +} diff --git a/ntsimulator/deploy/base/yang/nts-network-function.yang b/ntsimulator/deploy/base/yang/nts-network-function.yang index 65fee7b..626038d 100644 --- a/ntsimulator/deploy/base/yang/nts-network-function.yang +++ b/ntsimulator/deploy/base/yang/nts-network-function.yang @@ -6,39 +6,57 @@ module nts-network-function { import nts-common { prefix ntsc; } + import ietf-yang-types { + prefix yang; + } organization "O-RAN-SC"; contact " Web: - Editors: + Editors: Alex Stancu Adrian Lita Martin Skorupski "; description "This module contains YANG definitions for the Network Topology Simulator - Network Functions"; + revision 2021-03-26 { + description + "Added info container, and expanted feature control mechanism and status."; + reference + "O-RAN-SC SIM project"; + } + revision 2021-03-17 { + description + "Renamed datastore-random-populate RPC to datastore-populate"; + reference + "O-RAN-SC SIM project"; + } + revision 2020-12-11 { + description + "Added function-type to simulated function."; + reference + "O-RAN-SC SIM project"; + } revision 2020-11-30 { description "Cleared revision for nts-common import."; reference "O-RAN-SC SIM project"; } - revision 2020-10-28 { description "Add RPC for clearing the fault counters."; reference "O-RAN-SC SIM project"; } - revision 2020-10-13 { description "Add RPC for datastore populating and feature control."; reference "O-RAN-SC SIM project"; } - revision 2020-09-07 { description "Initial revision for the Network Topology Simulator - Next Generation"; @@ -46,33 +64,9 @@ module nts-network-function { "O-RAN-SC SIM project"; } - container simulation { - container network-function { - uses ntsc:mount-point-details-g; - uses ntsc:faults-g; - uses ntsc:netconf-config-g; - uses ntsc:ves-config-g; - description - "Container which encompasses the details of the network function."; - } - container sdn-controller { - uses ntsc:controller-g; - description - "Groups details about the SDN Controller."; - } - container ves-endpoint { - uses ntsc:ves-endpoint-g; - description - "Groups details about the VES Collector endpoint."; - } - description - "Root level container which controls the Network Function."; - } - - rpc datastore-random-populate { + rpc datastore-populate { description - "Operation to populate the datastore with random data for all the containing YANG models."; - + "Operation to populate the datastore with data for all the containing YANG models, based on settings in config.json"; output { uses ntsc:rpc-status-g; } @@ -82,11 +76,15 @@ module nts-network-function { description "Operation to control the features in a Network Function."; input { - leaf features { - type ntsc:feature-type; - mandatory true; - description - "A bit-wise list with features to be activated."; + leaf start-features { + type ntsc:feature-type; + description + "A bit-wise list with features to be activated."; + } + leaf stop-features { + type ntsc:feature-type; + description + "A bit-wise list with features to be deactivated."; } } output { @@ -99,25 +97,25 @@ module nts-network-function { "Operation to control the features in a Network Function."; input { leaf notification-format { - type enumeration { - enum xml { + type enumeration { + enum xml { description "The notification string is formatted as XML."; - } - enum json { + } + enum json { description "The notification string is formatted as JSON."; - } } - mandatory true; - description - "The format of the notification string."; + } + mandatory true; + description + "The format of the notification string."; } leaf notification-object { - type string; - mandatory true; - description - "A JSON string containing the notification object to be sent by the device."; + type string; + mandatory true; + description + "A JSON string containing the notification object to be sent by the device."; } } output { @@ -130,10 +128,10 @@ module nts-network-function { "Operation to generate a VES notification from a Network Function."; input { leaf file-location { - type string; - mandatory true; - description - "A string containing the location of the file on the server."; + type string; + mandatory true; + description + "A string containing the location of the file on the server."; } } output { @@ -144,10 +142,56 @@ module nts-network-function { rpc clear-fault-counters { description "Operation to clear the fault counters."; - output { uses ntsc:rpc-status-g; } } -} //end module \ No newline at end of file + container info { + config false; + description + "Information about NTS application and modules."; + leaf build-time { + type yang:date-and-time; + description + "Build time of NTS application."; + } + leaf version { + type string; + description + "NTS version of current network-function."; + } + leaf started-features { + type ntsc:feature-type; + description + "A bit-wise list with currently started features."; + } + } + container simulation { + description + "Root level container which controls the Network Function."; + container network-function { + description + "Container which encompasses the details of the network function."; + leaf function-type { + type string; + description + "Type of network function that is simulated."; + } + uses ntsc:mount-point-details-g; + uses ntsc:faults-g; + uses ntsc:netconf-config-g; + uses ntsc:ves-config-g; + } + container sdn-controller { + description + "Groups details about the SDN Controller."; + uses ntsc:controller-g; + } + container ves-endpoint { + description + "Groups details about the VES Collector endpoint."; + uses ntsc:ves-endpoint-g; + } + } +} diff --git a/ntsimulator/deploy/nts-manager/Dockerfile b/ntsimulator/deploy/nts-manager/Dockerfile new file mode 100644 index 0000000..11790fb --- /dev/null +++ b/ntsimulator/deploy/nts-manager/Dockerfile @@ -0,0 +1,38 @@ +# +# Copyright 2020 highstreet technologies GmbH and others +# +# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +# +# 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. + +################ +#### DEVICE #### +################ + +FROM nexus3.o-ran-sc.org:10004/o-ran-sc/nts-ng-base:latest +LABEL maintainer="alexandru.stancu@highstreet-technologies.com / adrian.lita@highstreet-technologies.com" + +# ntsim-ng configuration and deployment +COPY ./yang /opt/dev/deploy/yang +COPY ./config.json /opt/dev/ntsim-ng/config/config.json + +# ntsim-ng init docker +RUN /opt/dev/ntsim-ng/ntsim-ng --container-init -w /opt/dev/ntsim-ng + +# add exposed ports +EXPOSE 830-929 +EXPOSE 21-22 + +ENV NTS_FUNCTION_TYPE=NTS_FUNCTION_TYPE_MANAGER + +# run +WORKDIR /opt/dev/workspace +CMD ["/opt/dev/ntsim-ng/ntsim-ng", "-w/opt/dev/ntsim-ng", "--supervisor"] diff --git a/ntsimulator/deploy/nts-manager/config.json b/ntsimulator/deploy/nts-manager/config.json index aafc0d3..f71c4f9 100644 --- a/ntsimulator/deploy/nts-manager/config.json +++ b/ntsimulator/deploy/nts-manager/config.json @@ -1,26 +1,30 @@ { - "docker-rules": { + "container-rules": { "excluded-modules": [], "excluded-features": ["faults-status"] }, + + "supervisor-rules": { + "netopeer": { + "path": "/usr/local/bin/netopeer2-server", + "args": ["-d", "-v2"], + "autorestart": true, + "stdout": "log/netopeer-stdout.log", + "stderr": "log/netopeer-stderr.log" + }, - "populate-rules" : { - "excluded-modules": [ - "sysrepo", - "sysrepo-monitoring", - "ietf-yang-library", - "ietf-netconf-acm", - "ietf-netconf-monitoring", - "nc-notifications", - "ietf-keystore", - "ietf-truststore", - "ietf-system", - "ietf-netconf-server", - "nts-network-function", - "nts-manager" - ], - - "default-list-instances": 2, - "custom-list-instances" : [] + "sshd": { + "path": "/usr/sbin/sshd", + "args": ["-D"], + "autorestart": true, + "stdout": "log/sshd-stdout.log", + "stderr": "log/sshd-stderr.log" + }, + + "ntsim-manager": { + "path": "/opt/dev/ntsim-ng/ntsim-ng", + "args": ["-w/opt/dev/ntsim-ng", "-m"], + "nomanual": true + } } } \ No newline at end of file diff --git a/ntsimulator/deploy/nts-manager/container-tag.yaml b/ntsimulator/deploy/nts-manager/container-tag.yaml index e0c7ce8..ee93a5d 100644 --- a/ntsimulator/deploy/nts-manager/container-tag.yaml +++ b/ntsimulator/deploy/nts-manager/container-tag.yaml @@ -1,2 +1,2 @@ --- -tag: 1.0.6 \ No newline at end of file +tag: 1.2.0 \ No newline at end of file diff --git a/ntsimulator/deploy/nts-manager/local.Dockerfile b/ntsimulator/deploy/nts-manager/local.Dockerfile new file mode 100644 index 0000000..d07a799 --- /dev/null +++ b/ntsimulator/deploy/nts-manager/local.Dockerfile @@ -0,0 +1,38 @@ +# +# Copyright 2020 highstreet technologies GmbH and others +# +# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +# +# 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. + +################ +#### DEVICE #### +################ + +FROM o-ran-sc/nts-ng-base:latest +LABEL maintainer="alexandru.stancu@highstreet-technologies.com / adrian.lita@highstreet-technologies.com" + +# ntsim-ng configuration and deployment +COPY ./yang /opt/dev/deploy/yang +COPY ./config.json /opt/dev/ntsim-ng/config/config.json + +# ntsim-ng init docker +RUN /opt/dev/ntsim-ng/ntsim-ng --container-init -w /opt/dev/ntsim-ng + +# add exposed ports +EXPOSE 830-929 +EXPOSE 21-22 + +ENV NTS_FUNCTION_TYPE=NTS_FUNCTION_TYPE_MANAGER + +# run +WORKDIR /opt/dev/workspace +CMD ["/opt/dev/ntsim-ng/ntsim-ng", "-w/opt/dev/ntsim-ng", "--supervisor"] diff --git a/ntsimulator/deploy/nts-manager/supervisord.conf b/ntsimulator/deploy/nts-manager/supervisord.conf deleted file mode 100644 index 9e0ca99..0000000 --- a/ntsimulator/deploy/nts-manager/supervisord.conf +++ /dev/null @@ -1,22 +0,0 @@ -[supervisord] -nodaemon=true -logfile=/var/log/supervisord.log -loglevel=debug - -[program:netopeer2-server] -command=/usr/local/bin/netopeer2-server -d -autorestart=true -redirect_stderr=true -priority=2 - -[program:sshd] -command=/usr/sbin/sshd -D -autorestart=true -redirect_stderr=true -priority=3 - -[program:ntsim-ng] -command=/opt/dev/ntsim-ng/ntsim-ng -w /opt/dev/ntsim-ng -n -m -autorestart=false -redirect_stderr=true -priority=4 diff --git a/ntsimulator/deploy/nts-manager/yang/nts-manager.yang b/ntsimulator/deploy/nts-manager/yang/nts-manager.yang index 311a730..5f7bc14 100644 --- a/ntsimulator/deploy/nts-manager/yang/nts-manager.yang +++ b/ntsimulator/deploy/nts-manager/yang/nts-manager.yang @@ -6,7 +6,6 @@ module nts-manager { import ietf-inet-types { prefix inet; } - import nts-common { prefix ntsc; } @@ -15,20 +14,37 @@ module nts-manager { "O-RAN-SC"; contact " Web: - Editors: + Editors: Alex Stancu Adrian Lita Martin Skorupski "; description "This module contains YANG definitions for the Network Topology Simulator - Manager."; + revision 2021-03-26 { + description + "Added NTS_PROTOCOL_TYPE_BASE identities and changed instance/networking container; also added multi-base port support."; + reference + "O-RAN-SC SIM project"; + } + revision 2021-02-15 { + description + "Added notifications for sending feedback."; + reference + "O-RAN-SC SIM project"; + } + revision 2021-01-20 { + description + "Added available-network-functions."; + reference + "O-RAN-SC SIM project"; + } revision 2020-11-30 { description "Cleared revision for nts-common import."; reference "O-RAN-SC SIM project"; } - revision 2020-10-06 { description "Initial revision for the Network Topology Simulator - Next Generation"; @@ -36,6 +52,47 @@ module nts-manager { "O-RAN-SC SIM project"; } + identity NTS_PROTOCOL_TYPE_BASE { + description + "Base identity for protocol."; + } + + identity NTS_PROTOCOL_TYPE_NETCONF_SSH { + base NTS_PROTOCOL_TYPE_BASE; + description + "Identity for NETCONF SSH protocol."; + } + + identity NTS_PROTOCOL_TYPE_NETCONF_TLS { + base NTS_PROTOCOL_TYPE_BASE; + description + "Identity for NETCONF TLS protocol."; + } + + identity NTS_PROTOCOL_TYPE_FTP { + base NTS_PROTOCOL_TYPE_BASE; + description + "Identity for FTP protocol."; + } + + identity NTS_PROTOCOL_TYPE_SFTP { + base NTS_PROTOCOL_TYPE_BASE; + description + "Identity for SFTP protocol."; + } + + identity NTS_PROTOCOL_TYPE_HTTP { + base NTS_PROTOCOL_TYPE_BASE; + description + "Identity for HTTP protocol."; + } + + identity NTS_PROTOCOL_TYPE_HTTPS { + base NTS_PROTOCOL_TYPE_BASE; + description + "Identity for HTTPS protocol."; + } + typedef percent { type decimal64 { fraction-digits 2; @@ -46,163 +103,301 @@ module nts-manager { } grouping instance-g { - leaf name { - type string; + description + "An instance of a network function which is running. The equivalent on the host machine is a docker container."; + leaf name { + type string; + description + "The name of the running instance. It is the same as the docker container name which exposes this network function."; + } + leaf is-mounted { + type boolean; + description + "Whether the instance is mounted or not to a controller."; + } + container networking { + description + "Groups the details about networking information."; + leaf docker-ip { + type inet:ip-address; description - "The name of the running instance. It is the same as the docker container name which exposes this network function."; + "The IP address of the docker container implementing the network function instance."; } - container networking { - leaf docker-ip { - type inet:ip-address; - description - "The IP address of the docker container implementing the network function instance."; - } - leaf-list docker-port { - type inet:port-number; - description - "The ports which are exposed inside the docker container implementing the network function instance."; - } - leaf host-ip { - type inet:ip-address; - description - "The Host machine IP address pointing to the docker container implementing the network function instance."; - } - leaf-list host-port { - type inet:port-number; - description - "The Host machine ports mapped to the docker container implementing the network function instance."; - } + list docker-ports { + key "port"; + description + "The ports which are exposed inside the docker container implementing the network function instance."; + leaf port { + type inet:port-number; description - "Groups the details about networking information."; - } - description - "An instance of a network function which is running. The equivalent on the host machine is a docker container."; - } - grouping network-function-g { - leaf function-type { + "Port number."; + } + leaf protocol { type identityref { - base ntsc:NTS_FUNCTION_TYPE_BASE; + base NTS_PROTOCOL_TYPE_BASE; } - description "Type of network function to be simulated."; - } - leaf started-instances { - type uint16; - mandatory true; description - "How many instances of this type are started."; + "Protocol attached to current port."; + } } - leaf mounted-instances { - type uint16; - must '. <= ../started-instances' { - error-message - "The number of mounted instances cannot be greater that the number of started instances."; - } - mandatory true; - description - "How many instances of this type are mounted in the SDN Controller."; + leaf host-ip { + type inet:ip-address; + description + "The Host machine IP address pointing to the docker container implementing the network function instance."; } - - uses ntsc:mount-point-details-g; - - leaf docker-instance-name { - type string; - mandatory true; + list host-ports { + key "port"; + description + "The Host machine ports mapped to the docker container implementing the network function instance."; + leaf port { + type inet:port-number; description - "The prefix of each docker container being started."; - } - - leaf docker-version-tag { - type string; - mandatory true; + "Port number."; + } + leaf protocol { + type identityref { + base NTS_PROTOCOL_TYPE_BASE; + } description - "The version tag of the docker image to be started."; + "Protocol attached to current port."; + } } + } + } - leaf docker-repository { - type string; - mandatory true; - description - "The prefix containing the docker repository information, if needed."; - } - uses ntsc:faults-g; - uses ntsc:netconf-config-g; - uses ntsc:ves-config-g; - container instances { - config false; - list instance { - key "name"; - uses ntsc:mount-point-details-g; - uses instance-g; - description - "Describes a running instance."; - } - description - "Groups details about instances which are running."; + grouping network-function-g { + description + "Contains all the details of a simulated device."; + leaf function-type { + type identityref { + base ntsc:NTS_FUNCTION_TYPE_BASE; } description - "Contains all the details of a simulated device."; + "Type of network function to be simulated."; + } + leaf started-instances { + type uint16; + mandatory true; + description + "How many instances of this type are started."; + } + leaf mounted-instances { + type uint16; + must '. <= ../started-instances' { + error-message "The number of mounted instances cannot be greater that the number of started instances."; + } + mandatory true; + description + "How many instances of this type are mounted in the SDN Controller."; + } + uses ntsc:mount-point-details-g; + leaf docker-instance-name { + type string; + mandatory true; + description + "The prefix of each docker container being started."; + } + leaf docker-version-tag { + type string; + mandatory true; + description + "The version tag of the docker image to be started."; + } + leaf docker-repository { + type string; + mandatory true; + description + "The prefix containing the docker repository information, if needed."; + } + uses ntsc:faults-g; + uses ntsc:netconf-config-g; + uses ntsc:ves-config-g; + container instances { + config false; + description + "Groups details about instances which are running."; + list instance { + key "name"; + description + "Describes a running instance."; + uses ntsc:mount-point-details-g; + uses instance-g; + } + } } + grouping simulation-information-g { - leaf base-port { - type inet:port-number; - config false; - description - "The base Host machine port from where the simulation can allocate ports incrementally."; - } - leaf ssh-connections { - type uint8; - config false; - description - "The number of SSH Endpoints each network function instance exposes."; + description + "Groups information about the simulation status."; + container ports { + config false; + description + "Contains information on ports used."; + leaf netconf-ssh-port { + type inet:port-number; + description + "The base Host machine port from where the simulation can allocate ports incrementally for NETCONF SSH protocol."; } - leaf tls-connections { - type uint8; - config false; - description - "The number of TLS Endpoints each network function instance exposes."; + leaf netconf-tls-port { + type inet:port-number; + description + "The base Host machine port from where the simulation can allocate ports incrementally for NETCONF TLS protocol."; } - leaf cpu-usage { - type percent; - config false; + leaf transport-ftp-port { + type inet:port-number; description - "Specifies the CPU load generated by the simulation."; + "The base Host machine port from where the simulation can allocate ports incrementally for FTP protocol."; } - leaf mem-usage { - type uint32; - config false; + leaf transport-sftp-port { + type inet:port-number; description - "Specifies the RAM in MB used by the simulation."; + "The base Host machine port from where the simulation can allocate ports incrementally for SFTP protocol."; } + } + leaf ssh-connections { + type uint8; + config false; + description + "The number of SSH Endpoints each network function instance exposes."; + } + leaf tls-connections { + type uint8; + config false; + description + "The number of TLS Endpoints each network function instance exposes."; + } + leaf cpu-usage { + type percent; + config false; + description + "Specifies the CPU load generated by the simulation."; + } + leaf mem-usage { + type uint32; + config false; + description + "Specifies the RAM in MB used by the simulation."; + } + leaf last-operation-status { + type string; + config false; description - "Groups information about the simulation status."; + "Specifies the status of the most recent operation performed by the Manager."; + } } - container simulation { - container network-functions { - list network-function { - key "function-type"; - unique "docker-instance-name"; - uses network-function-g; - description - "List containing different simulated network function types and their details."; - } - description - "Container which encompasses all simulated network functions."; - } - container sdn-controller { - uses ntsc:controller-g; - description - "Groups details about the SDN Controller."; + grouping network-function-image-g { + description + "Groups details about a NF docker image."; + leaf function-type { + type identityref { + base ntsc:NTS_FUNCTION_TYPE_BASE; } - container ves-endpoint { - uses ntsc:ves-endpoint-g; - description - "Groups details about the VES Collector endpoint."; + config false; + description + "Type of network function to be simulated."; + } + leaf docker-image-name { + type string; + config false; + mandatory true; + description + "The prefix of each docker container being started."; + } + leaf docker-version-tag { + type string; + config false; + mandatory true; + description + "The version tag of the docker image to be started."; + } + leaf docker-repository { + type string; + config false; + mandatory true; + description + "The prefix containing the docker repository information, if needed."; + } + } + + notification instance-changed { + description + "Sent by the Manager every time something occurs in any of the simulated NF instances."; + leaf change-status { + type string; + mandatory true; + description + "The status of the change which was executed to the NF instance."; + } + leaf function-type { + type identityref { + base ntsc:NTS_FUNCTION_TYPE_BASE; } - uses simulation-information-g; + mandatory true; description - "Root level container which controls the NTS."; + "Type of the NF instance."; + } + uses instance-g { + refine "name" { + mandatory true; + } + } } + notification operation-status-changed { + description + "Sent by the Manager every time a user operation is finished."; + leaf operation-status { + type string; + mandatory true; + description + "The status of the operation which was executed by the Manager."; + } + leaf error-message { + type string; + description + "Detailed error message from the Manager."; + } + } -} //end module \ No newline at end of file + container simulation { + presence "Enables simulation configuration."; + description + "Root level container which controls the NTS."; + container available-images { + config false; + description + "Container which encompasses all NF docker images available on the host machine."; + list network-function-image { + description + "List containing available network function docker images and their respective details."; + uses network-function-image-g; + } + } + container network-functions { + presence "Enables NF configuration."; + description + "Container which encompasses all simulated network functions."; + list network-function { + key "function-type"; + unique "docker-instance-name"; + description + "List containing different simulated network function types and their details."; + uses network-function-g; + } + } + container sdn-controller { + presence "Enables SDN Controller detail configuration."; + description + "Groups details about the SDN Controller."; + uses ntsc:controller-g; + } + container ves-endpoint { + presence "Enables VES endpoint detail configuration."; + description + "Groups details about the VES Collector endpoint."; + uses ntsc:ves-endpoint-g; + } + uses simulation-information-g; + } +} diff --git a/ntsimulator/deploy/o-ran-du/Dockerfile b/ntsimulator/deploy/o-ran-du/Dockerfile new file mode 100644 index 0000000..bdb4cd8 --- /dev/null +++ b/ntsimulator/deploy/o-ran-du/Dockerfile @@ -0,0 +1,39 @@ +# +# Copyright 2020 highstreet technologies GmbH and others +# +# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +# +# 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. + +################ +#### DEVICE #### +################ + +FROM nexus3.o-ran-sc.org:10004/o-ran-sc/nts-ng-base:latest +LABEL maintainer="alexandru.stancu@highstreet-technologies.com / adrian.lita@highstreet-technologies.com" + +# ntsim-ng configuration and deployment +COPY ./yang /opt/dev/deploy/yang +COPY ./data /opt/dev/deploy/data +COPY ./config.json /opt/dev/ntsim-ng/config/config.json + +# ntsim-ng init docker +RUN /opt/dev/ntsim-ng/ntsim-ng --container-init -w /opt/dev/ntsim-ng + +# add exposed ports +EXPOSE 830-929 +EXPOSE 21-22 + +ENV NTS_FUNCTION_TYPE=NTS_FUNCTION_TYPE_O_RAN_O_DU + +# run +WORKDIR /opt/dev/workspace +CMD ["/opt/dev/ntsim-ng/ntsim-ng", "-w/opt/dev/ntsim-ng", "--supervisor"] diff --git a/ntsimulator/deploy/o-ran-du/config.json b/ntsimulator/deploy/o-ran-du/config.json new file mode 100644 index 0000000..3696617 --- /dev/null +++ b/ntsimulator/deploy/o-ran-du/config.json @@ -0,0 +1,144 @@ +{ + "container-rules": { + "excluded-modules": [], + "excluded-features": [] + }, + + "supervisor-rules": { + "netopeer": { + "path": "/usr/local/bin/netopeer2-server", + "args": ["-d", "-v2"], + "autorestart": true, + "stdout": "log/netopeer-stdout.log", + "stderr": "log/netopeer-stderr.log" + }, + + "sshd": { + "path": "/usr/sbin/sshd", + "args": ["-D"], + "autorestart": true, + "stdout": "log/sshd-stdout.log", + "stderr": "log/sshd-stderr.log" + }, + + "ntsim-network-function": { + "path": "/opt/dev/ntsim-ng/ntsim-ng", + "args": ["-w/opt/dev/ntsim-ng", "-f"], + "nomanual": true + } + }, + + "datastore-random-generation-rules" : { + "excluded-modules": [ + "sysrepo", + "sysrepo-monitoring", + "ietf-yang-library", + "ietf-netconf-acm", + "ietf-netconf-monitoring", + "nc-notifications", + "ietf-keystore", + "ietf-truststore", + "ietf-system", + "ietf-netconf-server", + "nts-network-function" + ], + + "default-list-instances": 2, + "custom-list-instances" : [] + }, + + "datastore-populate-rules": { + "random-generation-enabled": true, + + "pre-generated-operational-data": [ + "../deploy/data/o-ran-sc-du-hello-world-operational.xml" + ], + "pre-generated-running-data": [ + "../deploy/data/o-ran-sc-du-hello-world-running.xml" + ] + }, + + "fault-rules" : { + "yang-notif-template" : "$$uint16_counter$$%%object%%%%affected-object%%%%fault-severity%%%%cleared%%%%text%%%%date-time%%", + "choosing-method" : "linear", + "faults" : [ + { + "condition" : "CPRI Port Down", + "object" : "Slot-0-Port-A", + "severity" : "MAJOR", + "date-time" : "$$time$$", + "specific-problem" : "CPRI Port Down", + + "fault-severity" : "MAJOR", + "affected-object" : "%%object%%", + "cleared" : "false", + "text" : "CPRI Port Down" + }, + + { + "condition" : "CPRI Port Down", + "object" : "Slot-0-Port-A", + "severity" : "NORMAL", + "date-time" : "$$time$$", + "specific-problem" : "CPRI Port Down", + + "fault-severity" : "MAJOR", + "affected-object" : "%%object%%", + "cleared" : "true", + "text" : "CPRI Port Down" + }, + + { + "condition" : "CPRI Port Down", + "object" : "Slot-0-Port-C", + "severity" : "MAJOR", + "date-time" : "$$time$$", + "specific-problem" : "CPRI Port Down", + + "fault-severity" : "MAJOR", + "affected-object" : "%%object%%", + "cleared" : "false", + "text" : "CPRI Port Down" + }, + + { + "condition" : "CPRI Port Down", + "object" : "Slot-0-Port-C", + "severity" : "NORMAL", + "date-time" : "$$time$$", + "specific-problem" : "CPRI Port Down", + + "fault-severity" : "MAJOR", + "affected-object" : "%%object%%", + "cleared" : "true", + "text" : "CPRI Port Down" + }, + + { + "condition" : "CPRI Port Down", + "object" : "Slot-2-Port-B", + "severity" : "MAJOR", + "date-time" : "$$time$$", + "specific-problem" : "CPRI Port Down", + + "fault-severity" : "MAJOR", + "affected-object" : "%%object%%", + "cleared" : "false", + "text" : "CPRI Port Down" + }, + + { + "condition" : "CPRI Port Down", + "object" : "Slot-2-Port-B", + "severity" : "NORMAL", + "date-time" : "$$time$$", + "specific-problem" : "CPRI Port Down", + + "fault-severity" : "MAJOR", + "affected-object" : "%%object%%", + "cleared" : "true", + "text" : "CPRI Port Down" + } + ] + } +} \ No newline at end of file diff --git a/ntsimulator/deploy/o-ran-du/container-tag.yaml b/ntsimulator/deploy/o-ran-du/container-tag.yaml new file mode 100644 index 0000000..ee93a5d --- /dev/null +++ b/ntsimulator/deploy/o-ran-du/container-tag.yaml @@ -0,0 +1,2 @@ +--- +tag: 1.2.0 \ No newline at end of file diff --git a/ntsimulator/deploy/o-ran-du/data/README.md b/ntsimulator/deploy/o-ran-du/data/README.md new file mode 100644 index 0000000..7b501f4 --- /dev/null +++ b/ntsimulator/deploy/o-ran-du/data/README.md @@ -0,0 +1,2 @@ +This folder should contain XML/JSON data for pre-populating running/operational. +Data files by themselves are not taken into account until added to config.json diff --git a/ntsimulator/deploy/o-ran-du/data/o-ran-sc-du-hello-world-operational.xml b/ntsimulator/deploy/o-ran-du/data/o-ran-sc-du-hello-world-operational.xml new file mode 100644 index 0000000..e832268 --- /dev/null +++ b/ntsimulator/deploy/o-ran-du/data/o-ran-sc-du-hello-world-operational.xml @@ -0,0 +1,14 @@ + + + O-RU-1 + connected + + + O-RU-2 + disconnected + + + O-RU-3 + unable-to-connect + + \ No newline at end of file diff --git a/ntsimulator/deploy/o-ran-du/data/o-ran-sc-du-hello-world-running.xml b/ntsimulator/deploy/o-ran-du/data/o-ran-sc-du-hello-world-running.xml new file mode 100644 index 0000000..756ba3b --- /dev/null +++ b/ntsimulator/deploy/o-ran-du/data/o-ran-sc-du-hello-world-running.xml @@ -0,0 +1,11 @@ + + + O-RU-1 + + + O-RU-2 + + + O-RU-3 + + \ No newline at end of file diff --git a/ntsimulator/deploy/x-ran/ubuntu.Dockerfile b/ntsimulator/deploy/o-ran-du/local.Dockerfile similarity index 80% rename from ntsimulator/deploy/x-ran/ubuntu.Dockerfile rename to ntsimulator/deploy/o-ran-du/local.Dockerfile index f5cdd80..ae00eb7 100644 --- a/ntsimulator/deploy/x-ran/ubuntu.Dockerfile +++ b/ntsimulator/deploy/o-ran-du/local.Dockerfile @@ -17,18 +17,16 @@ #### DEVICE #### ################ -FROM nexus3.o-ran-sc.org:10004/o-ran-sc/nts-ng-base:latest +FROM o-ran-sc/nts-ng-base:latest LABEL maintainer="alexandru.stancu@highstreet-technologies.com / adrian.lita@highstreet-technologies.com" # ntsim-ng configuration and deployment COPY ./yang /opt/dev/deploy/yang +COPY ./data /opt/dev/deploy/data COPY ./config.json /opt/dev/ntsim-ng/config/config.json # ntsim-ng init docker -RUN /opt/dev/ntsim-ng/ntsim-ng --docker-init -w /opt/dev/ntsim-ng - -# supervisor configuration -COPY ./supervisord.conf /etc/supervisord.conf +RUN /opt/dev/ntsim-ng/ntsim-ng --container-init -w /opt/dev/ntsim-ng # finishing container build ARG BUILD_DATE @@ -38,6 +36,8 @@ LABEL build-date=$BUILD_DATE EXPOSE 830-929 EXPOSE 21-22 +ENV NTS_FUNCTION_TYPE=NTS_FUNCTION_TYPE_O_RAN_O_DU + # run WORKDIR /opt/dev/workspace -CMD ["sh", "-c", "/usr/bin/supervisord -c /etc/supervisord.conf"] +CMD ["/opt/dev/ntsim-ng/ntsim-ng", "-w/opt/dev/ntsim-ng", "--supervisor"] diff --git a/ntsimulator/deploy/o-ran-du/yang/ietf-system.yang b/ntsimulator/deploy/o-ran-du/yang/ietf-system.yang new file mode 100644 index 0000000..141ddba --- /dev/null +++ b/ntsimulator/deploy/o-ran-du/yang/ietf-system.yang @@ -0,0 +1,802 @@ +module ietf-system { + namespace "urn:ietf:params:xml:ns:yang:ietf-system"; + prefix "sys"; + + import ietf-yang-types { + prefix yang; + } + + import ietf-inet-types { + prefix inet; + } + + import ietf-netconf-acm { + prefix nacm; + } + + import iana-crypt-hash { + prefix ianach; + } + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + WG Chair: Thomas Nadeau + + + WG Chair: Juergen Schoenwaelder + + + Editor: Andy Bierman + + + Editor: Martin Bjorklund + "; + + description + "This module contains a collection of YANG definitions for the + configuration and identification of some common system + properties within a device containing a NETCONF server. This + includes data node definitions for system identification, + time-of-day management, user management, DNS resolver + configuration, and some protocol operations for system + management. + + Copyright (c) 2014 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 + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 7317; see + the RFC itself for full legal notices."; + + revision 2014-08-06 { + description + "Initial revision."; + reference + "RFC 7317: A YANG Data Model for System Management"; + } + + /* + * Typedefs + */ + + typedef timezone-name { + type string; + description + "A time zone name as used by the Time Zone Database, + sometimes referred to as the 'Olson Database'. + + The exact set of valid values is an implementation-specific + matter. Client discovery of the exact set of time zone names + for a particular server is out of scope."; + reference + "RFC 6557: Procedures for Maintaining the Time Zone Database"; + } + + /* + * Features + */ + + feature radius { + description + "Indicates that the device can be configured as a RADIUS + client."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS)"; + } + + feature authentication { + description + "Indicates that the device supports configuration of + user authentication."; + } + + feature local-users { + if-feature authentication; + description + "Indicates that the device supports configuration of + local user authentication."; + } + + feature radius-authentication { + if-feature radius; + if-feature authentication; + description + "Indicates that the device supports configuration of user + authentication over RADIUS."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS) + RFC 5607: Remote Authentication Dial-In User Service (RADIUS) + Authorization for Network Access Server (NAS) + Management"; + } + + feature ntp { + description + "Indicates that the device can be configured to use one or + more NTP servers to set the system date and time."; + } + + feature ntp-udp-port { + if-feature ntp; + description + "Indicates that the device supports the configuration of + the UDP port for NTP servers. + + This is a 'feature', since many implementations do not support + any port other than the default port."; + } + + feature timezone-name { + description + "Indicates that the local time zone on the device + can be configured to use the TZ database + to set the time zone and manage daylight saving time."; + reference + "RFC 6557: Procedures for Maintaining the Time Zone Database"; + } + + feature dns-udp-tcp-port { + description + "Indicates that the device supports the configuration of + the UDP and TCP port for DNS servers. + + This is a 'feature', since many implementations do not support + any port other than the default port."; + } + + + /* + * Identities + */ + + identity authentication-method { + description + "Base identity for user authentication methods."; + } + + identity radius { + base authentication-method; + description + "Indicates user authentication using RADIUS."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS) + RFC 5607: Remote Authentication Dial-In User Service (RADIUS) + Authorization for Network Access Server (NAS) + Management"; + } + + identity local-users { + base authentication-method; + description + "Indicates password-based authentication of locally + configured users."; + } + + identity radius-authentication-type { + description + "Base identity for RADIUS authentication types."; + } + + identity radius-pap { + base radius-authentication-type; + description + "The device requests Password Authentication Protocol (PAP) + authentication from the RADIUS server."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS)"; + } + + identity radius-chap { + base radius-authentication-type; + description + "The device requests Challenge Handshake Authentication + Protocol (CHAP) authentication from the RADIUS server."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS)"; + } + + /* + * Configuration data nodes + */ + + container system { + description + "System group configuration."; + + leaf contact { + type string; + description + "The administrator contact information for the system. + + A server implementation MAY map this leaf to the sysContact + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and sysContact. The definition of + such a mechanism is outside the scope of this document."; + reference + "RFC 3418: Management Information Base (MIB) for the + Simple Network Management Protocol (SNMP) + SNMPv2-MIB.sysContact"; + } + leaf hostname { + type inet:domain-name; + description + "The name of the host. This name can be a single domain + label or the fully qualified domain name of the host."; + } + leaf location { + type string; + description + "The system location. + + A server implementation MAY map this leaf to the sysLocation + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and sysLocation. The definition + of such a mechanism is outside the scope of this document."; + reference + "RFC 3418: Management Information Base (MIB) for the + Simple Network Management Protocol (SNMP) + SNMPv2-MIB.sysLocation"; + } + + container clock { + description + "Configuration of the system date and time properties."; + + choice timezone { + description + "The system time zone information."; + + case timezone-name { + if-feature timezone-name; + leaf timezone-name { + type timezone-name; + description + "The TZ database name to use for the system, such + as 'Europe/Stockholm'."; + } + } + case timezone-utc-offset { + leaf timezone-utc-offset { + type int16 { + range "-1500 .. 1500"; + } + units "minutes"; + description + "The number of minutes to add to UTC time to + identify the time zone for this system. For example, + 'UTC - 8:00 hours' would be represented as '-480'. + Note that automatic daylight saving time adjustment + is not provided if this object is used."; + } + } + } + } + + container ntp { + if-feature ntp; + presence + "Enables the NTP client unless the 'enabled' leaf + (which defaults to 'true') is set to 'false'"; + description + "Configuration of the NTP client."; + + leaf enabled { + type boolean; + default true; + description + "Indicates that the system should attempt to + synchronize the system clock with an NTP server + from the 'ntp/server' list."; + } + list server { + key name; + description + "List of NTP servers to use for system clock + synchronization. If '/system/ntp/enabled' + is 'true', then the system will attempt to + contact and utilize the specified NTP servers."; + + leaf name { + type string; + description + "An arbitrary name for the NTP server."; + } + choice transport { + mandatory true; + description + "The transport-protocol-specific parameters for this + server."; + + case udp { + container udp { + description + "Contains UDP-specific configuration parameters + for NTP."; + leaf address { + type inet:host; + mandatory true; + description + "The address of the NTP server."; + } + leaf port { + if-feature ntp-udp-port; + type inet:port-number; + default 123; + description + "The port number of the NTP server."; + } + } + } + } + leaf association-type { + type enumeration { + enum server { + description + "Use client association mode. This device + will not provide synchronization to the + configured NTP server."; + } + enum peer { + description + "Use symmetric active association mode. + This device may provide synchronization + to the configured NTP server."; + } + enum pool { + description + "Use client association mode with one or + more of the NTP servers found by DNS + resolution of the domain name given by + the 'address' leaf. This device will not + provide synchronization to the servers."; + } + } + default server; + description + "The desired association type for this NTP server."; + } + leaf iburst { + type boolean; + default false; + description + "Indicates whether this server should enable burst + synchronization or not."; + } + leaf prefer { + type boolean; + default false; + description + "Indicates whether this server should be preferred + or not."; + } + } + } + + container dns-resolver { + description + "Configuration of the DNS resolver."; + + leaf-list search { + type inet:domain-name; + ordered-by user; + description + "An ordered list of domains to search when resolving + a host name."; + } + list server { + key name; + ordered-by user; + description + "List of the DNS servers that the resolver should query. + + When the resolver is invoked by a calling application, it + sends the query to the first name server in this list. If + no response has been received within 'timeout' seconds, + the resolver continues with the next server in the list. + If no response is received from any server, the resolver + continues with the first server again. When the resolver + has traversed the list 'attempts' times without receiving + any response, it gives up and returns an error to the + calling application. + + Implementations MAY limit the number of entries in this + list."; + + leaf name { + type string; + description + "An arbitrary name for the DNS server."; + } + choice transport { + mandatory true; + description + "The transport-protocol-specific parameters for this + server."; + + case udp-and-tcp { + container udp-and-tcp { + description + "Contains UDP- and TCP-specific configuration + parameters for DNS."; + reference + "RFC 1035: Domain Names - Implementation and + Specification + RFC 5966: DNS Transport over TCP - Implementation + Requirements"; + + leaf address { + type inet:ip-address; + mandatory true; + description + "The address of the DNS server."; + } + leaf port { + if-feature dns-udp-tcp-port; + type inet:port-number; + default 53; + description + "The UDP and TCP port number of the DNS server."; + } + } + } + } + } + container options { + description + "Resolver options. The set of available options has been + limited to those that are generally available across + different resolver implementations and generally useful."; + leaf timeout { + type uint8 { + range "1..max"; + } + units "seconds"; + default "5"; + description + "The amount of time the resolver will wait for a + response from each remote name server before + retrying the query via a different name server."; + } + leaf attempts { + type uint8 { + range "1..max"; + } + default "2"; + description + "The number of times the resolver will send a query to + all of its name servers before giving up and returning + an error to the calling application."; + } + } + } + + container radius { + if-feature radius; + + description + "Configuration of the RADIUS client."; + + list server { + key name; + ordered-by user; + description + "List of RADIUS servers used by the device. + + When the RADIUS client is invoked by a calling + application, it sends the query to the first server in + this list. If no response has been received within + 'timeout' seconds, the client continues with the next + server in the list. If no response is received from any + server, the client continues with the first server again. + When the client has traversed the list 'attempts' times + without receiving any response, it gives up and returns an + error to the calling application."; + + leaf name { + type string; + description + "An arbitrary name for the RADIUS server."; + } + choice transport { + mandatory true; + description + "The transport-protocol-specific parameters for this + server."; + + case udp { + container udp { + description + "Contains UDP-specific configuration parameters + for RADIUS."; + leaf address { + type inet:host; + mandatory true; + description + "The address of the RADIUS server."; + } + + leaf authentication-port { + type inet:port-number; + default "1812"; + description + "The port number of the RADIUS server."; + } + leaf shared-secret { + type string; + mandatory true; + nacm:default-deny-all; + description + "The shared secret, which is known to both the + RADIUS client and server."; + reference + "RFC 2865: Remote Authentication Dial In User + Service (RADIUS)"; + } + } + } + } + leaf authentication-type { + type identityref { + base radius-authentication-type; + } + default radius-pap; + description + "The authentication type requested from the RADIUS + server."; + } + } + container options { + description + "RADIUS client options."; + + leaf timeout { + type uint8 { + range "1..max"; + } + units "seconds"; + default "5"; + description + "The number of seconds the device will wait for a + response from each RADIUS server before trying with a + different server."; + } + + leaf attempts { + type uint8 { + range "1..max"; + } + default "2"; + description + "The number of times the device will send a query to + all of its RADIUS servers before giving up."; + } + } + } + + container authentication { + nacm:default-deny-write; + if-feature authentication; + + description + "The authentication configuration subtree."; + + leaf-list user-authentication-order { + type identityref { + base authentication-method; + } + must '(. != "sys:radius" or ../../radius/server)' { + error-message + "When 'radius' is used, a RADIUS server" + + " must be configured."; + description + "When 'radius' is used as an authentication method, + a RADIUS server must be configured."; + } + ordered-by user; + + description + "When the device authenticates a user with a password, + it tries the authentication methods in this leaf-list in + order. If authentication with one method fails, the next + method is used. If no method succeeds, the user is + denied access. + + An empty user-authentication-order leaf-list still allows + authentication of users using mechanisms that do not + involve a password. + + If the 'radius-authentication' feature is advertised by + the NETCONF server, the 'radius' identity can be added to + this list. + + If the 'local-users' feature is advertised by the + NETCONF server, the 'local-users' identity can be + added to this list."; + } + + list user { + if-feature local-users; + key name; + description + "The list of local users configured on this device."; + + leaf name { + type string; + description + "The user name string identifying this entry."; + } + leaf password { + type ianach:crypt-hash; + description + "The password for this entry."; + } + list authorized-key { + key name; + description + "A list of public SSH keys for this user. These keys + are allowed for SSH authentication, as described in + RFC 4253."; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer + Protocol"; + + leaf name { + type string; + description + "An arbitrary name for the SSH key."; + } + + leaf algorithm { + type string; + mandatory true; + description + "The public key algorithm name for this SSH key. + + Valid values are the values in the IANA 'Secure Shell + (SSH) Protocol Parameters' registry, Public Key + Algorithm Names."; + reference + "IANA 'Secure Shell (SSH) Protocol Parameters' + registry, Public Key Algorithm Names"; + } + leaf key-data { + type binary; + mandatory true; + description + "The binary public key data for this SSH key, as + specified by RFC 4253, Section 6.6, i.e.: + + string certificate or public key format + identifier + byte[n] key/certificate data."; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer + Protocol"; + } + } + } + } + } + + /* + * Operational state data nodes + */ + + container system-state { + config false; + description + "System group operational state."; + + container platform { + description + "Contains vendor-specific information for + identifying the system platform and operating system."; + reference + "IEEE Std 1003.1-2008 - sys/utsname.h"; + + leaf os-name { + type string; + description + "The name of the operating system in use - + for example, 'Linux'."; + reference + "IEEE Std 1003.1-2008 - utsname.sysname"; + } + leaf os-release { + type string; + description + "The current release level of the operating + system in use. This string MAY indicate + the OS source code revision."; + reference + "IEEE Std 1003.1-2008 - utsname.release"; + } + leaf os-version { + type string; + description + "The current version level of the operating + system in use. This string MAY indicate + the specific OS build date and target variant + information."; + reference + "IEEE Std 1003.1-2008 - utsname.version"; + } + leaf machine { + type string; + description + "A vendor-specific identifier string representing + the hardware in use."; + reference + "IEEE Std 1003.1-2008 - utsname.machine"; + } + } + + container clock { + description + "Monitoring of the system date and time properties."; + + leaf current-datetime { + type yang:date-and-time; + description + "The current system date and time."; + } + + + leaf boot-datetime { + type yang:date-and-time; + description + "The system date and time when the system last restarted."; + } + } + } + + rpc set-current-datetime { + nacm:default-deny-all; + description + "Set the /system-state/clock/current-datetime leaf + to the specified value. + + If the system is using NTP (i.e., /system/ntp/enabled + is set to 'true'), then this operation will fail with + error-tag 'operation-failed' and error-app-tag value of + 'ntp-active'."; + input { + leaf current-datetime { + type yang:date-and-time; + mandatory true; + description + "The current system date and time."; + } + } + } + + rpc system-restart { + nacm:default-deny-all; + description + "Request that the entire system be restarted immediately. + A server SHOULD send an rpc reply to the client before + restarting the system."; + } + + rpc system-shutdown { + nacm:default-deny-all; + description + "Request that the entire system be shut down immediately. + A server SHOULD send an rpc reply to the client before + shutting down the system."; + } + +} diff --git a/ntsimulator/deploy/o-ran-du/yang/o-ran-sc-du-hello-world.yang b/ntsimulator/deploy/o-ran-du/yang/o-ran-sc-du-hello-world.yang new file mode 100644 index 0000000..77115f5 --- /dev/null +++ b/ntsimulator/deploy/o-ran-du/yang/o-ran-sc-du-hello-world.yang @@ -0,0 +1,200 @@ +module o-ran-sc-du-hello-world { + yang-version 1.1; + namespace "urn:o-ran-sc:yang:o-ran-sc-du-hello-world"; + prefix duhw; + + organization + "O-RAN Software Community"; + contact + "www.o-ran-sc.org"; + description + "This module contains the O-RAN Software Community Distributed Unit + API description. This schema was created to support the + O-RAN-SC D-Release RSAC use case. + This standalone model is the absolute minimum and therefore + called 'hello-world'. + + Copyright 2021 the O-RAN Software Community. + + Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + + 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."; + + revision 2021-03-06 { + description + "initial revision"; + reference + "https://wiki.o-ran-sc.org/pages/viewpage.action?pageId=20878423"; + } + + // TypeDefinitions + + typedef connection-status { + type enumeration { + enum disconnected { + value 0; + description + "The connection to the remote network function is not established."; + } + enum connecting { + value 1; + description + "The system is about to connect to the remote network function."; + } + enum connected { + value 2; + description + "The system is connected to the remote network function."; + } + enum disconnecting { + value 3; + description + "The system is about to disconnect from the remote network + function."; + } + enum unable-to-connect { + value 4; + description + "This value is reported, when the system tried several times + to connect and finally gave up."; + } + } + description + "A non extensible enumeration representing a connection status."; + } + + typedef o-ru-reference { + type leafref { + path "/network-function/du-to-ru-connection/name"; + } + description + "A reference to a remote network function representing an O-RU."; + } + + // Abstract object classes - groupings + + grouping connection-grp { + description + "An abstract object class representing a connection or link to an + external component."; + leaf name { + type string; + description + "It is proposed to use the network unique identifier of the remote + network function. + Note: After discussion the string was not restricted by a 'length' + statement of a 'pattern' statement. Please avoid leading and ending + spaces and consecutive spaces and any character outside of UTF-8-"; + } + leaf status { + type connection-status; + default "disconnected"; + config false; + description + "The value represents the connection status. "; + } + } + + grouping network-function-grp { + description + "An abstract object class grouping the O-RAN-SC-DU parameters with + focus on RSAC D-release Closed-Loop use case."; + list du-to-ru-connection { + key "name"; + description + "A list of connection objects to O-RAN-SC radio units."; + uses connection-grp; + } + } + + grouping rpc-output { + description + "A generic RPC output syntax."; + leaf response-status { + type enumeration { + enum ok { + value 200; + description + "The system has successfully performed that request."; + } + enum accepted { + value 202; + description + "The system has received and accepted the request. It continues + processing the request. The final status of the processing + procedures are reported by a notification service. This response + status is typically for long running transactions."; + } + enum internal-server-error { + value 500; + description + "The request cannot be performed."; + } + } + mandatory true; + description + "The response status related to the corresponding request. + Its values are inspired by HTTP response status codes."; + reference + "RFC 7231 – Response Status Codes - Section 6.3.4"; + } + leaf message { + type string; + description + "A human readable text complementary to the response status. "; + } + } + + // Data nodes + + container network-function { + description + "The root container for the configuration and operational data. + The object implements the 'network-function-grp'"; + uses network-function-grp; + } + + // Remote procedure calls - actions on root level + + rpc connect { + description + "An action to establish the connection to a remote network function."; + input { + leaf remote-network-function { + type o-ru-reference; + mandatory true; + description + "An reference to a remote network function - an O-RU - to which + a connection should be established."; + } + } + output { + uses rpc-output; + } + } + + rpc disconnect { + description + "An action to destroy the connection to a remote network function."; + input { + leaf remote-network-function { + type o-ru-reference; + mandatory true; + description + "An reference to a remote network function - an O-RU - to which + the connection should be destroyed."; + } + } + output { + uses rpc-output; + } + } +} diff --git a/ntsimulator/deploy/o-ran-du/yang/onap-system.yang b/ntsimulator/deploy/o-ran-du/yang/onap-system.yang new file mode 100644 index 0000000..3e19429 --- /dev/null +++ b/ntsimulator/deploy/o-ran-du/yang/onap-system.yang @@ -0,0 +1,59 @@ +module onap-system { + yang-version 1.1; + namespace "urn:onap:system"; + prefix os; + + import ietf-inet-types { + prefix inet; + } + import ietf-system { + prefix sys; + } + + organization + "ONAP - Open Network Automation Platform"; + contact + "Web: + Editors: + Alex Stancu + Adrian Lita + Martin Skorupski "; + description + "This module augments ietf-system with ONAP details. + + Copyright 2020 the O-RAN Alliance. + + Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + + 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."; + + revision 2020-10-26 { + description + "Initial revision for the ietf-system augmentation for ONAP."; + reference + "https://jira.onap.org/browse/SDNC-1396"; + } + + augment "/sys:system" { + leaf name { + type string; + description + "The name of the system."; + } + leaf web-ui { + type inet:uri; + description + "The URI of the system Web UI."; + } + description + "Enhancing the system information."; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/Dockerfile b/ntsimulator/deploy/o-ran-ru-fh/Dockerfile new file mode 100644 index 0000000..7a2b56a --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/Dockerfile @@ -0,0 +1,39 @@ +# +# Copyright 2020 highstreet technologies GmbH and others +# +# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +# +# 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. + +################ +#### DEVICE #### +################ + +FROM nexus3.o-ran-sc.org:10004/o-ran-sc/nts-ng-base:latest +LABEL maintainer="alexandru.stancu@highstreet-technologies.com / adrian.lita@highstreet-technologies.com" + +# ntsim-ng configuration and deployment +COPY ./yang /opt/dev/deploy/yang +COPY ./data /opt/dev/deploy/data +COPY ./config.json /opt/dev/ntsim-ng/config/config.json + +# ntsim-ng init docker +RUN /opt/dev/ntsim-ng/ntsim-ng --container-init -w /opt/dev/ntsim-ng + +# add exposed ports +EXPOSE 830-929 +EXPOSE 21-22 + +ENV NTS_FUNCTION_TYPE=NTS_FUNCTION_TYPE_O_RAN_O_RU_FH + +# run +WORKDIR /opt/dev/workspace +CMD ["/opt/dev/ntsim-ng/ntsim-ng", "-w/opt/dev/ntsim-ng", "--supervisor"] diff --git a/ntsimulator/deploy/o-ran-ru-fh/config.json b/ntsimulator/deploy/o-ran-ru-fh/config.json new file mode 100644 index 0000000..818320d --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/config.json @@ -0,0 +1,163 @@ +{ + "container-rules": { + "excluded-modules": [], + "excluded-features": [] + }, + + "supervisor-rules": { + "netopeer": { + "path": "/usr/local/bin/netopeer2-server", + "args": ["-d", "-v2"], + "autorestart": true, + "stdout": "log/netopeer-stdout.log", + "stderr": "log/netopeer-stderr.log" + }, + + "sshd": { + "path": "/usr/sbin/sshd", + "args": ["-D"], + "autorestart": true, + "stdout": "log/sshd-stdout.log", + "stderr": "log/sshd-stderr.log" + }, + + "ntsim-network-function": { + "path": "/opt/dev/ntsim-ng/ntsim-ng", + "args": ["-w/opt/dev/ntsim-ng", "-f"], + "nomanual": true + } + }, + + "datastore-random-generation-rules" : { + "excluded-modules": [ + "sysrepo", + "sysrepo-monitoring", + "ietf-yang-library", + "ietf-netconf-acm", + "ietf-netconf-monitoring", + "nc-notifications", + "ietf-keystore", + "ietf-truststore", + "ietf-system", + "ietf-netconf-server", + "ietf-alarms", + "ietf-network-instance", + "ietf-restconf", + "ietf-yang-schema-mount", + "ietf-subscribed-notifications", + "o-ran-uplane-conf", + "o-ran-performance-management", + "o-ran-transceiver", + "o-ran-mplane-int", + "o-ran-processing-element", + "o-ran-shared-cell", + "nts-network-function" + ], + + "default-list-instances": 2, + "custom-list-instances" : [ + {"/ietf-interfaces:interfaces/interface": 4} + + ], + + "restrict-schema": [ + {"/ietf-interfaces:interfaces/interface/type": ["iana-if-type:ethernetCsmacd"]} + ] + + }, + + "datastore-populate-rules": { + "random-generation-enabled": true, + + "pre-generated-operational-data": [ + "../deploy/data/ietf-hardware-operational.json" + ], + "pre-generated-running-data": [ + "../deploy/data/ietf-hardware-running.json" + ] + }, + + "fault-rules" : { + "yang-notif-template" : "$$uint16_counter$$%%object%%%%affected-object%%%%fault-severity%%%%cleared%%%%text%%%%date-time%%", + "choosing-method" : "linear", + "faults" : [ + { + "condition" : "CPRI Port Down", + "object" : "Slot-0-Port-A", + "severity" : "MAJOR", + "date-time" : "$$time$$", + "specific-problem" : "CPRI Port Down", + + "fault-severity" : "MAJOR", + "affected-object" : "%%object%%", + "cleared" : "false", + "text" : "CPRI Port Down" + }, + + { + "condition" : "CPRI Port Down", + "object" : "Slot-0-Port-A", + "severity" : "NORMAL", + "date-time" : "$$time$$", + "specific-problem" : "CPRI Port Down", + + "fault-severity" : "MAJOR", + "affected-object" : "%%object%%", + "cleared" : "true", + "text" : "CPRI Port Down" + }, + + { + "condition" : "CPRI Port Down", + "object" : "Slot-0-Port-C", + "severity" : "MAJOR", + "date-time" : "$$time$$", + "specific-problem" : "CPRI Port Down", + + "fault-severity" : "MAJOR", + "affected-object" : "%%object%%", + "cleared" : "false", + "text" : "CPRI Port Down" + }, + + { + "condition" : "CPRI Port Down", + "object" : "Slot-0-Port-C", + "severity" : "NORMAL", + "date-time" : "$$time$$", + "specific-problem" : "CPRI Port Down", + + "fault-severity" : "MAJOR", + "affected-object" : "%%object%%", + "cleared" : "true", + "text" : "CPRI Port Down" + }, + + { + "condition" : "CPRI Port Down", + "object" : "Slot-2-Port-B", + "severity" : "MAJOR", + "date-time" : "$$time$$", + "specific-problem" : "CPRI Port Down", + + "fault-severity" : "MAJOR", + "affected-object" : "%%object%%", + "cleared" : "false", + "text" : "CPRI Port Down" + }, + + { + "condition" : "CPRI Port Down", + "object" : "Slot-2-Port-B", + "severity" : "NORMAL", + "date-time" : "$$time$$", + "specific-problem" : "CPRI Port Down", + + "fault-severity" : "MAJOR", + "affected-object" : "%%object%%", + "cleared" : "true", + "text" : "CPRI Port Down" + } + ] + } +} \ No newline at end of file diff --git a/ntsimulator/deploy/o-ran-ru-fh/container-tag.yaml b/ntsimulator/deploy/o-ran-ru-fh/container-tag.yaml new file mode 100644 index 0000000..ee93a5d --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/container-tag.yaml @@ -0,0 +1,2 @@ +--- +tag: 1.2.0 \ No newline at end of file diff --git a/ntsimulator/deploy/o-ran-ru-fh/data/README.md b/ntsimulator/deploy/o-ran-ru-fh/data/README.md new file mode 100644 index 0000000..7b501f4 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/data/README.md @@ -0,0 +1,2 @@ +This folder should contain XML/JSON data for pre-populating running/operational. +Data files by themselves are not taken into account until added to config.json diff --git a/ntsimulator/deploy/o-ran-ru-fh/data/ietf-hardware-operational.json b/ntsimulator/deploy/o-ran-ru-fh/data/ietf-hardware-operational.json new file mode 100644 index 0000000..18c83c9 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/data/ietf-hardware-operational.json @@ -0,0 +1,307 @@ +{ + "ietf-hardware:hardware": { + "component": [ + { + "name": "chassis", + "serial-num": "23412", + "software-rev": "3.8.1 (2029-10-30 11:47:59)", + "mfg-name": "NTS", + "model-name": "O1-O-RU-Simulator", + "description": "O-RAN O-RU O1 Simulator", + "state": { + "oper-state": "enabled" + }, + "contains-child": [ + "chassis-temperature-exhaust", + "chassis-temperature-inlet", + "chassis-fan0", + "chassis-fan1", + "chassis-fan2", + "chassis-fan3", + "cpu", + "slot0", + "slot2" + ] + }, + { + "name": "chassis-temperature-exhaust", + "sensor-data": { + "value": 30, + "value-type": "celsius", + "value-timestamp": "2021-03-18T19:51:50.3Z", + "oper-status": "ok" + }, + "state": { + "oper-state": "enabled" + } + }, + { + "name": "chassis-temperature-inlet", + "sensor-data": { + "value": 29, + "value-type": "celsius", + "value-timestamp": "2021-03-18T19:51:50.3Z", + "oper-status": "ok" + }, + "state": { + "oper-state": "enabled" + } + }, + { + "name": "chassis-fan0", + "state": { + "oper-state": "enabled" + }, + "contains-child": [ + "chassis-fan0-speed" + ] + }, + { + "name": "chassis-fan0-speed", + "sensor-data": { + "value": 4100, + "value-type": "rpm", + "value-timestamp": "2021-03-18T19:51:50.3Z", + "oper-status": "ok" + }, + "state": { + "oper-state": "enabled" + } + }, + { + "name": "chassis-fan1", + "state": { + "oper-state": "enabled" + }, + "contains-child": [ + "chassis-fan1-speed" + ] + }, + { + "name": "chassis-fan1-speed", + "sensor-data": { + "value": 4100, + "value-type": "rpm", + "value-timestamp": "2021-03-18T19:51:50.3Z", + "oper-status": "ok" + }, + "state": { + "oper-state": "enabled" + } + }, + { + "name": "chassis-fan2", + "state": { + "oper-state": "enabled" + }, + "contains-child": [ + "chassis-fan2-speed" + ] + }, + { + "name": "chassis-fan2-speed", + "sensor-data": { + "value": 4100, + "value-type": "rpm", + "value-timestamp": "2021-03-18T19:51:50.3Z", + "oper-status": "ok" + }, + "state": { + "oper-state": "enabled" + } + }, + { + "name": "chassis-fan3", + "state": { + "oper-state": "enabled" + }, + "contains-child": [ + "chassis-fan3-speed" + ] + }, + { + "name": "chassis-fan3-speed", + "sensor-data": { + "value": 1000, + "value-type": "rpm", + "value-timestamp": "2021-03-18T19:51:50.3Z", + "oper-status": "ok" + }, + "state": { + "oper-state": "enabled" + } + }, + { + "name": "cpu", + "state": { + "oper-state": "enabled" + }, + "contains-child": [ + "cpu-temperature" + ] + }, + { + "name": "cpu-temperature", + "sensor-data": { + "value": 30, + "value-type": "celsius", + "value-timestamp": "2021-03-18T19:51:50.3Z", + "oper-status": "ok" + }, + "state": { + "oper-state": "enabled" + } + }, + { + "name": "slot0", + "serial-num": "7220530", + "firmware-rev": "12.00.42-S (0F7F1001)", + "software-rev": "0", + "model-name": "385A-SFP-2P-40-FHL-JC3", + "state": { + "oper-state": "enabled" + }, + "contains-child": [ + "slot0-temperature", + "slot0-logical0", + "slot0-logical1", + "slot0-logical2" + ] + }, + { + "name": "slot0-temperature", + "sensor-data": { + "value": 51, + "value-type": "celsius", + "value-timestamp": "2021-03-18T19:51:50.3Z", + "oper-status": "ok" + }, + "state": { + "oper-state": "enabled" + } + }, + { + "name": "slot0-logical0", + "description": "SLOT0-AZ", + "state": { + "oper-state": "enabled" + }, + "contains-child": [ + "slot0-logical0-bbu", + "slot0-logical0-rrh" + ] + }, + { + "name": "slot0-logical0-bbu", + "serial-num": "AGNN214S", + "mfg-name": "ACME GMBH.", + "model-name": "ANSHEONXH-E7", + "state": { + "oper-state": "enabled" + }, + "contains-child": [ + "slot0-logical0-bbu-temperature" + ] + }, + { + "name": "slot0-logical0-bbu-temperature", + "sensor-data": { + "value": 37, + "value-type": "celsius", + "value-timestamp": "2021-03-18T19:51:50.3Z", + "oper-status": "ok" + }, + "state": { + "oper-state": "enabled" + } + }, + { + "name": "slot0-logical0-rrh", + "serial-num": "AGNF714S", + "mfg-name": "ACME GMBH.", + "model-name": "ANSHEONXH-E7", + "state": { + "oper-state": "enabled" + }, + "contains-child": [ + "slot0-logical0-rrh-temperature" + ] + }, + { + "name": "slot0-logical0-rrh-temperature", + "sensor-data": { + "value": 35, + "value-type": "celsius", + "value-timestamp": "2021-03-18T19:51:50.3Z", + "oper-status": "ok" + }, + "state": { + "oper-state": "enabled" + } + }, + { + "name": "slot0-logical1", + "description": "SLOT0-B", + "state": { + "oper-state": "disabled" + } + }, + { + "name": "slot0-logical2", + "description": "SLOT0-C", + "state": { + "oper-state": "disabled" + } + }, + { + "name": "slot2", + "serial-num": "2522642", + "firmware-rev": "12.00.42-S (0F7F1001)", + "software-rev": "0", + "model-name": "339B-SFP-2P-75-FHL-JC3", + "state": { + "oper-state": "enabled" + }, + "contains-child": [ + "slot2-temperature", + "slot2-logical0", + "slot2-logical1", + "slot2-logical2" + ] + }, + { + "name": "slot2-temperature", + "sensor-data": { + "value": 49, + "value-type": "celsius", + "value-timestamp": "2021-03-18T19:51:50.3Z", + "oper-status": "ok" + }, + "state": { + "oper-state": "enabled" + } + }, + { + "name": "slot2-logical0", + "description": "SLOT2-C", + "state": { + "oper-state": "disabled" + } + }, + { + "name": "slot2-logical1", + "description": "SLOT3-A", + "state": { + "oper-state": "disabled" + } + }, + { + "name": "slot2-logical2", + "description": "SLOT3-B", + "state": { + "oper-state": "disabled" + } + } + ] + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/data/ietf-hardware-running.json b/ntsimulator/deploy/o-ran-ru-fh/data/ietf-hardware-running.json new file mode 100644 index 0000000..ab757fa --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/data/ietf-hardware-running.json @@ -0,0 +1,276 @@ +{ + "ietf-hardware:hardware": { + "component": [ + { + "name": "chassis", + "alias": "chassis", + "class": "iana-hardware:chassis", + "state": { + "admin-state": "unlocked" + } + }, + { + "name": "chassis-temperature-exhaust", + "alias": "chassis-temperature-exhaust", + "class": "iana-hardware:sensor", + "state": { + "admin-state": "locked" + }, + "parent": "chassis", + "parent-rel-pos": 0 + }, + { + "name": "chassis-temperature-inlet", + "alias": "chassis-temperature-inlet", + "class": "iana-hardware:sensor", + "state": { + "admin-state": "locked" + }, + "parent": "chassis", + "parent-rel-pos": 1 + }, + { + "name": "chassis-fan0", + "alias": "chassis-fan0", + "class": "iana-hardware:fan", + "state": { + "admin-state": "locked" + }, + "parent": "chassis", + "parent-rel-pos": 2 + }, + { + "name": "chassis-fan0-speed", + "alias": "chassis-fan0-speed", + "class": "iana-hardware:sensor", + "state": { + "admin-state": "locked" + }, + "parent": "chassis-fan0", + "parent-rel-pos": 0 + }, + { + "name": "chassis-fan1", + "alias": "chassis-fan1", + "class": "iana-hardware:fan", + "state": { + "admin-state": "locked" + }, + "parent": "chassis", + "parent-rel-pos": 3 + }, + { + "name": "chassis-fan1-speed", + "alias": "chassis-fan1-speed", + "class": "iana-hardware:sensor", + "state": { + "admin-state": "locked" + }, + "parent": "chassis-fan1", + "parent-rel-pos": 0 + }, + { + "name": "chassis-fan2", + "alias": "chassis-fan2", + "class": "iana-hardware:fan", + "state": { + "admin-state": "locked" + }, + "parent": "chassis", + "parent-rel-pos": 4 + }, + { + "name": "chassis-fan2-speed", + "alias": "chassis-fan2-speed", + "class": "iana-hardware:sensor", + "state": { + "admin-state": "locked" + }, + "parent": "chassis-fan2", + "parent-rel-pos": 0 + }, + { + "name": "chassis-fan3", + "alias": "chassis-fan3", + "class": "iana-hardware:fan", + "state": { + "admin-state": "locked" + }, + "parent": "chassis", + "parent-rel-pos": 5 + }, + { + "name": "chassis-fan3-speed", + "alias": "chassis-fan3-speed", + "class": "iana-hardware:sensor", + "state": { + "admin-state": "locked" + }, + "parent": "chassis-fan3", + "parent-rel-pos": 0 + }, + { + "name": "cpu", + "alias": "cpu", + "class": "iana-hardware:cpu", + "state": { + "admin-state": "locked" + }, + "parent": "chassis", + "parent-rel-pos": 6 + }, + { + "name": "cpu-temperature", + "alias": "cpu-temperature", + "class": "iana-hardware:sensor", + "state": { + "admin-state": "locked" + }, + "parent": "cpu", + "parent-rel-pos": 0 + }, + { + "name": "slot0", + "alias": "slot0", + "class": "iana-hardware:module", + "state": { + "admin-state": "unlocked" + }, + "parent": "chassis", + "parent-rel-pos": 7 + }, + { + "name": "slot0-temperature", + "alias": "slot0-temperature", + "class": "iana-hardware:sensor", + "state": { + "admin-state": "locked" + }, + "parent": "slot0", + "parent-rel-pos": 0 + }, + { + "name": "slot0-logical0", + "alias": "Slot0-A", + "class": "iana-hardware:module", + "state": { + "admin-state": "unlocked" + }, + "parent": "slot0", + "parent-rel-pos": 1 + }, + { + "name": "slot0-logical0-bbu", + "alias": "Slot0-A-bbu", + "class": "iana-hardware:port", + "state": { + "admin-state": "unlocked" + }, + "parent": "slot0-logical0", + "parent-rel-pos": 0, + "o-ran-hardware:o-ran-name": "slot0-logical0-bbu" + }, + { + "name": "slot0-logical0-bbu-temperature", + "alias": "Slot0-A-bbu-temperature", + "class": "iana-hardware:sensor", + "state": { + "admin-state": "locked" + }, + "parent": "slot0-logical0-bbu", + "parent-rel-pos": 0 + }, + { + "name": "slot0-logical0-rrh", + "alias": "Slot0-A-rrh", + "class": "iana-hardware:port", + "state": { + "admin-state": "unlocked" + }, + "parent": "slot0-logical0", + "parent-rel-pos": 1, + "o-ran-hardware:o-ran-name": "slot0-logical0-rrh" + }, + { + "name": "slot0-logical0-rrh-temperature", + "alias": "Slot0-A-rrh-temperature", + "class": "iana-hardware:sensor", + "state": { + "admin-state": "locked" + }, + "parent": "slot0-logical0-rrh", + "parent-rel-pos": 0 + }, + { + "name": "slot0-logical1", + "alias": "Slot0-B", + "class": "iana-hardware:module", + "state": { + "admin-state": "unlocked" + }, + "parent": "slot0", + "parent-rel-pos": 2 + }, + { + "name": "slot0-logical2", + "alias": "Slot0-C", + "class": "iana-hardware:module", + "state": { + "admin-state": "unlocked" + }, + "parent": "slot0", + "parent-rel-pos": 3 + }, + { + "name": "slot2", + "alias": "slot2", + "class": "iana-hardware:module", + "state": { + "admin-state": "unlocked" + }, + "parent": "chassis", + "parent-rel-pos": 9 + }, + { + "name": "slot2-temperature", + "alias": "slot2-temperature", + "class": "iana-hardware:sensor", + "state": { + "admin-state": "locked" + }, + "parent": "slot2", + "parent-rel-pos": 0 + }, + { + "name": "slot2-logical0", + "alias": "Slot2-C", + "class": "iana-hardware:module", + "state": { + "admin-state": "unlocked" + }, + "parent": "slot2", + "parent-rel-pos": 1 + }, + { + "name": "slot2-logical1", + "alias": "Slot3-A", + "class": "iana-hardware:module", + "state": { + "admin-state": "unlocked" + }, + "parent": "slot2", + "parent-rel-pos": 2 + }, + { + "name": "slot2-logical2", + "alias": "Slot3-B", + "class": "iana-hardware:module", + "state": { + "admin-state": "unlocked" + }, + "parent": "slot2", + "parent-rel-pos": 3 + } + ] + } +} diff --git a/ntsimulator/deploy/o-ran/ubuntu.Dockerfile b/ntsimulator/deploy/o-ran-ru-fh/local.Dockerfile similarity index 80% rename from ntsimulator/deploy/o-ran/ubuntu.Dockerfile rename to ntsimulator/deploy/o-ran-ru-fh/local.Dockerfile index f5cdd80..3c62017 100644 --- a/ntsimulator/deploy/o-ran/ubuntu.Dockerfile +++ b/ntsimulator/deploy/o-ran-ru-fh/local.Dockerfile @@ -17,18 +17,16 @@ #### DEVICE #### ################ -FROM nexus3.o-ran-sc.org:10004/o-ran-sc/nts-ng-base:latest +FROM o-ran-sc/nts-ng-base:latest LABEL maintainer="alexandru.stancu@highstreet-technologies.com / adrian.lita@highstreet-technologies.com" # ntsim-ng configuration and deployment COPY ./yang /opt/dev/deploy/yang +COPY ./data /opt/dev/deploy/data COPY ./config.json /opt/dev/ntsim-ng/config/config.json # ntsim-ng init docker -RUN /opt/dev/ntsim-ng/ntsim-ng --docker-init -w /opt/dev/ntsim-ng - -# supervisor configuration -COPY ./supervisord.conf /etc/supervisord.conf +RUN /opt/dev/ntsim-ng/ntsim-ng --container-init -w /opt/dev/ntsim-ng # finishing container build ARG BUILD_DATE @@ -38,6 +36,8 @@ LABEL build-date=$BUILD_DATE EXPOSE 830-929 EXPOSE 21-22 +ENV NTS_FUNCTION_TYPE=NTS_FUNCTION_TYPE_O_RAN_O_RU_FH + # run WORKDIR /opt/dev/workspace -CMD ["sh", "-c", "/usr/bin/supervisord -c /etc/supervisord.conf"] +CMD ["/opt/dev/ntsim-ng/ntsim-ng", "-w/opt/dev/ntsim-ng", "--supervisor"] diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/iana-hardware@2018-03-13.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/iana-hardware@2018-03-13.yang new file mode 100644 index 0000000..52bcaf3 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/iana-hardware@2018-03-13.yang @@ -0,0 +1,180 @@ +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."; +} +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/iana-if-type@2017-01-19.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/iana-if-type@2017-01-19.yang new file mode 100644 index 0000000..24d04e6 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/iana-if-type@2017-01-19.yang @@ -0,0 +1,1611 @@ +module iana-if-type { + namespace "urn:ietf:params:xml:ns:yang:iana-if-type"; + prefix ianaift; + + import ietf-interfaces { + prefix if; + } + + organization "IANA"; + contact + " Internet Assigned Numbers Authority + Postal: ICANN + 12025 Waterfront Drive, Suite 300 + Los Angeles, CA 90094-2536 + United States + Tel: +1 310 301 5800 + "; + description + "This YANG module defines YANG identities for IANA-registered + interface types. + This YANG module is maintained by IANA and reflects the + 'ifType definitions' registry. + The latest revision of this YANG module can be obtained from + the IANA web site. + Requests for new values should be made to IANA via + email (iana&iana.org). + Copyright (c) 2014 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 + (http://trustee.ietf.org/license-info). + The initial version of this YANG module is part of RFC 7224; + see the RFC itself for full legal notices."; + reference + "IANA 'ifType definitions' registry. + "; + + revision 2017-01-19 { + description + "Registered ifType 289."; + } + + revision 2016-11-23 { + description + "Registered ifTypes 283-288."; + } + + revision 2016-06-09 { + description + "Registered ifType 282."; + } + revision 2016-05-03 { + description + "Registered ifType 281."; + } + revision 2015-06-12 { + description + "Corrected formatting issue."; + } + revision 2014-09-24 { + description + "Registered ifType 280."; + } + revision 2014-09-19 { + description + "Registered ifType 279."; + } + revision 2014-07-03 { + description + "Registered ifTypes 277-278."; + } + revision 2014-05-19 { + description + "Updated the contact address."; + } + revision 2014-05-08 { + description + "Initial revision."; + reference + "RFC 7224: IANA Interface Type YANG Module"; + } + + identity iana-interface-type { + base if:interface-type; + description + "This identity is used as a base for all interface types + defined in the 'ifType definitions' registry."; + } + + identity other { + base iana-interface-type; + } + identity regular1822 { + base iana-interface-type; + } + identity hdh1822 { + base iana-interface-type; + } + identity ddnX25 { + base iana-interface-type; + } + identity rfc877x25 { + base iana-interface-type; + reference + "RFC 1382 - SNMP MIB Extension for the X.25 Packet Layer"; + } + identity ethernetCsmacd { + base iana-interface-type; + description + "For all Ethernet-like interfaces, regardless of speed, + as per RFC 3635."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity iso88023Csmacd { + base iana-interface-type; + status deprecated; + description + "Deprecated via RFC 3635. + Use ethernetCsmacd(6) instead."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity iso88024TokenBus { + base iana-interface-type; + } + identity iso88025TokenRing { + base iana-interface-type; + } + identity iso88026Man { + base iana-interface-type; + } + identity starLan { + base iana-interface-type; + status deprecated; + description + "Deprecated via RFC 3635. + Use ethernetCsmacd(6) instead."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity proteon10Mbit { + base iana-interface-type; + } + identity proteon80Mbit { + base iana-interface-type; + } + identity hyperchannel { + base iana-interface-type; + } + identity fddi { + base iana-interface-type; + reference + "RFC 1512 - FDDI Management Information Base"; + } + identity lapb { + base iana-interface-type; + reference + "RFC 1381 - SNMP MIB Extension for X.25 LAPB"; + } + identity sdlc { + base iana-interface-type; + } + identity ds1 { + base iana-interface-type; + description + "DS1-MIB."; + reference + "RFC 4805 - Definitions of Managed Objects for the + DS1, J1, E1, DS2, and E2 Interface Types"; + } + identity e1 { + base iana-interface-type; + status obsolete; + description + "Obsolete; see DS1-MIB."; + reference + "RFC 4805 - Definitions of Managed Objects for the + DS1, J1, E1, DS2, and E2 Interface Types"; + } + identity basicISDN { + base iana-interface-type; + description + "No longer used. See also RFC 2127."; + } + identity primaryISDN { + base iana-interface-type; + description + "No longer used. See also RFC 2127."; + } + identity propPointToPointSerial { + base iana-interface-type; + description + "Proprietary serial."; + } + identity ppp { + base iana-interface-type; + } + identity softwareLoopback { + base iana-interface-type; + } + identity eon { + base iana-interface-type; + description + "CLNP over IP."; + } + identity ethernet3Mbit { + base iana-interface-type; + } + identity nsip { + base iana-interface-type; + description + "XNS over IP."; + } + identity slip { + base iana-interface-type; + description + "Generic SLIP."; + } + identity ultra { + base iana-interface-type; + description + "Ultra Technologies."; + } + identity ds3 { + base iana-interface-type; + description + "DS3-MIB."; + reference + "RFC 3896 - Definitions of Managed Objects for the + DS3/E3 Interface Type"; + } + identity sip { + base iana-interface-type; + description + "SMDS, coffee."; + reference + "RFC 1694 - Definitions of Managed Objects for SMDS + Interfaces using SMIv2"; + } + identity frameRelay { + base iana-interface-type; + description + "DTE only."; + reference + "RFC 2115 - Management Information Base for Frame Relay + DTEs Using SMIv2"; + } + identity rs232 { + base iana-interface-type; + reference + "RFC 1659 - Definitions of Managed Objects for RS-232-like + Hardware Devices using SMIv2"; + } + identity para { + base iana-interface-type; + description + "Parallel-port."; + reference + "RFC 1660 - Definitions of Managed Objects for + Parallel-printer-like Hardware Devices using + SMIv2"; + } + identity arcnet { + base iana-interface-type; + description + "ARCnet."; + } + identity arcnetPlus { + base iana-interface-type; + description + "ARCnet Plus."; + } + identity atm { + base iana-interface-type; + description + "ATM cells."; + } + identity miox25 { + base iana-interface-type; + reference + "RFC 1461 - SNMP MIB extension for Multiprotocol + Interconnect over X.25"; + } + identity sonet { + base iana-interface-type; + description + "SONET or SDH."; + } + identity x25ple { + base iana-interface-type; + reference + "RFC 2127 - ISDN Management Information Base using SMIv2"; + } + identity iso88022llc { + base iana-interface-type; + } + identity localTalk { + base iana-interface-type; + } + identity smdsDxi { + base iana-interface-type; + } + identity frameRelayService { + base iana-interface-type; + description + "FRNETSERV-MIB."; + reference + "RFC 2954 - Definitions of Managed Objects for Frame + Relay Service"; + } + identity v35 { + base iana-interface-type; + } + identity hssi { + base iana-interface-type; + } + identity hippi { + base iana-interface-type; + } + identity modem { + base iana-interface-type; + description + "Generic modem."; + } + identity aal5 { + base iana-interface-type; + description + "AAL5 over ATM."; + } + identity sonetPath { + base iana-interface-type; + } + identity sonetVT { + base iana-interface-type; + } + identity smdsIcip { + base iana-interface-type; + description + "SMDS InterCarrier Interface."; + } + identity propVirtual { + base iana-interface-type; + description + "Proprietary virtual/internal."; + reference + "RFC 2863 - The Interfaces Group MIB"; + } + identity propMultiplexor { + base iana-interface-type; + description + "Proprietary multiplexing."; + reference + "RFC 2863 - The Interfaces Group MIB"; + } + identity ieee80212 { + base iana-interface-type; + description + "100BaseVG."; + } + identity fibreChannel { + base iana-interface-type; + description + "Fibre Channel."; + } + identity hippiInterface { + base iana-interface-type; + description + "HIPPI interfaces."; + } + identity frameRelayInterconnect { + base iana-interface-type; + status obsolete; + description + "Obsolete; use either + frameRelay(32) or frameRelayService(44)."; + } + identity aflane8023 { + base iana-interface-type; + description + "ATM Emulated LAN for 802.3."; + } + identity aflane8025 { + base iana-interface-type; + description + "ATM Emulated LAN for 802.5."; + } + identity cctEmul { + base iana-interface-type; + description + "ATM Emulated circuit."; + } + identity fastEther { + base iana-interface-type; + status deprecated; + description + "Obsoleted via RFC 3635. + ethernetCsmacd(6) should be used instead."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity isdn { + base iana-interface-type; + description + "ISDN and X.25."; + reference + "RFC 1356 - Multiprotocol Interconnect on X.25 and ISDN + in the Packet Mode"; + } + identity v11 { + base iana-interface-type; + description + "CCITT V.11/X.21."; + } + identity v36 { + base iana-interface-type; + description + "CCITT V.36."; + } + identity g703at64k { + base iana-interface-type; + description + "CCITT G703 at 64Kbps."; + } + identity g703at2mb { + base iana-interface-type; + status obsolete; + description + "Obsolete; see DS1-MIB."; + } + identity qllc { + base iana-interface-type; + description + "SNA QLLC."; + } + identity fastEtherFX { + base iana-interface-type; + status deprecated; + description + "Obsoleted via RFC 3635. + ethernetCsmacd(6) should be used instead."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity channel { + base iana-interface-type; + description + "Channel."; + } + identity ieee80211 { + base iana-interface-type; + description + "Radio spread spectrum."; + } + identity ibm370parChan { + base iana-interface-type; + description + "IBM System 360/370 OEMI Channel."; + } + identity escon { + base iana-interface-type; + description + "IBM Enterprise Systems Connection."; + } + identity dlsw { + base iana-interface-type; + description + "Data Link Switching."; + } + identity isdns { + base iana-interface-type; + description + "ISDN S/T interface."; + } + identity isdnu { + base iana-interface-type; + description + "ISDN U interface."; + } + identity lapd { + base iana-interface-type; + description + "Link Access Protocol D."; + } + identity ipSwitch { + base iana-interface-type; + description + "IP Switching Objects."; + } + identity rsrb { + base iana-interface-type; + description + "Remote Source Route Bridging."; + } + identity atmLogical { + base iana-interface-type; + description + "ATM Logical Port."; + reference + "RFC 3606 - Definitions of Supplemental Managed Objects + for ATM Interface"; + } + identity ds0 { + base iana-interface-type; + description + "Digital Signal Level 0."; + reference + "RFC 2494 - Definitions of Managed Objects for the DS0 + and DS0 Bundle Interface Type"; + } + identity ds0Bundle { + base iana-interface-type; + description + "Group of ds0s on the same ds1."; + reference + "RFC 2494 - Definitions of Managed Objects for the DS0 + and DS0 Bundle Interface Type"; + } + identity bsc { + base iana-interface-type; + description + "Bisynchronous Protocol."; + } + identity async { + base iana-interface-type; + description + "Asynchronous Protocol."; + } + identity cnr { + base iana-interface-type; + description + "Combat Net Radio."; + } + identity iso88025Dtr { + base iana-interface-type; + description + "ISO 802.5r DTR."; + } + identity eplrs { + base iana-interface-type; + description + "Ext Pos Loc Report Sys."; + } + identity arap { + base iana-interface-type; + description + "Appletalk Remote Access Protocol."; + } + identity propCnls { + base iana-interface-type; + description + "Proprietary Connectionless Protocol."; + } + identity hostPad { + base iana-interface-type; + description + "CCITT-ITU X.29 PAD Protocol."; + } + identity termPad { + base iana-interface-type; + description + "CCITT-ITU X.3 PAD Facility."; + } + identity frameRelayMPI { + base iana-interface-type; + description + "Multiproto Interconnect over FR."; + } + identity x213 { + base iana-interface-type; + description + "CCITT-ITU X213."; + } + identity adsl { + base iana-interface-type; + description + "Asymmetric Digital Subscriber Loop."; + } + identity radsl { + base iana-interface-type; + description + "Rate-Adapt. Digital Subscriber Loop."; + } + identity sdsl { + base iana-interface-type; + description + "Symmetric Digital Subscriber Loop."; + } + identity vdsl { + base iana-interface-type; + description + "Very H-Speed Digital Subscrib. Loop."; + } + identity iso88025CRFPInt { + base iana-interface-type; + description + "ISO 802.5 CRFP."; + } + identity myrinet { + base iana-interface-type; + description + "Myricom Myrinet."; + } + identity voiceEM { + base iana-interface-type; + description + "Voice recEive and transMit."; + } + identity voiceFXO { + base iana-interface-type; + description + "Voice Foreign Exchange Office."; + } + identity voiceFXS { + base iana-interface-type; + description + "Voice Foreign Exchange Station."; + } + identity voiceEncap { + base iana-interface-type; + description + "Voice encapsulation."; + } + identity voiceOverIp { + base iana-interface-type; + description + "Voice over IP encapsulation."; + } + identity atmDxi { + base iana-interface-type; + description + "ATM DXI."; + } + identity atmFuni { + base iana-interface-type; + description + "ATM FUNI."; + } + identity atmIma { + base iana-interface-type; + description + "ATM IMA."; + } + identity pppMultilinkBundle { + base iana-interface-type; + description + "PPP Multilink Bundle."; + } + identity ipOverCdlc { + base iana-interface-type; + description + "IBM ipOverCdlc."; + } + identity ipOverClaw { + base iana-interface-type; + description + "IBM Common Link Access to Workstn."; + } + identity stackToStack { + base iana-interface-type; + description + "IBM stackToStack."; + } + identity virtualIpAddress { + base iana-interface-type; + description + "IBM VIPA."; + } + identity mpc { + base iana-interface-type; + description + "IBM multi-protocol channel support."; + } + identity ipOverAtm { + base iana-interface-type; + description + "IBM ipOverAtm."; + reference + "RFC 2320 - Definitions of Managed Objects for Classical IP + and ARP Over ATM Using SMIv2 (IPOA-MIB)"; + } + identity iso88025Fiber { + base iana-interface-type; + description + "ISO 802.5j Fiber Token Ring."; + } + identity tdlc { + base iana-interface-type; + description + "IBM twinaxial data link control."; + } + identity gigabitEthernet { + base iana-interface-type; + status deprecated; + description + "Obsoleted via RFC 3635. + ethernetCsmacd(6) should be used instead."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity hdlc { + base iana-interface-type; + description + "HDLC."; + } + identity lapf { + base iana-interface-type; + description + "LAP F."; + } + identity v37 { + base iana-interface-type; + description + "V.37."; + } + identity x25mlp { + base iana-interface-type; + description + "Multi-Link Protocol."; + } + identity x25huntGroup { + base iana-interface-type; + description + "X25 Hunt Group."; + } + identity transpHdlc { + base iana-interface-type; + description + "Transp HDLC."; + } + identity interleave { + base iana-interface-type; + description + "Interleave channel."; + } + identity fast { + base iana-interface-type; + description + "Fast channel."; + } + identity ip { + base iana-interface-type; + description + "IP (for APPN HPR in IP networks)."; + } + identity docsCableMaclayer { + base iana-interface-type; + description + "CATV Mac Layer."; + } + identity docsCableDownstream { + base iana-interface-type; + description + "CATV Downstream interface."; + } + identity docsCableUpstream { + base iana-interface-type; + description + "CATV Upstream interface."; + } + identity a12MppSwitch { + base iana-interface-type; + description + "Avalon Parallel Processor."; + } + identity tunnel { + base iana-interface-type; + description + "Encapsulation interface."; + } + identity coffee { + base iana-interface-type; + description + "Coffee pot."; + reference + "RFC 2325 - Coffee MIB"; + } + identity ces { + base iana-interface-type; + description + "Circuit Emulation Service."; + } + identity atmSubInterface { + base iana-interface-type; + description + "ATM Sub Interface."; + } + identity l2vlan { + base iana-interface-type; + description + "Layer 2 Virtual LAN using 802.1Q."; + } + identity l3ipvlan { + base iana-interface-type; + description + "Layer 3 Virtual LAN using IP."; + } + identity l3ipxvlan { + base iana-interface-type; + description + "Layer 3 Virtual LAN using IPX."; + } + identity digitalPowerline { + base iana-interface-type; + description + "IP over Power Lines."; + } + identity mediaMailOverIp { + base iana-interface-type; + description + "Multimedia Mail over IP."; + } + identity dtm { + base iana-interface-type; + description + "Dynamic synchronous Transfer Mode."; + } + identity dcn { + base iana-interface-type; + description + "Data Communications Network."; + } + identity ipForward { + base iana-interface-type; + description + "IP Forwarding Interface."; + } + identity msdsl { + base iana-interface-type; + description + "Multi-rate Symmetric DSL."; + } + identity ieee1394 { + base iana-interface-type; + + description + "IEEE1394 High Performance Serial Bus."; + } + identity if-gsn { + base iana-interface-type; + description + "HIPPI-6400."; + } + identity dvbRccMacLayer { + base iana-interface-type; + description + "DVB-RCC MAC Layer."; + } + identity dvbRccDownstream { + base iana-interface-type; + description + "DVB-RCC Downstream Channel."; + } + identity dvbRccUpstream { + base iana-interface-type; + description + "DVB-RCC Upstream Channel."; + } + identity atmVirtual { + base iana-interface-type; + description + "ATM Virtual Interface."; + } + identity mplsTunnel { + base iana-interface-type; + description + "MPLS Tunnel Virtual Interface."; + } + identity srp { + base iana-interface-type; + description + "Spatial Reuse Protocol."; + } + identity voiceOverAtm { + base iana-interface-type; + description + "Voice over ATM."; + } + identity voiceOverFrameRelay { + base iana-interface-type; + description + "Voice Over Frame Relay."; + } + identity idsl { + base iana-interface-type; + description + "Digital Subscriber Loop over ISDN."; + } + identity compositeLink { + base iana-interface-type; + description + "Avici Composite Link Interface."; + } + identity ss7SigLink { + base iana-interface-type; + description + "SS7 Signaling Link."; + } + identity propWirelessP2P { + base iana-interface-type; + description + "Prop. P2P wireless interface."; + } + identity frForward { + base iana-interface-type; + description + "Frame Forward Interface."; + } + identity rfc1483 { + base iana-interface-type; + description + "Multiprotocol over ATM AAL5."; + reference + "RFC 1483 - Multiprotocol Encapsulation over ATM + Adaptation Layer 5"; + } + identity usb { + base iana-interface-type; + description + "USB Interface."; + } + identity ieee8023adLag { + base iana-interface-type; + description + "IEEE 802.3ad Link Aggregate."; + } + identity bgppolicyaccounting { + base iana-interface-type; + description + "BGP Policy Accounting."; + } + identity frf16MfrBundle { + base iana-interface-type; + description + "FRF.16 Multilink Frame Relay."; + } + identity h323Gatekeeper { + base iana-interface-type; + description + "H323 Gatekeeper."; + } + identity h323Proxy { + base iana-interface-type; + description + "H323 Voice and Video Proxy."; + } + identity mpls { + base iana-interface-type; + description + "MPLS."; + } + identity mfSigLink { + base iana-interface-type; + description + "Multi-frequency signaling link."; + } + identity hdsl2 { + base iana-interface-type; + description + "High Bit-Rate DSL - 2nd generation."; + } + identity shdsl { + base iana-interface-type; + description + "Multirate HDSL2."; + } + identity ds1FDL { + base iana-interface-type; + description + "Facility Data Link (4Kbps) on a DS1."; + } + identity pos { + base iana-interface-type; + description + "Packet over SONET/SDH Interface."; + } + identity dvbAsiIn { + base iana-interface-type; + description + "DVB-ASI Input."; + } + identity dvbAsiOut { + base iana-interface-type; + description + "DVB-ASI Output."; + } + identity plc { + base iana-interface-type; + description + "Power Line Communications."; + } + identity nfas { + base iana-interface-type; + description + "Non-Facility Associated Signaling."; + } + identity tr008 { + base iana-interface-type; + description + "TR008."; + } + identity gr303RDT { + base iana-interface-type; + description + "Remote Digital Terminal."; + } + identity gr303IDT { + base iana-interface-type; + description + "Integrated Digital Terminal."; + } + identity isup { + base iana-interface-type; + description + "ISUP."; + } + identity propDocsWirelessMaclayer { + base iana-interface-type; + description + "Cisco proprietary Maclayer."; + } + identity propDocsWirelessDownstream { + base iana-interface-type; + description + "Cisco proprietary Downstream."; + } + identity propDocsWirelessUpstream { + base iana-interface-type; + description + "Cisco proprietary Upstream."; + } + identity hiperlan2 { + base iana-interface-type; + description + "HIPERLAN Type 2 Radio Interface."; + } + identity propBWAp2Mp { + base iana-interface-type; + description + "PropBroadbandWirelessAccesspt2Multipt (use of this value + for IEEE 802.16 WMAN interfaces as per IEEE Std 802.16f + is deprecated, and ieee80216WMAN(237) should be used + instead)."; + } + identity sonetOverheadChannel { + base iana-interface-type; + description + "SONET Overhead Channel."; + } + identity digitalWrapperOverheadChannel { + base iana-interface-type; + description + "Digital Wrapper."; + } + identity aal2 { + base iana-interface-type; + description + "ATM adaptation layer 2."; + } + identity radioMAC { + base iana-interface-type; + description + "MAC layer over radio links."; + } + identity atmRadio { + base iana-interface-type; + description + "ATM over radio links."; + } + identity imt { + base iana-interface-type; + description + "Inter-Machine Trunks."; + } + identity mvl { + base iana-interface-type; + description + "Multiple Virtual Lines DSL."; + } + identity reachDSL { + base iana-interface-type; + description + "Long Reach DSL."; + } + identity frDlciEndPt { + base iana-interface-type; + description + "Frame Relay DLCI End Point."; + } + identity atmVciEndPt { + base iana-interface-type; + description + "ATM VCI End Point."; + } + identity opticalChannel { + base iana-interface-type; + description + "Optical Channel."; + } + identity opticalTransport { + base iana-interface-type; + description + "Optical Transport."; + } + identity propAtm { + base iana-interface-type; + description + "Proprietary ATM."; + } + identity voiceOverCable { + base iana-interface-type; + description + "Voice Over Cable Interface."; + } + identity infiniband { + base iana-interface-type; + description + "Infiniband."; + } + identity teLink { + base iana-interface-type; + description + "TE Link."; + } + identity q2931 { + base iana-interface-type; + description + "Q.2931."; + } + identity virtualTg { + base iana-interface-type; + description + "Virtual Trunk Group."; + } + identity sipTg { + base iana-interface-type; + description + "SIP Trunk Group."; + } + identity sipSig { + base iana-interface-type; + description + "SIP Signaling."; + } + identity docsCableUpstreamChannel { + base iana-interface-type; + description + "CATV Upstream Channel."; + } + identity econet { + base iana-interface-type; + description + "Acorn Econet."; + } + identity pon155 { + base iana-interface-type; + description + "FSAN 155Mb Symetrical PON interface."; + } + identity pon622 { + base iana-interface-type; + description + "FSAN 622Mb Symetrical PON interface."; + } + identity bridge { + base iana-interface-type; + description + "Transparent bridge interface."; + } + identity linegroup { + base iana-interface-type; + description + "Interface common to multiple lines."; + } + identity voiceEMFGD { + base iana-interface-type; + description + "Voice E&M Feature Group D."; + } + identity voiceFGDEANA { + base iana-interface-type; + description + "Voice FGD Exchange Access North American."; + } + identity voiceDID { + base iana-interface-type; + description + "Voice Direct Inward Dialing."; + } + identity mpegTransport { + base iana-interface-type; + description + "MPEG transport interface."; + } + identity sixToFour { + base iana-interface-type; + status deprecated; + description + "6to4 interface (DEPRECATED)."; + reference + "RFC 4087 - IP Tunnel MIB"; + } + identity gtp { + base iana-interface-type; + description + "GTP (GPRS Tunneling Protocol)."; + } + identity pdnEtherLoop1 { + base iana-interface-type; + description + "Paradyne EtherLoop 1."; + } + identity pdnEtherLoop2 { + base iana-interface-type; + description + "Paradyne EtherLoop 2."; + } + identity opticalChannelGroup { + base iana-interface-type; + description + "Optical Channel Group."; + } + identity homepna { + base iana-interface-type; + description + "HomePNA ITU-T G.989."; + } + identity gfp { + base iana-interface-type; + description + "Generic Framing Procedure (GFP)."; + } + identity ciscoISLvlan { + base iana-interface-type; + description + "Layer 2 Virtual LAN using Cisco ISL."; + } + identity actelisMetaLOOP { + base iana-interface-type; + description + "Acteleis proprietary MetaLOOP High Speed Link."; + } + identity fcipLink { + base iana-interface-type; + description + "FCIP Link."; + } + identity rpr { + base iana-interface-type; + description + "Resilient Packet Ring Interface Type."; + } + identity qam { + base iana-interface-type; + description + "RF Qam Interface."; + } + identity lmp { + base iana-interface-type; + description + "Link Management Protocol."; + reference + "RFC 4327 - Link Management Protocol (LMP) Management + Information Base (MIB)"; + } + identity cblVectaStar { + base iana-interface-type; + description + "Cambridge Broadband Networks Limited VectaStar."; + } + identity docsCableMCmtsDownstream { + base iana-interface-type; + description + "CATV Modular CMTS Downstream Interface."; + } + identity adsl2 { + base iana-interface-type; + status deprecated; + description + "Asymmetric Digital Subscriber Loop Version 2 + (DEPRECATED/OBSOLETED - please use adsl2plus(238) + instead)."; + reference + "RFC 4706 - Definitions of Managed Objects for Asymmetric + Digital Subscriber Line 2 (ADSL2)"; + } + identity macSecControlledIF { + base iana-interface-type; + description + "MACSecControlled."; + } + identity macSecUncontrolledIF { + base iana-interface-type; + description + "MACSecUncontrolled."; + } + identity aviciOpticalEther { + base iana-interface-type; + description + "Avici Optical Ethernet Aggregate."; + } + identity atmbond { + base iana-interface-type; + description + "atmbond."; + } + identity voiceFGDOS { + base iana-interface-type; + description + "Voice FGD Operator Services."; + } + identity mocaVersion1 { + base iana-interface-type; + description + "MultiMedia over Coax Alliance (MoCA) Interface + as documented in information provided privately to IANA."; + } + identity ieee80216WMAN { + base iana-interface-type; + description + "IEEE 802.16 WMAN interface."; + } + identity adsl2plus { + base iana-interface-type; + description + "Asymmetric Digital Subscriber Loop Version 2 - + Version 2 Plus and all variants."; + } + identity dvbRcsMacLayer { + base iana-interface-type; + description + "DVB-RCS MAC Layer."; + reference + "RFC 5728 - The SatLabs Group DVB-RCS MIB"; + } + identity dvbTdm { + base iana-interface-type; + description + "DVB Satellite TDM."; + reference + "RFC 5728 - The SatLabs Group DVB-RCS MIB"; + } + identity dvbRcsTdma { + base iana-interface-type; + description + "DVB-RCS TDMA."; + reference + "RFC 5728 - The SatLabs Group DVB-RCS MIB"; + } + identity x86Laps { + base iana-interface-type; + description + "LAPS based on ITU-T X.86/Y.1323."; + } + identity wwanPP { + base iana-interface-type; + description + "3GPP WWAN."; + } + identity wwanPP2 { + base iana-interface-type; + description + "3GPP2 WWAN."; + } + identity voiceEBS { + base iana-interface-type; + description + "Voice P-phone EBS physical interface."; + } + identity ifPwType { + base iana-interface-type; + description + "Pseudowire interface type."; + reference + "RFC 5601 - Pseudowire (PW) Management Information Base (MIB)"; + } + identity ilan { + base iana-interface-type; + description + "Internal LAN on a bridge per IEEE 802.1ap."; + } + identity pip { + base iana-interface-type; + description + "Provider Instance Port on a bridge per IEEE 802.1ah PBB."; + } + identity aluELP { + base iana-interface-type; + description + "Alcatel-Lucent Ethernet Link Protection."; + } + identity gpon { + base iana-interface-type; + description + "Gigabit-capable passive optical networks (G-PON) as per + ITU-T G.948."; + } + identity vdsl2 { + base iana-interface-type; + description + "Very high speed digital subscriber line Version 2 + (as per ITU-T Recommendation G.993.2)."; + reference + "RFC 5650 - Definitions of Managed Objects for Very High + Speed Digital Subscriber Line 2 (VDSL2)"; + } + identity capwapDot11Profile { + base iana-interface-type; + description + "WLAN Profile Interface."; + reference + "RFC 5834 - Control and Provisioning of Wireless Access + Points (CAPWAP) Protocol Binding MIB for + IEEE 802.11"; + } + identity capwapDot11Bss { + base iana-interface-type; + description + "WLAN BSS Interface."; + reference + "RFC 5834 - Control and Provisioning of Wireless Access + Points (CAPWAP) Protocol Binding MIB for + IEEE 802.11"; + } + identity capwapWtpVirtualRadio { + base iana-interface-type; + description + "WTP Virtual Radio Interface."; + reference + "RFC 5833 - Control and Provisioning of Wireless Access + Points (CAPWAP) Protocol Base MIB"; + } + identity bits { + base iana-interface-type; + description + "bitsport."; + } + identity docsCableUpstreamRfPort { + base iana-interface-type; + description + "DOCSIS CATV Upstream RF Port."; + } + identity cableDownstreamRfPort { + base iana-interface-type; + description + "CATV downstream RF Port."; + } + identity vmwareVirtualNic { + base iana-interface-type; + description + "VMware Virtual Network Interface."; + } + identity ieee802154 { + base iana-interface-type; + description + "IEEE 802.15.4 WPAN interface."; + reference + "IEEE 802.15.4-2006"; + } + identity otnOdu { + base iana-interface-type; + description + "OTN Optical Data Unit."; + } + identity otnOtu { + base iana-interface-type; + description + "OTN Optical channel Transport Unit."; + } + identity ifVfiType { + base iana-interface-type; + description + "VPLS Forwarding Instance Interface Type."; + } + identity g9981 { + base iana-interface-type; + description + "G.998.1 bonded interface."; + } + identity g9982 { + base iana-interface-type; + description + "G.998.2 bonded interface."; + } + identity g9983 { + base iana-interface-type; + description + "G.998.3 bonded interface."; + } + + identity aluEpon { + base iana-interface-type; + description + "Ethernet Passive Optical Networks (E-PON)."; + } + identity aluEponOnu { + base iana-interface-type; + description + "EPON Optical Network Unit."; + } + identity aluEponPhysicalUni { + base iana-interface-type; + description + "EPON physical User to Network interface."; + } + identity aluEponLogicalLink { + base iana-interface-type; + description + "The emulation of a point-to-point link over the EPON + layer."; + } + identity aluGponOnu { + base iana-interface-type; + description + "GPON Optical Network Unit."; + reference + "ITU-T G.984.2"; + } + identity aluGponPhysicalUni { + base iana-interface-type; + description + "GPON physical User to Network interface."; + reference + "ITU-T G.984.2"; + } + identity vmwareNicTeam { + base iana-interface-type; + description + "VMware NIC Team."; + } + identity docsOfdmDownstream { + base iana-interface-type; + description + "CATV Downstream OFDM interface."; + } + identity docsOfdmaUpstream { + base iana-interface-type; + description + "CATV Upstream OFDMA interface."; + } + identity gfast { + base iana-interface-type; + description + "G.fast port."; + reference + "ITU-T G.9701"; + } + identity sdci { + base iana-interface-type; + description + "SDCI (IO-Link)."; + reference + "IEC 61131-9 Edition 1.0 2013-09"; + } + identity xboxWireless { + base iana-interface-type; + description + "Xbox wireless."; + } + identity fastdsl { + base iana-interface-type; + description + "FastDSL."; + reference + "BBF TR-355"; + } + identity docsCableScte55d1FwdOob { + base iana-interface-type; + description + "Cable SCTE 55-1 OOB Forward Channel."; + } + identity docsCableScte55d1RetOob { + base iana-interface-type; + description + "Cable SCTE 55-1 OOB Return Channel."; + } + identity docsCableScte55d2DsOob { + base iana-interface-type; + description + "Cable SCTE 55-2 OOB Downstream Channel."; + } + identity docsCableScte55d2UsOob { + base iana-interface-type; + description + "Cable SCTE 55-2 OOB Upstream Channel."; + } + identity docsCableNdf { + base iana-interface-type; + description + "Cable Narrowband Digital Forward."; + } + identity docsCableNdr { + base iana-interface-type; + description + "Cable Narrowband Digital Return."; + } + identity ptm { + base iana-interface-type; + description + "Packet Transfer Mode."; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-alarms@2019-09-11.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-alarms@2019-09-11.yang new file mode 100644 index 0000000..a1c195f --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-alarms@2019-09-11.yang @@ -0,0 +1,1526 @@ +module ietf-alarms { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-alarms"; + prefix al; + + import ietf-yang-types { + prefix yang; + reference + "RFC 6991: Common YANG Data Types."; + } + + organization + "IETF CCAMP Working Group"; + contact + "WG Web: + WG List: + + Editor: Stefan Vallin + + + Editor: Martin Bjorklund + "; + description + "This module defines an interface for managing alarms. Main + inputs to the module design are the 3GPP Alarm Integration + Reference Point (IRP), ITU-T X.733, and ANSI/ISA-18.2 alarm + standards. + Main features of this module include: + + * Alarm list: + A list of all alarms. Cleared alarms stay in + the list until explicitly purged. + + * Operator actions on alarms: + Acknowledging and closing alarms. + + * Administrative actions on alarms: + Purging alarms from the list according to specific + criteria. + + * Alarm inventory: + A management application can read all + alarm types implemented by the system. + + * Alarm shelving: + Shelving (blocking) alarms according + to specific criteria. + + * Alarm profiles: + A management system can attach further + information to alarm types, for example, + overriding system-default severity + levels. + + This module uses a stateful view on alarms. An alarm is a state + for a specific resource (note that an alarm is not a + notification). An alarm type is a possible alarm state for a + resource. For example, the tuple: + + ('link-alarm', 'GigabitEthernet0/25') + + is an alarm of type 'link-alarm' on the resource + 'GigabitEthernet0/25'. + + Alarm types are identified using YANG identities and an optional + string-based qualifier. The string-based qualifier allows for + dynamic extension of the statically defined alarm types. Alarm + types identify a possible alarm state and not the individual + notifications. For example, the traditional 'link-down' and + 'link-up' notifications are two notifications referring to the + same alarm type 'link-alarm'. + + With this design, there is no ambiguity about how alarm and + alarm clear correlation should be performed; notifications that + report the same resource and alarm type are considered updates + of the same alarm, e.g., clearing an active alarm or changing + the severity of an alarm. The instrumentation can update the + severity and alarm text on an existing alarm. The above alarm + example can therefore look like the following: + + (('link-alarm', 'GigabitEthernet0/25'), + warning, + 'interface down while interface admin state is up') + + There is a clear separation between updates on the alarm from + the underlying resource, like clear, and updates from an + operator, like acknowledging or closing an alarm: + + (('link-alarm', 'GigabitEthernet0/25'), + warning, + 'interface down while interface admin state is up', + cleared, + closed) + + Administrative actions like removing closed alarms older than a + given time is supported. + + This YANG module does not define how the underlying + instrumentation detects and clears the specific alarms. That + belongs to the Standards Development Organization (SDO) or + enterprise that owns that specific technology. + + The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL + NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED', + 'MAY', and 'OPTIONAL' in this document are to be interpreted as + described in BCP 14 (RFC 2119) (RFC 8174) when, and only when, + they appear in all capitals, as shown here. + + Copyright (c) 2019 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 8632; see + the RFC itself for full legal notices."; + + revision 2019-09-11 { + description + "Initial revision."; + reference + "RFC 8632: A YANG Data Model for Alarm Management"; + } + + /* + * Features + */ + + feature operator-actions { + description + "This feature indicates that the system supports operator + states on alarms."; + } + + feature alarm-shelving { + description + "This feature indicates that the system supports shelving + (blocking) alarms. + + Alarm shelving may have an impact on server processing + resources in order to match alarms against shelf + criteria."; + } + + feature alarm-history { + description + "This feature indicates that the server maintains a history + of state changes for each alarm. For example, if an alarm + toggles between cleared and active 10 times, these state + changes are present in a separate list in the alarm. + + Keeping the alarm history may have an impact on server + memory resources."; + } + + feature alarm-summary { + description + "This feature indicates that the server summarizes the number + of alarms per severity and operator state."; + } + + feature alarm-profile { + description + "The system enables clients to configure further information + to each alarm type."; + } + + feature severity-assignment { + description + "The system supports configurable alarm severity levels."; + reference + "ITU-T Recommendation M.3100: + Generic network information model + ITU-T Recommendation M.3160: + Generic, protocol-neutral management information model"; + } + + feature root-cause-analysis { + description + "The system supports identifying candidate root-cause + resources for an alarm, for example, a disk partition + root cause for a logger failure alarm."; + } + + feature service-impact-analysis { + description + "The system supports identifying candidate-impacted + resources for an alarm, for example, an interface state change + resulting in a link alarm, which can refer to a link as being + impacted."; + } + + feature alarm-correlation { + description + "The system supports correlating/grouping alarms + that belong together."; + } + + /* + * Identities + */ + + identity alarm-type-id { + description + "Base identity for alarm types. A unique identification of + the alarm, not including the resource. Different resources + can share alarm types. If the resource reports the same + alarm type, it is considered to be the same alarm. The alarm + type is a simplification of the different X.733 and 3GPP Alarm + IRP correlation mechanisms, and it allows for + hierarchical extensions. + + A string-based qualifier can be used in addition to the + identity in order to have different alarm types based on + information not known at design time, such as values in + textual SNMP Notification varbinds. + + Standards and vendors can define sub-identities to clearly + identify specific alarm types. + + This identity is abstract and MUST NOT be used for alarms."; + } + + /* + * Common types + */ + + typedef resource { + type union { + type instance-identifier { + require-instance false; + } + type yang:object-identifier; + type string; + type yang:uuid; + } + description + "This is an identification of the alarming resource, such as an + interface. It should be as fine-grained as possible to both + guide the operator and guarantee uniqueness of the alarms. + + If the alarming resource is modeled in YANG, this type will + be an instance-identifier. + + If the resource is an SNMP object, the type will be an + 'object-identifier'. + + If the resource is anything else, for example, a distinguished + name or a Common Information Model (CIM) path, this type will + be a string. + + If the alarming object is identified by a Universally Unique + Identifier (UUID), use the uuid type. Be cautious when using + this type, since a UUID is hard to use for an operator. + + If the server supports several models, the precedence should + be in the order as given in the union definition."; + } + + typedef resource-match { + type union { + type yang:xpath1.0; + type yang:object-identifier; + type string; + } + description + "This type is used to match resources of type 'resource'. + Since the type 'resource' is a union of different types, the + 'resource-match' type is also a union of corresponding types. + + If the type is given as an XPath 1.0 expression, a resource + of type 'instance-identifier' matches if the instance is part + of the node set that is the result of evaluating the XPath 1.0 + expression. For example, the XPath 1.0 expression: + + /ietf-interfaces:interfaces/ietf-interfaces:interface + [ietf-interfaces:type='ianaift:ethernetCsmacd'] + + would match the resource instance-identifier: + + /if:interfaces/if:interface[if:name='eth1'], + + assuming that the interface 'eth1' is of type + 'ianaift:ethernetCsmacd'. + + If the type is given as an object identifier, a resource of + type 'object-identifier' matches if the match object + identifier is a prefix of the resource's object identifier. + For example, the value: + + 1.3.6.1.2.1.2.2 + + would match the resource object identifier: + + 1.3.6.1.2.1.2.2.1.1.5 + + If the type is given as an UUID or a string, it is interpreted + as an XML Schema regular expression, which matches a resource + of type 'yang:uuid' or 'string' if the given regular + expression matches the resource string. + + If the type is given as an XPath expression, it is evaluated + in the following XPath context: + + o The set of namespace declarations is the set of prefix + and namespace pairs for all YANG modules implemented by + the server, where the prefix is the YANG module name and + the namespace is as defined by the 'namespace' statement + in the YANG module. + + If a leaf of this type is encoded in XML, all namespace + declarations in scope on the leaf element are added to + the set of namespace declarations. If a prefix found in + the XML is already present in the set of namespace + declarations, the namespace in the XML is used. + + o The set of variable bindings is empty. + + o The function library is the core function library, and + the functions are defined in Section 10 of RFC 7950. + + o The context node is the root node in the data tree."; + reference + "XML Schema Part 2: Datatypes Second Edition, + World Wide Web Consortium Recommendation + REC-xmlschema-2-20041028"; + } + + typedef alarm-text { + type string; + description + "The string used to inform operators about the alarm. This + MUST contain enough information for an operator to be able to + understand the problem and how to resolve it. If this string + contains structure, this format should be clearly documented + for programs to be able to parse that information."; + } + + typedef severity { + type enumeration { + enum indeterminate { + value 2; + description + "Indicates that the severity level could not be + determined. This level SHOULD be avoided."; + } + enum warning { + value 3; + description + "The 'warning' severity level indicates the detection of a + potential or impending service-affecting fault, before any + significant effects have been felt. Action should be + taken to further diagnose (if necessary) and correct the + problem in order to prevent it from becoming a more + serious service-affecting fault."; + } + enum minor { + value 4; + description + "The 'minor' severity level indicates the existence of a + non-service-affecting fault condition and that corrective + action should be taken in order to prevent a more serious + (for example, service-affecting) fault. Such a severity + can be reported, for example, when the detected alarm + condition is not currently degrading the capacity of the + resource."; + } + enum major { + value 5; + description + "The 'major' severity level indicates that a service- + affecting condition has developed and an urgent corrective + action is required. Such a severity can be reported, for + example, when there is a severe degradation in the + capability of the resource and its full capability must be + restored."; + } + enum critical { + value 6; + description + "The 'critical' severity level indicates that a service- + affecting condition has occurred and an immediate + corrective action is required. Such a severity can be + reported, for example, when a resource becomes totally out + of service and its capability must be restored."; + } + } + description + "The severity level of the alarm. Note well that the value + 'clear' is not included. Whether or not an alarm is cleared + is a separate boolean flag."; + reference + "ITU-T Recommendation X.733: Information Technology + - Open Systems Interconnection + - System Management: Alarm Reporting Function"; + } + + typedef severity-with-clear { + type union { + type enumeration { + enum cleared { + value 1; + description + "The alarm is cleared by the instrumentation."; + } + } + type severity; + } + description + "The severity level of the alarm including clear. This is used + only in notifications reporting state changes for an alarm."; + } + + typedef writable-operator-state { + type enumeration { + enum none { + value 1; + description + "The alarm is not being taken care of."; + } + enum ack { + value 2; + description + "The alarm is being taken care of. Corrective action not + taken yet or has failed"; + } + enum closed { + value 3; + description + "Corrective action taken successfully."; + } + } + description + "Operator states on an alarm. The 'closed' state indicates + that an operator considers the alarm being resolved. This is + separate from the alarm's 'is-cleared' leaf."; + } + + typedef operator-state { + type union { + type writable-operator-state; + type enumeration { + enum shelved { + value 4; + description + "The alarm is shelved. Alarms in /alarms/shelved-alarms/ + MUST be assigned this operator state by the server as + the last entry in the 'operator-state-change' list. The + text for that entry SHOULD include the shelf name."; + } + enum un-shelved { + value 5; + description + "The alarm is moved back to 'alarm-list' from a shelf. + Alarms that are moved from /alarms/shelved-alarms/ to + /alarms/alarm-list MUST be assigned this state by the + server as the last entry in the 'operator-state-change' + list. The text for that entry SHOULD include the shelf + name."; + } + } + } + description + "Operator states on an alarm. The 'closed' state indicates + that an operator considers the alarm being resolved. This is + separate from the alarm's 'is-cleared' leaf."; + } + + /* Alarm type */ + + typedef alarm-type-id { + type identityref { + base alarm-type-id; + } + description + "Identifies an alarm type. The description of the alarm type + id MUST indicate whether or not the alarm type is abstract. + An abstract alarm type is used as a base for other alarm type + ids and will not be used as a value for an alarm or be present + in the alarm inventory."; + } + + typedef alarm-type-qualifier { + type string; + description + "If an alarm type cannot be fully specified at design time by + 'alarm-type-id', this string qualifier is used in addition to + fully define a unique alarm type. + + The definition of alarm qualifiers is considered to be part of + the instrumentation and is out of scope for this module. An + empty string is used when this is part of a key."; + } + + /* + * Groupings + */ + + grouping common-alarm-parameters { + description + "Common parameters for an alarm. + + This grouping is used both in the alarm list and in the + notification representing an alarm-state change."; + leaf resource { + type resource; + mandatory true; + description + "The alarming resource. See also 'alt-resource'. This could + be, for example, a reference to the alarming interface"; + } + leaf alarm-type-id { + type alarm-type-id; + mandatory true; + description + "This leaf and the leaf 'alarm-type-qualifier' together + provide a unique identification of the alarm type."; + } + leaf alarm-type-qualifier { + type alarm-type-qualifier; + description + "This leaf is used when the 'alarm-type-id' leaf cannot + uniquely identify the alarm type. Normally, this is not the + case, and this leaf is the empty string."; + } + leaf-list alt-resource { + type resource; + description + "Used if the alarming resource is available over other + interfaces. This field can contain SNMP OIDs, CIM paths, or + 3GPP distinguished names, for example."; + } + list related-alarm { + if-feature "alarm-correlation"; + key "resource alarm-type-id alarm-type-qualifier"; + description + "References to related alarms. Note that the related alarm + might have been purged from the alarm list."; + leaf resource { + type leafref { + path "/alarms/alarm-list/alarm/resource"; + require-instance false; + } + description + "The alarming resource for the related alarm."; + } + leaf alarm-type-id { + type leafref { + path "/alarms/alarm-list/alarm" + + "[resource=current()/../resource]" + + "/alarm-type-id"; + require-instance false; + } + description + "The alarm type identifier for the related alarm."; + } + leaf alarm-type-qualifier { + type leafref { + path "/alarms/alarm-list/alarm" + + "[resource=current()/../resource]" + + "[alarm-type-id=current()/../alarm-type-id]" + + "/alarm-type-qualifier"; + require-instance false; + } + description + "The alarm qualifier for the related alarm."; + } + } + leaf-list impacted-resource { + if-feature "service-impact-analysis"; + type resource; + description + "Resources that might be affected by this alarm. If the + system creates an alarm on a resource and also has a mapping + to other resources that might be impacted, these resources + can be listed in this leaf-list. In this way, the system + can create one alarm instead of several. For example, if an + interface has an alarm, the 'impacted-resource' can + reference the aggregated port channels."; + } + leaf-list root-cause-resource { + if-feature "root-cause-analysis"; + type resource; + description + "Resources that are candidates for causing the alarm. If the + system has a mechanism to understand the candidate root + causes of an alarm, this leaf-list can be used to list the + root-cause candidate resources. In this way, the system can + create one alarm instead of several. An example might be a + logging system (alarm resource) that fails; the alarm can + reference the file system in the 'root-cause-resource' + leaf-list. Note that the intended use is not to also send + an alarm with the 'root-cause-resource' as an alarming + resource. The 'root-cause-resource' leaf-list is a hint and + should not also generate an alarm for the same problem."; + } + } + + grouping alarm-state-change-parameters { + description + "Parameters for an alarm-state change. + + This grouping is used both in the alarm list's status-change + list and in the notification representing an alarm-state + change."; + leaf time { + type yang:date-and-time; + mandatory true; + description + "The time the status of the alarm changed. The value + represents the time the real alarm-state change appeared in + the resource and not when it was added to the alarm + list. The /alarm-list/alarm/last-changed MUST be set to the + same value."; + } + leaf perceived-severity { + type severity-with-clear; + mandatory true; + description + "The severity of the alarm as defined by X.733. Note that + this may not be the original severity since the alarm may + have changed severity."; + reference + "ITU-T Recommendation X.733: Information Technology + - Open Systems Interconnection + - System Management: Alarm Reporting Function"; + } + leaf alarm-text { + type alarm-text; + mandatory true; + description + "A user-friendly text describing the alarm-state change."; + reference + "ITU-T Recommendation X.733: Information Technology + - Open Systems Interconnection + - System Management: Alarm Reporting Function"; + } + } + + grouping operator-parameters { + description + "This grouping defines parameters that can be changed by an + operator."; + leaf time { + type yang:date-and-time; + mandatory true; + description + "Timestamp for operator action on the alarm."; + } + leaf operator { + type string; + mandatory true; + description + "The name of the operator that has acted on this alarm."; + } + leaf state { + type operator-state; + mandatory true; + description + "The operator's view of the alarm state."; + } + leaf text { + type string; + description + "Additional optional textual information provided by the + operator."; + } + } + + grouping resource-alarm-parameters { + description + "Alarm parameters that originate from the resource view."; + leaf is-cleared { + type boolean; + mandatory true; + description + "Indicates the current clearance state of the alarm. An + alarm might toggle from active alarm to cleared alarm and + back to active again."; + } + leaf last-raised { + type yang:date-and-time; + mandatory true; + description + "An alarm may change severity level and toggle between + active and cleared during its lifetime. This leaf indicates + the last time it was raised ('is-cleared' = 'false')."; + } + leaf last-changed { + type yang:date-and-time; + mandatory true; + description + "A timestamp when the 'status-change' or + 'operator-state-change' list was last changed."; + } + leaf perceived-severity { + type severity; + mandatory true; + description + "The last severity of the alarm. + + If an alarm was raised with severity 'warning' but later + changed to 'major', this leaf will show 'major'."; + } + leaf alarm-text { + type alarm-text; + mandatory true; + description + "The last reported alarm text. This text should contain + information for an operator to be able to understand the + problem and how to resolve it."; + } + list status-change { + if-feature "alarm-history"; + key "time"; + min-elements 1; + description + "A list of status-change events for this alarm. + + The entry with latest timestamp in this list MUST + correspond to the leafs 'is-cleared', 'perceived-severity', + and 'alarm-text' for the alarm. + + This list is ordered according to the timestamps of alarm + state changes. The first item corresponds to the latest + state change. + + The following state changes create an entry in this + list: + - changed severity (warning, minor, major, critical) + - clearance status; this also updates the 'is-cleared' + leaf + - alarm-text update"; + uses alarm-state-change-parameters; + } + } + + grouping filter-input { + description + "Grouping to specify a filter construct on alarm information."; + leaf alarm-clearance-status { + type enumeration { + enum any { + description + "Ignore alarm-clearance status."; + } + enum cleared { + description + "Filter cleared alarms."; + } + enum not-cleared { + description + "Filter not-cleared alarms."; + } + } + mandatory true; + description + "The clearance status of the alarm."; + } + container older-than { + presence "Age specification"; + description + "Matches the 'last-status-change' leaf in the alarm."; + choice age-spec { + description + "Filter using date and time age."; + case seconds { + leaf seconds { + type uint16; + description + "Age expressed in seconds."; + } + } + case minutes { + leaf minutes { + type uint16; + description + "Age expressed in minutes."; + } + } + case hours { + leaf hours { + type uint16; + description + "Age expressed in hours."; + } + } + case days { + leaf days { + type uint16; + description + "Age expressed in days."; + } + } + case weeks { + leaf weeks { + type uint16; + description + "Age expressed in weeks."; + } + } + } + } + container severity { + presence "Severity filter"; + choice sev-spec { + description + "Filter based on severity level."; + leaf below { + type severity; + description + "Severity less than this leaf."; + } + leaf is { + type severity; + description + "Severity level equal to this leaf."; + } + leaf above { + type severity; + description + "Severity level higher than this leaf."; + } + } + description + "Filter based on severity."; + } + container operator-state-filter { + if-feature "operator-actions"; + presence "Operator state filter"; + leaf state { + type operator-state; + description + "Filter on operator state."; + } + leaf user { + type string; + description + "Filter based on which operator."; + } + description + "Filter based on operator state."; + } + } + + /* + * The /alarms data tree + */ + + container alarms { + description + "The top container for this module."; + container control { + description + "Configuration to control the alarm behavior."; + leaf max-alarm-status-changes { + type union { + type uint16; + type enumeration { + enum infinite { + description + "The status-change entries are accumulated + infinitely."; + } + } + } + default "32"; + description + "The 'status-change' entries are kept in a circular list + per alarm. When this number is exceeded, the oldest + status change entry is automatically removed. If the + value is 'infinite', the status-change entries are + accumulated infinitely."; + } + leaf notify-status-changes { + type enumeration { + enum all-state-changes { + description + "Send notifications for all status changes."; + } + enum raise-and-clear { + description + "Send notifications only for raise, clear, and + re-raise. Notifications for severity-level changes or + alarm-text changes are not sent."; + } + enum severity-level { + description + "Only send notifications for alarm-state changes + crossing the level specified in + 'notify-severity-level'. Always send clear + notifications."; + } + } + must '. != "severity-level" or ../notify-severity-level' { + description + "When notify-status-changes is 'severity-level', a value + must be given for 'notify-severity-level'."; + } + default "all-state-changes"; + description + "This leaf controls the notifications sent for alarm status + updates. There are three options: + + 1. Notifications are sent for all updates, severity-level + changes, and alarm-text changes. + + 2. Notifications are only sent for alarm raise and clear. + + 3. Notifications are sent for status changes equal to or + above the specified severity level. Clear + notifications shall always be sent. Notifications + shall also be sent for state changes that make an + alarm less severe than the specified level. + + For example, in option 3, assume that the severity level + is set to major and that the alarm has the following state + changes: + + [(Time, severity, clear)]: + [(T1, major, -), (T2, minor, -), (T3, warning, -), + (T4, minor, -), (T5, major, -), (T6, critical, -), + (T7, major. -), (T8, major, clear)] + + In that case, notifications will be sent at times + T1, T2, T5, T6, T7, and T8."; + } + leaf notify-severity-level { + when '../notify-status-changes = "severity-level"'; + type severity; + description + "Only send notifications for alarm-state changes crossing + the specified level. Always send clear notifications."; + } + container alarm-shelving { + if-feature "alarm-shelving"; + description + "The 'alarm-shelving/shelf' list is used to shelve + (block/filter) alarms. The conditions in the shelf + criteria are logically ANDed. The first matching shelf is + used, and an alarm is shelved only for this first match. + Matching alarms MUST appear in the + /alarms/shelved-alarms/shelved-alarm list, and + non-matching /alarms MUST appear in the + /alarms/alarm-list/alarm list. The server does not send + any notifications for shelved alarms. + + The server MUST maintain states (e.g., severity + changes) for the shelved alarms. + + Alarms that match the criteria shall have an + operator state 'shelved'. When the shelf + configuration removes an alarm from the shelf, the server + shall add the operator state 'un-shelved'."; + list shelf { + key "name"; + ordered-by user; + leaf name { + type string; + description + "An arbitrary name for the alarm shelf."; + } + description + "Each entry defines the criteria for shelving alarms. + Criteria are ANDed. If no criteria are specified, + all alarms will be shelved."; + leaf-list resource { + type resource-match; + description + "Shelve alarms for matching resources."; + } + list alarm-type { + key "alarm-type-id alarm-type-qualifier-match"; + description + "Any alarm matching the combined criteria of + 'alarm-type-id' and 'alarm-type-qualifier-match' + MUST be matched."; + leaf alarm-type-id { + type alarm-type-id; + description + "Shelve all alarms that have an 'alarm-type-id' that + is equal to or derived from the given + 'alarm-type-id'."; + } + leaf alarm-type-qualifier-match { + type string; + description + "An XML Schema regular expression that is used to + match an alarm type qualifier. Shelve all alarms + that match this regular expression for the alarm + type qualifier."; + reference + "XML Schema Part 2: Datatypes Second Edition, + World Wide Web Consortium Recommendation + REC-xmlschema-2-20041028"; + } + } + leaf description { + type string; + description + "An optional textual description of the shelf. This + description should include the reason for shelving + these alarms."; + } + } + } + } + container alarm-inventory { + config false; + description + "The 'alarm-inventory/alarm-type' list contains all possible + alarm types for the system. + + If the system knows for which resources a specific alarm + type can appear, it is also identified in the inventory. + The list also tells if each alarm type has a corresponding + clear state. The inventory shall only contain concrete + alarm types. + + The alarm inventory MUST be updated by the system when new + alarms can appear. This can be the case when installing new + software modules or inserting new card types. A + notification 'alarm-inventory-changed' is sent when the + inventory is changed."; + list alarm-type { + key "alarm-type-id alarm-type-qualifier"; + description + "An entry in this list defines a possible alarm."; + leaf alarm-type-id { + type alarm-type-id; + description + "The statically defined alarm type identifier for this + possible alarm."; + } + leaf alarm-type-qualifier { + type alarm-type-qualifier; + description + "The optionally dynamically defined alarm type identifier + for this possible alarm."; + } + leaf-list resource { + type resource-match; + description + "Optionally, specifies for which resources the alarm type + is valid."; + } + leaf will-clear { + type boolean; + mandatory true; + description + "This leaf tells the operator if the alarm will be + cleared when the correct corrective action has been + taken. Implementations SHOULD strive for detecting the + cleared state for all alarm types. + + If this leaf is 'true', the operator can monitor the + alarm until it becomes cleared after the corrective + action has been taken. + + If this leaf is 'false', the operator needs to validate + that the alarm is no longer active using other + mechanisms. Alarms can lack a corresponding clear due + to missing instrumentation or no logical + corresponding clear state."; + } + leaf-list severity-level { + type severity; + description + "This leaf-list indicates the possible severity levels of + this alarm type. Note well that 'clear' is not part of + the severity type. In general, the severity level + should be defined by the instrumentation based on the + dynamic state, rather than being defined statically by + the alarm type, in order to provide a relevant severity + level based on dynamic state and context. However, most + alarm types have a defined set of possible severity + levels, and this should be provided here."; + } + leaf description { + type string; + mandatory true; + description + "A description of the possible alarm. It SHOULD include + information on possible underlying root causes and + corrective actions."; + } + } + } + container summary { + if-feature "alarm-summary"; + config false; + description + "This container gives a summary of the number of alarms."; + list alarm-summary { + key "severity"; + description + "A global summary of all alarms in the system. The summary + does not include shelved alarms."; + leaf severity { + type severity; + description + "Alarm summary for this severity level."; + } + leaf total { + type yang:gauge32; + description + "Total number of alarms of this severity level."; + } + leaf not-cleared { + type yang:gauge32; + description + "Total number of alarms of this severity level + that are not cleared."; + } + leaf cleared { + type yang:gauge32; + description + "For this severity level, the number of alarms that are + cleared."; + } + leaf cleared-not-closed { + if-feature "operator-actions"; + type yang:gauge32; + description + "For this severity level, the number of alarms that are + cleared but not closed."; + } + leaf cleared-closed { + if-feature "operator-actions"; + type yang:gauge32; + description + "For this severity level, the number of alarms that are + cleared and closed."; + } + leaf not-cleared-closed { + if-feature "operator-actions"; + type yang:gauge32; + description + "For this severity level, the number of alarms that are + not cleared but closed."; + } + leaf not-cleared-not-closed { + if-feature "operator-actions"; + type yang:gauge32; + description + "For this severity level, the number of alarms that are + not cleared and not closed."; + } + } + leaf shelves-active { + if-feature "alarm-shelving"; + type empty; + description + "This is a hint to the operator that there are active + alarm shelves. This leaf MUST exist if the + /alarms/shelved-alarms/number-of-shelved-alarms is > 0."; + } + } + container alarm-list { + config false; + description + "The alarms in the system."; + leaf number-of-alarms { + type yang:gauge32; + description + "This object shows the total number of + alarms in the system, i.e., the total number + of entries in the alarm list."; + } + leaf last-changed { + type yang:date-and-time; + description + "A timestamp when the alarm list was last + changed. The value can be used by a manager to + initiate an alarm resynchronization procedure."; + } + list alarm { + key "resource alarm-type-id alarm-type-qualifier"; + description + "The list of alarms. Each entry in the list holds one + alarm for a given alarm type and resource. An alarm can + be updated from the underlying resource or by the user. + The following leafs are maintained by the resource: + 'is-cleared', 'last-change', 'perceived-severity', and + 'alarm-text'. An operator can change 'operator-state' and + 'operator-text'. + + Entries appear in the alarm list the first time an alarm + becomes active for a given alarm type and resource. + Entries do not get deleted when the alarm is cleared. + Clear status is represented as a boolean flag. + + Alarm entries are removed, i.e., purged, from the list by + an explicit purge action. For example, purge all alarms + that are cleared and in closed operator state that are + older than 24 hours. Purged alarms are removed from the + alarm list. If the alarm resource state changes after a + purge, the alarm will reappear in the alarm list. + + Systems may also remove alarms based on locally configured + policies; this is out of scope for this module."; + uses common-alarm-parameters; + leaf time-created { + type yang:date-and-time; + mandatory true; + description + "The timestamp when this alarm entry was created. This + represents the first time the alarm appeared; it can + also represent that the alarm reappeared after a purge. + Further state changes of the same alarm do not change + this leaf; these changes will update the 'last-changed' + leaf."; + } + uses resource-alarm-parameters; + list operator-state-change { + if-feature "operator-actions"; + key "time"; + description + "This list is used by operators to indicate the state of + human intervention on an alarm. For example, if an + operator has seen an alarm, the operator can add a new + item to this list indicating that the alarm is + acknowledged."; + uses operator-parameters; + } + action set-operator-state { + if-feature "operator-actions"; + description + "This is a means for the operator to indicate the level + of human intervention on an alarm."; + input { + leaf state { + type writable-operator-state; + mandatory true; + description + "Set this operator state."; + } + leaf text { + type string; + description + "Additional optional textual information."; + } + } + } + notification operator-action { + if-feature "operator-actions"; + description + "This notification is used to report that an operator + acted upon an alarm."; + uses operator-parameters; + } + } + action purge-alarms { + description + "This operation requests that the server delete entries + from the alarm list according to the supplied criteria. + + Typically, this operation is used to delete alarms that + are in closed operator state and older than a specified + time. + + The number of purged alarms is returned as an output + parameter."; + input { + uses filter-input; + } + output { + leaf purged-alarms { + type uint32; + description + "Number of purged alarms."; + } + } + } + action compress-alarms { + if-feature "alarm-history"; + description + "This operation requests that the server compress + entries in the alarm list by removing all but the + latest 'status-change' entry for all matching alarms. + Conditions in the input are logically ANDed. If no + input condition is given, all alarms are compressed."; + input { + leaf resource { + type resource-match; + description + "Compress the alarms matching this resource."; + } + leaf alarm-type-id { + type leafref { + path "/alarms/alarm-list/alarm/alarm-type-id"; + require-instance false; + } + description + "Compress alarms with this 'alarm-type-id'."; + } + leaf alarm-type-qualifier { + type leafref { + path "/alarms/alarm-list/alarm/alarm-type-qualifier"; + require-instance false; + } + description + "Compress the alarms with this + 'alarm-type-qualifier'."; + } + } + output { + leaf compressed-alarms { + type uint32; + description + "Number of compressed alarm entries."; + } + } + } + } + container shelved-alarms { + if-feature "alarm-shelving"; + config false; + description + "The shelved alarms. Alarms appear here if they match the + criteria in /alarms/control/alarm-shelving. This list does + not generate any notifications. The list represents alarms + that are considered not relevant by the operator. Alarms in + this list have an 'operator-state' of 'shelved'. This + cannot be changed."; + leaf number-of-shelved-alarms { + type yang:gauge32; + description + "This object shows the total number of current + alarms, i.e., the total number of entries + in the alarm list."; + } + leaf shelved-alarms-last-changed { + type yang:date-and-time; + description + "A timestamp when the shelved-alarm list was last changed. + The value can be used by a manager to initiate an alarm + resynchronization procedure."; + } + list shelved-alarm { + key "resource alarm-type-id alarm-type-qualifier"; + description + "The list of shelved alarms. Shelved alarms can only be + updated from the underlying resource; no operator actions + are supported."; + uses common-alarm-parameters; + leaf shelf-name { + type leafref { + path "/alarms/control/alarm-shelving/shelf/name"; + require-instance false; + } + description + "The name of the shelf."; + } + uses resource-alarm-parameters; + list operator-state-change { + if-feature "operator-actions"; + key "time"; + description + "This list is used by operators to indicate the state of + human intervention on an alarm. For shelved alarms, the + system has set the list item in the list to 'shelved'."; + uses operator-parameters; + } + } + action purge-shelved-alarms { + description + "This operation requests that the server delete entries from + the shelved-alarm list according to the supplied criteria. + In the shelved-alarm list, it makes sense to delete alarms + that are not relevant anymore. + + The number of purged alarms is returned as an output + parameter."; + input { + uses filter-input; + } + output { + leaf purged-alarms { + type uint32; + description + "Number of purged alarms."; + } + } + } + action compress-shelved-alarms { + if-feature "alarm-history"; + description + "This operation requests that the server compress entries + in the shelved-alarm list by removing all but the latest + 'status-change' entry for all matching shelved alarms. + Conditions in the input are logically ANDed. If no input + condition is given, all alarms are compressed."; + input { + leaf resource { + type leafref { + path "/alarms/shelved-alarms/shelved-alarm/resource"; + require-instance false; + } + description + "Compress the alarms with this resource."; + } + leaf alarm-type-id { + type leafref { + path "/alarms/shelved-alarms/shelved-alarm" + + "/alarm-type-id"; + require-instance false; + } + description + "Compress alarms with this 'alarm-type-id'."; + } + leaf alarm-type-qualifier { + type leafref { + path "/alarms/shelved-alarms/shelved-alarm" + + "/alarm-type-qualifier"; + require-instance false; + } + description + "Compress the alarms with this + 'alarm-type-qualifier'."; + } + } + output { + leaf compressed-alarms { + type uint32; + description + "Number of compressed alarm entries."; + } + } + } + } + list alarm-profile { + if-feature "alarm-profile"; + key "alarm-type-id alarm-type-qualifier-match resource"; + ordered-by user; + description + "This list is used to assign further information or + configuration for each alarm type. This module supports a + mechanism where the client can override the system-default + alarm severity levels. The 'alarm-profile' is also a useful + augmentation point for specific additions to alarm types."; + leaf alarm-type-id { + type alarm-type-id; + description + "The alarm type identifier to match."; + } + leaf alarm-type-qualifier-match { + type string; + description + "An XML Schema regular expression that is used to match the + alarm type qualifier."; + reference + "XML Schema Part 2: Datatypes Second Edition, + World Wide Web Consortium Recommendation + REC-xmlschema-2-20041028"; + } + leaf resource { + type resource-match; + description + "Specifies which resources to match."; + } + leaf description { + type string; + mandatory true; + description + "A description of the alarm profile."; + } + container alarm-severity-assignment-profile { + if-feature "severity-assignment"; + description + "The client can override the system-default severity + level."; + reference + "ITU-T Recommendation M.3100: + Generic network information model + ITU-T Recommendation M.3160: + Generic, protocol-neutral management information model"; + leaf-list severity-level { + type severity; + ordered-by user; + description + "Specifies the configured severity level(s) for the + matching alarm. If the alarm has several severity + levels, the leaf-list shall be given in rising severity + order. The original M3100/M3160 ASAP function only + allows for a one-to-one mapping between alarm type and + severity, but since YANG module supports stateful + alarms, the mapping must allow for several severity + levels. + + Assume a high-utilization alarm type with two thresholds + with the system-default severity levels of threshold1 = + warning and threshold2 = minor. Setting this leaf-list + to (minor, major) will assign the severity levels as + threshold1 = minor and threshold2 = major"; + } + } + } + } + + /* + * Notifications + */ + + notification alarm-notification { + description + "This notification is used to report a state change for an + alarm. The same notification is used for reporting a newly + raised alarm, a cleared alarm, or changing the text and/or + severity of an existing alarm."; + uses common-alarm-parameters; + uses alarm-state-change-parameters; + } + + notification alarm-inventory-changed { + description + "This notification is used to report that the list of possible + alarms has changed. This can happen when, for example, a new + software module is installed or a new physical card is + inserted."; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-crypto-types@2019-10-18.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-crypto-types@2019-10-18.yang new file mode 100644 index 0000000..c620734 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-crypto-types@2019-10-18.yang @@ -0,0 +1,2173 @@ +module ietf-crypto-types { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-crypto-types"; + prefix ct; + + import ietf-yang-types { + prefix yang; + reference + "RFC 6991: Common YANG Data Types"; + } + + import ietf-netconf-acm { + prefix nacm; + reference + "RFC 8341: Network Configuration Access Control Model"; + } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + contact + "WG Web: + WG List: + Author: Kent Watsen + Author: Wang Haiguang "; + + description + "This module defines common YANG types for cryptographic + applications. + + Copyright (c) 2019 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 XXXX + (https://www.rfc-editor.org/info/rfcXXXX); see the RFC + itself for full legal notices.; + + The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', + 'SHALL NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', + 'NOT RECOMMENDED', 'MAY', and 'OPTIONAL' in this document + are to be interpreted as described in BCP 14 (RFC 2119) + (RFC 8174) when, and only when, they appear in all + capitals, as shown here."; + + revision 2019-10-18 { + description + "Initial version"; + reference + "RFC XXXX: Common YANG Data Types for Cryptography"; + } + + /**************************************/ + /* Identities for Hash Algorithms */ + /**************************************/ + + typedef hash-algorithm-t { + type union { + type uint16; + type enumeration { + enum NONE { + value 0; + description + "Hash algorithm is NULL."; + } + enum sha1 { + value 1; + status obsolete; + description + "The SHA1 algorithm."; + reference + "RFC 3174: US Secure Hash Algorithms 1 (SHA1)."; + } + enum sha-224 { + value 2; + description + "The SHA-224 algorithm."; + reference + "RFC 6234: US Secure Hash Algorithms."; + } + enum sha-256 { + value 3; + description + "The SHA-256 algorithm."; + reference + "RFC 6234: US Secure Hash Algorithms."; + } + enum sha-384 { + value 4; + description + "The SHA-384 algorithm."; + reference + "RFC 6234: US Secure Hash Algorithms."; + } + enum sha-512 { + value 5; + description + "The SHA-512 algorithm."; + reference + "RFC 6234: US Secure Hash Algorithms."; + } + enum shake-128 { + value 6; + description + "The SHA3 algorithm with 128-bits output."; + reference + "National Institute of Standards and Technology, + SHA-3 Standard: Permutation-Based Hash and + Extendable-Output Functions, FIPS PUB 202, DOI + 10.6028/NIST.FIPS.202, August 2015."; + } + enum shake-224 { + value 7; + description + "The SHA3 algorithm with 224-bits output."; + reference + "National Institute of Standards and Technology, + SHA-3 Standard: Permutation-Based Hash and + Extendable-Output Functions, FIPS PUB 202, DOI + 10.6028/NIST.FIPS.202, August 2015."; + } + enum shake-256 { + value 8; + description + "The SHA3 algorithm with 256-bits output."; + reference + "National Institute of Standards and Technology, + SHA-3 Standard: Permutation-Based Hash and + Extendable-Output Functions, FIPS PUB 202, DOI + 10.6028/NIST.FIPS.202, August 2015."; + } + enum shake-384 { + value 9; + description + "The SHA3 algorithm with 384-bits output."; + reference + "National Institute of Standards and Technology, + SHA-3 Standard: Permutation-Based Hash and + Extendable-Output Functions, FIPS PUB 202, DOI + 10.6028/NIST.FIPS.202, August 2015."; + } + enum shake-512 { + value 10; + description + "The SHA3 algorithm with 384-bits output."; + reference + "National Institute of Standards and Technology, + SHA-3 Standard: Permutation-Based Hash and + Extendable-Output Functions, FIPS PUB 202, DOI + 10.6028/NIST.FIPS.202, August 2015."; + } + } + } + default "0"; + description + "The uint16 filed shall be set by individual protocol families + according to the hash algorithm value assigned by IANA. The + setting is optional and by default is 0. The enumeration + filed is set to the selected hash algorithm."; + } + + /***********************************************/ + /* Identities for Asymmetric Key Algorithms */ + /***********************************************/ + + typedef asymmetric-key-algorithm-t { + type union { + type uint16; + type enumeration { + enum NONE { + value 0; + description + "Asymetric key algorithm is NULL."; + } + enum rsa1024 { + value 1; + description + "The RSA algorithm using a 1024-bit key."; + reference + "RFC 8017: PKCS #1: RSA Cryptography + Specifications Version 2.2."; + } + enum rsa2048 { + value 2; + description + "The RSA algorithm using a 2048-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + enum rsa3072 { + value 3; + description + "The RSA algorithm using a 3072-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + enum rsa4096 { + value 4; + description + "The RSA algorithm using a 4096-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + enum rsa7680 { + value 5; + description + "The RSA algorithm using a 7680-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + enum rsa15360 { + value 6; + description + "The RSA algorithm using a 15360-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + enum secp192r1 { + value 7; + description + "The asymmetric algorithm using a NIST P192 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms. + RFC 5480: + Elliptic Curve Cryptography Subject Public Key + Information."; + } + enum secp224r1 { + value 8; + description + "The asymmetric algorithm using a NIST P224 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms. + RFC 5480: + Elliptic Curve Cryptography Subject Public Key + Information."; + } + enum secp256r1 { + value 9; + description + "The asymmetric algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms. + RFC 5480: + Elliptic Curve Cryptography Subject Public Key + Information."; + } + enum secp384r1 { + value 10; + description + "The asymmetric algorithm using a NIST P384 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms. + RFC 5480: + Elliptic Curve Cryptography Subject Public Key + Information."; + } + enum secp521r1 { + value 11; + description + "The asymmetric algorithm using a NIST P521 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms. + RFC 5480: + Elliptic Curve Cryptography Subject Public Key + Information."; + } + enum x25519 { + value 12; + description + "The asymmetric algorithm using a x.25519 Curve."; + reference + "RFC 7748: + Elliptic Curves for Security."; + } + enum x448 { + value 13; + description + "The asymmetric algorithm using a x.448 Curve."; + reference + "RFC 7748: + Elliptic Curves for Security."; + } + } + } + default "0"; + description + "The uint16 filed shall be set by individual protocol + families according to the asymmetric key algorithm value + assigned by IANA. The setting is optional and by default + is 0. The enumeration filed is set to the selected + asymmetric key algorithm."; + } + + /*************************************/ + /* Identities for MAC Algorithms */ + /*************************************/ + + typedef mac-algorithm-t { + type union { + type uint16; + type enumeration { + enum NONE { + value 0; + description + "mac algorithm is NULL."; + } + enum hmac-sha1 { + value 1; + description + "Generating MAC using SHA1 hash function"; + reference + "RFC 3174: US Secure Hash Algorithm 1 (SHA1)"; + } + enum hmac-sha1-96 { + value 2; + description + "Generating MAC using SHA1 hash function"; + reference + "RFC 2404: The Use of HMAC-SHA-1-96 within ESP and AH"; + } + enum hmac-sha2-224 { + value 3; + description + "Generating MAC using SHA2 hash function"; + reference + "RFC 6234: US Secure Hash Algorithms + (SHA and SHA-based HMAC and HKDF)"; + } + enum hmac-sha2-256 { + value 4; + description + "Generating MAC using SHA2 hash function"; + reference + "RFC 6234: US Secure Hash Algorithms + (SHA and SHA-based HMAC and HKDF)"; + } + enum hmac-sha2-256-128 { + value 5; + description + "Generating a 256 bits MAC using SHA2 hash function and + truncate it to 128 bits"; + reference + "RFC 4868: Using HMAC-SHA-256, HMAC-SHA-384, + and HMAC-SHA-512 with IPsec"; + } + enum hmac-sha2-384 { + value 6; + description + "Generating a 384 bits MAC using SHA2 hash function"; + reference + "RFC 6234: US Secure Hash Algorithms + (SHA and SHA-based HMAC and HKDF)"; + } + enum hmac-sha2-384-192 { + value 7; + description + "Generating a 384 bits MAC using SHA2 hash function and + truncate it to 192 bits"; + reference + "RFC 4868: Using HMAC-SHA-256, HMAC-SHA-384, + and HMAC-SHA-512 with IPsec"; + } + enum hmac-sha2-512 { + value 8; + description + "Generating a 512 bits MAC using SHA2 hash function"; + reference + "RFC 6234: US Secure Hash Algorithms + (SHA and SHA-based HMAC and HKDF)"; + } + enum hmac-sha2-512-256 { + value 9; + description + "Generating a 512 bits MAC using SHA2 hash function and + truncate it to 256 bits"; + reference + "RFC 4868: Using HMAC-SHA-256, HMAC-SHA-384, + and HMAC-SHA-512 with IPsec"; + } + enum aes-128-gmac { + value 10; + description + "Generating 128-bit MAC using the Advanced Encryption + Standard (AES) Galois Message Authentication Code + (GMAC) as a mechanism to provide data origin + authentication."; + reference + "RFC 4543: + The Use of Galois Message Authentication Code (GMAC) + in IPsec ESP and AH"; + } + enum aes-192-gmac { + value 11; + description + "Generating 192-bit MAC using the Advanced Encryption + Standard (AES) Galois Message Authentication Code + (GMAC) as a mechanism to provide data origin + authentication."; + reference + "RFC 4543: + The Use of Galois Message Authentication Code (GMAC) + in IPsec ESP and AH"; + } + enum aes-256-gmac { + value 12; + description + "Generating 256-bit MAC using the Advanced Encryption + Standard (AES) Galois Message Authentication Code + (GMAC) as a mechanism to provide data origin + authentication."; + reference + "RFC 4543: + The Use of Galois Message Authentication Code (GMAC) + in IPsec ESP and AH"; + } + enum aes-cmac-96 { + value 13; + description + "Generating 96-bit MAC using Advanced Encryption + Standard (AES) Cipher-based Message Authentication + Code (CMAC)"; + reference + "RFC 4494: + The AES-CMAC Algorithm and its Use with IPsec"; + } + enum aes-cmac-128 { + value 14; + description + "Generating 128-bit MAC using Advanced Encryption + Standard (AES) Cipher-based Message Authentication + Code (CMAC)"; + reference + "RFC 4494: + The AES-CMAC Algorithm and its Use with IPsec"; + } + enum sha1-des3-kd { + value 15; + description + "Generating MAC using triple DES encryption function"; + reference + "RFC 3961: + Encryption and Checksum Specifications for Kerberos + 5"; + } + } + } + default "0"; + description + "The uint16 filed shall be set by individual protocol + families according to the mac algorithm value assigned by + IANA. The setting is optional and by default is 0. The + enumeration filed is set to the selected mac algorithm."; + } + + /********************************************/ + /* Identities for Encryption Algorithms */ + /********************************************/ + + typedef encryption-algorithm-t { + type union { + type uint16; + type enumeration { + enum NONE { + value 0; + description + "Encryption algorithm is NULL."; + } + enum aes-128-cbc { + value 1; + description + "Encrypt message with AES algorithm in CBC mode with + a key length of 128 bits."; + reference + "RFC 3565: Use of the Advanced Encryption Standard (AES) + Encryption Algorithm in Cryptographic Message Syntax + (CMS)"; + } + enum aes-192-cbc { + value 2; + description + "Encrypt message with AES algorithm in CBC mode with + a key length of 192 bits"; + reference + "RFC 3565: Use of the Advanced Encryption Standard (AES) + Encryption Algorithm in Cryptographic Message Syntax + (CMS)"; + } + enum aes-256-cbc { + value 3; + description + "Encrypt message with AES algorithm in CBC mode with + a key length of 256 bits"; + reference + "RFC 3565: Use of the Advanced Encryption Standard (AES) + Encryption Algorithm in Cryptographic Message Syntax + (CMS)"; + } + enum aes-128-ctr { + value 4; + description + "Encrypt message with AES algorithm in CTR mode with + a key length of 128 bits"; + reference + "RFC 3686: + Using Advanced Encryption Standard (AES) Counter + Mode with IPsec Encapsulating Security Payload + (ESP)"; + } + enum aes-192-ctr { + value 5; + description + "Encrypt message with AES algorithm in CTR mode with + a key length of 192 bits"; + reference + "RFC 3686: + Using Advanced Encryption Standard (AES) Counter + Mode with IPsec Encapsulating Security Payload + (ESP)"; + } + enum aes-256-ctr { + value 6; + description + "Encrypt message with AES algorithm in CTR mode with + a key length of 256 bits"; + reference + "RFC 3686: + Using Advanced Encryption Standard (AES) Counter + Mode with IPsec Encapsulating Security Payload + (ESP)"; + } + enum des3-cbc-sha1-kd { + value 7; + description + "Encrypt message with 3DES algorithm in CBC mode + with sha1 function for key derivation"; + reference + "RFC 3961: + Encryption and Checksum Specifications for + Kerberos 5"; + } + enum rc4-hmac { + value 8; + description + "Encrypt message with rc4 algorithm"; + reference + "RFC 4757: + The RC4-HMAC Kerberos Encryption Types Used by + Microsoft Windows"; + } + enum rc4-hmac-exp { + value 9; + description + "Encrypt message with rc4 algorithm that is exportable"; + reference + "RFC 4757: + The RC4-HMAC Kerberos Encryption Types Used by + Microsoft Windows"; + } + } + } + default "0"; + description + "The uint16 filed shall be set by individual protocol + families according to the encryption algorithm value + assigned by IANA. The setting is optional and by default + is 0. The enumeration filed is set to the selected + encryption algorithm."; + } + + /****************************************************/ + /* Identities for Encryption and MAC Algorithms */ + /****************************************************/ + + typedef encryption-and-mac-algorithm-t { + type union { + type uint16; + type enumeration { + enum NONE { + value 0; + description + "Encryption and MAC algorithm is NULL."; + reference + "None"; + } + enum aes-128-ccm { + value 1; + description + "Encrypt message with AES algorithm in CCM + mode with a key length of 128 bits; it can + also be used for generating MAC"; + reference + "RFC 4309: Using Advanced Encryption Standard + (AES) CCM Mode with IPsec Encapsulating Security + Payload (ESP)"; + } + enum aes-192-ccm { + value 2; + description + "Encrypt message with AES algorithm in CCM + mode with a key length of 192 bits; it can + also be used for generating MAC"; + reference + "RFC 4309: Using Advanced Encryption Standard + (AES) CCM Mode with IPsec Encapsulating Security + Payload (ESP)"; + } + enum aes-256-ccm { + value 3; + description + "Encrypt message with AES algorithm in CCM + mode with a key length of 256 bits; it can + also be used for generating MAC"; + reference + "RFC 4309: Using Advanced Encryption Standard + (AES) CCM Mode with IPsec Encapsulating Security + Payload (ESP)"; + } + enum aes-128-gcm { + value 4; + description + "Encrypt message with AES algorithm in GCM + mode with a key length of 128 bits; it can + also be used for generating MAC"; + reference + "RFC 4106: The Use of Galois/Counter Mode (GCM) + in IPsec Encapsulating Security Payload (ESP)"; + } + enum aes-192-gcm { + value 5; + description + "Encrypt message with AES algorithm in GCM + mode with a key length of 192 bits; it can + also be used for generating MAC"; + reference + "RFC 4106: The Use of Galois/Counter Mode (GCM) + in IPsec Encapsulating Security Payload (ESP)"; + } + enum aes-256-gcm { + value 6; + description + "Encrypt message with AES algorithm in GCM + mode with a key length of 256 bits; it can + also be used for generating MAC"; + reference + "RFC 4106: The Use of Galois/Counter Mode (GCM) + in IPsec Encapsulating Security Payload (ESP)"; + } + enum chacha20-poly1305 { + value 7; + description + "Encrypt message with chacha20 algorithm and generate + MAC with POLY1305; it can also be used for generating + MAC"; + reference + "RFC 8439: ChaCha20 and Poly1305 for IETF Protocols"; + } + } + } + default "0"; + description + "The uint16 filed shall be set by individual protocol + families according to the encryption and mac algorithm value + assigned by IANA. The setting is optional and by default is + 0. The enumeration filed is set to the selected encryption + and mac algorithm."; + } + + /******************************************/ + /* Identities for signature algorithm */ + /******************************************/ + + typedef signature-algorithm-t { + type union { + type uint16; + type enumeration { + enum NONE { + value 0; + description + "Signature algorithm is NULL"; + } + enum dsa-sha1 { + value 1; + description + "The signature algorithm using DSA algorithm with SHA1 + hash algorithm"; + reference + "RFC 4253: + The Secure Shell (SSH) Transport Layer Protocol"; + } + enum rsassa-pkcs1-sha1 { + value 2; + description + "The signature algorithm using RSASSA-PKCS1-v1_5 with + the SHA1 hash algorithm."; + reference + "RFC 4253: + The Secure Shell (SSH) Transport Layer Protocol"; + } + enum rsassa-pkcs1-sha256 { + value 3; + description + "The signature algorithm using RSASSA-PKCS1-v1_5 with + the SHA256 hash algorithm."; + reference + "RFC 8332: + Use of RSA Keys with SHA-256 and SHA-512 in the + Secure Shell (SSH) Protocol + RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum rsassa-pkcs1-sha384 { + value 4; + description + "The signature algorithm using RSASSA-PKCS1-v1_5 with + the SHA384 hash algorithm."; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum rsassa-pkcs1-sha512 { + value 5; + description + "The signature algorithm using RSASSA-PKCS1-v1_5 with + the SHA512 hash algorithm."; + reference + "RFC 8332: + Use of RSA Keys with SHA-256 and SHA-512 in the + Secure Shell (SSH) Protocol + RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum rsassa-pss-rsae-sha256 { + value 6; + description + "The signature algorithm using RSASSA-PSS with mask + generation function 1 and SHA256 hash algorithm. If + the public key is carried in an X.509 certificate, + it MUST use the rsaEncryption OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum rsassa-pss-rsae-sha384 { + value 7; + description + "The signature algorithm using RSASSA-PSS with mask + generation function 1 and SHA384 hash algorithm. If + the public key is carried in an X.509 certificate, + it MUST use the rsaEncryption OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum rsassa-pss-rsae-sha512 { + value 8; + description + "The signature algorithm using RSASSA-PSS with mask + generation function 1 and SHA512 hash algorithm. If + the public key is carried in an X.509 certificate, + it MUST use the rsaEncryption OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum rsassa-pss-pss-sha256 { + value 9; + description + "The signature algorithm using RSASSA-PSS with mask + generation function 1 and SHA256 hash algorithm. If + the public key is carried in an X.509 certificate, + it MUST use the rsaEncryption OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum rsassa-pss-pss-sha384 { + value 10; + description + "The signature algorithm using RSASSA-PSS with mask + generation function 1 and SHA384 hash algorithm. If + the public key is carried in an X.509 certificate, + it MUST use the rsaEncryption OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum rsassa-pss-pss-sha512 { + value 11; + description + "The signature algorithm using RSASSA-PSS with mask + generation function 1 and SHA512 hash algorithm. If + the public key is carried in an X.509 certificate, + it MUST use the rsaEncryption OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum ecdsa-secp256r1-sha256 { + value 12; + description + "The signature algorithm using ECDSA with curve name + secp256r1 and SHA256 hash algorithm."; + reference + "RFC 5656: + Elliptic Curve Algorithm Integration in the Secure + Shell Transport Layer + RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum ecdsa-secp384r1-sha384 { + value 13; + description + "The signature algorithm using ECDSA with curve name + secp384r1 and SHA384 hash algorithm."; + reference + "RFC 5656: + Elliptic Curve Algorithm Integration in the Secure + Shell Transport Layer + RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum ecdsa-secp521r1-sha512 { + value 14; + description + "The signature algorithm using ECDSA with curve name + secp521r1 and SHA512 hash algorithm."; + reference + "RFC 5656: + Elliptic Curve Algorithm Integration in the Secure + Shell Transport Layer + RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum ed25519 { + value 15; + description + "The signature algorithm using EdDSA with curve x25519"; + reference + "RFC 8032: + Edwards-Curve Digital Signature Algorithm (EdDSA)"; + } + enum ed25519-cts { + value 16; + description + "The signature algorithm using EdDSA with curve x25519 + with phflag = 0"; + reference + "RFC 8032: + Edwards-Curve Digital Signature Algorithm (EdDSA)"; + } + enum ed25519-ph { + value 17; + description + "The signature algorithm using EdDSA with curve x25519 + with phflag = 1"; + reference + "RFC 8032: + Edwards-Curve Digital Signature Algorithm (EdDSA)"; + } + enum ed25519-sha512 { + value 18; + description + "The signature algorithm using EdDSA with curve x25519 + and SHA-512 function"; + reference + "RFC 8419: + Use of Edwards-Curve Digital Signature Algorithm + (EdDSA) Signatures in the Cryptographic Message + Syntax (CMS)"; + } + enum ed448 { + value 19; + description + "The signature algorithm using EdDSA with curve x448"; + reference + "RFC 8032: + Edwards-Curve Digital Signature Algorithm (EdDSA)"; + } + enum ed448-ph { + value 20; + description + "The signature algorithm using EdDSA with curve x448 + and with PH being SHAKE256(x, 64) and phflag being 1"; + reference + "RFC 8032: + Edwards-Curve Digital Signature Algorithm (EdDSA)"; + } + enum ed448-shake256 { + value 21; + description + "The signature algorithm using EdDSA with curve x448 + and SHAKE-256 function"; + reference + "RFC 8419: + Use of Edwards-Curve Digital Signature Algorithm + (EdDSA) Signatures in the Cryptographic Message + Syntax (CMS)"; + } + enum ed448-shake256-len { + value 22; + description + "The signature algorithm using EdDSA with curve x448 + and SHAKE-256 function and a customized hash output"; + reference + "RFC 8419: + Use of Edwards-Curve Digital Signature Algorithm + (EdDSA) Signatures in the Cryptographic Message + Syntax (CMS)"; + } + enum rsa-sha2-256 { + value 23; + description + "The signature algorithm using RSA with SHA2 function + for SSH protocol"; + reference + "RFC 8332: + Use of RSA Keys with SHA-256 and SHA-512 + in the Secure Shell (SSH) Protocol"; + } + enum rsa-sha2-512 { + value 24; + description + "The signature algorithm using RSA with SHA2 function + for SSH protocol"; + reference + "RFC 8332: + Use of RSA Keys with SHA-256 and SHA-512 + in the Secure Shell (SSH) Protocol"; + } + enum eccsi { + value 25; + description + "The signature algorithm using ECCSI signature as + defined in RFC 6507."; + reference + "RFC 6507: + Elliptic Curve-Based Certificateless Signatures + for Identity-based Encryption (ECCSI)"; + } + } + } + default "0"; + description + "The uint16 filed shall be set by individual protocol + families according to the signature algorithm value + assigned by IANA. The setting is optional and by default + is 0. The enumeration filed is set to the selected + signature algorithm."; + } + + /**********************************************/ + /* Identities for key exchange algorithms */ + /**********************************************/ + + typedef key-exchange-algorithm-t { + type union { + type uint16; + type enumeration { + enum NONE { + value 0; + description + "Key exchange algorithm is NULL."; + } + enum psk-only { + value 1; + description + "Using Pre-shared key for authentication and key + exchange"; + reference + "RFC 4279: + Pre-Shared Key cipher suites for Transport Layer + Security (TLS)"; + } + enum dhe-ffdhe2048 { + value 2; + description + "Ephemeral Diffie Hellman key exchange with 2048 bit + finite field"; + reference + "RFC 7919: + Negotiated Finite Field Diffie-Hellman Ephemeral + Parameters for Transport Layer Security (TLS)"; + } + enum dhe-ffdhe3072 { + value 3; + description + "Ephemeral Diffie Hellman key exchange with 3072 bit + finite field"; + reference + "RFC 7919: + Negotiated Finite Field Diffie-Hellman Ephemeral + Parameters for Transport Layer Security (TLS)"; + } + enum dhe-ffdhe4096 { + value 4; + description + "Ephemeral Diffie Hellman key exchange with 4096 bit + finite field"; + reference + "RFC 7919: + Negotiated Finite Field Diffie-Hellman Ephemeral + Parameters for Transport Layer Security (TLS)"; + } + enum dhe-ffdhe6144 { + value 5; + description + "Ephemeral Diffie Hellman key exchange with 6144 bit + finite field"; + reference + "RFC 7919: + Negotiated Finite Field Diffie-Hellman Ephemeral + Parameters for Transport Layer Security (TLS)"; + } + enum dhe-ffdhe8192 { + value 6; + description + "Ephemeral Diffie Hellman key exchange with 8192 bit + finite field"; + reference + "RFC 7919: + Negotiated Finite Field Diffie-Hellman Ephemeral + Parameters for Transport Layer Security (TLS)"; + } + enum psk-dhe-ffdhe2048 { + value 7; + description + "Key exchange using pre-shared key with Diffie-Hellman + key generation mechanism, where the DH group is + FFDHE2048"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum psk-dhe-ffdhe3072 { + value 8; + description + "Key exchange using pre-shared key with Diffie-Hellman + key generation mechanism, where the DH group is + FFDHE3072"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum psk-dhe-ffdhe4096 { + value 9; + description + "Key exchange using pre-shared key with Diffie-Hellman + key generation mechanism, where the DH group is + FFDHE4096"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum psk-dhe-ffdhe6144 { + value 10; + description + "Key exchange using pre-shared key with Diffie-Hellman + key generation mechanism, where the DH group is + FFDHE6144"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum psk-dhe-ffdhe8192 { + value 11; + description + "Key exchange using pre-shared key with Diffie-Hellman + key generation mechanism, where the DH group is + FFDHE8192"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum ecdhe-secp256r1 { + value 12; + description + "Ephemeral Diffie Hellman key exchange with elliptic + group over curve secp256r1"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites + for Transport Layer Security (TLS) Versions 1.2 + and Earlier"; + } + enum ecdhe-secp384r1 { + value 13; + description + "Ephemeral Diffie Hellman key exchange with elliptic + group over curve secp384r1"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites + for Transport Layer Security (TLS) Versions 1.2 + and Earlier"; + } + enum ecdhe-secp521r1 { + value 14; + description + "Ephemeral Diffie Hellman key exchange with elliptic + group over curve secp521r1"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites + for Transport Layer Security (TLS) Versions 1.2 + and Earlier"; + } + enum ecdhe-x25519 { + value 15; + description + "Ephemeral Diffie Hellman key exchange with elliptic + group over curve x25519"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites + for Transport Layer Security (TLS) Versions 1.2 + and Earlier"; + } + enum ecdhe-x448 { + value 16; + description + "Ephemeral Diffie Hellman key exchange with elliptic + group over curve x448"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites + for Transport Layer Security (TLS) Versions 1.2 + and Earlier"; + } + enum psk-ecdhe-secp256r1 { + value 17; + description + "Key exchange using pre-shared key with elliptic + group-based Ephemeral Diffie Hellman key exchange + over curve secp256r1"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum psk-ecdhe-secp384r1 { + value 18; + description + "Key exchange using pre-shared key with elliptic + group-based Ephemeral Diffie Hellman key exchange + over curve secp384r1"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum psk-ecdhe-secp521r1 { + value 19; + description + "Key exchange using pre-shared key with elliptic + group-based Ephemeral Diffie Hellman key exchange + over curve secp521r1"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum psk-ecdhe-x25519 { + value 20; + description + "Key exchange using pre-shared key with elliptic + group-based Ephemeral Diffie Hellman key exchange + over curve x25519"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum psk-ecdhe-x448 { + value 21; + description + "Key exchange using pre-shared key with elliptic + group-based Ephemeral Diffie Hellman key exchange + over curve x448"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol + Version 1.3"; + } + enum diffie-hellman-group14-sha1 { + value 22; + description + "Using DH group14 and SHA1 for key exchange"; + reference + "RFC 4253: + The Secure Shell (SSH) Transport Layer Protocol"; + } + enum diffie-hellman-group14-sha256 { + value 23; + description + "Using DH group14 and SHA-256 for key exchange"; + reference + "RFC 8268: + More Modular Exponentiation (MODP) Diffie-Hellman (DH) + Key Exchange (KEX) Groups for Secure Shell (SSH)"; + } + enum diffie-hellman-group15-sha512 { + value 24; + description + "Using DH group15 and SHA-512 for key exchange"; + reference + "RFC 8268: + More Modular Exponentiation (MODP) Diffie-Hellman (DH) + Key Exchange (KEX) Groups for Secure Shell (SSH)"; + } + enum diffie-hellman-group16-sha512 { + value 25; + description + "Using DH group16 and SHA-512 for key exchange"; + reference + "RFC 8268: + More Modular Exponentiation (MODP) Diffie-Hellman (DH) + Key Exchange (KEX) Groups for Secure Shell (SSH)"; + } + enum diffie-hellman-group17-sha512 { + value 26; + description + "Using DH group17 and SHA-512 for key exchange"; + reference + "RFC 8268: + More Modular Exponentiation (MODP) Diffie-Hellman (DH) + Key Exchange (KEX) Groups for Secure Shell (SSH)"; + } + enum diffie-hellman-group18-sha512 { + value 27; + description + "Using DH group18 and SHA-512 for key exchange"; + reference + "RFC 8268: + More Modular Exponentiation (MODP) Diffie-Hellman (DH) + Key Exchange (KEX) Groups for Secure Shell (SSH)"; + } + enum ecdh-sha2-secp256r1 { + value 28; + description + "Elliptic curve-based Diffie Hellman key exchange over + curve ecp256r1 and using SHA2 for MAC generation"; + reference + "RFC 6239: + Suite B Cryptographic Suites for Secure Shell (SSH)"; + } + enum ecdh-sha2-secp384r1 { + value 29; + description + "Elliptic curve-based Diffie Hellman key exchange over + curve ecp384r1 and using SHA2 for MAC generation"; + reference + "RFC 6239: + Suite B Cryptographic Suites for Secure Shell (SSH)"; + } + enum ecdh-x25519-x9.63-sha256 { + value 30; + description + "Elliptic curve-based Diffie Hellman key exchange over + curve x.25519 and using ANSI x9.63 with SHA256 as KDF"; + reference + "RFC 8418: + Use of the Elliptic Curve Diffie-Hellman Key Agreement + Algorithm with X25519 and X448 in the Cryptographic + Message Syntax (CMS)"; + } + enum ecdh-x25519-x9.63-sha384 { + value 31; + description + "Elliptic curve-based Diffie Hellman key exchange over + curve x.25519 and using ANSI x9.63 with SHA384 as KDF"; + reference + "RFC 8418: + Use of the Elliptic Curve Diffie-Hellman Key Agreement + Algorithm with X25519 and X448 in the Cryptographic + Message Syntax (CMS)"; + } + enum ecdh-x25519-x9.63-sha512 { + value 32; + description + "Elliptic curve-based Diffie Hellman key exchange over + curve x.25519 and using ANSI x9.63 with SHA512 as KDF"; + reference + "RFC 8418: + Use of the Elliptic Curve Diffie-Hellman Key Agreement + Algorithm with X25519 and X448 in the Cryptographic + Message Syntax (CMS)"; + } + enum ecdh-x25519-hkdf-sha256 { + value 33; + description + "Elliptic curve-based Diffie Hellman key exchange over + curve x.25519 and using HKDF with SHA256 as KDF"; + reference + "RFC 8418: + Use of the Elliptic Curve Diffie-Hellman Key Agreement + Algorithm with X25519 and X448 in the Cryptographic + Message Syntax (CMS)"; + } + enum ecdh-x25519-hkdf-sha384 { + value 34; + description + "Elliptic curve-based Diffie Hellman key exchange over + curve x.25519 and using HKDF with SHA384 as KDF"; + reference + "RFC 8418: + Use of the Elliptic Curve Diffie-Hellman Key Agreement + Algorithm with X25519 and X448 in the Cryptographic + Message Syntax (CMS)"; + } + enum ecdh-x25519-hkdf-sha512 { + value 35; + description + "Elliptic curve-based Diffie Hellman key exchange over + curve x.25519 and using HKDF with SHA512 as KDF"; + reference + "RFC 8418: + Use of the Elliptic Curve Diffie-Hellman Key Agreement + Algorithm with X25519 and X448 in the Cryptographic + Message Syntax (CMS)"; + } + enum ecdh-x448-x9.63-sha256 { + value 36; + description + "Elliptic curve-based Diffie Hellman key exchange over + curve x.448 and using ANSI x9.63 with SHA256 as KDF"; + reference + "RFC 8418: + Use of the Elliptic Curve Diffie-Hellman Key Agreement + Algorithm with X25519 and X448 in the Cryptographic + Message Syntax (CMS)"; + } + enum ecdh-x448-x9.63-sha384 { + value 37; + description + "Elliptic curve-based Diffie Hellman key exchange over + curve x.448 and using ANSI x9.63 with SHA384 as KDF"; + reference + "RFC 8418: + Use of the Elliptic Curve Diffie-Hellman Key Agreement + Algorithm with X25519 and X448 in the Cryptographic + Message Syntax (CMS)"; + } + enum ecdh-x448-x9.63-sha512 { + value 38; + description + "Elliptic curve-based Diffie Hellman key exchange over + curve x.448 and using ANSI x9.63 with SHA512 as KDF"; + reference + "RFC 8418: + Use of the Elliptic Curve Diffie-Hellman Key Agreement + Algorithm with X25519 and X448 in the Cryptographic + Message Syntax (CMS)"; + } + enum ecdh-x448-hkdf-sha256 { + value 39; + description + "Elliptic curve-based Diffie Hellman key exchange over + curve x.448 and using HKDF with SHA256 as KDF"; + reference + "RFC 8418: + Use of the Elliptic Curve Diffie-Hellman Key Agreement + Algorithm with X25519 and X448 in the Cryptographic + Message Syntax (CMS)"; + } + enum ecdh-x448-hkdf-sha384 { + value 40; + description + "Elliptic curve-based Diffie Hellman key exchange over + curve x.448 and using HKDF with SHA384 as KDF"; + reference + "RFC 8418: + Use of the Elliptic Curve Diffie-Hellman Key Agreement + Algorithm with X25519 and X448 in the Cryptographic + Message Syntax (CMS)"; + } + enum ecdh-x448-hkdf-sha512 { + value 41; + description + "Elliptic curve-based Diffie Hellman key exchange over + curve x.448 and using HKDF with SHA512 as KDF"; + reference + "RFC 8418: + Use of the Elliptic Curve Diffie-Hellman Key Agreement + Algorithm with X25519 and X448 in the Cryptographic + Message Syntax (CMS)"; + } + + enum rsaes-oaep { + value 42; + description + "RSAES-OAEP combines the RSAEP and RSADP primitives with + the EME-OAEP encoding method"; + reference + "RFC 8017: + PKCS #1: + RSA Cryptography Specifications Version 2.2."; + } + enum rsaes-pkcs1-v1_5 { + value 43; + description + "RSAES-PKCS1-v1_5 combines the RSAEP and RSADP + primitives with the EME-PKCS1-v1_5 encoding method"; + reference + "RFC 8017: + PKCS #1: + RSA Cryptography Specifications Version 2.2."; + } + } + } + default "0"; + description + "The uint16 filed shall be set by individual protocol + families according to the key exchange algorithm value + assigned by IANA. The setting is optional and by default + is 0. The enumeration filed is set to the selected key + exchange algorithm."; + } + + /********************************************/ + /* Identities for Key Format Structures */ + /********************************************/ + + /*** all key format types ****/ + + identity key-format-base { + description "Base key-format identity for all keys."; + } + + identity public-key-format { + base "key-format-base"; + description "Base key-format identity for public keys."; + } + + identity private-key-format { + base "key-format-base"; + description "Base key-format identity for private keys."; + } + + identity symmetric-key-format { + base "key-format-base"; + description "Base key-format identity for symmetric keys."; + } + + /**** for private keys ****/ + + identity rsa-private-key-format { + base "private-key-format"; + description "An RSAPrivateKey (from RFC 3447)."; + } + + identity ec-private-key-format { + base "private-key-format"; + description "An ECPrivateKey (from RFC 5915)"; + } + + identity one-asymmetric-key-format { + base "private-key-format"; + description "A OneAsymmetricKey (from RFC 5958)."; + } + + identity encrypted-private-key-format { + base "private-key-format"; + description + "A CMS EncryptedData structure (RFC 5652) + containing a OneAsymmetricKey (RFC 5958)."; + } + + /**** for public keys ****/ + + identity ssh-public-key-format { + base "public-key-format"; + description + "The public key format described by RFC 4716."; + } + + identity subject-public-key-info-format { + base "public-key-format"; + description + "A SubjectPublicKeyInfo (from RFC 5280)."; + } + + /**** for symmetric keys ****/ + + identity octet-string-key-format { + base "symmetric-key-format"; + description "An OctetString from ASN.1."; + /* + // Knowing that it is an "OctetString" isn't really helpful. + // Knowing the length of the octet string would be helpful, + // as it relates to the algorithm's block size. We may want + // to only (for now) use "one-symmetric-key-format" for + // symmetric keys...were the usability issues Juergen + // mentioned before only apply to asymmetric keys? + */ + } + + identity one-symmetric-key-format { + base "symmetric-key-format"; + description "A OneSymmetricKey (from RFC6031)."; + } + + identity encrypted-symmetric-key-format { + base "symmetric-key-format"; + description + "A CMS EncryptedData structure (RFC 5652) + containing a OneSymmetricKey (RFC 6031)."; + } + + /***************************************************/ + /* Typedefs for ASN.1 structures from RFC 5280 */ + /***************************************************/ + + typedef x509 { + type binary; + description + "A Certificate structure, as specified in RFC 5280, + encoded using ASN.1 distinguished encoding rules (DER), + as specified in ITU-T X.690."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + + typedef crl { + type binary; + description + "A CertificateList structure, as specified in RFC 5280, + encoded using ASN.1 distinguished encoding rules (DER), + as specified in ITU-T X.690."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + + /***********************************************/ + /* Typedefs for ASN.1 structures from 5652 */ + /***********************************************/ + + typedef cms { + type binary; + description + "A ContentInfo structure, as specified in RFC 5652, + encoded using ASN.1 distinguished encoding rules (DER), + as specified in ITU-T X.690."; + reference + "RFC 5652: + Cryptographic Message Syntax (CMS) + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + typedef data-content-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + data content type, as described by Section 4 in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef signed-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + signed-data content type, as described by Section 5 in + RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef enveloped-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + enveloped-data content type, as described by Section 6 + in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef digested-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + digested-data content type, as described by Section 7 + in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef encrypted-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + encrypted-data content type, as described by Section 8 + in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + typedef authenticated-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + authenticated-data content type, as described by Section 9 + in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + /***************************************************/ + /* Typedefs for structures related to RFC 4253 */ + /***************************************************/ + + typedef ssh-host-key { + type binary; + description + "The binary public key data for this SSH key, as + specified by RFC 4253, Section 6.6, i.e.: + + string certificate or public key format + identifier + byte[n] key/certificate data."; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer + Protocol"; + } + + /*********************************************************/ + /* Typedefs for ASN.1 structures related to RFC 5280 */ + /*********************************************************/ + + typedef trust-anchor-cert-x509 { + type x509; + description + "A Certificate structure that MUST encode a self-signed + root certificate."; + } + + typedef end-entity-cert-x509 { + type x509; + description + "A Certificate structure that MUST encode a certificate + that is neither self-signed nor having Basic constraint + CA true."; + } + + /*********************************************************/ + /* Typedefs for ASN.1 structures related to RFC 5652 */ + /*********************************************************/ + + typedef trust-anchor-cert-cms { + type signed-data-cms; + description + "A CMS SignedData structure that MUST contain the chain of + X.509 certificates needed to authenticate the certificate + presented by a client or end-entity. + + The CMS MUST contain only a single chain of certificates. + The client or end-entity certificate MUST only authenticate + to last intermediate CA certificate listed in the chain. + + In all cases, the chain MUST include a self-signed root + certificate. In the case where the root certificate is + itself the issuer of the client or end-entity certificate, + only one certificate is present. + + This CMS structure MAY (as applicable where this type is + used) also contain suitably fresh (as defined by local + policy) revocation objects with which the device can + verify the revocation status of the certificates. + + This CMS encodes the degenerate form of the SignedData + structure that is commonly used to disseminate X.509 + certificates and revocation objects (RFC 5280)."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile."; + } + + typedef end-entity-cert-cms { + type signed-data-cms; + description + "A CMS SignedData structure that MUST contain the end + entity certificate itself, and MAY contain any number + of intermediate certificates leading up to a trust + anchor certificate. The trust anchor certificate + MAY be included as well. + + The CMS MUST contain a single end entity certificate. + The CMS MUST NOT contain any spurious certificates. + + This CMS structure MAY (as applicable where this type is + used) also contain suitably fresh (as defined by local + policy) revocation objects with which the device can + verify the revocation status of the certificates. + + This CMS encodes the degenerate form of the SignedData + structure that is commonly used to disseminate X.509 + certificates and revocation objects (RFC 5280)."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile."; + } + + typedef ssh-public-key-type { // DELETE? + type binary; + description + "The binary public key data for this SSH key, as + specified by RFC 4253, Section 6.6, i.e.: + + string certificate or public key format + identifier + byte[n] key/certificate data."; + reference + "RFC 4253: The Secure Shell (SSH) Transport + Layer Protocol"; + } + + /**********************************************/ + /* Groupings for keys and/or certificates */ + /**********************************************/ + + grouping symmetric-key-grouping { + description + "A symmetric key and algorithm."; + leaf algorithm { + type encryption-algorithm-t; + mandatory true; + description + "The algorithm to be used when generating the key."; + reference + "RFC CCCC: Common YANG Data Types for Cryptography"; + } + leaf key-format { + nacm:default-deny-write; + when "../key"; + type identityref { + base symmetric-key-format; + } + description "Identifies the symmetric key's format."; + } + choice key-type { + mandatory true; + description + "Choice between key types."; + leaf key { + nacm:default-deny-all; + type binary; + //must "../key-format"; FIXME: remove comment if approach ok + description + "The binary value of the key. The interpretation of + the value is defined by 'key-format'. For example, + FIXME."; + reference + "RFC XXXX: FIXME"; + } + leaf hidden-key { + nacm:default-deny-write; + type empty; + description + "A permanently hidden key. How such keys are created + is outside the scope of this module."; + } + } + } + + grouping public-key-grouping { + description + "A public key and its associated algorithm."; + leaf algorithm { + nacm:default-deny-write; + type asymmetric-key-algorithm-t; + mandatory true; + description + "Identifies the key's algorithm."; + reference + "RFC CCCC: Common YANG Data Types for Cryptography"; + } + leaf public-key-format { + nacm:default-deny-write; + when "../public-key"; + type identityref { + base public-key-format; + } + description "Identifies the key's format."; + } + leaf public-key { + nacm:default-deny-write; + type binary; + //must "../public-key-format"; FIXME: rm comment if approach ok + mandatory true; + description + "The binary value of the public key. The interpretation + of the value is defined by 'public-key-format' field."; + } + } + + grouping asymmetric-key-pair-grouping { + description + "A private key and its associated public key and algorithm."; + uses public-key-grouping; + leaf private-key-format { + nacm:default-deny-write; + when "../private-key"; + type identityref { + base private-key-format; + } + description "Identifies the key's format."; + } + choice private-key-type { + mandatory true; + description + "Choice between key types."; + leaf private-key { + nacm:default-deny-all; + type binary; + //must "../private-key-format"; FIXME: rm comment if ok + description + "The value of the binary key. The key's value is + interpreted by the 'private-key-format' field."; + } + leaf hidden-private-key { + nacm:default-deny-write; + type empty; + description + "A permanently hidden key. How such keys are created + is outside the scope of this module."; + } + } + } + + grouping trust-anchor-cert-grouping { + description + "A trust anchor certificate, and a notification for when + it is about to (or already has) expire."; + leaf cert { + nacm:default-deny-write; + type trust-anchor-cert-cms; + description + "The binary certificate data for this certificate."; + reference + "RFC YYYY: Common YANG Data Types for Cryptography"; + } + notification certificate-expiration { + description + "A notification indicating that the configured certificate + is either about to expire or has already expired. When to + send notifications is an implementation specific decision, + but it is RECOMMENDED that a notification be sent once a + month for 3 months, then once a week for four weeks, and + then once a day thereafter until the issue is resolved."; + leaf expiration-date { + type yang:date-and-time; + mandatory true; + description + "Identifies the expiration date on the certificate."; + } + } + } + + grouping trust-anchor-certs-grouping { + description + "A list of trust anchor certificates, and a notification + for when one is about to (or already has) expire."; + leaf-list cert { + nacm:default-deny-write; + type trust-anchor-cert-cms; + description + "The binary certificate data for this certificate."; + reference + "RFC YYYY: Common YANG Data Types for Cryptography"; + } + notification certificate-expiration { + description + "A notification indicating that the configured certificate + is either about to expire or has already expired. When to + send notifications is an implementation specific decision, + but it is RECOMMENDED that a notification be sent once a + month for 3 months, then once a week for four weeks, and + then once a day thereafter until the issue is resolved."; + leaf expiration-date { + type yang:date-and-time; + mandatory true; + description + "Identifies the expiration date on the certificate."; + } + } + } + + grouping end-entity-cert-grouping { + description + "An end entity certificate, and a notification for when + it is about to (or already has) expire. Implementations + SHOULD assert that, where used, the end entity certificate + contains the expected public key."; + leaf cert { + nacm:default-deny-write; + type end-entity-cert-cms; + description + "The binary certificate data for this certificate."; + reference + "RFC YYYY: Common YANG Data Types for Cryptography"; + } + notification certificate-expiration { + description + "A notification indicating that the configured certificate + is either about to expire or has already expired. When to + send notifications is an implementation specific decision, + but it is RECOMMENDED that a notification be sent once a + month for 3 months, then once a week for four weeks, and + then once a day thereafter until the issue is resolved."; + leaf expiration-date { + type yang:date-and-time; + mandatory true; + description + "Identifies the expiration date on the certificate."; + } + } + } + + grouping end-entity-certs-grouping { + description + "A list of end entity certificates, and a notification for + when one is about to (or already has) expire."; + leaf-list cert { + nacm:default-deny-write; + type end-entity-cert-cms; + description + "The binary certificate data for this certificate."; + reference + "RFC YYYY: Common YANG Data Types for Cryptography"; + } + notification certificate-expiration { + description + "A notification indicating that the configured certificate + is either about to expire or has already expired. When to + send notifications is an implementation specific decision, + but it is RECOMMENDED that a notification be sent once a + month for 3 months, then once a week for four weeks, and + then once a day thereafter until the issue is resolved."; + leaf expiration-date { + type yang:date-and-time; + mandatory true; + description + "Identifies the expiration date on the certificate."; + } + } + } + + grouping asymmetric-key-pair-with-cert-grouping { + description + "A private/public key pair and an associated certificate. + Implementations SHOULD assert that certificates contain + the matching public key."; + uses asymmetric-key-pair-grouping; + uses end-entity-cert-grouping; + action generate-certificate-signing-request { + nacm:default-deny-all; + description + "Generates a certificate signing request structure for + the associated asymmetric key using the passed subject + and attribute values. The specified assertions need + to be appropriate for the certificate's use. For + example, an entity certificate for a TLS server + SHOULD have values that enable clients to satisfy + RFC 6125 processing."; + input { + leaf subject { + type binary; + mandatory true; + description + "The 'subject' field per the CertificationRequestInfo + structure as specified by RFC 2986, Section 4.1 + encoded using the ASN.1 distinguished encoding + rules (DER), as specified in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + leaf attributes { + type binary; // FIXME: does this need to be mandatory? + description + "The 'attributes' field from the structure + CertificationRequestInfo as specified by RFC 2986, + Section 4.1 encoded using the ASN.1 distinguished + encoding rules (DER), as specified in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + } + output { + leaf certificate-signing-request { + type binary; + mandatory true; + description + "A CertificationRequest structure as specified by + RFC 2986, Section 4.2 encoded using the ASN.1 + distinguished encoding rules (DER), as specified + in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + } + } // generate-certificate-signing-request + } // asymmetric-key-pair-with-cert-grouping + + grouping asymmetric-key-pair-with-certs-grouping { + description + "A private/public key pair and associated certificates. + Implementations SHOULD assert that certificates contain + the matching public key."; + uses asymmetric-key-pair-grouping; + container certificates { + nacm:default-deny-write; + description + "Certificates associated with this asymmetric key. + More than one certificate supports, for instance, + a TPM-protected asymmetric key that has both IDevID + and LDevID certificates associated."; + list certificate { + key "name"; + description + "A certificate for this asymmetric key."; + leaf name { + type string; + description + "An arbitrary name for the certificate. If the name + matches the name of a certificate that exists + independently in (i.e., an IDevID), + then the 'cert' node MUST NOT be configured."; + } + uses end-entity-cert-grouping; + } + } // certificates + action generate-certificate-signing-request { + nacm:default-deny-all; + description + "Generates a certificate signing request structure for + the associated asymmetric key using the passed subject + and attribute values. The specified assertions need + to be appropriate for the certificate's use. For + example, an entity certificate for a TLS server + SHOULD have values that enable clients to satisfy + RFC 6125 processing."; + input { + leaf subject { + type binary; + mandatory true; + description + "The 'subject' field per the CertificationRequestInfo + structure as specified by RFC 2986, Section 4.1 + encoded using the ASN.1 distinguished encoding + rules (DER), as specified in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + leaf attributes { + type binary; // FIXME: does this need to be mandatory? + description + "The 'attributes' field from the structure + CertificationRequestInfo as specified by RFC 2986, + Section 4.1 encoded using the ASN.1 distinguished + encoding rules (DER), as specified in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + } + output { + leaf certificate-signing-request { + type binary; + mandatory true; + description + "A CertificationRequest structure as specified by + RFC 2986, Section 4.2 encoded using the ASN.1 + distinguished encoding rules (DER), as specified + in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + } + } // generate-certificate-signing-request + } // asymmetric-key-pair-with-certs-grouping +} \ No newline at end of file diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-dhcpv6-types@2018-01-30.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-dhcpv6-types@2018-01-30.yang new file mode 100644 index 0000000..c0d7193 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-dhcpv6-types@2018-01-30.yang @@ -0,0 +1,207 @@ +module ietf-dhcpv6-types { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-dhcpv6-types"; + prefix "dhcpv6-types"; + + import ietf-inet-types { + prefix inet; + } + import ietf-yang-types { + prefix yang; + } + + organization "DHC WG"; + contact + "cuiyong@tsinghua.edu.cn + lh.sunlinh@gmail.com + ian.farrer@telekom.de + sladjana.zechlin@telekom.de + hezihao9512@gmail.com"; + + description "This model defines a YANG data model that can be + used to define some commonly used DHCPv6 types"; + + revision 2018-01-30 { + description "Initial revision"; + reference "I-D: draft-ietf-dhc-dhcpv6-yang"; + } + + /* + * Grouping + */ + grouping vendor-infor { + description "Vendor information."; + container vendor-info { + description ""; + leaf ent-num { + type uint32; + mandatory true; + description "enterprise number"; + } + leaf-list data { + type string; + description "specific vendor info"; + } + } + } + + grouping duid { + description + "Each server and client has only one DUID (DHCP Unique Identifier). + The DUID here identifies a unique DHCPv6 server for clients. DUID + consists of a two-octet type field and an arbitrary length (no more + than 128 bytes) content field. Currently there are four defined types + of DUIDs in RFC3315 and RFC6355 - DUID-LLT, DUID-EN, DUID-LL and + DUID-UUID. DUID-Uknown represents those unconventional DUIDs."; + reference "RFC3315: Section 9 and RFC6355: Section 4"; + leaf type-code { + type uint16; + default 65535; + description "Type code of this DUID"; + } + choice duid-type { + default duid-unknown; + description "Selects the format for the DUID."; + case duid-llt { + description "DUID Based on Link-layer Address Plus Time + (Type 1 - DUID-LLT)"; + reference "RFC3315 Section 9.2"; + leaf duid-llt-hardware-type { + type uint16; + description "Hardware type as assigned by IANA (RFC826)."; + } + leaf duid-llt-time { + type yang:timeticks; + description "The time value is the time that the DUID is + generated represented in seconds since midnight (UTC), + January 1, 2000, modulo 2^32."; + } + leaf duid-llt-link-layer-addr { + type yang:mac-address; + description "Link-layer address as described in RFC2464"; + } + } + case duid-en { + description "DUID Assigned by Vendor Based on Enterprise Number + (Type 2 - DUID-EN)"; + reference "RFC3315 Section 9.3"; + leaf duid-en-enterprise-number { + type uint32; + description "Vendor's registered Private Enterprise Number as + maintained by IANA"; + } + leaf duid-en-identifier { + type string; + description "Indentifier, unique to the device that is + using it"; + } + } + case duid-ll { + description "DUID Based on Link-layer Address (Type 3 - DUID-LL)"; + reference "RFC3315 Section 9.4"; + leaf duid-ll-hardware-type { + type uint16; + description "Hardware type as assigned by IANA (RFC826)."; + } + leaf duid-ll-link-layer-addr { + type yang:mac-address; + description "Link-layer address as described in RFC2464"; + } + } + case duid-uuid { + description "DUID Based on Universally Unique Identifier + (Type 4 - DUID-UUID)"; + reference "RFC6335 Defination of the UUID-Based Unique Identifier"; + leaf uuid { + type yang:uuid; + description "A Universally Unique IDentifier in the string + representation defined in RFC 4122. The canonical + representation uses lowercase characters"; + } + } + case duid-unknown { + description "DUID based on free raw bytes"; + leaf data { + type binary; + description "The bits to be used as the identifier"; + } + } + } + } + + grouping portset-para { + description "portset parameters"; + container port-parameter { + description "port parameter"; + leaf offset { + type uint8; + mandatory true; + description "offset in a port set"; + } + leaf psid-len { + type uint8; + mandatory true; + description "length of a psid"; + } + leaf psid { + type uint16; + mandatory true; + description "psid value"; + } + } + } + + grouping iaid { + description "IA is a construct through which a server and a + client can identify, group, and manage a set of related IPv6 + addresses. The key of the list is a 4-byte number IAID defined + in [RFC3315]."; + list identity-association { + config "false"; + description "IA"; + leaf iaid { + type uint32; + mandatory true; + description "IAID"; + } + leaf ia-type { + type string; + mandatory true; + description "IA type"; + } + leaf-list ipv6-addr { + type inet:ipv6-address; + description "ipv6 address"; + } + leaf-list ipv6-prefix { + type inet:ipv6-prefix; + description "ipv6 prefix"; + } + leaf-list prefix-length { + type uint8; + description "ipv6 prefix length"; + } + leaf t1-time { + type yang:timeticks; + mandatory true; + description "t1 time"; + } + leaf t2-time { + type yang:timeticks; + mandatory true; + description "t2 time"; + } + leaf preferred-lifetime { + type yang:timeticks; + mandatory true; + description "preferred lifetime"; + } + leaf valid-lifetime { + type yang:timeticks; + mandatory true; + description "valid lifetime"; + } + } + } + +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-hardware@2018-03-13.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-hardware@2018-03-13.yang new file mode 100644 index 0000000..f444e26 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-hardware@2018-03-13.yang @@ -0,0 +1,1141 @@ +module ietf-hardware { +yang-version 1.1; +namespace "urn:ietf:params:xml:ns:yang:ietf-hardware"; +prefix hw; + +import ietf-inet-types { + prefix inet; +} +import ietf-yang-types { + prefix yang; +} +import iana-hardware { + prefix ianahw; +} + +organization + "IETF NETMOD (Network Modeling) Working Group"; + +contact + "WG Web: + WG List: + Editor: Andy Bierman + + Editor: Martin Bjorklund + + Editor: Jie Dong + + Editor: Dan Romascanu + "; + +description + "This module contains a collection of YANG definitions for + managing hardware. + This data model is designed for the Network Management Datastore + Architecture (NMDA) defined in RFC 8342. + 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). + This version of this YANG module is part of RFC 8348; see + the RFC itself for full legal notices."; + +revision 2018-03-13 { + description + "Initial revision."; + reference + "RFC 8348: A YANG Data Model for Hardware Management"; +} + +/* + * Features + */ + +feature entity-mib { + description + "This feature indicates that the device implements + the ENTITY-MIB."; + reference + "RFC 6933: Entity MIB (Version 4)"; +} + +feature hardware-state { + description + "Indicates that ENTITY-STATE-MIB objects are supported"; + reference + "RFC 4268: Entity State MIB"; +} + +feature hardware-sensor { + description + "Indicates that ENTITY-SENSOR-MIB objects are supported"; + reference + "RFC 3433: Entity Sensor Management Information Base"; +} + +/* + * Typedefs + */ + +typedef admin-state { + type enumeration { + enum unknown { + value 1; + description + "The resource is unable to report administrative state."; + } + enum locked { + value 2; + description + "The resource is administratively prohibited from use."; + } + enum shutting-down { + value 3; + description + "The resource usage is administratively limited to current + instances of use."; + } + enum unlocked { + value 4; + description + "The resource is not administratively prohibited from + use."; + } + } + description + "Represents the various possible administrative states."; + reference + "RFC 4268: Entity State MIB - EntityAdminState"; +} + +typedef oper-state { + type enumeration { + enum unknown { + value 1; + description + "The resource is unable to report its operational state."; + } + enum disabled { + value 2; + description + "The resource is totally inoperable."; + } + enum enabled { + value 3; + + description + "The resource is partially or fully operable."; + } + enum testing { + value 4; + description + "The resource is currently being tested and cannot + therefore report whether or not it is operational."; + } + } + description + "Represents the possible values of operational states."; + reference + "RFC 4268: Entity State MIB - EntityOperState"; +} + +typedef usage-state { + type enumeration { + enum unknown { + value 1; + description + "The resource is unable to report usage state."; + } + enum idle { + value 2; + description + "The resource is servicing no users."; + } + enum active { + value 3; + description + "The resource is currently in use, and it has sufficient + spare capacity to provide for additional users."; + } + enum busy { + value 4; + description + "The resource is currently in use, but it currently has no + spare capacity to provide for additional users."; + } + } + description + "Represents the possible values of usage states."; + reference + "RFC 4268: Entity State MIB - EntityUsageState"; +} + +typedef alarm-state { + type bits { + bit unknown { + position 0; + description + "The resource is unable to report alarm state."; + } + bit under-repair { + position 1; + description + "The resource is currently being repaired, which, depending + on the implementation, may make the other values in this + bit string not meaningful."; + } + bit critical { + position 2; + description + "One or more critical alarms are active against the + resource."; + } + bit major { + position 3; + description + "One or more major alarms are active against the + resource."; + } + bit minor { + position 4; + description + "One or more minor alarms are active against the + resource."; + } + bit warning { + position 5; + description + "One or more warning alarms are active against the + resource."; + } + bit indeterminate { + position 6; + description + "One or more alarms of whose perceived severity cannot be + determined are active against this resource."; + } + } + description + "Represents the possible values of alarm states. An alarm is a + persistent indication of an error or warning condition. + When no bits of this attribute are set, then no active alarms + are known against this component and it is not under repair."; + reference + "RFC 4268: Entity State MIB - EntityAlarmStatus"; +} + +typedef standby-state { + type enumeration { + enum unknown { + value 1; + description + "The resource is unable to report standby state."; + } + enum hot-standby { + value 2; + description + "The resource is not providing service, but it will be + immediately able to take over the role of the resource to + be backed up, without the need for initialization + activity, and will contain the same information as the + resource to be backed up."; + } + enum cold-standby { + value 3; + description + "The resource is to back up another resource, but it will + not be immediately able to take over the role of a + resource to be backed up and will require some + initialization activity."; + } + enum providing-service { + value 4; + description + "The resource is providing service."; + } + } + description + "Represents the possible values of standby states."; + reference + "RFC 4268: Entity State MIB - EntityStandbyStatus"; +} + +typedef sensor-value-type { + type enumeration { + enum other { + value 1; + description + "A measure other than those listed below."; + } + enum unknown { + value 2; + description + "An unknown measurement or arbitrary, relative numbers"; + } + enum volts-AC { + value 3; + description + "A measure of electric potential (alternating current)."; + } + enum volts-DC { + value 4; + description + "A measure of electric potential (direct current)."; + } + enum amperes { + value 5; + description + "A measure of electric current."; + } + enum watts { + value 6; + description + "A measure of power."; + } + enum hertz { + value 7; + description + "A measure of frequency."; + } + enum celsius { + value 8; + description + "A measure of temperature."; + } + enum percent-RH { + value 9; + description + "A measure of percent relative humidity."; + } + enum rpm { + value 10; + description + "A measure of shaft revolutions per minute."; + } + enum cmm { + value 11; + description + "A measure of cubic meters per minute (airflow)."; + } + enum truth-value { + value 12; + description + "Value is one of 1 (true) or 2 (false)"; + } + } + description + "A node using this data type represents the sensor measurement + data type associated with a physical sensor value. The actual + data units are determined by examining a node of this type + together with the associated sensor-value-scale node. + A node of this type SHOULD be defined together with nodes of + type sensor-value-scale and type sensor-value-precision. + These three types are used to identify the semantics of a node + of type sensor-value."; + reference + "RFC 3433: Entity Sensor Management Information Base - + EntitySensorDataType"; +} + +typedef sensor-value-scale { + type enumeration { + enum yocto { + value 1; + description + "Data scaling factor of 10^-24."; + } + enum zepto { + value 2; + description + "Data scaling factor of 10^-21."; + } + enum atto { + value 3; + description + "Data scaling factor of 10^-18."; + } + enum femto { + value 4; + description + "Data scaling factor of 10^-15."; + } + enum pico { + value 5; + description + "Data scaling factor of 10^-12."; + } + enum nano { + value 6; + description + "Data scaling factor of 10^-9."; + } + enum micro { + value 7; + description + "Data scaling factor of 10^-6."; + } + enum milli { + value 8; + description + "Data scaling factor of 10^-3."; + } + enum units { + value 9; + description + "Data scaling factor of 10^0."; + } + enum kilo { + value 10; + description + "Data scaling factor of 10^3."; + } + enum mega { + value 11; + description + "Data scaling factor of 10^6."; + } + enum giga { + value 12; + description + "Data scaling factor of 10^9."; + } + enum tera { + value 13; + description + "Data scaling factor of 10^12."; + } + enum peta { + value 14; + description + "Data scaling factor of 10^15."; + } + enum exa { + value 15; + description + "Data scaling factor of 10^18."; + } + enum zetta { + value 16; + description + "Data scaling factor of 10^21."; + } + enum yotta { + value 17; + description + "Data scaling factor of 10^24."; + } + } + description + "A node using this data type represents a data scaling factor, + represented with an International System of Units (SI) prefix. + The actual data units are determined by examining a node of + this type together with the associated sensor-value-type. + A node of this type SHOULD be defined together with nodes of + type sensor-value-type and type sensor-value-precision. + Together, associated nodes of these three types are used to + identify the semantics of a node of type sensor-value."; + reference + "RFC 3433: Entity Sensor Management Information Base - + EntitySensorDataScale"; +} + +typedef sensor-value-precision { + type int8 { + range "-8 .. 9"; + } + description + "A node using this data type represents a sensor value + precision range. + A node of this type SHOULD be defined together with nodes of + type sensor-value-type and type sensor-value-scale. Together, + associated nodes of these three types are used to identify the + semantics of a node of type sensor-value. + If a node of this type contains a value in the range 1 to 9, + it represents the number of decimal places in the fractional + part of an associated sensor-value fixed-point number. + If a node of this type contains a value in the range -8 to -1, + it represents the number of accurate digits in the associated + sensor-value fixed-point number. + The value zero indicates the associated sensor-value node is + not a fixed-point number. + Server implementers must choose a value for the associated + sensor-value-precision node so that the precision and accuracy + of the associated sensor-value node is correctly indicated. + For example, a component representing a temperature sensor + that can measure 0 to 100 degrees C in 0.1 degree + increments, +/- 0.05 degrees, would have a + sensor-value-precision value of '1', a sensor-value-scale + value of 'units', and a sensor-value ranging from '0' to + '1000'. The sensor-value would be interpreted as + 'degrees C * 10'."; + reference + "RFC 3433: Entity Sensor Management Information Base - + EntitySensorPrecision"; +} + +typedef sensor-value { + type int32 { + range "-1000000000 .. 1000000000"; + } + description + "A node using this data type represents a sensor value. + A node of this type SHOULD be defined together with nodes of + type sensor-value-type, type sensor-value-scale, and + type sensor-value-precision. Together, associated nodes of + those three types are used to identify the semantics of a node + of this data type. + The semantics of a node using this data type are determined by + the value of the associated sensor-value-type node. + If the associated sensor-value-type node is equal to 'voltsAC', + 'voltsDC', 'amperes', 'watts', 'hertz', 'celsius', or 'cmm', + then a node of this type MUST contain a fixed-point number + ranging from -999,999,999 to +999,999,999. The value + -1000000000 indicates an underflow error. The value + +1000000000 indicates an overflow error. The + sensor-value-precision indicates how many fractional digits + are represented in the associated sensor-value node. + If the associated sensor-value-type node is equal to + 'percentRH', then a node of this type MUST contain a number + ranging from 0 to 100. + If the associated sensor-value-type node is equal to 'rpm', + then a node of this type MUST contain a number ranging from + -999,999,999 to +999,999,999. + If the associated sensor-value-type node is equal to + 'truth-value', then a node of this type MUST contain either the + value 1 (true) or the value 2 (false). + If the associated sensor-value-type node is equal to 'other' or + 'unknown', then a node of this type MUST contain a number + ranging from -1000000000 to 1000000000."; + reference + "RFC 3433: Entity Sensor Management Information Base - + EntitySensorValue"; +} + +typedef sensor-status { + type enumeration { + enum ok { + value 1; + description + "Indicates that the server can obtain the sensor value."; + } + enum unavailable { + value 2; + description + "Indicates that the server presently cannot obtain the + sensor value."; + } + enum nonoperational { + value 3; + description + "Indicates that the server believes the sensor is broken. + The sensor could have a hard failure (disconnected wire) + or a soft failure such as out-of-range, jittery, or wildly + fluctuating readings."; + } + } + description + "A node using this data type represents the operational status + of a physical sensor."; + reference + "RFC 3433: Entity Sensor Management Information Base - + EntitySensorStatus"; +} + +/* + * Data nodes + */ + +container hardware { + description + "Data nodes representing components. + If the server supports configuration of hardware components, + then this data model is instantiated in the configuration + datastores supported by the server. The leaf-list 'datastore' + for the module 'ietf-hardware' in the YANG library provides + this information."; + + leaf last-change { + type yang:date-and-time; + config false; + description + "The time the '/hardware/component' list changed in the + operational state."; + } + + list component { + key name; + description + "List of components. + When the server detects a new hardware component, it + initializes a list entry in the operational state. + If the server does not support configuration of hardware + components, list entries in the operational state are + initialized with values for all nodes as detected by the + implementation. + Otherwise, this procedure is followed: + 1. If there is an entry in the '/hardware/component' list + in the intended configuration with values for the nodes + 'class', 'parent', and 'parent-rel-pos' that are equal + to the detected values, then the list entry in the + operational state is initialized with the configured + values, including the 'name'. + 2. Otherwise (i.e., there is no matching configuration + entry), the list entry in the operational state is + initialized with values for all nodes as detected by + the implementation. + If the '/hardware/component' list in the intended + configuration is modified, then the system MUST behave as if + it re-initializes itself and follow the procedure in (1)."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalEntry"; + + leaf name { + type string; + description + "The name assigned to this component. + This name is not required to be the same as + entPhysicalName."; + } + + leaf class { + type identityref { + base ianahw:hardware-class; + } + mandatory true; + description + "An indication of the general hardware type of the + component."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalClass"; + } + + leaf physical-index { + if-feature entity-mib; + type int32 { + range "1..2147483647"; + } + config false; + description + "The entPhysicalIndex for the entPhysicalEntry represented + by this list entry."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalIndex"; + } + + leaf description { + type string; + config false; + description + "A textual description of the component. This node should + contain a string that identifies the manufacturer's name + for the component and should be set to a distinct value + for each version or model of the component."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalDescr"; + } + + leaf parent { + type leafref { + path "../../component/name"; + require-instance false; + } + description + "The name of the component that physically contains this + component. + If this leaf is not instantiated, it indicates that this + component is not contained in any other component. + In the event that a physical component is contained by + more than one physical component (e.g., double-wide + modules), this node contains the name of one of these + components. An implementation MUST use the same name + every time this node is instantiated."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalContainedIn"; + } + + leaf parent-rel-pos { + type int32 { + range "0 .. 2147483647"; + } + description + "An indication of the relative position of this child + component among all its sibling components. Sibling + components are defined as components that: + o share the same value of the 'parent' node and + o share a common base identity for the 'class' node. + Note that the last rule gives implementations flexibility + in how components are numbered. For example, some + implementations might have a single number series for all + components derived from 'ianahw:port', while some others + might have different number series for different + components with identities derived from 'ianahw:port' (for + example, one for registered jack 45 (RJ45) and one for + small form-factor pluggable (SFP))."; + + reference + "RFC 6933: Entity MIB (Version 4) - + entPhysicalParentRelPos"; + } + + leaf-list contains-child { + type leafref { + path "../../component/name"; + } + config false; + description + "The name of the contained component."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalChildIndex"; + } + + leaf hardware-rev { + type string; + config false; + description + "The vendor-specific hardware revision string for the + component. The preferred value is the hardware revision + identifier actually printed on the component itself (if + present)."; + reference + "RFC 6933: Entity MIB (Version 4) - + entPhysicalHardwareRev"; + } + + leaf firmware-rev { + type string; + config false; + description + "The vendor-specific firmware revision string for the + component."; + reference + "RFC 6933: Entity MIB (Version 4) - + entPhysicalFirmwareRev"; + } + + leaf software-rev { + type string; + config false; + + description + "The vendor-specific software revision string for the + component."; + reference + "RFC 6933: Entity MIB (Version 4) - + entPhysicalSoftwareRev"; + } + + leaf serial-num { + type string; + config false; + description + "The vendor-specific serial number string for the + component. The preferred value is the serial number + string actually printed on the component itself (if + present)."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalSerialNum"; + } + + leaf mfg-name { + type string; + config false; + description + "The name of the manufacturer of this physical component. + The preferred value is the manufacturer name string + actually printed on the component itself (if present). + Note that comparisons between instances of the + 'model-name', 'firmware-rev', 'software-rev', and + 'serial-num' nodes are only meaningful amongst components + with the same value of 'mfg-name'. + If the manufacturer name string associated with the + physical component is unknown to the server, then this + node is not instantiated."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalMfgName"; + } + + leaf model-name { + type string; + config false; + description + "The vendor-specific model name identifier string + associated with this physical component. The preferred + value is the customer-visible part number, which may be + printed on the component itself. + If the model name string associated with the physical + component is unknown to the server, then this node is not + instantiated."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalModelName"; + } + + leaf alias { + type string; + description + "An 'alias' name for the component, as specified by a + network manager, that provides a non-volatile 'handle' for + the component. + If no configured value exists, the server MAY set the + value of this node to a locally unique value in the + operational state. + A server implementation MAY map this leaf to the + entPhysicalAlias MIB object. Such an implementation needs + to use some mechanism to handle the differences in size + and characters allowed between this leaf and + entPhysicalAlias. The definition of such a mechanism is + outside the scope of this document."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalAlias"; + } + + leaf asset-id { + type string; + description + "This node is a user-assigned asset tracking identifier for + the component. + A server implementation MAY map this leaf to the + entPhysicalAssetID MIB object. Such an implementation + needs to use some mechanism to handle the differences in + size and characters allowed between this leaf and + entPhysicalAssetID. The definition of such a mechanism is + outside the scope of this document."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalAssetID"; + } + + leaf is-fru { + type boolean; + config false; + + description + "This node indicates whether or not this component is + considered a 'field-replaceable unit' by the vendor. If + this node contains the value 'true', then this component + identifies a field-replaceable unit. For all components + that are permanently contained within a field-replaceable + unit, the value 'false' should be returned for this + node."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalIsFRU"; + } + + leaf mfg-date { + type yang:date-and-time; + config false; + description + "The date of manufacturing of the managed component."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalMfgDate"; + } + + leaf-list uri { + type inet:uri; + description + "This node contains identification information about the + component."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalUris"; + } + + leaf uuid { + type yang:uuid; + config false; + description + "A Universally Unique Identifier of the component."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalUUID"; + } + + container state { + if-feature hardware-state; + description + "State-related nodes"; + reference + "RFC 4268: Entity State MIB"; + + leaf state-last-changed { + type yang:date-and-time; + config false; + description + "The date and time when the value of any of the + admin-state, oper-state, usage-state, alarm-state, or + standby-state changed for this component. + If there has been no change since the last + re-initialization of the local system, this node + contains the date and time of local system + initialization. If there has been no change since the + component was added to the local system, this node + contains the date and time of the insertion."; + reference + "RFC 4268: Entity State MIB - entStateLastChanged"; + } + + leaf admin-state { + type admin-state; + description + "The administrative state for this component. + This node refers to a component's administrative + permission to service both other components within its + containment hierarchy as well other users of its + services defined by means outside the scope of this + module. + Some components exhibit only a subset of the remaining + administrative state values. Some components cannot be + locked; hence, this node exhibits only the 'unlocked' + state. Other components cannot be shut down gracefully; + hence, this node does not exhibit the 'shutting-down' + state."; + reference + "RFC 4268: Entity State MIB - entStateAdmin"; + } + + leaf oper-state { + type oper-state; + config false; + description + "The operational state for this component. + Note that this node does not follow the administrative + state. An administrative state of 'down' does not + predict an operational state of 'disabled'. + Note that some implementations may not be able to + accurately report oper-state while the admin-state node + has a value other than 'unlocked'. In these cases, this + node MUST have a value of 'unknown'."; + reference + "RFC 4268: Entity State MIB - entStateOper"; + } + + leaf usage-state { + type usage-state; + config false; + description + "The usage state for this component. + This node refers to a component's ability to service + more components in a containment hierarchy. + Some components will exhibit only a subset of the usage + state values. Components that are unable to ever + service any components within a containment hierarchy + will always have a usage state of 'busy'. In some + cases, a component will be able to support only one + other component within its containment hierarchy and + will therefore only exhibit values of 'idle' and + 'busy'."; + reference + "RFC 4268: Entity State MIB - entStateUsage"; + } + + leaf alarm-state { + type alarm-state; + config false; + description + "The alarm state for this component. It does not + include the alarms raised on child components within its + containment hierarchy."; + reference + "RFC 4268: Entity State MIB - entStateAlarm"; + } + + leaf standby-state { + type standby-state; + config false; + description + "The standby state for this component. + Some components will exhibit only a subset of the + remaining standby state values. If this component + cannot operate in a standby role, the value of this node + will always be 'providing-service'."; + reference + "RFC 4268: Entity State MIB - entStateStandby"; + } + } + + container sensor-data { + when 'derived-from-or-self(../class, + "ianahw:sensor")' { + description + "Sensor data nodes present for any component of type + 'sensor'"; + } + if-feature hardware-sensor; + config false; + + description + "Sensor-related nodes."; + reference + "RFC 3433: Entity Sensor Management Information Base"; + + leaf value { + type sensor-value; + description + "The most recent measurement obtained by the server + for this sensor. + A client that periodically fetches this node should also + fetch the nodes 'value-type', 'value-scale', and + 'value-precision', since they may change when the value + is changed."; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorValue"; + } + + leaf value-type { + type sensor-value-type; + description + "The type of data units associated with the + sensor value"; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorType"; + } + leaf value-scale { + type sensor-value-scale; + description + "The (power of 10) scaling factor associated + with the sensor value"; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorScale"; + } + + leaf value-precision { + type sensor-value-precision; + description + "The number of decimal places of precision + associated with the sensor value"; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorPrecision"; + } + + leaf oper-status { + type sensor-status; + description + "The operational status of the sensor."; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorOperStatus"; + } + + leaf units-display { + type string; + description + "A textual description of the data units that should be + used in the display of the sensor value."; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorUnitsDisplay"; + } + + leaf value-timestamp { + type yang:date-and-time; + description + "The time the status and/or value of this sensor was last + obtained by the server."; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorValueTimeStamp"; + } + leaf value-update-rate { + type uint32; + units "milliseconds"; + description + "An indication of the frequency that the server updates + the associated 'value' node, represented in + milliseconds. The value zero indicates: + - the sensor value is updated on demand (e.g., + when polled by the server for a get-request), + - the sensor value is updated when the sensor + value changes (event-driven), or + - the server does not know the update rate."; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorValueUpdateRate"; + } + } + } +} + +/* + * Notifications + */ + +notification hardware-state-change { + description + "A hardware-state-change notification is generated when the + value of /hardware/last-change changes in the operational + state."; + reference + "RFC 6933: Entity MIB (Version 4) - entConfigChange"; +} + +notification hardware-state-oper-enabled { + if-feature hardware-state; + description + "A hardware-state-oper-enabled notification signifies that a + component has transitioned into the 'enabled' state."; + + leaf name { + type leafref { + path "/hardware/component/name"; + } + + description + "The name of the component that has transitioned into the + 'enabled' state."; + } + leaf admin-state { + type leafref { + path "/hardware/component/state/admin-state"; + } + description + "The administrative state for the component."; + } + leaf alarm-state { + type leafref { + path "/hardware/component/state/alarm-state"; + } + description + "The alarm state for the component."; + } + reference + "RFC 4268: Entity State MIB - entStateOperEnabled"; +} + +notification hardware-state-oper-disabled { + if-feature hardware-state; + description + "A hardware-state-oper-disabled notification signifies that a + component has transitioned into the 'disabled' state."; + + leaf name { + type leafref { + path "/hardware/component/name"; + } + description + "The name of the component that has transitioned into the + 'disabled' state."; + } + leaf admin-state { + type leafref { + path "/hardware/component/state/admin-state"; + } + description + "The administrative state for the component."; + } + leaf alarm-state { + type leafref { + path "/hardware/component/state/alarm-state"; + } + + description + "The alarm state for the component."; + } + reference + "RFC 4268: Entity State MIB - entStateOperDisabled"; +} + +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-inet-types@2013-07-15.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-inet-types@2013-07-15.yang new file mode 100644 index 0000000..4b0db8e --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-inet-types@2013-07-15.yang @@ -0,0 +1,429 @@ +module ietf-inet-types { + +namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types"; +prefix "inet"; + +organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + +contact + "WG Web: + WG List: + WG Chair: David Kessens + + WG Chair: Juergen Schoenwaelder + + Editor: Juergen Schoenwaelder + "; + +description + "This module contains a collection of generally useful derived + YANG data types for Internet addresses and related things. + Copyright (c) 2013 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 + (http://trustee.ietf.org/license-info). + This version of this YANG module is part of RFC 6991; see + the RFC itself for full legal notices."; + +revision 2013-07-15 { + description + "This revision adds the following new data types: + - ip-address-no-zone + - ipv4-address-no-zone + - ipv6-address-no-zone"; + reference + "RFC 6991: Common YANG Data Types"; +} + +revision 2010-09-24 { + description + "Initial revision."; + reference + "RFC 6021: Common YANG Data Types"; +} + +/*** collection of types related to protocol fields ***/ + +typedef ip-version { + type enumeration { + enum unknown { + value "0"; + description + "An unknown or unspecified version of the Internet + protocol."; + } + enum ipv4 { + value "1"; + description + "The IPv4 protocol as defined in RFC 791."; + } + enum ipv6 { + value "2"; + description + "The IPv6 protocol as defined in RFC 2460."; + } + } + description + "This value represents the version of the IP protocol. + In the value set and its semantics, this type is equivalent + to the InetVersion textual convention of the SMIv2."; + reference + "RFC 791: Internet Protocol + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification + RFC 4001: Textual Conventions for Internet Network Addresses"; +} + +typedef dscp { + type uint8 { + range "0..63"; + } + description + "The dscp type represents a Differentiated Services Code Point + that may be used for marking packets in a traffic stream. + In the value set and its semantics, this type is equivalent + to the Dscp textual convention of the SMIv2."; + reference + "RFC 3289: Management Information Base for the Differentiated + Services Architecture + RFC 2474: Definition of the Differentiated Services Field + (DS Field) in the IPv4 and IPv6 Headers + RFC 2780: IANA Allocation Guidelines For Values In + the Internet Protocol and Related Headers"; +} + +typedef ipv6-flow-label { + type uint32 { + range "0..1048575"; + } + description + "The ipv6-flow-label type represents the flow identifier or Flow + Label in an IPv6 packet header that may be used to + discriminate traffic flows. + In the value set and its semantics, this type is equivalent + to the IPv6FlowLabel textual convention of the SMIv2."; + reference + "RFC 3595: Textual Conventions for IPv6 Flow Label + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification"; +} + +typedef port-number { + type uint16 { + range "0..65535"; + } + description + "The port-number type represents a 16-bit port number of an + Internet transport-layer protocol such as UDP, TCP, DCCP, or + SCTP. Port numbers are assigned by IANA. A current list of + all assignments is available from . + Note that the port number value zero is reserved by IANA. In + situations where the value zero does not make sense, it can + be excluded by subtyping the port-number type. + In the value set and its semantics, this type is equivalent + to the InetPortNumber textual convention of the SMIv2."; + reference + "RFC 768: User Datagram Protocol + RFC 793: Transmission Control Protocol + RFC 4960: Stream Control Transmission Protocol + RFC 4340: Datagram Congestion Control Protocol (DCCP) + RFC 4001: Textual Conventions for Internet Network Addresses"; +} + +/*** collection of types related to autonomous systems ***/ + +typedef as-number { + type uint32; + description + "The as-number type represents autonomous system numbers + which identify an Autonomous System (AS). An AS is a set + of routers under a single technical administration, using + an interior gateway protocol and common metrics to route + packets within the AS, and using an exterior gateway + protocol to route packets to other ASes. IANA maintains + the AS number space and has delegated large parts to the + regional registries. + Autonomous system numbers were originally limited to 16 + bits. BGP extensions have enlarged the autonomous system + number space to 32 bits. This type therefore uses an uint32 + base type without a range restriction in order to support + a larger autonomous system number space. + In the value set and its semantics, this type is equivalent + to the InetAutonomousSystemNumber textual convention of + the SMIv2."; + reference + "RFC 1930: Guidelines for creation, selection, and registration + of an Autonomous System (AS) + RFC 4271: A Border Gateway Protocol 4 (BGP-4) + RFC 4001: Textual Conventions for Internet Network Addresses + RFC 6793: BGP Support for Four-Octet Autonomous System (AS) + Number Space"; +} + +/*** collection of types related to IP addresses and hostnames ***/ + +typedef ip-address { + type union { + type inet:ipv4-address; + type inet:ipv6-address; + } + description + "The ip-address type represents an IP address and is IP + version neutral. The format of the textual representation + implies the IP version. This type supports scoped addresses + by allowing zone identifiers in the address format."; + reference + "RFC 4007: IPv6 Scoped Address Architecture"; +} + +typedef ipv4-address { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '(%[\p{N}\p{L}]+)?'; + } + description + "The ipv4-address type represents an IPv4 address in + dotted-quad notation. The IPv4 address may include a zone + index, separated by a % sign. + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + The canonical format for the zone index is the numerical + format"; +} + +typedef ipv6-address { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(%[\p{N}\p{L}]+)?'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(%.+)?'; + } + description + "The ipv6-address type represents an IPv6 address in full, + mixed, shortened, and shortened-mixed notation. The IPv6 + address may include a zone index, separated by a % sign. + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + The canonical format of IPv6 addresses uses the textual + representation defined in Section 4 of RFC 5952. The + canonical format for the zone index is the numerical + format as described in Section 11.2 of RFC 4007."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation"; +} + +typedef ip-address-no-zone { + type union { + type inet:ipv4-address-no-zone; + type inet:ipv6-address-no-zone; + } + description + "The ip-address-no-zone type represents an IP address and is + IP version neutral. The format of the textual representation + implies the IP version. This type does not support scoped + addresses since it does not allow zone identifiers in the + address format."; + reference + "RFC 4007: IPv6 Scoped Address Architecture"; +} + +typedef ipv4-address-no-zone { + type inet:ipv4-address { + pattern '[0-9\.]*'; + } + description + "An IPv4 address without a zone index. This type, derived from + ipv4-address, may be used in situations where the zone is + known from the context and hence no zone index is needed."; +} + +typedef ipv6-address-no-zone { + type inet:ipv6-address { + pattern '[0-9a-fA-F:\.]*'; + } + description + "An IPv6 address without a zone index. This type, derived from + ipv6-address, may be used in situations where the zone is + known from the context and hence no zone index is needed."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation"; +} + +typedef ip-prefix { + type union { + type inet:ipv4-prefix; + type inet:ipv6-prefix; + } + description + "The ip-prefix type represents an IP prefix and is IP + version neutral. The format of the textual representations + implies the IP version."; +} + +typedef ipv4-prefix { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '/(([0-9])|([1-2][0-9])|(3[0-2]))'; + } + description + "The ipv4-prefix type represents an IPv4 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 32. + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + The canonical format of an IPv4 prefix has all bits of + the IPv4 address set to zero that are not part of the + IPv4 prefix."; +} + +typedef ipv6-prefix { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(/.+)'; + } + + description + "The ipv6-prefix type represents an IPv6 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 128. + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + The IPv6 address should have all bits that do not belong + to the prefix set to zero. + The canonical format of an IPv6 prefix has all bits of + the IPv6 address set to zero that are not part of the + IPv6 prefix. Furthermore, the IPv6 address is represented + as defined in Section 4 of RFC 5952."; + reference + "RFC 5952: A Recommendation for IPv6 Address Text + Representation"; +} + +/*** collection of domain name and URI types ***/ + +typedef domain-name { + type string { + pattern + '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*' + + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)' + + '|\.'; + length "1..253"; + } + description + "The domain-name type represents a DNS domain name. The + name SHOULD be fully qualified whenever possible. + Internet domain names are only loosely specified. Section + 3.5 of RFC 1034 recommends a syntax (modified in Section + 2.1 of RFC 1123). The pattern above is intended to allow + for current practice in domain name use, and some possible + future expansion. It is designed to hold various types of + domain names, including names used for A or AAAA records + (host names) and other records, such as SRV records. Note + that Internet host names have a stricter syntax (described + in RFC 952) than the DNS recommendations in RFCs 1034 and + 1123, and that systems that want to store host names in + schema nodes using the domain-name type are recommended to + adhere to this stricter standard to ensure interoperability. + The encoding of DNS names in the DNS protocol is limited + to 255 characters. Since the encoding consists of labels + prefixed by a length bytes and there is a trailing NULL + byte, only 253 characters can appear in the textual dotted + notation. + The description clause of schema nodes using the domain-name + type MUST describe when and how these names are resolved to + IP addresses. Note that the resolution of a domain-name value + may require to query multiple DNS records (e.g., A for IPv4 + and AAAA for IPv6). The order of the resolution process and + which DNS record takes precedence can either be defined + explicitly or may depend on the configuration of the + resolver. + Domain-name values use the US-ASCII encoding. Their canonical + format uses lowercase US-ASCII characters. Internationalized + domain names MUST be A-labels as per RFC 5890."; + reference + "RFC 952: DoD Internet Host Table Specification + RFC 1034: Domain Names - Concepts and Facilities + RFC 1123: Requirements for Internet Hosts -- Application + and Support + RFC 2782: A DNS RR for specifying the location of services + (DNS SRV) + RFC 5890: Internationalized Domain Names in Applications + (IDNA): Definitions and Document Framework"; +} + +typedef host { + type union { + type inet:ip-address; + type inet:domain-name; + } + description + "The host type represents either an IP address or a DNS + domain name."; +} + +typedef uri { + type string; + description + "The uri type represents a Uniform Resource Identifier + (URI) as defined by STD 66. + Objects using the uri type MUST be in US-ASCII encoding, + and MUST be normalized as described by RFC 3986 Sections + 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary + percent-encoding is removed, and all case-insensitive + characters are set to lowercase except for hexadecimal + digits, which are normalized to uppercase as described in + Section 6.2.2.1. + The purpose of this normalization is to help provide + unique URIs. Note that this normalization is not + sufficient to provide uniqueness. Two URIs that are + textually distinct after this normalization may still be + equivalent. + Objects using the uri type may restrict the schemes that + they permit. For example, 'data:' and 'urn:' schemes + might not be appropriate. + A zero-length URI is not a valid URI. This can be used to + express 'URI absent' where required. + In the value set and its semantics, this type is equivalent + to the Uri SMIv2 textual convention defined in RFC 5017."; + reference + "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax + RFC 3305: Report from the Joint W3C/IETF URI Planning Interest + Group: Uniform Resource Identifiers (URIs), URLs, + and Uniform Resource Names (URNs): Clarifications + and Recommendations + RFC 5017: MIB Textual Conventions for Uniform Resource + Identifiers (URIs)"; +} + +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-interfaces@2018-02-20.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-interfaces@2018-02-20.yang new file mode 100644 index 0000000..8dae9d3 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-interfaces@2018-02-20.yang @@ -0,0 +1,1073 @@ +module ietf-interfaces { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-interfaces"; + prefix if; + + import ietf-yang-types { + prefix yang; + } + + organization + "IETF NETMOD (Network Modeling) Working Group"; + + contact + "WG Web: + WG List: + Editor: Martin Bjorklund + "; + + description + "This module contains a collection of YANG definitions for + managing network interfaces. + 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). + This version of this YANG module is part of RFC 8343; see + the RFC itself for full legal notices."; + + revision 2018-02-20 { + description + "Updated to support NMDA."; + reference + "RFC 8343: A YANG Data Model for Interface Management"; + } + + revision 2014-05-08 { + description + "Initial revision."; + reference + "RFC 7223: A YANG Data Model for Interface Management"; + } + + /* + * Typedefs + */ + + typedef interface-ref { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + description + "This type is used by data models that need to reference + interfaces."; + } + + /* + * Identities + */ + + identity interface-type { + description + "Base identity from which specific interface types are + derived."; + } + + /* + * Features + */ + + feature arbitrary-names { + description + "This feature indicates that the device allows user-controlled + interfaces to be named arbitrarily."; + } + feature pre-provisioning { + description + "This feature indicates that the device supports + pre-provisioning of interface configuration, i.e., it is + possible to configure an interface whose physical interface + hardware is not present on the device."; + } + feature if-mib { + description + "This feature indicates that the device implements + the IF-MIB."; + reference + "RFC 2863: The Interfaces Group MIB"; + } + + /* + * Data nodes + */ + + container interfaces { + description + "Interface parameters."; + + list interface { + key "name"; + + description + "The list of interfaces on the device. + The status of an interface is available in this list in the + operational state. If the configuration of a + system-controlled interface cannot be used by the system + (e.g., the interface hardware present does not match the + interface type), then the configuration is not applied to + the system-controlled interface shown in the operational + state. If the configuration of a user-controlled interface + cannot be used by the system, the configured interface is + not instantiated in the operational state. + System-controlled interfaces created by the system are + always present in this list in the operational state, + whether or not they are configured."; + + leaf name { + type string; + description + "The name of the interface. + A device MAY restrict the allowed values for this leaf, + possibly depending on the type of the interface. + For system-controlled interfaces, this leaf is the + device-specific name of the interface. + If a client tries to create configuration for a + system-controlled interface that is not present in the + operational state, the server MAY reject the request if + the implementation does not support pre-provisioning of + interfaces or if the name refers to an interface that can + never exist in the system. A Network Configuration + Protocol (NETCONF) server MUST reply with an rpc-error + with the error-tag 'invalid-value' in this case. + If the device supports pre-provisioning of interface + configuration, the 'pre-provisioning' feature is + advertised. + If the device allows arbitrarily named user-controlled + interfaces, the 'arbitrary-names' feature is advertised. + When a configured user-controlled interface is created by + the system, it is instantiated with the same name in the + operational state. + A server implementation MAY map this leaf to the ifName + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and ifName. The definition of + such a mechanism is outside the scope of this document."; + reference + "RFC 2863: The Interfaces Group MIB - ifName"; + } + + leaf description { + type string; + description + "A textual description of the interface. + A server implementation MAY map this leaf to the ifAlias + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and ifAlias. The definition of + such a mechanism is outside the scope of this document. + Since ifAlias is defined to be stored in non-volatile + storage, the MIB implementation MUST map ifAlias to the + value of 'description' in the persistently stored + configuration."; + reference + "RFC 2863: The Interfaces Group MIB - ifAlias"; + } + + leaf type { + type identityref { + base interface-type; + } + mandatory true; + description + "The type of the interface. + When an interface entry is created, a server MAY + initialize the type leaf with a valid value, e.g., if it + is possible to derive the type from the name of the + interface. + If a client tries to set the type of an interface to a + value that can never be used by the system, e.g., if the + type is not supported or if the type does not match the + name of the interface, the server MUST reject the request. + A NETCONF server MUST reply with an rpc-error with the + error-tag 'invalid-value' in this case."; + reference + "RFC 2863: The Interfaces Group MIB - ifType"; + } + + leaf enabled { + type boolean; + default "true"; + description + "This leaf contains the configured, desired state of the + interface. + Systems that implement the IF-MIB use the value of this + leaf in the intended configuration to set + IF-MIB.ifAdminStatus to 'up' or 'down' after an ifEntry + has been initialized, as described in RFC 2863. + Changes in this leaf in the intended configuration are + reflected in ifAdminStatus."; + reference + "RFC 2863: The Interfaces Group MIB - ifAdminStatus"; + } + + leaf link-up-down-trap-enable { + if-feature if-mib; + type enumeration { + enum enabled { + value 1; + description + "The device will generate linkUp/linkDown SNMP + notifications for this interface."; + } + enum disabled { + value 2; + description + "The device will not generate linkUp/linkDown SNMP + notifications for this interface."; + } + } + description + "Controls whether linkUp/linkDown SNMP notifications + should be generated for this interface. + If this node is not configured, the value 'enabled' is + operationally used by the server for interfaces that do + not operate on top of any other interface (i.e., there are + no 'lower-layer-if' entries), and 'disabled' otherwise."; + reference + "RFC 2863: The Interfaces Group MIB - + ifLinkUpDownTrapEnable"; + } + + leaf admin-status { + if-feature if-mib; + type enumeration { + enum up { + value 1; + description + "Ready to pass packets."; + } + enum down { + value 2; + description + "Not ready to pass packets and not in some test mode."; + } + enum testing { + value 3; + description + "In some test mode."; + } + } + config false; + mandatory true; + description + "The desired state of the interface. + This leaf has the same read semantics as ifAdminStatus."; + reference + "RFC 2863: The Interfaces Group MIB - ifAdminStatus"; + } + + leaf oper-status { + type enumeration { + enum up { + value 1; + description + "Ready to pass packets."; + } + enum down { + value 2; + + description + "The interface does not pass any packets."; + } + enum testing { + value 3; + description + "In some test mode. No operational packets can + be passed."; + } + enum unknown { + value 4; + description + "Status cannot be determined for some reason."; + } + enum dormant { + value 5; + description + "Waiting for some external event."; + } + enum not-present { + value 6; + description + "Some component (typically hardware) is missing."; + } + enum lower-layer-down { + value 7; + description + "Down due to state of lower-layer interface(s)."; + } + } + config false; + mandatory true; + description + "The current operational state of the interface. + This leaf has the same semantics as ifOperStatus."; + reference + "RFC 2863: The Interfaces Group MIB - ifOperStatus"; + } + + leaf last-change { + type yang:date-and-time; + config false; + description + "The time the interface entered its current operational + state. If the current state was entered prior to the + last re-initialization of the local network management + subsystem, then this node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - ifLastChange"; + } + + leaf if-index { + if-feature if-mib; + type int32 { + range "1..2147483647"; + } + config false; + mandatory true; + description + "The ifIndex value for the ifEntry represented by this + interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifIndex"; + } + + leaf phys-address { + type yang:phys-address; + config false; + description + "The interface's address at its protocol sub-layer. For + example, for an 802.x interface, this object normally + contains a Media Access Control (MAC) address. The + interface's media-specific modules must define the bit + and byte ordering and the format of the value of this + object. For interfaces that do not have such an address + (e.g., a serial line), this node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - ifPhysAddress"; + } + + leaf-list higher-layer-if { + type interface-ref; + config false; + description + "A list of references to interfaces layered on top of this + interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifStackTable"; + } + + leaf-list lower-layer-if { + type interface-ref; + config false; + + description + "A list of references to interfaces layered underneath this + interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifStackTable"; + } + + leaf speed { + type yang:gauge64; + units "bits/second"; + config false; + description + "An estimate of the interface's current bandwidth in bits + per second. For interfaces that do not vary in + bandwidth or for those where no accurate estimation can + be made, this node should contain the nominal bandwidth. + For interfaces that have no concept of bandwidth, this + node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - + ifSpeed, ifHighSpeed"; + } + + container statistics { + config false; + description + "A collection of interface-related statistics objects."; + + leaf discontinuity-time { + type yang:date-and-time; + mandatory true; + description + "The time on the most recent occasion at which any one or + more of this interface's counters suffered a + discontinuity. If no such discontinuities have occurred + since the last re-initialization of the local management + subsystem, then this node contains the time the local + management subsystem re-initialized itself."; + } + + leaf in-octets { + type yang:counter64; + description + "The total number of octets received on the interface, + including framing characters. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCInOctets"; + } + + leaf in-unicast-pkts { + type yang:counter64; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were not addressed to a + multicast or broadcast address at this sub-layer. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCInUcastPkts"; + } + + leaf in-broadcast-pkts { + type yang:counter64; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were addressed to a broadcast + address at this sub-layer. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCInBroadcastPkts"; + } + + leaf in-multicast-pkts { + type yang:counter64; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were addressed to a multicast + address at this sub-layer. For a MAC-layer protocol, + this includes both Group and Functional addresses. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCInMulticastPkts"; + } + + leaf in-discards { + type yang:counter32; + description + "The number of inbound packets that were chosen to be + discarded even though no errors had been detected to + prevent their being deliverable to a higher-layer + protocol. One possible reason for discarding such a + packet could be to free up buffer space. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifInDiscards"; + } + + leaf in-errors { + type yang:counter32; + description + "For packet-oriented interfaces, the number of inbound + packets that contained errors preventing them from being + deliverable to a higher-layer protocol. For character- + oriented or fixed-length interfaces, the number of + inbound transmission units that contained errors + preventing them from being deliverable to a higher-layer + protocol. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifInErrors"; + } + + leaf in-unknown-protos { + type yang:counter32; + + description + "For packet-oriented interfaces, the number of packets + received via the interface that were discarded because + of an unknown or unsupported protocol. For + character-oriented or fixed-length interfaces that + support protocol multiplexing, the number of + transmission units received via the interface that were + discarded because of an unknown or unsupported protocol. + For any interface that does not support protocol + multiplexing, this counter is not present. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifInUnknownProtos"; + } + + leaf out-octets { + type yang:counter64; + description + "The total number of octets transmitted out of the + interface, including framing characters. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCOutOctets"; + } + + leaf out-unicast-pkts { + type yang:counter64; + description + "The total number of packets that higher-level protocols + requested be transmitted and that were not addressed + to a multicast or broadcast address at this sub-layer, + including those that were discarded or not sent. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCOutUcastPkts"; + } + + leaf out-broadcast-pkts { + type yang:counter64; + description + "The total number of packets that higher-level protocols + requested be transmitted and that were addressed to a + broadcast address at this sub-layer, including those + that were discarded or not sent. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCOutBroadcastPkts"; + } + + leaf out-multicast-pkts { + type yang:counter64; + description + "The total number of packets that higher-level protocols + requested be transmitted and that were addressed to a + multicast address at this sub-layer, including those + that were discarded or not sent. For a MAC-layer + protocol, this includes both Group and Functional + addresses. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCOutMulticastPkts"; + } + + leaf out-discards { + type yang:counter32; + description + "The number of outbound packets that were chosen to be + discarded even though no errors had been detected to + prevent their being transmitted. One possible reason + for discarding such a packet could be to free up buffer + space. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifOutDiscards"; + } + + leaf out-errors { + type yang:counter32; + description + "For packet-oriented interfaces, the number of outbound + packets that could not be transmitted because of errors. + For character-oriented or fixed-length interfaces, the + number of outbound transmission units that could not be + transmitted because of errors. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifOutErrors"; + } + } + + } + } + + /* + * Legacy typedefs + */ + + typedef interface-state-ref { + type leafref { + path "/if:interfaces-state/if:interface/if:name"; + } + status deprecated; + description + "This type is used by data models that need to reference + the operationally present interfaces."; + } + + /* + * Legacy operational state data nodes + */ + + container interfaces-state { + config false; + status deprecated; + description + "Data nodes for the operational state of interfaces."; + + list interface { + key "name"; + status deprecated; + + description + "The list of interfaces on the device. + System-controlled interfaces created by the system are + always present in this list, whether or not they are + configured."; + + leaf name { + type string; + status deprecated; + description + "The name of the interface. + A server implementation MAY map this leaf to the ifName + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and ifName. The definition of + such a mechanism is outside the scope of this document."; + reference + "RFC 2863: The Interfaces Group MIB - ifName"; + } + + leaf type { + type identityref { + base interface-type; + } + mandatory true; + status deprecated; + description + "The type of the interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifType"; + } + + leaf admin-status { + if-feature if-mib; + type enumeration { + enum up { + value 1; + description + "Ready to pass packets."; + } + enum down { + value 2; + description + "Not ready to pass packets and not in some test mode."; + } + enum testing { + value 3; + description + "In some test mode."; + } + } + mandatory true; + status deprecated; + description + "The desired state of the interface. + This leaf has the same read semantics as ifAdminStatus."; + reference + "RFC 2863: The Interfaces Group MIB - ifAdminStatus"; + } + + leaf oper-status { + type enumeration { + enum up { + value 1; + description + "Ready to pass packets."; + } + enum down { + value 2; + description + "The interface does not pass any packets."; + } + enum testing { + value 3; + description + "In some test mode. No operational packets can + be passed."; + } + enum unknown { + value 4; + description + "Status cannot be determined for some reason."; + } + enum dormant { + value 5; + description + "Waiting for some external event."; + } + enum not-present { + value 6; + description + "Some component (typically hardware) is missing."; + } + enum lower-layer-down { + value 7; + description + "Down due to state of lower-layer interface(s)."; + } + } + mandatory true; + status deprecated; + description + "The current operational state of the interface. + This leaf has the same semantics as ifOperStatus."; + reference + "RFC 2863: The Interfaces Group MIB - ifOperStatus"; + } + + leaf last-change { + type yang:date-and-time; + status deprecated; + description + "The time the interface entered its current operational + state. If the current state was entered prior to the + last re-initialization of the local network management + subsystem, then this node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - ifLastChange"; + } + + leaf if-index { + if-feature if-mib; + type int32 { + range "1..2147483647"; + } + mandatory true; + status deprecated; + description + "The ifIndex value for the ifEntry represented by this + interface."; + + reference + "RFC 2863: The Interfaces Group MIB - ifIndex"; + } + + leaf phys-address { + type yang:phys-address; + status deprecated; + description + "The interface's address at its protocol sub-layer. For + example, for an 802.x interface, this object normally + contains a Media Access Control (MAC) address. The + interface's media-specific modules must define the bit + and byte ordering and the format of the value of this + object. For interfaces that do not have such an address + (e.g., a serial line), this node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - ifPhysAddress"; + } + + leaf-list higher-layer-if { + type interface-state-ref; + status deprecated; + description + "A list of references to interfaces layered on top of this + interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifStackTable"; + } + + leaf-list lower-layer-if { + type interface-state-ref; + status deprecated; + description + "A list of references to interfaces layered underneath this + interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifStackTable"; + } + + leaf speed { + type yang:gauge64; + units "bits/second"; + status deprecated; + description + "An estimate of the interface's current bandwidth in bits + per second. For interfaces that do not vary in + bandwidth or for those where no accurate estimation can + be made, this node should contain the nominal bandwidth. + For interfaces that have no concept of bandwidth, this + node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - + ifSpeed, ifHighSpeed"; + } + + container statistics { + status deprecated; + description + "A collection of interface-related statistics objects."; + + leaf discontinuity-time { + type yang:date-and-time; + mandatory true; + status deprecated; + description + "The time on the most recent occasion at which any one or + more of this interface's counters suffered a + discontinuity. If no such discontinuities have occurred + since the last re-initialization of the local management + subsystem, then this node contains the time the local + management subsystem re-initialized itself."; + } + + leaf in-octets { + type yang:counter64; + status deprecated; + description + "The total number of octets received on the interface, + including framing characters. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCInOctets"; + } + + leaf in-unicast-pkts { + type yang:counter64; + status deprecated; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were not addressed to a + multicast or broadcast address at this sub-layer. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCInUcastPkts"; + } + + leaf in-broadcast-pkts { + type yang:counter64; + status deprecated; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were addressed to a broadcast + address at this sub-layer. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCInBroadcastPkts"; + } + + leaf in-multicast-pkts { + type yang:counter64; + status deprecated; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were addressed to a multicast + address at this sub-layer. For a MAC-layer protocol, + this includes both Group and Functional addresses. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCInMulticastPkts"; + } + + leaf in-discards { + type yang:counter32; + status deprecated; + + description + "The number of inbound packets that were chosen to be + discarded even though no errors had been detected to + prevent their being deliverable to a higher-layer + protocol. One possible reason for discarding such a + packet could be to free up buffer space. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifInDiscards"; + } + + leaf in-errors { + type yang:counter32; + status deprecated; + description + "For packet-oriented interfaces, the number of inbound + packets that contained errors preventing them from being + deliverable to a higher-layer protocol. For character- + oriented or fixed-length interfaces, the number of + inbound transmission units that contained errors + preventing them from being deliverable to a higher-layer + protocol. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifInErrors"; + } + + leaf in-unknown-protos { + type yang:counter32; + status deprecated; + description + "For packet-oriented interfaces, the number of packets + received via the interface that were discarded because + of an unknown or unsupported protocol. For + character-oriented or fixed-length interfaces that + support protocol multiplexing, the number of + transmission units received via the interface that were + discarded because of an unknown or unsupported protocol. + For any interface that does not support protocol + multiplexing, this counter is not present. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifInUnknownProtos"; + } + + leaf out-octets { + type yang:counter64; + status deprecated; + description + "The total number of octets transmitted out of the + interface, including framing characters. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCOutOctets"; + } + + leaf out-unicast-pkts { + type yang:counter64; + status deprecated; + description + "The total number of packets that higher-level protocols + requested be transmitted and that were not addressed + to a multicast or broadcast address at this sub-layer, + including those that were discarded or not sent. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCOutUcastPkts"; + } + + leaf out-broadcast-pkts { + type yang:counter64; + status deprecated; + + description + "The total number of packets that higher-level protocols + requested be transmitted and that were addressed to a + broadcast address at this sub-layer, including those + that were discarded or not sent. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCOutBroadcastPkts"; + } + + leaf out-multicast-pkts { + type yang:counter64; + status deprecated; + description + "The total number of packets that higher-level protocols + requested be transmitted and that were addressed to a + multicast address at this sub-layer, including those + that were discarded or not sent. For a MAC-layer + protocol, this includes both Group and Functional + addresses. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCOutMulticastPkts"; + } + + leaf out-discards { + type yang:counter32; + status deprecated; + description + "The number of outbound packets that were chosen to be + discarded even though no errors had been detected to + prevent their being transmitted. One possible reason + for discarding such a packet could be to free up buffer + space. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifOutDiscards"; + } + + leaf out-errors { + type yang:counter32; + status deprecated; + description + "For packet-oriented interfaces, the number of outbound + packets that could not be transmitted because of errors. + For character-oriented or fixed-length interfaces, the + number of outbound transmission units that could not be + transmitted because of errors. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifOutErrors"; + } + } + } + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-ip@2018-02-22.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-ip@2018-02-22.yang new file mode 100644 index 0000000..449081b --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-ip@2018-02-22.yang @@ -0,0 +1,860 @@ +module ietf-ip { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-ip"; + prefix ip; + + import ietf-interfaces { + prefix if; + } + import ietf-inet-types { + prefix inet; + } + import ietf-yang-types { + prefix yang; + } + + organization + "IETF NETMOD (Network Modeling) Working Group"; + + contact + "WG Web: + WG List: + Editor: Martin Bjorklund + "; + description + "This module contains a collection of YANG definitions for + managing IP implementations. + 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). + This version of this YANG module is part of RFC 8344; see + the RFC itself for full legal notices."; + + revision 2018-02-22 { + description + "Updated to support NMDA."; + reference + "RFC 8344: A YANG Data Model for IP Management"; + } + + revision 2014-06-16 { + description + "Initial revision."; + reference + "RFC 7277: A YANG Data Model for IP Management"; + } + + /* + * Features + */ + + feature ipv4-non-contiguous-netmasks { + description + "Indicates support for configuring non-contiguous + subnet masks."; + } + + feature ipv6-privacy-autoconf { + description + "Indicates support for privacy extensions for stateless address + autoconfiguration in IPv6."; + reference + "RFC 4941: Privacy Extensions for Stateless Address + Autoconfiguration in IPv6"; + } + + /* + * Typedefs + */ + + typedef ip-address-origin { + type enumeration { + enum other { + description + "None of the following."; + } + + enum static { + description + "Indicates that the address has been statically + configured -- for example, using the Network Configuration + Protocol (NETCONF) or a command line interface."; + } + enum dhcp { + description + "Indicates an address that has been assigned to this + system by a DHCP server."; + } + enum link-layer { + description + "Indicates an address created by IPv6 stateless + autoconfiguration that embeds a link-layer address in its + interface identifier."; + } + enum random { + description + "Indicates an address chosen by the system at + random, e.g., an IPv4 address within 169.254/16, a + temporary address as described in RFC 4941, or a + semantically opaque address as described in RFC 7217."; + reference + "RFC 4941: Privacy Extensions for Stateless Address + Autoconfiguration in IPv6 + RFC 7217: A Method for Generating Semantically Opaque + Interface Identifiers with IPv6 Stateless + Address Autoconfiguration (SLAAC)"; + } + } + description + "The origin of an address."; + } + + typedef neighbor-origin { + type enumeration { + enum other { + description + "None of the following."; + } + enum static { + description + "Indicates that the mapping has been statically + configured -- for example, using NETCONF or a command line + interface."; + } + + enum dynamic { + description + "Indicates that the mapping has been dynamically resolved + using, for example, IPv4 ARP or the IPv6 Neighbor + Discovery protocol."; + } + } + description + "The origin of a neighbor entry."; + } + + /* + * Data nodes + */ + + augment "/if:interfaces/if:interface" { + description + "IP parameters on interfaces. + If an interface is not capable of running IP, the server + must not allow the client to configure these parameters."; + + container ipv4 { + presence + "Enables IPv4 unless the 'enabled' leaf + (which defaults to 'true') is set to 'false'"; + description + "Parameters for the IPv4 address family."; + + leaf enabled { + type boolean; + default true; + description + "Controls whether IPv4 is enabled or disabled on this + interface. When IPv4 is enabled, this interface is + connected to an IPv4 stack, and the interface can send + and receive IPv4 packets."; + } + leaf forwarding { + type boolean; + default false; + description + "Controls IPv4 packet forwarding of datagrams received by, + but not addressed to, this interface. IPv4 routers + forward datagrams. IPv4 hosts do not (except those + source-routed via the host)."; + } + + leaf mtu { + type uint16 { + range "68..max"; + } + units "octets"; + description + "The size, in octets, of the largest IPv4 packet that the + interface will send and receive. + The server may restrict the allowed values for this leaf, + depending on the interface's type. + If this leaf is not configured, the operationally used MTU + depends on the interface's type."; + reference + "RFC 791: Internet Protocol"; + } + list address { + key "ip"; + description + "The list of IPv4 addresses on the interface."; + + leaf ip { + type inet:ipv4-address-no-zone; + description + "The IPv4 address on the interface."; + } + choice subnet { + mandatory true; + description + "The subnet can be specified as a prefix length or, + if the server supports non-contiguous netmasks, as + a netmask."; + leaf prefix-length { + type uint8 { + range "0..32"; + } + description + "The length of the subnet prefix."; + } + leaf netmask { + if-feature ipv4-non-contiguous-netmasks; + type yang:dotted-quad; + description + "The subnet specified as a netmask."; + } + } + + leaf origin { + type ip-address-origin; + config false; + description + "The origin of this address."; + } + } + list neighbor { + key "ip"; + description + "A list of mappings from IPv4 addresses to + link-layer addresses. + Entries in this list in the intended configuration are + used as static entries in the ARP Cache. + In the operational state, this list represents the ARP + Cache."; + reference + "RFC 826: An Ethernet Address Resolution Protocol"; + + leaf ip { + type inet:ipv4-address-no-zone; + description + "The IPv4 address of the neighbor node."; + } + leaf link-layer-address { + type yang:phys-address; + mandatory true; + description + "The link-layer address of the neighbor node."; + } + leaf origin { + type neighbor-origin; + config false; + description + "The origin of this neighbor entry."; + } + } + } + + container ipv6 { + presence + "Enables IPv6 unless the 'enabled' leaf + (which defaults to 'true') is set to 'false'"; + description + "Parameters for the IPv6 address family."; + + leaf enabled { + type boolean; + default true; + description + "Controls whether IPv6 is enabled or disabled on this + interface. When IPv6 is enabled, this interface is + connected to an IPv6 stack, and the interface can send + and receive IPv6 packets."; + } + leaf forwarding { + type boolean; + default false; + description + "Controls IPv6 packet forwarding of datagrams received by, + but not addressed to, this interface. IPv6 routers + forward datagrams. IPv6 hosts do not (except those + source-routed via the host)."; + reference + "RFC 4861: Neighbor Discovery for IP version 6 (IPv6) + Section 6.2.1, IsRouter"; + } + leaf mtu { + type uint32 { + range "1280..max"; + } + units "octets"; + description + "The size, in octets, of the largest IPv6 packet that the + interface will send and receive. + The server may restrict the allowed values for this leaf, + depending on the interface's type. + If this leaf is not configured, the operationally used MTU + depends on the interface's type."; + reference + "RFC 8200: Internet Protocol, Version 6 (IPv6) + Specification + Section 5"; + } + + list address { + key "ip"; + description + "The list of IPv6 addresses on the interface."; + + leaf ip { + type inet:ipv6-address-no-zone; + description + "The IPv6 address on the interface."; + } + leaf prefix-length { + type uint8 { + range "0..128"; + } + mandatory true; + description + "The length of the subnet prefix."; + } + leaf origin { + type ip-address-origin; + config false; + description + "The origin of this address."; + } + leaf status { + type enumeration { + enum preferred { + description + "This is a valid address that can appear as the + destination or source address of a packet."; + } + enum deprecated { + description + "This is a valid but deprecated address that should + no longer be used as a source address in new + communications, but packets addressed to such an + address are processed as expected."; + } + enum invalid { + description + "This isn't a valid address, and it shouldn't appear + as the destination or source address of a packet."; + } + + enum inaccessible { + description + "The address is not accessible because the interface + to which this address is assigned is not + operational."; + } + enum unknown { + description + "The status cannot be determined for some reason."; + } + enum tentative { + description + "The uniqueness of the address on the link is being + verified. Addresses in this state should not be + used for general communication and should only be + used to determine the uniqueness of the address."; + } + enum duplicate { + description + "The address has been determined to be non-unique on + the link and so must not be used."; + } + enum optimistic { + description + "The address is available for use, subject to + restrictions, while its uniqueness on a link is + being verified."; + } + } + config false; + description + "The status of an address. Most of the states correspond + to states from the IPv6 Stateless Address + Autoconfiguration protocol."; + reference + "RFC 4293: Management Information Base for the + Internet Protocol (IP) + - IpAddressStatusTC + RFC 4862: IPv6 Stateless Address Autoconfiguration"; + } + } + + list neighbor { + key "ip"; + description + "A list of mappings from IPv6 addresses to + link-layer addresses. + Entries in this list in the intended configuration are + used as static entries in the Neighbor Cache. + In the operational state, this list represents the + Neighbor Cache."; + reference + "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)"; + + leaf ip { + type inet:ipv6-address-no-zone; + description + "The IPv6 address of the neighbor node."; + } + leaf link-layer-address { + type yang:phys-address; + mandatory true; + description + "The link-layer address of the neighbor node. + In the operational state, if the neighbor's 'state' leaf + is 'incomplete', this leaf is not instantiated."; + } + leaf origin { + type neighbor-origin; + config false; + description + "The origin of this neighbor entry."; + } + leaf is-router { + type empty; + config false; + description + "Indicates that the neighbor node acts as a router."; + } + + leaf state { + type enumeration { + enum incomplete { + description + "Address resolution is in progress, and the + link-layer address of the neighbor has not yet been + determined."; + } + enum reachable { + description + "Roughly speaking, the neighbor is known to have been + reachable recently (within tens of seconds ago)."; + } + enum stale { + description + "The neighbor is no longer known to be reachable, but + until traffic is sent to the neighbor no attempt + should be made to verify its reachability."; + } + enum delay { + description + "The neighbor is no longer known to be reachable, and + traffic has recently been sent to the neighbor. + Rather than probe the neighbor immediately, however, + delay sending probes for a short while in order to + give upper-layer protocols a chance to provide + reachability confirmation."; + } + enum probe { + description + "The neighbor is no longer known to be reachable, and + unicast Neighbor Solicitation probes are being sent + to verify reachability."; + } + } + config false; + description + "The Neighbor Unreachability Detection state of this + entry."; + reference + "RFC 4861: Neighbor Discovery for IP version 6 (IPv6) + Section 7.3.2"; + } + } + + leaf dup-addr-detect-transmits { + type uint32; + default 1; + description + "The number of consecutive Neighbor Solicitation messages + sent while performing Duplicate Address Detection on a + tentative address. A value of zero indicates that + Duplicate Address Detection is not performed on + tentative addresses. A value of one indicates a single + transmission with no follow-up retransmissions."; + reference + "RFC 4862: IPv6 Stateless Address Autoconfiguration"; + } + container autoconf { + description + "Parameters to control the autoconfiguration of IPv6 + addresses, as described in RFC 4862."; + reference + "RFC 4862: IPv6 Stateless Address Autoconfiguration"; + + leaf create-global-addresses { + type boolean; + default true; + description + "If enabled, the host creates global addresses as + described in RFC 4862."; + reference + "RFC 4862: IPv6 Stateless Address Autoconfiguration + Section 5.5"; + } + leaf create-temporary-addresses { + if-feature ipv6-privacy-autoconf; + type boolean; + default false; + description + "If enabled, the host creates temporary addresses as + described in RFC 4941."; + reference + "RFC 4941: Privacy Extensions for Stateless Address + Autoconfiguration in IPv6"; + } + + leaf temporary-valid-lifetime { + if-feature ipv6-privacy-autoconf; + type uint32; + units "seconds"; + default 604800; + description + "The time period during which the temporary address + is valid."; + reference + "RFC 4941: Privacy Extensions for Stateless Address + Autoconfiguration in IPv6 + - TEMP_VALID_LIFETIME"; + } + leaf temporary-preferred-lifetime { + if-feature ipv6-privacy-autoconf; + type uint32; + units "seconds"; + default 86400; + description + "The time period during which the temporary address is + preferred."; + reference + "RFC 4941: Privacy Extensions for Stateless Address + Autoconfiguration in IPv6 + - TEMP_PREFERRED_LIFETIME"; + } + } + } + } + + /* + * Legacy operational state data nodes + */ + + augment "/if:interfaces-state/if:interface" { + status deprecated; + description + "Data nodes for the operational state of IP on interfaces."; + + container ipv4 { + presence + "Present if IPv4 is enabled on this interface"; + config false; + status deprecated; + description + "Interface-specific parameters for the IPv4 address family."; + + leaf forwarding { + type boolean; + status deprecated; + description + "Indicates whether IPv4 packet forwarding is enabled or + disabled on this interface."; + } + leaf mtu { + type uint16 { + range "68..max"; + } + units "octets"; + status deprecated; + description + "The size, in octets, of the largest IPv4 packet that the + interface will send and receive."; + reference + "RFC 791: Internet Protocol"; + } + list address { + key "ip"; + status deprecated; + description + "The list of IPv4 addresses on the interface."; + + leaf ip { + type inet:ipv4-address-no-zone; + status deprecated; + description + "The IPv4 address on the interface."; + } + choice subnet { + status deprecated; + description + "The subnet can be specified as a prefix length or, + if the server supports non-contiguous netmasks, as + a netmask."; + leaf prefix-length { + type uint8 { + range "0..32"; + } + status deprecated; + description + "The length of the subnet prefix."; + } + leaf netmask { + if-feature ipv4-non-contiguous-netmasks; + type yang:dotted-quad; + status deprecated; + description + "The subnet specified as a netmask."; + } + } + leaf origin { + type ip-address-origin; + status deprecated; + description + "The origin of this address."; + } + } + list neighbor { + key "ip"; + status deprecated; + description + "A list of mappings from IPv4 addresses to + link-layer addresses. + This list represents the ARP Cache."; + reference + "RFC 826: An Ethernet Address Resolution Protocol"; + + leaf ip { + type inet:ipv4-address-no-zone; + status deprecated; + description + "The IPv4 address of the neighbor node."; + } + + leaf link-layer-address { + type yang:phys-address; + status deprecated; + description + "The link-layer address of the neighbor node."; + } + leaf origin { + type neighbor-origin; + status deprecated; + description + "The origin of this neighbor entry."; + } + } + } + + container ipv6 { + presence + "Present if IPv6 is enabled on this interface"; + config false; + status deprecated; + description + "Parameters for the IPv6 address family."; + + leaf forwarding { + type boolean; + default false; + status deprecated; + description + "Indicates whether IPv6 packet forwarding is enabled or + disabled on this interface."; + reference + "RFC 4861: Neighbor Discovery for IP version 6 (IPv6) + Section 6.2.1, IsRouter"; + } + leaf mtu { + type uint32 { + range "1280..max"; + } + units "octets"; + status deprecated; + description + "The size, in octets, of the largest IPv6 packet that the + interface will send and receive."; + reference + "RFC 8200: Internet Protocol, Version 6 (IPv6) + Specification + Section 5"; + } + list address { + key "ip"; + status deprecated; + description + "The list of IPv6 addresses on the interface."; + + leaf ip { + type inet:ipv6-address-no-zone; + status deprecated; + description + "The IPv6 address on the interface."; + } + leaf prefix-length { + type uint8 { + range "0..128"; + } + mandatory true; + status deprecated; + description + "The length of the subnet prefix."; + } + leaf origin { + type ip-address-origin; + status deprecated; + description + "The origin of this address."; + } + leaf status { + type enumeration { + enum preferred { + description + "This is a valid address that can appear as the + destination or source address of a packet."; + } + enum deprecated { + description + "This is a valid but deprecated address that should + no longer be used as a source address in new + communications, but packets addressed to such an + address are processed as expected."; + } + enum invalid { + description + "This isn't a valid address, and it shouldn't appear + as the destination or source address of a packet."; + } + + enum inaccessible { + description + "The address is not accessible because the interface + to which this address is assigned is not + operational."; + } + enum unknown { + description + "The status cannot be determined for some reason."; + } + enum tentative { + description + "The uniqueness of the address on the link is being + verified. Addresses in this state should not be + used for general communication and should only be + used to determine the uniqueness of the address."; + } + enum duplicate { + description + "The address has been determined to be non-unique on + the link and so must not be used."; + } + enum optimistic { + description + "The address is available for use, subject to + restrictions, while its uniqueness on a link is + being verified."; + } + } + status deprecated; + description + "The status of an address. Most of the states correspond + to states from the IPv6 Stateless Address + Autoconfiguration protocol."; + reference + "RFC 4293: Management Information Base for the + Internet Protocol (IP) + - IpAddressStatusTC + RFC 4862: IPv6 Stateless Address Autoconfiguration"; + } + } + + list neighbor { + key "ip"; + status deprecated; + description + "A list of mappings from IPv6 addresses to + link-layer addresses. + This list represents the Neighbor Cache."; + reference + "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)"; + + leaf ip { + type inet:ipv6-address-no-zone; + status deprecated; + description + "The IPv6 address of the neighbor node."; + } + leaf link-layer-address { + type yang:phys-address; + status deprecated; + description + "The link-layer address of the neighbor node."; + } + leaf origin { + type neighbor-origin; + status deprecated; + description + "The origin of this neighbor entry."; + } + leaf is-router { + type empty; + status deprecated; + description + "Indicates that the neighbor node acts as a router."; + } + leaf state { + type enumeration { + enum incomplete { + description + "Address resolution is in progress, and the + link-layer address of the neighbor has not yet been + determined."; + } + enum reachable { + description + "Roughly speaking, the neighbor is known to have been + reachable recently (within tens of seconds ago)."; + } + enum stale { + description + "The neighbor is no longer known to be reachable, but + until traffic is sent to the neighbor no attempt + should be made to verify its reachability."; + } + enum delay { + description + "The neighbor is no longer known to be reachable, and + traffic has recently been sent to the neighbor. + Rather than probe the neighbor immediately, however, + delay sending probes for a short while in order to + give upper-layer protocols a chance to provide + reachability confirmation."; + } + enum probe { + description + "The neighbor is no longer known to be reachable, and + unicast Neighbor Solicitation probes are being sent + to verify reachability."; + } + } + status deprecated; + description + "The Neighbor Unreachability Detection state of this + entry."; + reference + "RFC 4861: Neighbor Discovery for IP version 6 (IPv6) + Section 7.3.2"; + } + } + } + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-netconf-acm@2018-02-14.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-netconf-acm@2018-02-14.yang new file mode 100644 index 0000000..ec9687a --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-netconf-acm@2018-02-14.yang @@ -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: + WG List: + Author: Andy Bierman + + Author: Martin Bjorklund + "; + + 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."; + } + } + } + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-network-instance@2019-01-21.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-network-instance@2019-01-21.yang new file mode 100644 index 0000000..fe92ca1 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-network-instance@2019-01-21.yang @@ -0,0 +1,282 @@ +module ietf-network-instance { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-network-instance"; + prefix ni; + + // import some basic types + + import ietf-interfaces { + prefix if; + reference + "RFC 8343: A YANG Data Model for Interface Management"; + } + import ietf-ip { + prefix ip; + reference + "RFC 8344: A YANG Data Model for IP Management"; + } + import ietf-yang-schema-mount { + prefix yangmnt; + reference + "RFC 8528: YANG Schema Mount"; + } + + organization + "IETF Routing Area (rtgwg) Working Group"; + contact + "WG Web: + WG List: + + Author: Lou Berger + + Author: Christian Hopps + + Author: Acee Lindem + + Author: Dean Bogdanovic + "; + description + "This module is used to support multiple network instances + within a single physical or virtual device. Network + instances are commonly known as VRFs (VPN Routing and + Forwarding) and VSIs (Virtual Switching Instances). + The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', + 'SHALL NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', + 'NOT RECOMMENDED', 'MAY', and 'OPTIONAL' in this document + are to be interpreted as described in BCP 14 (RFC 2119) + (RFC 8174) when, and only when, they appear in all capitals, + as shown here. + + Copyright (c) 2019 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 8529; see + the RFC itself for full legal notices."; + + revision 2019-01-21 { + description + "Initial revision."; + reference + "RFC 8529"; + } + + // top-level device definition statements + + container network-instances { + description + "Network instances, each of which consists of + VRFs and/or VSIs."; + reference + "RFC 8349: A YANG Data Model for Routing Management"; + list network-instance { + key "name"; + description + "List of network instances."; + leaf name { + type string; + mandatory true; + description + "device-scoped identifier for the network + instance."; + } + leaf enabled { + type boolean; + default "true"; + description + "Flag indicating whether or not the network + instance is enabled."; + } + leaf description { + type string; + description + "Description of the network instance + and its intended purpose."; + } + choice ni-type { + description + "This node serves as an anchor point for different types + of network instances. Each 'case' is expected to + differ in terms of the information needed in the + parent/core to support the NI and may differ in their + mounted-schema definition. When the mounted schema is + not expected to be the same for a specific type of NI, + a mount point should be defined."; + } + choice root-type { + mandatory true; + description + "Well-known mount points."; + container vrf-root { + description + "Container for mount point."; + yangmnt:mount-point "vrf-root" { + description + "Root for L3VPN-type models. This will typically + not be an inline-type mount point."; + } + } + container vsi-root { + description + "Container for mount point."; + yangmnt:mount-point "vsi-root" { + description + "Root for L2VPN-type models. This will typically + not be an inline-type mount point."; + } + } + container vv-root { + description + "Container for mount point."; + yangmnt:mount-point "vv-root" { + description + "Root models that support both L2VPN-type bridging + and L3VPN-type routing. This will typically + not be an inline-type mount point."; + } + } + } + } + } + + // augment statements + + augment "/if:interfaces/if:interface" { + description + "Add a node for the identification of the network + instance associated with the information configured + on a interface. + + Note that a standard error will be returned if the + identified leafref isn't present. If an interface cannot + be assigned for any other reason, the operation SHALL fail + with an error-tag of 'operation-failed' and an + error-app-tag of 'ni-assignment-failed'. A meaningful + error-info that indicates the source of the assignment + failure SHOULD also be provided."; + leaf bind-ni-name { + type leafref { + path "/network-instances/network-instance/name"; + } + description + "Network instance to which an interface is bound."; + } + } + augment "/if:interfaces/if:interface/ip:ipv4" { + description + "Add a node for the identification of the network + instance associated with the information configured + on an IPv4 interface. + + Note that a standard error will be returned if the + identified leafref isn't present. If an interface cannot + be assigned for any other reason, the operation SHALL fail + with an error-tag of 'operation-failed' and an + error-app-tag of 'ni-assignment-failed'. A meaningful + error-info that indicates the source of the assignment + failure SHOULD also be provided."; + leaf bind-ni-name { + type leafref { + path "/network-instances/network-instance/name"; + } + description + "Network instance to which IPv4 interface is bound."; + } + } + augment "/if:interfaces/if:interface/ip:ipv6" { + description + "Add a node for the identification of the network + instance associated with the information configured + on an IPv6 interface. + + Note that a standard error will be returned if the + identified leafref isn't present. If an interface cannot + be assigned for any other reason, the operation SHALL fail + with an error-tag of 'operation-failed' and an + error-app-tag of 'ni-assignment-failed'. A meaningful + error-info that indicates the source of the assignment + failure SHOULD also be provided."; + leaf bind-ni-name { + type leafref { + path "/network-instances/network-instance/name"; + } + description + "Network instance to which IPv6 interface is bound."; + } + } + + // notification statements + + notification bind-ni-name-failed { + description + "Indicates an error in the association of an interface to an + NI. Only generated after success is initially returned when + bind-ni-name is set. + + Note: Some errors may need to be reported for multiple + associations, e.g., a single error may need to be reported + for an IPv4 and an IPv6 bind-ni-name. + + At least one container with a bind-ni-name leaf MUST be + included in this notification."; + leaf name { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + mandatory true; + description + "Contains the interface name associated with the + failure."; + } + container interface { + description + "Generic interface type."; + leaf bind-ni-name { + type leafref { + path "/if:interfaces/if:interface" + + "/ni:bind-ni-name"; + } + description + "Contains the bind-ni-name associated with the + failure."; + } + } + container ipv4 { + description + "IPv4 interface type."; + leaf bind-ni-name { + type leafref { + path "/if:interfaces/if:interface/ip:ipv4/ni:bind-ni-name"; + } + description + "Contains the bind-ni-name associated with the + failure."; + } + } + container ipv6 { + description + "IPv6 interface type."; + leaf bind-ni-name { + type leafref { + path "/if:interfaces/if:interface/ip:ipv6" + + "/ni:bind-ni-name"; + } + description + "Contains the bind-ni-name associated with the + failure."; + } + } + leaf error-info { + type string; + description + "Optionally, indicates the source of the assignment + failure."; + } + } +} \ No newline at end of file diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-restconf@2017-01-26.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-restconf@2017-01-26.yang new file mode 100644 index 0000000..44dac71 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-restconf@2017-01-26.yang @@ -0,0 +1,278 @@ +module ietf-restconf { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-restconf"; + prefix "rc"; + + organization + "IETF NETCONF (Network Configuration) Working Group"; + + contact + "WG Web: + WG List: + + Author: Andy Bierman + + + Author: Martin Bjorklund + + + Author: Kent Watsen + "; + + description + "This module contains conceptual YANG specifications + for basic RESTCONF media type definitions used in + RESTCONF protocol messages. + + Note that the YANG definitions within this module do not + represent configuration data of any kind. + The 'restconf-media-type' YANG extension statement + provides a normative syntax for XML and JSON + message-encoding purposes. + + Copyright (c) 2017 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 + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 8040; see + the RFC itself for full legal notices."; + + revision 2017-01-26 { + description + "Initial revision."; + reference + "RFC 8040: RESTCONF Protocol."; + } + + extension yang-data { + argument name { + yin-element true; + } + description + "This extension is used to specify a YANG data template that + represents conceptual data defined in YANG. It is + intended to describe hierarchical data independent of + protocol context or specific message-encoding format. + Data definition statements within a yang-data extension + specify the generic syntax for the specific YANG data + template, whose name is the argument of the 'yang-data' + extension statement. + + Note that this extension does not define a media type. + A specification using this extension MUST specify the + message-encoding rules, including the content media type. + + The mandatory 'name' parameter value identifies the YANG + data template that is being defined. It contains the + template name. + + This extension is ignored unless it appears as a top-level + statement. It MUST contain data definition statements + that result in exactly one container data node definition. + An instance of a YANG data template can thus be translated + into an XML instance document, whose top-level element + corresponds to the top-level container. + The module name and namespace values for the YANG module using + the extension statement are assigned to instance document data + conforming to the data definition statements within + this extension. + + The substatements of this extension MUST follow the + 'data-def-stmt' rule in the YANG ABNF. + + The XPath document root is the extension statement itself, + such that the child nodes of the document root are + represented by the data-def-stmt substatements within + this extension. This conceptual document is the context + for the following YANG statements: + + - must-stmt + - when-stmt + - path-stmt + - min-elements-stmt + - max-elements-stmt + - mandatory-stmt + - unique-stmt + - ordered-by + - instance-identifier data type + + The following data-def-stmt substatements are constrained + when used within a 'yang-data' extension statement. + + - The list-stmt is not required to have a key-stmt defined. + - The if-feature-stmt is ignored if present. + - The config-stmt is ignored if present. + - The available identity values for any 'identityref' + leaf or leaf-list nodes are limited to the module + containing this extension statement and the modules + imported into that module. + "; + } + + rc:yang-data yang-errors { + uses errors; + } + + rc:yang-data yang-api { + uses restconf; + } + + grouping errors { + description + "A grouping that contains a YANG container + representing the syntax and semantics of a + YANG Patch error report within a response message."; + + container errors { + description + "Represents an error report returned by the server if + a request results in an error."; + + list error { + description + "An entry containing information about one + specific error that occurred while processing + a RESTCONF request."; + reference + "RFC 6241, Section 4.3."; + + leaf error-type { + type enumeration { + enum transport { + description + "The transport layer."; + } + enum rpc { + description + "The rpc or notification layer."; + } + enum protocol { + description + "The protocol operation layer."; + } + enum application { + description + "The server application layer."; + } + } + mandatory true; + description + "The protocol layer where the error occurred."; + } + + leaf error-tag { + type string; + mandatory true; + description + "The enumerated error-tag."; + } + + leaf error-app-tag { + type string; + description + "The application-specific error-tag."; + } + + leaf error-path { + type instance-identifier; + description + "The YANG instance identifier associated + with the error node."; + } + + leaf error-message { + type string; + description + "A message describing the error."; + } + + anydata error-info { + description + "This anydata value MUST represent a container with + zero or more data nodes representing additional + error information."; + } + } + } + } + + grouping restconf { + description + "Conceptual grouping representing the RESTCONF + root resource."; + + container restconf { + description + "Conceptual container representing the RESTCONF + root resource."; + + container data { + description + "Container representing the datastore resource. + Represents the conceptual root of all state data + and configuration data supported by the server. + The child nodes of this container can be any data + resources that are defined as top-level data nodes + from the YANG modules advertised by the server in + the 'ietf-yang-library' module."; + } + + container operations { + description + "Container for all operation resources. + + Each resource is represented as an empty leaf with the + name of the RPC operation from the YANG 'rpc' statement. + + For example, the 'system-restart' RPC operation defined + in the 'ietf-system' module would be represented as + an empty leaf in the 'ietf-system' namespace. This is + a conceptual leaf and will not actually be found in + the module: + + module ietf-system { + leaf system-reset { + type empty; + } + } + + To invoke the 'system-restart' RPC operation: + + POST /restconf/operations/ietf-system:system-restart + + To discover the RPC operations supported by the server: + + GET /restconf/operations + + In XML, the YANG module namespace identifies the module: + + + + In JSON, the YANG module name identifies the module: + + { 'ietf-system:system-restart' : [null] } + "; + } + leaf yang-library-version { + type string { + pattern '\d{4}-\d{2}-\d{2}'; + } + config false; + mandatory true; + description + "Identifies the revision date of the 'ietf-yang-library' + module that is implemented by this RESTCONF server. + Indicates the year, month, and day in YYYY-MM-DD + numeric format."; + } + } + } + +} \ No newline at end of file diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-subscribed-notifications@2019-09-09.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-subscribed-notifications@2019-09-09.yang new file mode 100644 index 0000000..14df349 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-subscribed-notifications@2019-09-09.yang @@ -0,0 +1,1350 @@ +module ietf-subscribed-notifications { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications"; + prefix sn; + + import ietf-inet-types { + prefix inet; + reference + "RFC 6991: Common YANG Data Types"; + } + import ietf-interfaces { + prefix if; + reference + "RFC 8343: A YANG Data Model for Interface Management"; + } + import ietf-netconf-acm { + prefix nacm; + reference + "RFC 8341: Network Configuration Access Control Model"; + } + import ietf-network-instance { + prefix ni; + reference + "RFC 8529: YANG Data Model for Network Instances"; + } + import ietf-restconf { + prefix rc; + reference + "RFC 8040: RESTCONF Protocol"; + } + import ietf-yang-types { + prefix yang; + reference + "RFC 6991: Common YANG Data Types"; + } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + contact + "WG Web: + WG List: + + Author: Alexander Clemm + + + Author: Eric Voit + + + Author: Alberto Gonzalez Prieto + + + Author: Einar Nilsen-Nygaard + + + Author: Ambika Prasad Tripathy + "; + description + "This module defines a YANG data model for subscribing to event + records and receiving matching content in notification messages. + + The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL + NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED', + 'MAY', and 'OPTIONAL' in this document are to be interpreted as + described in BCP 14 (RFC 2119) (RFC 8174) when, and only when, + they appear in all capitals, as shown here. + + Copyright (c) 2019 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 8639; see the + RFC itself for full legal notices."; + + revision 2019-09-09 { + description + "Initial version."; + reference + "RFC 8639: A YANG Data Model for Subscriptions to + Event Notifications"; + } + + /* + * FEATURES + */ + + feature configured { + description + "This feature indicates that configuration of subscriptions is + supported."; + } + + feature dscp { + description + "This feature indicates that a publisher supports the ability + to set the Differentiated Services Code Point (DSCP) value in + outgoing packets."; + } + + feature encode-json { + description + "This feature indicates that JSON encoding of notification + messages is supported."; + } + + feature encode-xml { + description + "This feature indicates that XML encoding of notification + messages is supported."; + } + + feature interface-designation { + description + "This feature indicates that a publisher supports sourcing all + receiver interactions for a configured subscription from a + single designated egress interface."; + } + + feature qos { + description + "This feature indicates that a publisher supports absolute + dependencies of one subscription's traffic over another + as well as weighted bandwidth sharing between subscriptions. + Both of these are Quality of Service (QoS) features that allow + differentiated treatment of notification messages between a + publisher and a specific receiver."; + } + + feature replay { + description + "This feature indicates that historical event record replay is + supported. With replay, it is possible for past event records + to be streamed in chronological order."; + } + + feature subtree { + description + "This feature indicates support for YANG subtree filtering."; + reference + "RFC 6241: Network Configuration Protocol (NETCONF), + Section 6"; + } + + feature supports-vrf { + description + "This feature indicates that a publisher supports VRF + configuration for configured subscriptions. VRF support for + dynamic subscriptions does not require this feature."; + reference + "RFC 8529: YANG Data Model for Network Instances, + Section 6"; + } + + feature xpath { + description + "This feature indicates support for XPath filtering."; + reference + "XML Path Language (XPath) Version 1.0 + (https://www.w3.org/TR/1999/REC-xpath-19991116)"; + } + + /* + * EXTENSIONS + */ + + extension subscription-state-notification { + description + "This statement applies only to notifications. It indicates + that the notification is a subscription state change + notification. Therefore, it does not participate in a regular + event stream and does not need to be specifically subscribed + to in order to be received. This statement can only occur as + a substatement of the YANG 'notification' statement. This + statement is not for use outside of this YANG module."; + } + + /* + * IDENTITIES + */ + /* Identities for RPC and notification errors */ + + identity delete-subscription-error { + description + "Base identity for the problem found while attempting to + fulfill either a 'delete-subscription' RPC request or a + 'kill-subscription' RPC request."; + } + + identity establish-subscription-error { + description + "Base identity for the problem found while attempting to + fulfill an 'establish-subscription' RPC request."; + } + + identity modify-subscription-error { + description + "Base identity for the problem found while attempting to + fulfill a 'modify-subscription' RPC request."; + } + + identity subscription-suspended-reason { + description + "Base identity for the problem condition communicated to a + receiver as part of a 'subscription-suspended' + notification."; + } + + identity subscription-terminated-reason { + description + "Base identity for the problem condition communicated to a + receiver as part of a 'subscription-terminated' + notification."; + } + + identity dscp-unavailable { + base establish-subscription-error; + if-feature "dscp"; + description + "The publisher is unable to mark notification messages with + prioritization information in a way that will be respected + during network transit."; + } + + identity encoding-unsupported { + base establish-subscription-error; + description + "Unable to encode notification messages in the desired + format."; + } + + identity filter-unavailable { + base subscription-terminated-reason; + description + "Referenced filter does not exist. This means a receiver is + referencing a filter that doesn't exist or to which it + does not have access permissions."; + } + + identity filter-unsupported { + base establish-subscription-error; + base modify-subscription-error; + description + "Cannot parse syntax in the filter. This failure can be from + a syntax error or a syntax too complex to be processed by the + publisher."; + } + + identity insufficient-resources { + base establish-subscription-error; + base modify-subscription-error; + base subscription-suspended-reason; + description + "The publisher does not have sufficient resources to support + the requested subscription. An example might be that + allocated CPU is too limited to generate the desired set of + notification messages."; + } + + identity no-such-subscription { + base modify-subscription-error; + base delete-subscription-error; + base subscription-terminated-reason; + description + "Referenced subscription doesn't exist. This may be as a + result of a nonexistent subscription ID, an ID that belongs to + another subscriber, or an ID for a configured subscription."; + } + + identity replay-unsupported { + base establish-subscription-error; + if-feature "replay"; + description + "Replay cannot be performed for this subscription. This means + the publisher will not provide the requested historic + information from the event stream via replay to this + receiver."; + } + + identity stream-unavailable { + base subscription-terminated-reason; + description + "Not a subscribable event stream. This means the referenced + event stream is not available for subscription by the + receiver."; + } + + identity suspension-timeout { + base subscription-terminated-reason; + description + "Termination of a previously suspended subscription. The + publisher has eliminated the subscription, as it exceeded a + time limit for suspension."; + } + + identity unsupportable-volume { + base subscription-suspended-reason; + description + "The publisher does not have the network bandwidth needed to + get the volume of generated information intended for a + receiver."; + } + + /* Identities for encodings */ + + identity configurable-encoding { + description + "If a transport identity derives from this identity, it means + that it supports configurable encodings. An example of a + configurable encoding might be a new identity such as + 'encode-cbor'. Such an identity could use + 'configurable-encoding' as its base. This would allow a + dynamic subscription encoded in JSON (RFC 8259) to request + that notification messages be encoded via the Concise Binary + Object Representation (CBOR) (RFC 7049). Further details for + any specific configurable encoding would be explored in a + transport document based on this specification."; + reference + "RFC 8259: The JavaScript Object Notation (JSON) Data + Interchange Format + RFC 7049: Concise Binary Object Representation (CBOR)"; + } + + identity encoding { + description + "Base identity to represent data encodings."; + } + + identity encode-xml { + base encoding; + if-feature "encode-xml"; + description + "Encode data using XML as described in RFC 7950."; + reference + "RFC 7950: The YANG 1.1 Data Modeling Language"; + } + + identity encode-json { + base encoding; + if-feature "encode-json"; + description + "Encode data using JSON as described in RFC 7951."; + reference + "RFC 7951: JSON Encoding of Data Modeled with YANG"; + } + + /* Identities for transports */ + + identity transport { + description + "An identity that represents the underlying mechanism for + passing notification messages."; + } + + /* + * TYPEDEFs + */ + + typedef encoding { + type identityref { + base encoding; + } + description + "Specifies a data encoding, e.g., for a data subscription."; + } + + typedef stream-filter-ref { + type leafref { + path "/sn:filters/sn:stream-filter/sn:name"; + } + description + "This type is used to reference an event stream filter."; + } + + typedef stream-ref { + type leafref { + path "/sn:streams/sn:stream/sn:name"; + } + description + "This type is used to reference a system-provided + event stream."; + } + + typedef subscription-id { + type uint32; + description + "A type for subscription identifiers."; + } + + typedef transport { + type identityref { + base transport; + } + description + "Specifies the transport used to send notification messages + to a receiver."; + } + + /* + * GROUPINGS + */ + + grouping stream-filter-elements { + description + "This grouping defines the base for filters applied to event + streams."; + choice filter-spec { + description + "The content filter specification for this request."; + anydata stream-subtree-filter { + if-feature "subtree"; + description + "Event stream evaluation criteria encoded in the syntax of + a subtree filter as defined in RFC 6241, Section 6. + + The subtree filter is applied to the representation of + individual, delineated event records as contained in the + event stream. + + If the subtree filter returns a non-empty node set, the + filter matches the event record, and the event record is + included in the notification message sent to the + receivers."; + reference + "RFC 6241: Network Configuration Protocol (NETCONF), + Section 6"; + } + leaf stream-xpath-filter { + if-feature "xpath"; + type yang:xpath1.0; + description + "Event stream evaluation criteria encoded in the syntax of + an XPath 1.0 expression. + + The XPath expression is evaluated on the representation of + individual, delineated event records as contained in + the event stream. + + The result of the XPath expression is converted to a + boolean value using the standard XPath 1.0 rules. If the + boolean value is 'true', the filter matches the event + record, and the event record is included in the + notification message sent to the receivers. + + The expression is evaluated in the following XPath + context: + + o The set of namespace declarations is the set of + prefix and namespace pairs for all YANG modules + implemented by the server, where the prefix is the + YANG module name and the namespace is as defined by + the 'namespace' statement in the YANG module. + + If the leaf is encoded in XML, all namespace + declarations in scope on the 'stream-xpath-filter' + leaf element are added to the set of namespace + declarations. If a prefix found in the XML is + already present in the set of namespace + declarations, the namespace in the XML is used. + + o The set of variable bindings is empty. + + o The function library is comprised of the core + function library and the XPath functions defined in + Section 10 in RFC 7950. + + o The context node is the root node."; + reference + "XML Path Language (XPath) Version 1.0 + (https://www.w3.org/TR/1999/REC-xpath-19991116) + RFC 7950: The YANG 1.1 Data Modeling Language, + Section 10"; + } + } + } + + grouping update-qos { + description + "This grouping describes QoS information concerning a + subscription. This information is passed to lower layers + for transport prioritization and treatment."; + leaf dscp { + if-feature "dscp"; + type inet:dscp; + default "0"; + description + "The desired network transport priority level. This is the + priority set on notification messages encapsulating the + results of the subscription. This transport priority is + shared for all receivers of a given subscription."; + } + leaf weighting { + if-feature "qos"; + type uint8 { + range "0 .. 255"; + } + description + "Relative weighting for a subscription. Larger weights get + more resources. Allows an underlying transport layer to + perform informed load-balance allocations between various + subscriptions."; + reference + "RFC 7540: Hypertext Transfer Protocol Version 2 (HTTP/2), + Section 5.3.2"; + } + leaf dependency { + if-feature "qos"; + type subscription-id; + description + "Provides the 'subscription-id' of a parent subscription. + The parent subscription has absolute precedence should + that parent have push updates ready to egress the publisher. + In other words, there should be no streaming of objects from + the current subscription if the parent has something ready + to push. + + If a dependency is asserted via configuration or via an RPC + but the referenced 'subscription-id' does not exist, the + dependency is silently discarded. If a referenced + subscription is deleted, this dependency is removed."; + reference + "RFC 7540: Hypertext Transfer Protocol Version 2 (HTTP/2), + Section 5.3.1"; + } + } + + grouping subscription-policy-modifiable { + description + "This grouping describes all objects that may be changed + in a subscription."; + choice target { + mandatory true; + description + "Identifies the source of information against which a + subscription is being applied as well as specifics on the + subset of information desired from that source."; + case stream { + choice stream-filter { + description + "An event stream filter can be applied to a subscription. + That filter will either come referenced from a global + list or be provided in the subscription itself."; + case by-reference { + description + "Apply a filter that has been configured separately."; + leaf stream-filter-name { + type stream-filter-ref; + mandatory true; + description + "References an existing event stream filter that is + to be applied to an event stream for the + subscription."; + } + } + case within-subscription { + description + "A local definition allows a filter to have the same + lifecycle as the subscription."; + uses stream-filter-elements; + } + } + } + } + leaf stop-time { + type yang:date-and-time; + description + "Identifies a time after which notification messages for a + subscription should not be sent. If 'stop-time' is not + present, the notification messages will continue until the + subscription is terminated. If 'replay-start-time' exists, + 'stop-time' must be for a subsequent time. If + 'replay-start-time' doesn't exist, 'stop-time', when + established, must be for a future time."; + } + } + + grouping subscription-policy-dynamic { + description + "This grouping describes the only information concerning a + subscription that can be passed over the RPCs defined in this + data model."; + uses subscription-policy-modifiable { + augment "target/stream" { + description + "Adds additional objects that can be modified by an RPC."; + leaf stream { + type stream-ref { + require-instance false; + } + mandatory true; + description + "Indicates the event stream to be considered for + this subscription."; + } + leaf replay-start-time { + if-feature "replay"; + type yang:date-and-time; + config false; + description + "Used to trigger the 'replay' feature for a dynamic + subscription, where event records that are selected + need to be at or after the specified starting time. If + 'replay-start-time' is not present, this is not a replay + subscription and event record push should start + immediately. It is never valid to specify start times + that are later than or equal to the current time."; + } + } + } + uses update-qos; + } + + grouping subscription-policy { + description + "This grouping describes the full set of policy information + concerning both dynamic and configured subscriptions, with the + exclusion of both receivers and networking information + specific to the publisher, such as what interface should be + used to transmit notification messages."; + uses subscription-policy-dynamic; + leaf transport { + if-feature "configured"; + type transport; + description + "For a configured subscription, this leaf specifies the + transport used to deliver messages destined for all + receivers of that subscription."; + } + leaf encoding { + when 'not(../transport) or derived-from(../transport, + "sn:configurable-encoding")'; + type encoding; + description + "The type of encoding for notification messages. For a + dynamic subscription, if not included as part of an + 'establish-subscription' RPC, the encoding will be populated + with the encoding used by that RPC. For a configured + subscription, if not explicitly configured, the encoding + will be the default encoding for an underlying transport."; + } + leaf purpose { + if-feature "configured"; + type string; + description + "Open text allowing a configuring entity to embed the + originator or other specifics of this subscription."; + } + } + + /* + * RPCs + */ + + rpc establish-subscription { + description + "This RPC allows a subscriber to create (and possibly + negotiate) a subscription on its own behalf. If successful, + the subscription remains in effect for the duration of the + subscriber's association with the publisher or until the + subscription is terminated. If an error occurs or the + publisher cannot meet the terms of a subscription, an RPC + error is returned, and the subscription is not created. + In that case, the RPC reply's 'error-info' MAY include + suggested parameter settings that would have a higher + likelihood of succeeding in a subsequent + 'establish-subscription' request."; + input { + uses subscription-policy-dynamic; + leaf encoding { + type encoding; + description + "The type of encoding for the subscribed data. If not + included as part of the RPC, the encoding MUST be set by + the publisher to be the encoding used by this RPC."; + } + } + output { + leaf id { + type subscription-id; + mandatory true; + description + "Identifier used for this subscription."; + } + leaf replay-start-time-revision { + if-feature "replay"; + type yang:date-and-time; + description + "If a replay has been requested, this object represents + the earliest time covered by the event buffer for the + requested event stream. The value of this object is the + 'replay-log-aged-time' if it exists. Otherwise, it is + the 'replay-log-creation-time'. All buffered event + records after this time will be replayed to a receiver. + This object will only be sent if the starting time has + been revised to be later than the time requested by the + subscriber."; + } + } + } + + rc:yang-data establish-subscription-stream-error-info { + container establish-subscription-stream-error-info { + description + "If any 'establish-subscription' RPC parameters are + unsupportable against the event stream, a subscription + is not created and the RPC error response MUST indicate the + reason why the subscription failed to be created. This + yang-data MAY be inserted as structured data in a + subscription's RPC error response to indicate the reason for + the failure. This yang-data MUST be inserted if hints are + to be provided back to the subscriber."; + leaf reason { + type identityref { + base establish-subscription-error; + } + description + "Indicates the reason why the subscription has failed to + be created to a targeted event stream."; + } + leaf filter-failure-hint { + type string; + description + "Information describing where and/or why a provided + filter was unsupportable for a subscription. The + syntax and semantics of this hint are + implementation specific."; + } + } + } + + rpc modify-subscription { + description + "This RPC allows a subscriber to modify a dynamic + subscription's parameters. If successful, the changed + subscription parameters remain in effect for the duration of + the subscription, until the subscription is again modified, or + until the subscription is terminated. In the case of an error + or an inability to meet the modified parameters, the + subscription is not modified and the original subscription + parameters remain in effect. In that case, the RPC error MAY + include 'error-info' suggested parameter hints that would have + a high likelihood of succeeding in a subsequent + 'modify-subscription' request. A successful + 'modify-subscription' will return a suspended subscription to + the 'active' state."; + input { + leaf id { + type subscription-id; + mandatory true; + description + "Identifier to use for this subscription."; + } + uses subscription-policy-modifiable; + } + } + + rc:yang-data modify-subscription-stream-error-info { + container modify-subscription-stream-error-info { + description + "This yang-data MAY be provided as part of a subscription's + RPC error response when there is a failure of a + 'modify-subscription' RPC that has been made against an + event stream. This yang-data MUST be used if hints are to + be provided back to the subscriber."; + leaf reason { + type identityref { + base modify-subscription-error; + } + description + "Information in a 'modify-subscription' RPC error response + that indicates the reason why the subscription to an event + stream has failed to be modified."; + } + leaf filter-failure-hint { + type string; + description + "Information describing where and/or why a provided + filter was unsupportable for a subscription. The syntax + and semantics of this hint are + implementation specific."; + } + } + } + + rpc delete-subscription { + description + "This RPC allows a subscriber to delete a subscription that + was previously created by that same subscriber using the + 'establish-subscription' RPC. + + If an error occurs, the server replies with an 'rpc-error' + where the 'error-info' field MAY contain a + 'delete-subscription-error-info' structure."; + input { + leaf id { + type subscription-id; + mandatory true; + description + "Identifier of the subscription that is to be deleted. + Only subscriptions that were created using + 'establish-subscription' from the same origin as this RPC + can be deleted via this RPC."; + } + } + } + + rpc kill-subscription { + nacm:default-deny-all; + description + "This RPC allows an operator to delete a dynamic subscription + without restrictions on the originating subscriber or + underlying transport session. + + If an error occurs, the server replies with an 'rpc-error' + where the 'error-info' field MAY contain a + 'delete-subscription-error-info' structure."; + input { + leaf id { + type subscription-id; + mandatory true; + description + "Identifier of the subscription that is to be deleted. + Only subscriptions that were created using + 'establish-subscription' can be deleted via this RPC."; + } + } + } + + rc:yang-data delete-subscription-error-info { + container delete-subscription-error-info { + description + "If a 'delete-subscription' RPC or a 'kill-subscription' RPC + fails, the subscription is not deleted and the RPC error + response MUST indicate the reason for this failure. This + yang-data MAY be inserted as structured data in a + subscription's RPC error response to indicate the reason + for the failure."; + leaf reason { + type identityref { + base delete-subscription-error; + } + mandatory true; + description + "Indicates the reason why the subscription has failed to be + deleted."; + } + } + } + + /* + * NOTIFICATIONS + */ + + notification replay-completed { + sn:subscription-state-notification; + if-feature "replay"; + description + "This notification is sent to indicate that all of the replay + notifications have been sent."; + leaf id { + type subscription-id; + mandatory true; + description + "This references the affected subscription."; + } + } + + notification subscription-completed { + sn:subscription-state-notification; + if-feature "configured"; + description + "This notification is sent to indicate that a subscription has + finished passing event records, as the 'stop-time' has been + reached."; + leaf id { + type subscription-id; + mandatory true; + description + "This references the gracefully completed subscription."; + } + } + + notification subscription-modified { + sn:subscription-state-notification; + description + "This notification indicates that a subscription has been + modified. Notification messages sent from this point on will + conform to the modified terms of the subscription. For + completeness, this subscription state change notification + includes both modified and unmodified aspects of a + subscription."; + leaf id { + type subscription-id; + mandatory true; + description + "This references the affected subscription."; + } + uses subscription-policy { + refine "target/stream/stream-filter/within-subscription" { + description + "Filter applied to the subscription. If the + 'stream-filter-name' is populated, the filter in the + subscription came from the 'filters' container. + Otherwise, it is populated in-line as part of the + subscription."; + } + } + } + + notification subscription-resumed { + sn:subscription-state-notification; + description + "This notification indicates that a subscription that had + previously been suspended has resumed. Notifications will + once again be sent. In addition, a 'subscription-resumed' + indicates that no modification of parameters has occurred + since the last time event records have been sent."; + leaf id { + type subscription-id; + mandatory true; + description + "This references the affected subscription."; + } + } + + notification subscription-started { + sn:subscription-state-notification; + if-feature "configured"; + description + "This notification indicates that a subscription has started + and notifications will now be sent."; + leaf id { + type subscription-id; + mandatory true; + description + "This references the affected subscription."; + } + uses subscription-policy { + refine "target/stream/replay-start-time" { + description + "Indicates the time that a replay is using for the + streaming of buffered event records. This will be + populated with the most recent of the following: + the event time of the previous event record sent to a + receiver, the 'replay-log-creation-time', the + 'replay-log-aged-time', or the most recent publisher + boot time."; + } + refine "target/stream/stream-filter/within-subscription" { + description + "Filter applied to the subscription. If the + 'stream-filter-name' is populated, the filter in the + subscription came from the 'filters' container. + Otherwise, it is populated in-line as part of the + subscription."; + } + augment "target/stream" { + description + "This augmentation adds additional parameters specific to a + 'subscription-started' notification."; + leaf replay-previous-event-time { + when '../replay-start-time'; + if-feature "replay"; + type yang:date-and-time; + description + "If there is at least one event in the replay buffer + prior to 'replay-start-time', this gives the time of + the event generated immediately prior to the + 'replay-start-time'. + + If a receiver previously received event records for + this configured subscription, it can compare this time + to the last event record previously received. If the + two are not the same (perhaps due to a reboot), then a + dynamic replay can be initiated to acquire any missing + event records."; + } + } + } + } + + notification subscription-suspended { + sn:subscription-state-notification; + description + "This notification indicates that a suspension of the + subscription by the publisher has occurred. No further + notifications will be sent until the subscription resumes. + This notification shall only be sent to receivers of a + subscription; it does not constitute a general-purpose + notification."; + leaf id { + type subscription-id; + mandatory true; + description + "This references the affected subscription."; + } + leaf reason { + type identityref { + base subscription-suspended-reason; + } + mandatory true; + description + "Identifies the condition that resulted in the suspension."; + } + } + + notification subscription-terminated { + sn:subscription-state-notification; + description + "This notification indicates that a subscription has been + terminated."; + leaf id { + type subscription-id; + mandatory true; + description + "This references the affected subscription."; + } + leaf reason { + type identityref { + base subscription-terminated-reason; + } + mandatory true; + description + "Identifies the condition that resulted in the termination."; + } + } + + /* + * DATA NODES + */ + + container streams { + config false; + description + "Contains information on the built-in event streams provided by + the publisher."; + list stream { + key "name"; + description + "Identifies the built-in event streams that are supported by + the publisher."; + leaf name { + type string; + description + "A handle for a system-provided event stream made up of a + sequential set of event records, each of which is + characterized by its own domain and semantics."; + } + leaf description { + type string; + description + "A description of the event stream, including such + information as the type of event records that are + available in this event stream."; + } + leaf replay-support { + if-feature "replay"; + type empty; + description + "Indicates that event record replay is available on this + event stream."; + } + leaf replay-log-creation-time { + when '../replay-support'; + if-feature "replay"; + type yang:date-and-time; + mandatory true; + description + "The timestamp of the creation of the log used to support + the replay function on this event stream. This time + might be earlier than the earliest available information + contained in the log. This object is updated if the log + resets for some reason."; + } + leaf replay-log-aged-time { + when '../replay-support'; + if-feature "replay"; + type yang:date-and-time; + description + "The timestamp associated with the last event record that + has been aged out of the log. This timestamp identifies + how far back in history this replay log extends, if it + doesn't extend back to the 'replay-log-creation-time'. + This object MUST be present if replay is supported and any + event records have been aged out of the log."; + } + } + } + container filters { + description + "Contains a list of configurable filters that can be applied to + subscriptions. This facilitates the reuse of complex filters + once defined."; + list stream-filter { + key "name"; + description + "A list of preconfigured filters that can be applied to + subscriptions."; + leaf name { + type string; + description + "A name to differentiate between filters."; + } + uses stream-filter-elements; + } + } + container subscriptions { + description + "Contains the list of currently active subscriptions, i.e., + subscriptions that are currently in effect, used for + subscription management and monitoring purposes. This + includes subscriptions that have been set up via + RPC primitives as well as subscriptions that have been + established via configuration."; + list subscription { + key "id"; + description + "The identity and specific parameters of a subscription. + Subscriptions in this list can be created using a control + channel or RPC or can be established through configuration. + + If the 'kill-subscription' RPC or configuration operations + are used to delete a subscription, a + 'subscription-terminated' message is sent to any active or + suspended receivers."; + leaf id { + type subscription-id; + description + "Identifier of a subscription; unique in a given + publisher."; + } + uses subscription-policy { + refine "target/stream/stream" { + description + "Indicates the event stream to be considered for this + subscription. If an event stream has been removed + and can no longer be referenced by an active + subscription, send a 'subscription-terminated' + notification with 'stream-unavailable' as the reason. + If a configured subscription refers to a nonexistent + event stream, move that subscription to the + 'invalid' state."; + } + refine "transport" { + description + "For a configured subscription, this leaf specifies the + transport used to deliver messages destined for all + receivers of that subscription. This object is + mandatory for subscriptions in the configuration + datastore. This object (1) is not mandatory for dynamic + subscriptions in the operational state datastore and + (2) should not be present for other types of dynamic + subscriptions."; + } + augment "target/stream" { + description + "Enables objects to be added to a configured stream + subscription."; + leaf configured-replay { + if-feature "configured"; + if-feature "replay"; + type empty; + description + "The presence of this leaf indicates that replay for + the configured subscription should start at the + earliest time in the event log or at the publisher + boot time, whichever is later."; + } + } + } + choice notification-message-origin { + if-feature "configured"; + description + "Identifies the egress interface on the publisher + from which notification messages are to be sent."; + case interface-originated { + description + "When notification messages are to egress a specific, + designated interface on the publisher."; + leaf source-interface { + if-feature "interface-designation"; + type if:interface-ref; + description + "References the interface for notification messages."; + } + } + case address-originated { + description + "When notification messages are to depart from a + publisher using a specific originating address and/or + routing context information."; + leaf source-vrf { + if-feature "supports-vrf"; + type leafref { + path "/ni:network-instances/ni:network-instance/ni:name"; + } + description + "VRF from which notification messages should egress a + publisher."; + } + leaf source-address { + type inet:ip-address-no-zone; + description + "The source address for the notification messages. + If a source VRF exists but this object doesn't, a + publisher's default address for that VRF must + be used."; + } + } + } + leaf configured-subscription-state { + if-feature "configured"; + type enumeration { + enum valid { + value 1; + description + "The subscription is supportable with its current + parameters."; + } + enum invalid { + value 2; + description + "The subscription as a whole is unsupportable with its + current parameters."; + } + enum concluded { + value 3; + description + "A subscription is inactive, as it has hit a + stop time. It no longer has receivers in the + 'active' or 'suspended' state, but the subscription + has not yet been removed from configuration."; + } + } + config false; + description + "The presence of this leaf indicates that the subscription + originated from configuration, not through a control + channel or RPC. The value indicates the state of the + subscription as established by the publisher."; + } + container receivers { + description + "Set of receivers in a subscription."; + list receiver { + key "name"; + min-elements 1; + description + "A host intended as a recipient for the notification + messages of a subscription. For configured + subscriptions, transport-specific network parameters + (or a leafref to those parameters) may be augmented to a + specific receiver in this list."; + leaf name { + type string; + description + "Identifies a unique receiver for a subscription."; + } + leaf sent-event-records { + type yang:zero-based-counter64; + config false; + description + "The number of event records sent to the receiver. The + count is initialized when a dynamic subscription is + established or when a configured receiver + transitions to the 'valid' state."; + } + leaf excluded-event-records { + type yang:zero-based-counter64; + config false; + description + "The number of event records explicitly removed via + either an event stream filter or an access control + filter so that they are not passed to a receiver. + This count is set to zero each time + 'sent-event-records' is initialized."; + } + leaf state { + type enumeration { + enum active { + value 1; + description + "The receiver is currently being sent any + applicable notification messages for the + subscription."; + } + enum suspended { + value 2; + description + "The receiver state is 'suspended', so the + publisher is currently unable to provide + notification messages for the subscription."; + } + enum connecting { + value 3; + if-feature "configured"; + description + "A subscription has been configured, but a + 'subscription-started' subscription state change + notification needs to be successfully received + before notification messages are sent. + + If the 'reset' action is invoked for a receiver of + an active configured subscription, the state + must be moved to 'connecting'."; + } + enum disconnected { + value 4; + if-feature "configured"; + description + "A subscription has failed to send a + 'subscription-started' state change to the + receiver. Additional connection attempts are not + currently being made."; + } + } + config false; + mandatory true; + description + "Specifies the state of a subscription from the + perspective of a particular receiver. With this + information, it is possible to determine whether a + publisher is currently generating notification + messages intended for that receiver."; + } + action reset { + if-feature "configured"; + description + "Allows the reset of this configured subscription's + receiver to the 'connecting' state. This enables the + connection process to be reinitiated."; + output { + leaf time { + type yang:date-and-time; + mandatory true; + description + "Time at which a publisher returned the receiver to + the 'connecting' state."; + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-system.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-system.yang new file mode 100644 index 0000000..141ddba --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-system.yang @@ -0,0 +1,802 @@ +module ietf-system { + namespace "urn:ietf:params:xml:ns:yang:ietf-system"; + prefix "sys"; + + import ietf-yang-types { + prefix yang; + } + + import ietf-inet-types { + prefix inet; + } + + import ietf-netconf-acm { + prefix nacm; + } + + import iana-crypt-hash { + prefix ianach; + } + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + WG Chair: Thomas Nadeau + + + WG Chair: Juergen Schoenwaelder + + + Editor: Andy Bierman + + + Editor: Martin Bjorklund + "; + + description + "This module contains a collection of YANG definitions for the + configuration and identification of some common system + properties within a device containing a NETCONF server. This + includes data node definitions for system identification, + time-of-day management, user management, DNS resolver + configuration, and some protocol operations for system + management. + + Copyright (c) 2014 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 + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 7317; see + the RFC itself for full legal notices."; + + revision 2014-08-06 { + description + "Initial revision."; + reference + "RFC 7317: A YANG Data Model for System Management"; + } + + /* + * Typedefs + */ + + typedef timezone-name { + type string; + description + "A time zone name as used by the Time Zone Database, + sometimes referred to as the 'Olson Database'. + + The exact set of valid values is an implementation-specific + matter. Client discovery of the exact set of time zone names + for a particular server is out of scope."; + reference + "RFC 6557: Procedures for Maintaining the Time Zone Database"; + } + + /* + * Features + */ + + feature radius { + description + "Indicates that the device can be configured as a RADIUS + client."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS)"; + } + + feature authentication { + description + "Indicates that the device supports configuration of + user authentication."; + } + + feature local-users { + if-feature authentication; + description + "Indicates that the device supports configuration of + local user authentication."; + } + + feature radius-authentication { + if-feature radius; + if-feature authentication; + description + "Indicates that the device supports configuration of user + authentication over RADIUS."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS) + RFC 5607: Remote Authentication Dial-In User Service (RADIUS) + Authorization for Network Access Server (NAS) + Management"; + } + + feature ntp { + description + "Indicates that the device can be configured to use one or + more NTP servers to set the system date and time."; + } + + feature ntp-udp-port { + if-feature ntp; + description + "Indicates that the device supports the configuration of + the UDP port for NTP servers. + + This is a 'feature', since many implementations do not support + any port other than the default port."; + } + + feature timezone-name { + description + "Indicates that the local time zone on the device + can be configured to use the TZ database + to set the time zone and manage daylight saving time."; + reference + "RFC 6557: Procedures for Maintaining the Time Zone Database"; + } + + feature dns-udp-tcp-port { + description + "Indicates that the device supports the configuration of + the UDP and TCP port for DNS servers. + + This is a 'feature', since many implementations do not support + any port other than the default port."; + } + + + /* + * Identities + */ + + identity authentication-method { + description + "Base identity for user authentication methods."; + } + + identity radius { + base authentication-method; + description + "Indicates user authentication using RADIUS."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS) + RFC 5607: Remote Authentication Dial-In User Service (RADIUS) + Authorization for Network Access Server (NAS) + Management"; + } + + identity local-users { + base authentication-method; + description + "Indicates password-based authentication of locally + configured users."; + } + + identity radius-authentication-type { + description + "Base identity for RADIUS authentication types."; + } + + identity radius-pap { + base radius-authentication-type; + description + "The device requests Password Authentication Protocol (PAP) + authentication from the RADIUS server."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS)"; + } + + identity radius-chap { + base radius-authentication-type; + description + "The device requests Challenge Handshake Authentication + Protocol (CHAP) authentication from the RADIUS server."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS)"; + } + + /* + * Configuration data nodes + */ + + container system { + description + "System group configuration."; + + leaf contact { + type string; + description + "The administrator contact information for the system. + + A server implementation MAY map this leaf to the sysContact + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and sysContact. The definition of + such a mechanism is outside the scope of this document."; + reference + "RFC 3418: Management Information Base (MIB) for the + Simple Network Management Protocol (SNMP) + SNMPv2-MIB.sysContact"; + } + leaf hostname { + type inet:domain-name; + description + "The name of the host. This name can be a single domain + label or the fully qualified domain name of the host."; + } + leaf location { + type string; + description + "The system location. + + A server implementation MAY map this leaf to the sysLocation + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and sysLocation. The definition + of such a mechanism is outside the scope of this document."; + reference + "RFC 3418: Management Information Base (MIB) for the + Simple Network Management Protocol (SNMP) + SNMPv2-MIB.sysLocation"; + } + + container clock { + description + "Configuration of the system date and time properties."; + + choice timezone { + description + "The system time zone information."; + + case timezone-name { + if-feature timezone-name; + leaf timezone-name { + type timezone-name; + description + "The TZ database name to use for the system, such + as 'Europe/Stockholm'."; + } + } + case timezone-utc-offset { + leaf timezone-utc-offset { + type int16 { + range "-1500 .. 1500"; + } + units "minutes"; + description + "The number of minutes to add to UTC time to + identify the time zone for this system. For example, + 'UTC - 8:00 hours' would be represented as '-480'. + Note that automatic daylight saving time adjustment + is not provided if this object is used."; + } + } + } + } + + container ntp { + if-feature ntp; + presence + "Enables the NTP client unless the 'enabled' leaf + (which defaults to 'true') is set to 'false'"; + description + "Configuration of the NTP client."; + + leaf enabled { + type boolean; + default true; + description + "Indicates that the system should attempt to + synchronize the system clock with an NTP server + from the 'ntp/server' list."; + } + list server { + key name; + description + "List of NTP servers to use for system clock + synchronization. If '/system/ntp/enabled' + is 'true', then the system will attempt to + contact and utilize the specified NTP servers."; + + leaf name { + type string; + description + "An arbitrary name for the NTP server."; + } + choice transport { + mandatory true; + description + "The transport-protocol-specific parameters for this + server."; + + case udp { + container udp { + description + "Contains UDP-specific configuration parameters + for NTP."; + leaf address { + type inet:host; + mandatory true; + description + "The address of the NTP server."; + } + leaf port { + if-feature ntp-udp-port; + type inet:port-number; + default 123; + description + "The port number of the NTP server."; + } + } + } + } + leaf association-type { + type enumeration { + enum server { + description + "Use client association mode. This device + will not provide synchronization to the + configured NTP server."; + } + enum peer { + description + "Use symmetric active association mode. + This device may provide synchronization + to the configured NTP server."; + } + enum pool { + description + "Use client association mode with one or + more of the NTP servers found by DNS + resolution of the domain name given by + the 'address' leaf. This device will not + provide synchronization to the servers."; + } + } + default server; + description + "The desired association type for this NTP server."; + } + leaf iburst { + type boolean; + default false; + description + "Indicates whether this server should enable burst + synchronization or not."; + } + leaf prefer { + type boolean; + default false; + description + "Indicates whether this server should be preferred + or not."; + } + } + } + + container dns-resolver { + description + "Configuration of the DNS resolver."; + + leaf-list search { + type inet:domain-name; + ordered-by user; + description + "An ordered list of domains to search when resolving + a host name."; + } + list server { + key name; + ordered-by user; + description + "List of the DNS servers that the resolver should query. + + When the resolver is invoked by a calling application, it + sends the query to the first name server in this list. If + no response has been received within 'timeout' seconds, + the resolver continues with the next server in the list. + If no response is received from any server, the resolver + continues with the first server again. When the resolver + has traversed the list 'attempts' times without receiving + any response, it gives up and returns an error to the + calling application. + + Implementations MAY limit the number of entries in this + list."; + + leaf name { + type string; + description + "An arbitrary name for the DNS server."; + } + choice transport { + mandatory true; + description + "The transport-protocol-specific parameters for this + server."; + + case udp-and-tcp { + container udp-and-tcp { + description + "Contains UDP- and TCP-specific configuration + parameters for DNS."; + reference + "RFC 1035: Domain Names - Implementation and + Specification + RFC 5966: DNS Transport over TCP - Implementation + Requirements"; + + leaf address { + type inet:ip-address; + mandatory true; + description + "The address of the DNS server."; + } + leaf port { + if-feature dns-udp-tcp-port; + type inet:port-number; + default 53; + description + "The UDP and TCP port number of the DNS server."; + } + } + } + } + } + container options { + description + "Resolver options. The set of available options has been + limited to those that are generally available across + different resolver implementations and generally useful."; + leaf timeout { + type uint8 { + range "1..max"; + } + units "seconds"; + default "5"; + description + "The amount of time the resolver will wait for a + response from each remote name server before + retrying the query via a different name server."; + } + leaf attempts { + type uint8 { + range "1..max"; + } + default "2"; + description + "The number of times the resolver will send a query to + all of its name servers before giving up and returning + an error to the calling application."; + } + } + } + + container radius { + if-feature radius; + + description + "Configuration of the RADIUS client."; + + list server { + key name; + ordered-by user; + description + "List of RADIUS servers used by the device. + + When the RADIUS client is invoked by a calling + application, it sends the query to the first server in + this list. If no response has been received within + 'timeout' seconds, the client continues with the next + server in the list. If no response is received from any + server, the client continues with the first server again. + When the client has traversed the list 'attempts' times + without receiving any response, it gives up and returns an + error to the calling application."; + + leaf name { + type string; + description + "An arbitrary name for the RADIUS server."; + } + choice transport { + mandatory true; + description + "The transport-protocol-specific parameters for this + server."; + + case udp { + container udp { + description + "Contains UDP-specific configuration parameters + for RADIUS."; + leaf address { + type inet:host; + mandatory true; + description + "The address of the RADIUS server."; + } + + leaf authentication-port { + type inet:port-number; + default "1812"; + description + "The port number of the RADIUS server."; + } + leaf shared-secret { + type string; + mandatory true; + nacm:default-deny-all; + description + "The shared secret, which is known to both the + RADIUS client and server."; + reference + "RFC 2865: Remote Authentication Dial In User + Service (RADIUS)"; + } + } + } + } + leaf authentication-type { + type identityref { + base radius-authentication-type; + } + default radius-pap; + description + "The authentication type requested from the RADIUS + server."; + } + } + container options { + description + "RADIUS client options."; + + leaf timeout { + type uint8 { + range "1..max"; + } + units "seconds"; + default "5"; + description + "The number of seconds the device will wait for a + response from each RADIUS server before trying with a + different server."; + } + + leaf attempts { + type uint8 { + range "1..max"; + } + default "2"; + description + "The number of times the device will send a query to + all of its RADIUS servers before giving up."; + } + } + } + + container authentication { + nacm:default-deny-write; + if-feature authentication; + + description + "The authentication configuration subtree."; + + leaf-list user-authentication-order { + type identityref { + base authentication-method; + } + must '(. != "sys:radius" or ../../radius/server)' { + error-message + "When 'radius' is used, a RADIUS server" + + " must be configured."; + description + "When 'radius' is used as an authentication method, + a RADIUS server must be configured."; + } + ordered-by user; + + description + "When the device authenticates a user with a password, + it tries the authentication methods in this leaf-list in + order. If authentication with one method fails, the next + method is used. If no method succeeds, the user is + denied access. + + An empty user-authentication-order leaf-list still allows + authentication of users using mechanisms that do not + involve a password. + + If the 'radius-authentication' feature is advertised by + the NETCONF server, the 'radius' identity can be added to + this list. + + If the 'local-users' feature is advertised by the + NETCONF server, the 'local-users' identity can be + added to this list."; + } + + list user { + if-feature local-users; + key name; + description + "The list of local users configured on this device."; + + leaf name { + type string; + description + "The user name string identifying this entry."; + } + leaf password { + type ianach:crypt-hash; + description + "The password for this entry."; + } + list authorized-key { + key name; + description + "A list of public SSH keys for this user. These keys + are allowed for SSH authentication, as described in + RFC 4253."; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer + Protocol"; + + leaf name { + type string; + description + "An arbitrary name for the SSH key."; + } + + leaf algorithm { + type string; + mandatory true; + description + "The public key algorithm name for this SSH key. + + Valid values are the values in the IANA 'Secure Shell + (SSH) Protocol Parameters' registry, Public Key + Algorithm Names."; + reference + "IANA 'Secure Shell (SSH) Protocol Parameters' + registry, Public Key Algorithm Names"; + } + leaf key-data { + type binary; + mandatory true; + description + "The binary public key data for this SSH key, as + specified by RFC 4253, Section 6.6, i.e.: + + string certificate or public key format + identifier + byte[n] key/certificate data."; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer + Protocol"; + } + } + } + } + } + + /* + * Operational state data nodes + */ + + container system-state { + config false; + description + "System group operational state."; + + container platform { + description + "Contains vendor-specific information for + identifying the system platform and operating system."; + reference + "IEEE Std 1003.1-2008 - sys/utsname.h"; + + leaf os-name { + type string; + description + "The name of the operating system in use - + for example, 'Linux'."; + reference + "IEEE Std 1003.1-2008 - utsname.sysname"; + } + leaf os-release { + type string; + description + "The current release level of the operating + system in use. This string MAY indicate + the OS source code revision."; + reference + "IEEE Std 1003.1-2008 - utsname.release"; + } + leaf os-version { + type string; + description + "The current version level of the operating + system in use. This string MAY indicate + the specific OS build date and target variant + information."; + reference + "IEEE Std 1003.1-2008 - utsname.version"; + } + leaf machine { + type string; + description + "A vendor-specific identifier string representing + the hardware in use."; + reference + "IEEE Std 1003.1-2008 - utsname.machine"; + } + } + + container clock { + description + "Monitoring of the system date and time properties."; + + leaf current-datetime { + type yang:date-and-time; + description + "The current system date and time."; + } + + + leaf boot-datetime { + type yang:date-and-time; + description + "The system date and time when the system last restarted."; + } + } + } + + rpc set-current-datetime { + nacm:default-deny-all; + description + "Set the /system-state/clock/current-datetime leaf + to the specified value. + + If the system is using NTP (i.e., /system/ntp/enabled + is set to 'true'), then this operation will fail with + error-tag 'operation-failed' and error-app-tag value of + 'ntp-active'."; + input { + leaf current-datetime { + type yang:date-and-time; + mandatory true; + description + "The current system date and time."; + } + } + } + + rpc system-restart { + nacm:default-deny-all; + description + "Request that the entire system be restarted immediately. + A server SHOULD send an rpc reply to the client before + restarting the system."; + } + + rpc system-shutdown { + nacm:default-deny-all; + description + "Request that the entire system be shut down immediately. + A server SHOULD send an rpc reply to the client before + shutting down the system."; + } + +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-yang-schema-mount@2019-01-14.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-yang-schema-mount@2019-01-14.yang new file mode 100644 index 0000000..1f4f242 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-yang-schema-mount@2019-01-14.yang @@ -0,0 +1,224 @@ +module ietf-yang-schema-mount { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount"; + prefix yangmnt; + + import ietf-inet-types { + prefix inet; + reference + "RFC 6991: Common YANG Data Types"; + } + + import ietf-yang-types { + prefix yang; + reference + "RFC 6991: Common YANG Data Types"; + } + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + Editor: Martin Bjorklund + + + Editor: Ladislav Lhotka + "; + + description + "This module defines a YANG extension statement that can be used + to incorporate data models defined in other YANG modules in a + module. It also defines operational state data that specify the + overall structure of the data model. + + The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL + NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED', + 'MAY', and 'OPTIONAL' in this document are to be interpreted as + described in BCP 14 (RFC 2119) (RFC 8174) when, and only when, + they appear in all capitals, as shown here. + + Copyright (c) 2019 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 8528; + see the RFC itself for full legal notices."; + + revision 2019-01-14 { + description + "Initial revision."; + reference + "RFC 8528: YANG Schema Mount"; + } + + /* + * Extensions + */ + + extension mount-point { + argument label; + description + "The argument 'label' is a YANG identifier, i.e., it is of the + type 'yang:yang-identifier'. + + The 'mount-point' statement MUST NOT be used in a YANG + version 1 module, neither explicitly nor via a 'uses' + statement. + The 'mount-point' statement MAY be present as a substatement + of 'container' and 'list' and MUST NOT be present elsewhere. + There MUST NOT be more than one 'mount-point' statement in a + given 'container' or 'list' statement. + + If a mount point is defined within a grouping, its label is + bound to the module where the grouping is used. + + A mount point defines a place in the node hierarchy where + other data models may be attached. A server that implements a + module with a mount point populates the + '/schema-mounts/mount-point' list with detailed information on + which data models are mounted at each mount point. + + Note that the 'mount-point' statement does not define a new + data node."; + } + + /* + * State data nodes + */ + + container schema-mounts { + config false; + description + "Contains information about the structure of the overall + mounted data model implemented in the server."; + list namespace { + key "prefix"; + description + "This list provides a mapping of namespace prefixes that are + used in XPath expressions of 'parent-reference' leafs to the + corresponding namespace URI references."; + leaf prefix { + type yang:yang-identifier; + description + "Namespace prefix."; + } + leaf uri { + type inet:uri; + description + "Namespace URI reference."; + } + } + list mount-point { + key "module label"; + + description + "Each entry of this list specifies a schema for a particular + mount point. + + Each mount point MUST be defined using the 'mount-point' + extension in one of the modules listed in the server's + YANG library instance with conformance type 'implement'."; + leaf module { + type yang:yang-identifier; + description + "Name of a module containing the mount point."; + } + leaf label { + type yang:yang-identifier; + description + "Label of the mount point defined using the 'mount-point' + extension."; + } + leaf config { + type boolean; + default "true"; + description + "If this leaf is set to 'false', then all data nodes in the + mounted schema are read-only ('config false'), regardless + of their 'config' property."; + } + choice schema-ref { + mandatory true; + description + "Alternatives for specifying the schema."; + container inline { + presence + "A complete self-contained schema is mounted at the + mount point."; + description + "This node indicates that the server has mounted at least + the module 'ietf-yang-library' at the mount point, and + its instantiation provides the information about the + mounted schema. + + Different instances of the mount point may have + different schemas mounted."; + } + container shared-schema { + presence + "The mounted schema together with the 'parent-reference' + make up the schema for this mount point."; + + description + "This node indicates that the server has mounted at least + the module 'ietf-yang-library' at the mount point, and + its instantiation provides the information about the + mounted schema. When XPath expressions in the mounted + schema are evaluated, the 'parent-reference' leaf-list + is taken into account. + + Different instances of the mount point MUST have the + same schema mounted."; + leaf-list parent-reference { + type yang:xpath1.0; + description + "Entries of this leaf-list are XPath 1.0 expressions + that are evaluated in the following context: + + - The context node is the node in the parent data tree + where the mount-point is defined. + + - The accessible tree is the parent data tree + *without* any nodes defined in modules that are + mounted inside the parent schema. + + - The context position and context size are both equal + to 1. + + - The set of variable bindings is empty. + + - The function library is the core function library + defined in the W3C XPath 1.0 document + (http://www.w3.org/TR/1999/REC-xpath-19991116) and + the functions defined in Section 10 of RFC 7950. + + - The set of namespace declarations is defined by the + 'namespace' list under 'schema-mounts'. + + Each XPath expression MUST evaluate to a node-set + (possibly empty). For the purposes of evaluating + XPath expressions whose context nodes are defined in + the mounted schema, the union of all these node-sets + together with ancestor nodes are added to the + accessible data tree. + + Note that in the case 'ietf-yang-schema-mount' is + itself mounted, a 'parent-reference' in the mounted + module may refer to nodes that were brought into the + accessible tree through a 'parent-reference' in the + parent schema."; + } + } + } + } + } +} \ No newline at end of file diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-yang-types@2013-07-15.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-yang-types@2013-07-15.yang new file mode 100644 index 0000000..45b8c55 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/ietf-yang-types@2013-07-15.yang @@ -0,0 +1,435 @@ +module ietf-yang-types { + +namespace "urn:ietf:params:xml:ns:yang:ietf-yang-types"; +prefix "yang"; + +organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + +contact + "WG Web: + WG List: + WG Chair: David Kessens + + WG Chair: Juergen Schoenwaelder + + Editor: Juergen Schoenwaelder + "; + +description + "This module contains a collection of generally useful derived + YANG data types. + Copyright (c) 2013 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 + (http://trustee.ietf.org/license-info). + This version of this YANG module is part of RFC 6991; see + the RFC itself for full legal notices."; + +revision 2013-07-15 { + description + "This revision adds the following new data types: + - yang-identifier + - hex-string + - uuid + - dotted-quad"; + reference + "RFC 6991: Common YANG Data Types"; +} + +revision 2010-09-24 { + description + "Initial revision."; + reference + "RFC 6021: Common YANG Data Types"; +} + +/*** collection of counter and gauge types ***/ + +typedef counter32 { + type uint32; + description + "The counter32 type represents a non-negative integer + that monotonically increases until it reaches a + maximum value of 2^32-1 (4294967295 decimal), when it + wraps around and starts increasing again from zero. + Counters have no defined 'initial' value, and thus, a + single value of a counter has (in general) no information + content. Discontinuities in the monotonically increasing + value normally occur at re-initialization of the + management system, and at other times as specified in the + description of a schema node using this type. If such + other times can occur, for example, the creation of + a schema node of type counter32 at times other than + re-initialization, then a corresponding schema node + should be defined, with an appropriate type, to indicate + the last discontinuity. + The counter32 type should not be used for configuration + schema nodes. A default statement SHOULD NOT be used in + combination with the type counter32. + In the value set and its semantics, this type is equivalent + to the Counter32 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; +} + +typedef zero-based-counter32 { + type yang:counter32; + default "0"; + description + "The zero-based-counter32 type represents a counter32 + that has the defined 'initial' value zero. + A schema node of this type will be set to zero (0) on creation + and will thereafter increase monotonically until it reaches + a maximum value of 2^32-1 (4294967295 decimal), when it + wraps around and starts increasing again from zero. + Provided that an application discovers a new schema node + of this type within the minimum time to wrap, it can use the + 'initial' value as a delta. It is important for a management + station to be aware of this minimum time and the actual time + between polls, and to discard data if the actual time is too + long or there is no defined minimum time. + In the value set and its semantics, this type is equivalent + to the ZeroBasedCounter32 textual convention of the SMIv2."; + reference + "RFC 4502: Remote Network Monitoring Management Information + Base Version 2"; +} + +typedef counter64 { + type uint64; + description + "The counter64 type represents a non-negative integer + that monotonically increases until it reaches a + maximum value of 2^64-1 (18446744073709551615 decimal), + when it wraps around and starts increasing again from zero. + Counters have no defined 'initial' value, and thus, a + single value of a counter has (in general) no information + content. Discontinuities in the monotonically increasing + value normally occur at re-initialization of the + management system, and at other times as specified in the + description of a schema node using this type. If such + other times can occur, for example, the creation of + a schema node of type counter64 at times other than + re-initialization, then a corresponding schema node + should be defined, with an appropriate type, to indicate + the last discontinuity. + The counter64 type should not be used for configuration + schema nodes. A default statement SHOULD NOT be used in + combination with the type counter64. + In the value set and its semantics, this type is equivalent + to the Counter64 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; +} + +typedef zero-based-counter64 { + type yang:counter64; + default "0"; + description + "The zero-based-counter64 type represents a counter64 that + has the defined 'initial' value zero. + A schema node of this type will be set to zero (0) on creation + and will thereafter increase monotonically until it reaches + a maximum value of 2^64-1 (18446744073709551615 decimal), + when it wraps around and starts increasing again from zero. + Provided that an application discovers a new schema node + of this type within the minimum time to wrap, it can use the + 'initial' value as a delta. It is important for a management + station to be aware of this minimum time and the actual time + between polls, and to discard data if the actual time is too + long or there is no defined minimum time. + In the value set and its semantics, this type is equivalent + to the ZeroBasedCounter64 textual convention of the SMIv2."; + reference + "RFC 2856: Textual Conventions for Additional High Capacity + Data Types"; +} + +typedef gauge32 { + type uint32; + description + "The gauge32 type represents a non-negative integer, which + may increase or decrease, but shall never exceed a maximum + value, nor fall below a minimum value. The maximum value + cannot be greater than 2^32-1 (4294967295 decimal), and + the minimum value cannot be smaller than 0. The value of + a gauge32 has its maximum value whenever the information + being modeled is greater than or equal to its maximum + value, and has its minimum value whenever the information + being modeled is smaller than or equal to its minimum value. + If the information being modeled subsequently decreases + below (increases above) the maximum (minimum) value, the + gauge32 also decreases (increases). + In the value set and its semantics, this type is equivalent + to the Gauge32 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; +} + +typedef gauge64 { + type uint64; + description + "The gauge64 type represents a non-negative integer, which + may increase or decrease, but shall never exceed a maximum + value, nor fall below a minimum value. The maximum value + cannot be greater than 2^64-1 (18446744073709551615), and + the minimum value cannot be smaller than 0. The value of + a gauge64 has its maximum value whenever the information + being modeled is greater than or equal to its maximum + value, and has its minimum value whenever the information + being modeled is smaller than or equal to its minimum value. + If the information being modeled subsequently decreases + below (increases above) the maximum (minimum) value, the + gauge64 also decreases (increases). + In the value set and its semantics, this type is equivalent + to the CounterBasedGauge64 SMIv2 textual convention defined + in RFC 2856"; + reference + "RFC 2856: Textual Conventions for Additional High Capacity + Data Types"; +} + +/*** collection of identifier-related types ***/ + +typedef object-identifier { + type string { + pattern '(([0-1](\.[1-3]?[0-9]))|(2\.(0|([1-9]\d*))))' + + '(\.(0|([1-9]\d*)))*'; + } + description + "The object-identifier type represents administratively + assigned names in a registration-hierarchical-name tree. + Values of this type are denoted as a sequence of numerical + non-negative sub-identifier values. Each sub-identifier + value MUST NOT exceed 2^32-1 (4294967295). Sub-identifiers + are separated by single dots and without any intermediate + whitespace. + The ASN.1 standard restricts the value space of the first + sub-identifier to 0, 1, or 2. Furthermore, the value space + of the second sub-identifier is restricted to the range + 0 to 39 if the first sub-identifier is 0 or 1. Finally, + the ASN.1 standard requires that an object identifier + has always at least two sub-identifiers. The pattern + captures these restrictions. + Although the number of sub-identifiers is not limited, + module designers should realize that there may be + implementations that stick with the SMIv2 limit of 128 + sub-identifiers. + This type is a superset of the SMIv2 OBJECT IDENTIFIER type + since it is not restricted to 128 sub-identifiers. Hence, + this type SHOULD NOT be used to represent the SMIv2 OBJECT + IDENTIFIER type; the object-identifier-128 type SHOULD be + used instead."; + reference + "ISO9834-1: Information technology -- Open Systems + Interconnection -- Procedures for the operation of OSI + Registration Authorities: General procedures and top + arcs of the ASN.1 Object Identifier tree"; +} + +typedef object-identifier-128 { + type object-identifier { + pattern '\d*(\.\d*){1,127}'; + } + description + "This type represents object-identifiers restricted to 128 + sub-identifiers. + In the value set and its semantics, this type is equivalent + to the OBJECT IDENTIFIER type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; +} + +typedef yang-identifier { + type string { + length "1..max"; + pattern '[a-zA-Z_][a-zA-Z0-9\-_.]*'; + pattern '.|..|[^xX].*|.[^mM].*|..[^lL].*'; + } + description + "A YANG identifier string as defined by the 'identifier' + rule in Section 12 of RFC 6020. An identifier must + start with an alphabetic character or an underscore + followed by an arbitrary sequence of alphabetic or + numeric characters, underscores, hyphens, or dots. + A YANG identifier MUST NOT start with any possible + combination of the lowercase or uppercase character + sequence 'xml'."; + reference + "RFC 6020: YANG - A Data Modeling Language for the Network + Configuration Protocol (NETCONF)"; +} + +/*** collection of types related to date and time***/ + +typedef date-and-time { + type string { + pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?' + + '(Z|[\+\-]\d{2}:\d{2})'; + } + description + "The date-and-time type is a profile of the ISO 8601 + standard for representation of dates and times using the + Gregorian calendar. The profile is defined by the + date-time production in Section 5.6 of RFC 3339. + The date-and-time type is compatible with the dateTime XML + schema type with the following notable exceptions: + (a) The date-and-time type does not allow negative years. + (b) The date-and-time time-offset -00:00 indicates an unknown + time zone (see RFC 3339) while -00:00 and +00:00 and Z + all represent the same time zone in dateTime. + (c) The canonical format (see below) of data-and-time values + differs from the canonical format used by the dateTime XML + schema type, which requires all times to be in UTC using + the time-offset 'Z'. + This type is not equivalent to the DateAndTime textual + convention of the SMIv2 since RFC 3339 uses a different + separator between full-date and full-time and provides + higher resolution of time-secfrac. + The canonical format for date-and-time values with a known time + zone uses a numeric time zone offset that is calculated using + the device's configured known offset to UTC time. A change of + the device's offset to UTC time will cause date-and-time values + to change accordingly. Such changes might happen periodically + in case a server follows automatically daylight saving time + (DST) time zone offset changes. The canonical format for + date-and-time values with an unknown time zone (usually + referring to the notion of local time) uses the time-offset + -00:00."; + reference + "RFC 3339: Date and Time on the Internet: Timestamps + RFC 2579: Textual Conventions for SMIv2 + XSD-TYPES: XML Schema Part 2: Datatypes Second Edition"; +} + +typedef timeticks { + type uint32; + description + "The timeticks type represents a non-negative integer that + represents the time, modulo 2^32 (4294967296 decimal), in + hundredths of a second between two epochs. When a schema + node is defined that uses this type, the description of + the schema node identifies both of the reference epochs. + In the value set and its semantics, this type is equivalent + to the TimeTicks type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; +} + +typedef timestamp { + type yang:timeticks; + description + "The timestamp type represents the value of an associated + timeticks schema node at which a specific occurrence + happened. The specific occurrence must be defined in the + description of any schema node defined using this type. When + the specific occurrence occurred prior to the last time the + associated timeticks attribute was zero, then the timestamp + value is zero. Note that this requires all timestamp values + to be reset to zero when the value of the associated timeticks + attribute reaches 497+ days and wraps around to zero. + The associated timeticks schema node must be specified + in the description of any schema node using this type. + In the value set and its semantics, this type is equivalent + to the TimeStamp textual convention of the SMIv2."; + reference + "RFC 2579: Textual Conventions for SMIv2"; +} + +/*** collection of generic address types ***/ + +typedef phys-address { + type string { + pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?'; + } + + description + "Represents media- or physical-level addresses represented + as a sequence octets, each octet represented by two hexadecimal + numbers. Octets are separated by colons. The canonical + representation uses lowercase characters. + In the value set and its semantics, this type is equivalent + to the PhysAddress textual convention of the SMIv2."; + reference + "RFC 2579: Textual Conventions for SMIv2"; +} + +typedef mac-address { + type string { + pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'; + } + description + "The mac-address type represents an IEEE 802 MAC address. + The canonical representation uses lowercase characters. + In the value set and its semantics, this type is equivalent + to the MacAddress textual convention of the SMIv2."; + reference + "IEEE 802: IEEE Standard for Local and Metropolitan Area + Networks: Overview and Architecture + RFC 2579: Textual Conventions for SMIv2"; +} + +/*** collection of XML-specific types ***/ + +typedef xpath1.0 { + type string; + description + "This type represents an XPATH 1.0 expression. + When a schema node is defined that uses this type, the + description of the schema node MUST specify the XPath + context in which the XPath expression is evaluated."; + reference + "XPATH: XML Path Language (XPath) Version 1.0"; +} + +/*** collection of string types ***/ + +typedef hex-string { + type string { + pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?'; + } + description + "A hexadecimal string with octets represented as hex digits + separated by colons. The canonical representation uses + lowercase characters."; +} + +typedef uuid { + type string { + pattern '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-' + + '[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'; + } + description + "A Universally Unique IDentifier in the string representation + defined in RFC 4122. The canonical representation uses + lowercase characters. + The following is an example of a UUID in string representation: + f81d4fae-7dec-11d0-a765-00a0c91e6bf6 + "; + reference + "RFC 4122: A Universally Unique IDentifier (UUID) URN + Namespace"; +} + +typedef dotted-quad { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'; + } + description + "An unsigned 32-bit number expressed in the dotted-quad + notation, i.e., four octets written as decimal numbers + and separated with the '.' (full stop) character."; +} +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ald-port@2019-07-03.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ald-port@2019-07-03.yang new file mode 100644 index 0000000..2cafb9e --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ald-port@2019-07-03.yang @@ -0,0 +1,238 @@ +module o-ran-ald-port { + yang-version 1.1; + namespace "urn:o-ran:ald-port:1.0"; + prefix "o-ran-ald-port"; + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the input state and output configuration for + the Antenna Line Device capability. + + 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 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"; + } + + + feature OVERCURRENT-SUPPORTED { + description + "This feature indicates that the equipment supports the over-current notification + capability."; + } + +// Groupings + + grouping aldport-group { + leaf over-current-supported { + type boolean; + config false; + description + "Set to TRUE when the equipment supports over curent notifications"; + } + + list ald-port { + key "name"; + + config false; + + description + "Leaf nodes describing ALD Port"; + leaf name { + type string { + length "1..255"; + } + description + "A name that is unique that identifies a ald port instance. + This name may be used in fault management to refer to a fault source + or affected object"; + } + + leaf port-id { + type uint8; + config false; + mandatory true; + + description + "A number which identifies an ALD Port. + The number of the Physical ALD port connector in the module. + If the module supports 2 ALD Port connectors, use 0 and 1."; + } + + leaf dc-control-support{ + type boolean; + config false; + mandatory true; + + description + "It is shown that on/off in the DC power supply is possible. + In case of False, power supply is always on."; + } + + leaf dc-enabled-status { + when "../dc-control-support = 'true'"; + type boolean; + default false; + description + "Status of DC voltage enabled on antenna line. + Valid only in case dc-control-support is true."; + } + + leaf supported-connector{ + type enumeration { + enum ANTENNA_CONNECTOR { + description + "This ald port is related to antenna connector"; + } + enum RS485_PORT { + description + "This ald port is related to RS485 port"; + } + } + config false; + mandatory true; + + description + "Informs about the connectors of Module which ALDs are connected to. + This value is depending on HW design."; + } + } + + list ald-port-dc-control { + key "name"; + + description + "Container needed to manage DC on ALD ports"; + + leaf name { + type leafref { + path "/ald-ports-io/ald-port/name"; + require-instance false; + } + mandatory true; + + description + "Name derived from unmodifiable list ald-port"; + } + + leaf dc-enabled{ + type boolean; + + description + "If dc-control-support is true case, this leaf is effective. + If dc-control-support is not true this leaf makes no action + In case of true, the power supply shall be turned on."; + } + } + } + + grouping overcurrent-group { + container overload-condition { + description + "Container used in notification"; + + leaf-list overloaded-ports { + type leafref { + path "/ald-ports-io/ald-port/name"; + } + description + "List of overloaded ports"; + } + } + } + + grouping dc-enabled-group { + list ald-port { + key name; + description + "list of ald-ports that has its dc-enabled-status changed"; + leaf name{ + type leafref { + path "/ald-ports-io/ald-port/name"; + } + description "Name of port which has changed"; + } + leaf dc-enabled-status{ + type leafref { + path "/ald-ports-io/ald-port/dc-enabled-status"; + } + description "New staus of dc-enabled-status"; + } + } + } + +// Top Level Container + + container ald-ports-io { + description + "ALD port information. + ALD port of the equipment that can be used to connect External Equipment (Antenna Line Devices). + Communication uses AISG over HDLC. + Physical connection depends on connector type offered by the port (RS-485 or antenna line) + Note: Single instance of ALD Port can point to more than one antenna line devices."; + + uses aldport-group; + } + + notification overcurrent-report { + if-feature OVERCURRENT-SUPPORTED; + + description + "The equipment is able to report overcurrent condition about Port. + This function is depending on HW design. + The notification depend on power consumption which connected ALD devices and module."; + + uses overcurrent-group; + } + + notification dc-enabled-status-change { + description + "The equipment is able to report the change of 'dc-enabled-status' of the ald-port. + This is applicable when the leaf 'dc-control-support' of the ald-pot is 'TRUE'."; + + uses dc-enabled-group; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ald@2019-07-03.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ald@2019-07-03.yang new file mode 100644 index 0000000..d09cc30 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ald@2019-07-03.yang @@ -0,0 +1,161 @@ +module o-ran-ald { + yang-version 1.1; + namespace "urn:o-ran:ald:1.0"; + prefix "o-ran-ald"; + + import o-ran-ald-port { + prefix "ap"; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the module for the ald communication. + + 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 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 ald-input { + leaf port-id { + type leafref { + path "/ap:ald-ports-io/ap:ald-port/ap:port-id"; + } + mandatory true; + description + "Unique ALD port identifier reported by radio"; + } + + leaf ald-req-msg { + type binary { + length "0..1200"; + } + + description + "Response message to be forwarded to ALD in type of binary-string"; + } + } + + grouping ald-output { + leaf port-id { + type leafref { + path "/ap:ald-ports-io/ap:ald-port/ap:port-id"; + } + mandatory true; + description + "Unique ALD port identifier reported by radio"; + } + + leaf status { + type enumeration { + enum ACCEPTED { + description + "Operation was accepted, message was processed towards ALD and response is provided"; + } + enum REJECTED { + description + "Operation was rejected by O-RU"; + } + } + mandatory true; + + description + "Status of RPC handling seen from equipment perspective"; + } + + leaf error-message { + when "../status='REJECTED'"; + type string; + + description + "Detailed error message when the status is rejected. E.g. wrong ALD port identifier was used in RPC received from Netconf Client"; + } + + leaf ald-resp-msg { + type binary { + length "0..1200"; + } + + description + "Response message forwarded from ALD in type of binary-string"; + } + + leaf frames-with-wrong-crc { + type uint32; + + description + "Number of frames with incorrect CRC (FCS) received from ALD - running counter"; + } + + leaf frames-without-stop-flag { + type uint32; + + description + "Number of frames without stop flag received from ALD - running counter"; + } + + leaf number-of-received-octets { + type uint32; + + description + "Number of octets received from HDLC bus - running counter"; + } + } + // rpc-statements + rpc ald-communication { + description + "Rpc to support communication between O-DU and Antenna Line Devices"; + + input { + uses ald-input; + } + + output { + uses ald-output; + } + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-antenna-calibration@2020-12-10.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-antenna-calibration@2020-12-10.yang new file mode 100644 index 0000000..bb99b77 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-antenna-calibration@2020-12-10.yang @@ -0,0 +1,466 @@ +module o-ran-antenna-calibration { + yang-version 1.1; + namespace "urn:o-ran:antcal:1.0"; + prefix "o-ran-antcal"; + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the configuration required for supporting the optional + antenna calibration functionality. + + 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 2020-12-10 { + description + "version 5.0.0 + + 1) O-RU-COORDINATED-ANT-CAL is added as optional feature + to provide the antenna calibration without RPC + on the condition that coordinated-calibration-support is true + and coordinated-calibration-allowed is true."; + + reference "ORAN-WG4.MP-v05.00"; + } + + revision 2019-07-03 { + description + "version 1.0.0 + + 1) Newly introduced model for supporting optional + antenna calibration functionality"; + + reference "ORAN-WG4.MP-v02.00"; + } + + feature O-RU-COORDINATED-ANT-CAL { + description + "Indicates that the O-RU needs user traffic to be coordinated from O-DU for antenna calibration."; + } + + grouping antenna-calibration-capabilities { + description "container for collection of leafs for antenna calibration"; + + leaf self-calibration-support { + type boolean; + default false; + description + "Indicates whether O-RU supports self-calibration or not. + + When true, indicates O-RU can initiate calibration without receiving an + rpc and/or impacting simultaneous CU-plane operation"; + } + leaf coordinated-calibration-support { + if-feature O-RU-COORDINATED-ANT-CAL; + type boolean; + default false; + description + "True means the O-RU is able to determine priori the time-frequency + resources required for self-calibration and indicate those to the O-DU + in the antenna-calibration-coordination notification."; + } + leaf number-of-calibration-symbols-per-block-dl { + type uint8 { + range "1..max"; + } + units symbols; + mandatory true; + description + "Indicates how many consecutive symbols are required for DL antenna + calibration operation"; + } + leaf number-of-calibration-symbols-per-block-ul { + type uint8 { + range "1..max"; + } + units symbols; + mandatory true; + description + "Indicates how many consecutive symbols are required for UL antenna + calibration operation"; + } + leaf interval-between-calibration-blocks { + type uint8; + units symbols; + description + "if time interval is required between consecutive antenna calibration + operation, defines this time value as unit of symbols. + + A common value is used here for the intervals + between DL-DL blocks, UL-UL blocks, DL-UL blocks and UL-DL blocks, + which is the largest minimum interval required between any two adjacent + calibration blocks."; + } + leaf number-of-calibration-blocks-per-step-dl { + type uint8 { + range "1..max"; + } + mandatory true; + description + "Indicates how many blocks are required for one step of DL antenna + calibration operation"; + } + leaf number-of-calibration-blocks-per-step-ul { + type uint8 { + range "1..max"; + } + mandatory true; + description + "Indicates how many blocks are required for one step of UL antenna + calibration operation"; + } + leaf interval-between-calibration-steps { + type uint8; + units radio-frames; + description + "If time interval is required between consecutive step of antenna + calibration operation, defines this time value as unit of radio frames"; + } + leaf number-of-calibration-steps { + type uint8 { + range "1..max"; + } + mandatory true; + description + "Indicates how many steps are required for whole DL/UL antenna + calibration operation"; + } + leaf calibration-period { + if-feature O-RU-COORDINATED-ANT-CAL; + type uint16; + units minutes; + description "peiodical interval between antenna calibrations in the case of support of feature O-RU-COORDINATED-ANT-CAL"; + } + } + + grouping antenna-calibration { + container antenna-calibration-capabilities { + config false; + description + "Describes the antenna calibration capabilities"; + uses antenna-calibration-capabilities; + } + container self-calibration-policy { + leaf self-calibration-allowed { + type boolean; + default false; + description + "whether the self-calibration is allowed by operator. + Note, self-calibration-alllowed and coordinated-calibration-allowed cannot both be set to true"; + } + leaf coordinated-calibration-allowed { + if-feature O-RU-COORDINATED-ANT-CAL; + type boolean; + must "../self-calibration-allowed = 'false'"; + default false; + description + "whether the coordinated-calibration is allowed by operator. + + True means that O-DU may beneficially use the indicated time-frequency resources + to adapt its operation during the antenna calibration operation, + e.g., consider the time-frequency resources as reserved for calibration. + Both calibrations (self-calibration-alllowed and coordinated-calibration-support) disallowed + or one of them allowed only"; + } + description + "Describes the self calibration policy of the operator"; + } + description + "Describe the grouping set of antenna calibration"; + } + + container antenna-calibration { + uses antenna-calibration; + description + "Describes the antenna calibration top node"; + } + + rpc start-antenna-calibration { + description + "The antenna calibration operation can start when NETCONF client sends a + calibration start command with resource allocation parameters. + These parameters indicate how the O-RU can perform the antenna + calibration operation; at which Symbol, Slot, and Frame. + This scheduling information can be generated by O-RU itself. + However, in a dynamic TDD environment, the DL and UL configuration + is only determined and known by O-DU. Consequently, only O-DU (NETCONF + client ) can determine and configure the scheduling and resource + allocation permitted for use by the antenna calibration operation"; + input { + uses antenna-calibration-data; + } + output { + leaf status { + type enumeration { + enum ACCEPTED { + description + "Status information to indicate that O-RU accepted RPC + antenna calibration start request"; + } + enum REJECTED { + description + "Status information to indicate that O-RU rejected RPC antenna + calibration start request"; + } + } + mandatory true; + description + "Status of whether antenna calibration trigger by RPC is accepted + by the O-RU"; + } + leaf error-message { + when "../status='REJECTED'"; + type string; + description + "Detailed error Message when the status is rejected, e.g., + because O-RU can not start antenna calibration + such as already running antenna calibration, + resource mask mismatch with O-RU antenna calibration capability, + overlapped DL and UL masks, insufficient memory, O-RU internal reason"; + } + } + } + + grouping antenna-calibration-data { + description "information set for the operation of antenna calibration"; + + leaf symbol-bitmask-dl { + type string { + length "14"; + pattern "[01]*"; + } + mandatory true; + description + "Bitmask indicating DL calibration symbol within a calibration slot. + First character in the string indicate first symbol, + next character in the string indicate second symbol and so on. + Value 1 indicates that the symbol may be used for calibration + and 0 means the symbol shall not be used for calibration."; + } + leaf symbol-bitmask-ul { + type string { + length "14"; + pattern "[01]*"; + } + mandatory true; + description + "Bitmask indicating UL calibration symbol within a calibration slot. + First character in the string indicate first symbol, + next character in the string indicate second symbol and so on. + Value 1 indicates that the symbol may be used for calibration + and 0 means the symbol shall not be used for calibration."; + } + leaf slot-bitmask-dl { + type string { + length "10..255"; + pattern "[01]*"; + } + mandatory true; + description + "Bitmask indicating DL calibration slot within a calibration frame. + First character in the string indicate first slot, + next character in the string indicate second slot and so on. + Value 1 indicates that the slot may be used for calibration + and 0 means the slot shall not be used for calibration."; + } + leaf slot-bitmask-ul { + type string { + length "10..255"; + pattern "[01]*"; + } + mandatory true; + description + "Bitmask indicating UL calibration slot within a calibration frame. + First character in the string indicate first slot, + next character in the string indicate second slot and so on. + Value 1 indicates that the slot may be used for calibration + and 0 means the slot shall not be used for calibration."; + } + leaf frame-bitmask-dl { + type string { + length "1..255"; + pattern "[01]*"; + } + mandatory true; + description + "Bitmask indicating DL calibration frame within a calibration step. + First character in the string indicate first radio frame equal to + the start-SFN, next character in the string indicate the next frame + and so on. + + Value 1 indicates that the frame may be used for calibration + and 0 means the frame shall not be used for calibration."; + } + leaf frame-bitmask-ul { + type string { + length "1..255"; + pattern "[01]*"; + } + mandatory true; + description + "Bitmask indicating UL calibration frame within a calibration step. + First character in the string indicate first radio frame equal to + the start-SFN, next character in the string indicate the next frame + and so on. + + Value 1 indicates that the frame is may be used for calibration + and 0 means the frame shall not be used for calibration."; + } + leaf calibration-step-size { + type uint8; + mandatory true; + description " Number of frames within a calibration step"; + } + leaf calibration-step-number { + type uint8; + mandatory true; + description "Number of calibration steps"; + } + leaf start-sfn { + type uint16 { + range "0..1023"; + } + mandatory true; + description "start SFN number of the first calibration step"; + } + } + + notification antenna-calibration-required { + list dl-calibration-frequency-chunk { + leaf start-calibration-frequency-dl { + type uint64; + description + "lowest frequency value in Hz of the frequency range is required for + DL antenna calibration operation."; + } + leaf end-calibration-frequency-dl { + type uint64; + description + "highest frequency value in Hz of the frequency range is required for + DL antenna calibration operation."; + } + description + "min/max frequency of dl spectrum chunk affected by calibration process"; + } + list ul-calibration-frequency-chunk { + leaf start-calibration-frequency-ul { + type uint64; + description + "lowest frequency value in Hz of the frequency range is required for + UL antenna calibration operation."; + } + leaf end-calibration-frequency-ul { + type uint64; + description + "highest frequency value in Hz of the frequency range is required for + UL antenna calibration operation."; + } + description + "min/max frequency of ul spectrum chunk affected by calibration process"; + } + + description + "this notification indicates that the antenna calibration is required in O-RU"; + } + + notification antenna-calibration-coordinated { + if-feature O-RU-COORDINATED-ANT-CAL; + list dl-calibration-frequency-chunk { + leaf start-calibration-frequency-dl { + type uint64; + description + "lowest frequency value in Hz of the frequency range is required for + DL antenna calibration operation."; + } + leaf end-calibration-frequency-dl { + type uint64; + description + "highest frequency value in Hz of the frequency range is required for + DL antenna calibration operation."; + } + description + "min/max frequency of dl spectrum chunk affected by calibration process"; + } + list ul-calibration-frequency-chunk { + leaf start-calibration-frequency-ul { + type uint64; + description + "lowest frequency value in Hz of the frequency range is required for + UL antenna calibration operation."; + } + leaf end-calibration-frequency-ul { + type uint64; + description + "highest frequency value in Hz of the frequency range is required for + UL antenna calibration operation."; + } + description + "min/max frequency of ul spectrum chunk affected by calibration process"; + } + uses antenna-calibration-data { + description + "In the case of support of feature O-RU-COORDINATED-ANT-CAL, + time-frequency resource determined by O-RU will be included"; + } + + description + "this notification indicates that coordinated antenna calibration is provided in O-RU. + It indicate the time-frequency resources will be sent to a subscribed O-DU at least 60 seconds + before the operation of the coordinated antenna calibration procedure."; + } + + notification antenna-calibration-result { + leaf status { + type enumeration { + enum SUCCESS { + description "O-RU has succeeded in calibrating its antenna"; + } + enum FAILURE { + description + "O-RU attemted to calibrate its antenna, but the procedure failed."; + } + } + mandatory true; + description + "Status of the antenna calibration procedure which has been triggered + by accepting an start-antenna-calibration RPC."; + } + leaf detailed-reason { + when "../status='FAILURE'"; + type string; + description + "Detailed reason when the status is FAILURE, e.g., + O-RU cannot complete the antenna calibration + because of lack of memory, self-calibration failure, etc"; + } + description + "This notification indicates the antenna calibration result"; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-beamforming@2020-04-17.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-beamforming@2020-04-17.yang new file mode 100644 index 0000000..7707dac --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-beamforming@2020-04-17.yang @@ -0,0 +1,888 @@ +module o-ran-beamforming { + yang-version 1.1; + namespace "urn:o-ran:beamforming:1.0"; + prefix "o-ran-bf"; + + import o-ran-uplane-conf { + prefix "up"; + } + + import o-ran-module-cap { + prefix "mcap"; + } + + import o-ran-compression-factors { + prefix "cf"; + revision-date 2020-08-10; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the beamforming capabilitites of an O-RU. + Only O-RUs that support beamforming shall support this module. + + Copyright 2020 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 "2020-04-17" { + description + "version 2.1.0 + + 1) corrected error where typedef refers to deprecated beam-id by + introducing new typedef and deprecating leafs defining coarse/fine + relationships that refer to beam-id and replacing with new ones based + on capability grouping"; + + reference "ORAN-WG4.M.0-v02.00"; + } + + revision "2019-07-03" { + description + "version 2.0.0 + + 1) re-designed/switched from per band to per capabilities-group for + addition flexibility + 2) added in new beam tilt feature + 3) adding possibilities to provide more compression types for beamforming + 4) Adding possibility to configure beamforming per capabilities group + 5) corrected xPATH boolean check from TRUE to true"; + + reference "ORAN-WG4.M.0-v02.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"; + } + + + feature MODIFY-BF-CONFIG { + description + "This feature indicates that the O-RU supports an optional feature to + modify beamforming configuration information"; + } + + feature BEAM-TILT { + description + "This feature indicates that the O-RU supports an optional feature to + allows to shift beam characteristic of all predefined-beams in elevation + and/or azimuth direction (i.e. changing the service area or sector + coverage) while preserving the beam adjacency among the beams within + the service area "; + } + + typedef beam-reference { + type leafref { + path "/o-ran-bf:beamforming-config/o-ran-bf:per-band-config/o-ran-bf:beam-information/o-ran-bf:beamforming-properties/o-ran-bf:beam-id"; + } + description + "This type is used by data models that need to reference a beam."; + } + + typedef beam-capabilities-reference { + type leafref { + path "/o-ran-bf:beamforming-config/o-ran-bf:capabilities-groups/o-ran-bf:beam-information/o-ran-bf:beamforming-properties/o-ran-bf:beam-id"; + } + description + "This type is used by data models that need to reference a beam based on capability group."; + } + + grouping beamforming-parameters { + leaf max-number-of-beam-ids { + type uint16; + mandatory true; + description + "Maximum number of supported Beam ID assigned to domain beamforming control"; + } + + leaf initial-beam-id { + type uint16; + mandatory true; + description + "First Beam ID that can be used for addressing of domain beams"; + } + + description "Group of common beamforming parameters"; + } + + grouping granularity-parameters { + leaf frequency-granularity { + type enumeration { + enum CC { + description + "Frequency granularity: per carrier component"; + } + + enum BAND { + description + "Frequency granularity: per band"; + } + } + mandatory true; + description "Supported time granularity of time-domain beamforming."; + } + + leaf time-granularity { + type enumeration { + enum SLOT { + description + "Time granularity: per slot"; + } + + enum SYMBOL { + description + "Time granularity: per symbol"; + } + } + mandatory true; + description "Supported time granularity of time-domain beamforming."; + } + description ""; + } + + grouping array-lists { + description + "Grouping for array lists"; + + leaf-list tx-array { + type leafref { + path "/up:user-plane-configuration/up:tx-arrays/up:name"; + } + description "tx arrays belonging to this band number"; + } + leaf-list rx-array { + type leafref { + path "/up:user-plane-configuration/up:rx-arrays/up:name"; + } + description "rx arrays belonging to this band number"; + } + } + + grouping static-properties { + description + "Grouping for static beamforming properties"; + + leaf rt-bf-weights-update-support { + type boolean; + description + "The parameter informs if O-RU supports real time beamforming weights update through C-Plane messaging"; + } + + choice beamforming-type { + case frequency { + container frequency-domain-beams { + when "../rt-bf-weights-update-support = 'true'"; + uses beamforming-parameters; + uses cf:compression-details; + + list additional-compression-method-supported { + uses cf:compression-details; + + description + "List of additional supported compression methods by O-RU"; + } + + description ""; + } + description "Set of parameters valid for O-RU, that supports beamforming in frequency domain."; + } + + case time { + container time-domain-beams { + when "../rt-bf-weights-update-support = 'true'"; + uses beamforming-parameters; + uses granularity-parameters; + uses cf:compression-details; + + list additional-compression-method-supported { + uses cf:compression-details; + + description + "List of additional supported compression methods by O-RU"; + } + + description ""; + } + description "Set of parameters valid for O-RU, that supports beamforming in time domain."; + } + + case hybrid { + container hybrid-beams { + when "../rt-bf-weights-update-support = 'true'"; + uses beamforming-parameters; + uses granularity-parameters; + uses cf:compression-details; + + list additional-compression-method-supported { + uses cf:compression-details; + + description + "List of additional supported compression methods by O-RU"; + } + + description ""; + } + description "Set of parameters valid for O-RU, that supports hybrid beamforming - in both time and frequency domain."; + } + description + "This value indicates beamforming type supported by O-RU"; + } + + leaf number-of-beams { + type uint16; + description + "This value indicates the max number of beam patterns O-RU can generate + and apply to the signal of each O-RU port (both DL and UL). + This value is equivalent to the maximum number of used beam IDs."; + } + } + + grouping beamforming-property { + description + "Grouping for beamforming property"; + + leaf beam-type { + type enumeration { + enum COARSE { + description "the beam-id corresponds to a coarse beam"; + } + enum FINE { + description "the beam-id corresponds to a fine beam"; + } + } + description + "This value indicates the beam resolution."; + } + + leaf beam-group-id { + type uint16; + description + "Beams with same beamGroupsID can be transmitted simultaneously."; + } + + leaf-list coarse-fine-beam-relation { + type beam-reference; + status deprecated; + description + "List of related coarse/fine beam."; + } + + leaf-list neighbour-beams { + type beam-reference; + status deprecated; + description + "A list of neighbor beams which might restrict co-scheduling due + to interference."; + } + + leaf-list coarse-fine-beam-capability-based-relation { + type beam-capabilities-reference; + description + "List of related coarse/fine beam."; + } + + leaf-list neighbour-beams-capability-based { + type beam-capabilities-reference; + description + "A list of neighbor beams which might restrict co-scheduling due + to interference."; + } + } + + grouping beamforming-properties-element { + description + "Grouping for beamforming-properties element"; + + leaf beam-id { + type uint16; + description + "This value indicates the beam ID whose beamforming properties are + described in the container."; + } + + container beamforming-property { + description + "Structure containing single set of beamforming properties."; + + uses beamforming-property; + } + } + + grouping band-num { + description + "Band information for the beamforming + related to the band number from module capabilities"; + + leaf band-number { + type leafref { + path "/mcap:module-capability/mcap:band-capabilities/mcap:band-number"; + } + description + "band information for the beamforming information + related to the band number of module capabilities"; + } + } + + grouping cap-group { + description + "Capabilities group grouping"; + + leaf capabilities-group { + type leafref { + path "/o-ran-bf:beamforming-config/o-ran-bf:capabilities-groups/o-ran-bf:capabilities-group"; + } + mandatory true; + description + "Capabilities group identification number to which it refers."; + } + + } + + grouping per-band-config-element { + description + "Grouping for per band config element"; + + uses band-num; + uses array-lists; + + container static-properties { + description + "the static beamforming related information"; + + uses static-properties; + } + + container beam-information { + description + "Beam information which exposes beamforming related O-RU capabilities."; + leaf number-of-beamforming-properties { + type uint16; + description + "This parameter indicates the number of beamFormingProperties entries."; + } + + list beamforming-properties { + key beam-id; + description + "Array for the beamforming properties at O-RU. + These parameters can be used by the beamforming control by the NETCONF client. + 'numberOfBeamformingProperties' indicaets the size of the array."; + + uses beamforming-properties-element; + } + } + } + + grouping operational-properties { + description + "Grouping for operational properties"; + + leaf number-of-writeable-beamforming-files { + type uint8 { + range "1 .. max"; + } + mandatory true; + description + "This leaf indicates the maximum number of writeable beamforming files + containing beamweights and/or attributes that the O-RU can store, taking + into account the maximum number of beam-IDs as defined by 3GPP + TS38.214 v15.x.x"; + } + + leaf update-bf-non-delete { + type boolean; + default false; + description + "When set to TRUE, indicates that an O-RU supports the capability + to apply the modified beamforming weight information by using rpc + activate-beamforming-weight without deletion of tx-array-carriers and + rx-array-carriers in advance, i.e., to a deactivated carrier"; + } + + leaf persistent-bf-files { + type boolean; + default false; + description + "When set to TRUE, indicates that the O-RU supports the capability + to store the modified beamforming weight information file in the + reset persistent memory"; + } + } + + grouping beamforming-supported-type { + description + "Grouping for type of beamforming supported"; + + leaf beamforming-trough-attributes-supported { + type boolean; + config false; + description + "Informs if beamforming can be controlled providing attributes to O-RU + (like angles, beamwidth)."; + } + + leaf beamforming-trough-ue-channel-info-supported { + type boolean; + config false; + description + "Informs if beamforming can be controlled by UE information."; + } + } + + grouping beamforming-config { + description + "Grouping for beamforming configuration"; + + list per-band-config { + key band-number; + config false; + status deprecated; + description "beamforming information per band"; + uses per-band-config-element; + } + + list capabilities-groups { + key capabilities-group; + description + "Capabilities groups identification number assigned to be referenced by operations + and notifications. + This also help to group particular beamforming capabilities and bind it with arrays"; + + leaf capabilities-group { + type uint16; + description + "Capabilities group identification number. Number which is used just for reference in RPC + and notification"; + } + uses per-band-config-element; + } + + container ue-specific-beamforming { + presence + "Indicates that the O-RU supports optional Section Type '6' Fields + (used for sending channel information for a specific UE)"; + config false; + description + "Information related to supput by the O-RU of Section Type 6 for + signalling UE-specific channel information to the O-RU"; + leaf max-number-of-ues { + type uint8; + description + "Indicates tha maximum number of UE -specific channel information + data sets supported by the O-RU"; + } + } + container operational-properties { + if-feature MODIFY-BF-CONFIG; + config false; + description "properties for dynamic beam weight/attribute support"; + + uses operational-properties; + } + } + + grouping beam-tilt-configuration { + description "grouping for beam-tilt feature"; + list predefined-beam-tilt-offset { + if-feature BEAM-TILT; + key capabilities-group; + description "Configuration of the predefined-beam-tilt-offset per capabilities-group"; + leaf capabilities-group { + type leafref { + path "/o-ran-bf:beamforming-config/o-ran-bf:capabilities-groups/o-ran-bf:capabilities-group"; + require-instance false; + } + mandatory true; + description + "Capabilities group identification number for which + the predefined-beam-tilt-offset relates to"; + } + leaf elevation-tilt-offset-angle { + type int16 { + range "-90..90"; + } + units degrees; + default 0; + description + "Value 0 represents the default service area of the predefined-beams + in elevation domain, i.e. no tilt offset. + + Values smaller than 0 represents an up-shift of the default service area + towards the zenith (i.e., corresponding to a decrease in zenith angle) and + values larger than 0 represent a down-shift of the default service area + away from the zenith (i.e., corresponding to an increase in zenith angle). + + If the value is greater than the maximum supported angle, then the maximum + angle is used for configuration. + If the value is less than the minimum supported angle, then the minimum + angle is used for configuration. + The actual angle used is (angle DIV granularity) * granularity. + + Any O-RU which is reset using the o-ran-operations:reset RPC shall reset + its offset angle to its default value."; + } + leaf azimuth-tilt-offset-angle { + type int16 { + range "-90..90"; + } + units degrees; + default 0; + description + "Value 0 represents the default service area of the predefined-beams + in azimuth domain, i.e., no tile offset. + + Azimuth tilt offset angle, represents counter-clockwise rotation around + z-axis. I.e., assuming view from the UE (observation of the O-RU + from the front), value larger than 0 and smaller than 0 + respectively represent right-shifted and left-shifted of the default + service area in azimuth domain. + + If the value is greater than the maximum supported angle, then the maximum + angle is used for configuration. + If the value is less than the minimum supported angle, then the minimum + angle is used for configuration. + The actual angle used is (angle DIV granularity) * granularity. + + Any O-RU which is reset using the o-ran-operations:reset RPC shall reset + its offset angle to its default value."; + } + } + } + + grouping beam-tilt-state { + description + "Grouping for beam tilt state"; + + list predefined-beam-tilt-offset-information { + key capabilities-group; + config false; + description + "Information which exposes predefined-beam-tilt-offset related O-RU capabilities."; + leaf capabilities-group { + type leafref { + path "/o-ran-bf:beamforming-config/o-ran-bf:capabilities-groups/o-ran-bf:capabilities-group"; + } + mandatory true; + description + "Capabilities group identification number for which + the predefined-beam-tilt-offset-information relates to"; + } + leaf elevation-tilt-offset-granularity { + type uint8 { + range "0..30"; + } + units Degrees; + mandatory true; + description + "Indication of the supported granularity for the + predefined-beam-tilt-offset in elevation domain. + + Value 0 represents that the O-RU doesn't support + the predefined-beam-tilt-offset in elevation domain."; + } + leaf azimuth-tilt-offset-granularity { + type uint8 { + range "0..30"; + } + units Degrees; + mandatory true; + description + "Indication of the supported granularity for the + predefined-beam-tilt-offset in azimuth domain. + + Value '0' represents that the O-RU doesn't support + the predefined-beam-tilt-offset in azimuth domain."; + } + leaf minimum-supported-elevation-tilt-offset { + type int16 { + range "-90..0"; + } + units Degrees; + mandatory true; + description + "The minimum value which can be configured for + 'elevation-tilt-offset-angle'."; + } + leaf maximum-supported-elevation-tilt-offset { + type int16 { + range "0..90"; + } + units Degrees; + mandatory true; + description + "The maximum value which can be configured for + 'elevation-tilt-offset-angle'."; + } + leaf minimum-supported-azimuth-tilt-offset { + type int16 { + range "-90..0"; + } + units Degrees; + mandatory true; + description + "The minimum value which can be configured for + 'azimuth-tilt-offset-angle'."; + } + leaf maximum-supported-azimuth-tilt-offset { + type int16 { + range "0..90"; + } + units Degrees; + mandatory true; + description + "The maximum value which can be configured for + 'azimuth-tilt-offset-angle'."; + } + leaf run-time-tilt-offset-supported { + type boolean; + mandatory true; + description + "If 'run-time-tilt-offset-supported' is FALSE, changing the values in + 'predefined-beam-tilt-offset' for a specific band shall be allowed only + if all 'tx-array-carriers' and 'rx-array-carriers' corresponding + to the band are INACTIVE."; + } + } + + } + + grouping beam-tilt-report { + description + "Grouping for beam tilt report"; + + list predefined-beam-tilt-state { + key capabilities-group; + config false; + description + "Information which exposes state of predefined-beam-tilt-offset."; + leaf capabilities-group { + type leafref { + path "/o-ran-bf:beamforming-config/o-ran-bf:capabilities-groups/o-ran-bf:capabilities-group"; + } + mandatory true; + description + "Capabilities group identification number for which + the predefined-beam-tilt-state relates to"; + } + leaf elevation-tilt-offset-angle { + type int16 { + range "-90..90"; + } + units Degrees; + mandatory true; + description + "Value 'zero' represents the default service area of the + predefined-beams in elevation domain. + + Values smaller than 0 represents an up-shift of the default service area + towards the zenith (i.e., corresponding to a decrease in zenith angle) and + values larger than 0 represent a down-shift of the default service area + away from the zenith (i.e., corresponding to an increase in zenith angle)."; + } + leaf azimuth-tilt-offset-angle { + type int16 { + range "-90..90"; + } + units Degrees; + mandatory true; + description + "Value 'zero' represents the default service area of the + predefined-beams in azimuth domain. + + Azimuth tilt offset angle, represents counter-clockwise rotation around + z-axis. I.e., assuming view from the UE (observation of the O-RU from + the front), value larger than 'zero' and smaller than 'zero' + respectively represent right-shifted and left-shifted of the default + service area in azimuth domain."; + } + } + + } + + container beamforming-config { + config false; + description + "A set of configuration data for the O-RU's beam forming functionality"; + + uses beamforming-config; + uses beamforming-supported-type; + container beam-tilt { + if-feature BEAM-TILT; + description "container for pre-defined beam tilt feature"; + uses beam-tilt-state; + uses beam-tilt-report; + } + } + + + rpc activate-beamforming-config { + if-feature MODIFY-BF-CONFIG; + description + "rpc to activate beamforming config information by indicating the file + stored in the folder O-RAN/beam-weights in advance"; + input { + leaf beamforming-config-file { + type string; + mandatory true; + description + "file name stored in O-RAN/beamforming/ folder is indicated"; + } + + uses band-num; + } + output { + leaf status { + type enumeration { + enum ACCEPTED { + description "O-RU has accepted the beamforming weight/attribute file"; + } + enum REJECTED { + description + "O-RU has rejected the beamforming weight/attribute file. The O-RU + should then use the default beamforming file."; + } + } + mandatory true; + description "Status of activation of beamforming config information"; + } + leaf error-message { + when "../status='REJECTED'"; + type string; + description + "Detailed error Message when the status is rejected, e.g., + because new beam forming file is attempted to be applied to a + carrier which is still active, or the beam-id does not exist."; + } + } + } + + rpc activate-beamforming-config-by-capability-group { + if-feature MODIFY-BF-CONFIG; + description + "rpc to activate beamforming config information by indicating the file + stored in the folder O-RAN/beam-weights in advance"; + input { + leaf beamforming-config-file { + type string; + mandatory true; + description + "file name stored in O-RAN/beamforming/ folder is indicated"; + } + + uses cap-group; + } + output { + leaf status { + type enumeration { + enum ACCEPTED { + description "O-RU has accepted the beamforming weight/attribute file"; + } + enum REJECTED { + description + "O-RU has rejected the beamforming weight/attribute file. The O-RU + should then use the default beamforming file."; + } + } + mandatory true; + description "Status of activation of beamforming config information"; + } + leaf error-message { + when "../status='REJECTED'"; + type string; + description + "Detailed error Message when the status is rejected, e.g., + because new beam forming file is attempted to be applied to a + carrier which is still active, or the beam-id does not exist."; + } + } + } + + + rpc modify-predefined-beam-tilt-offset { + if-feature BEAM-TILT; + description + "rpc to trigger the modification of the predefined beam tilt offset"; + input { + uses beam-tilt-configuration; + } + output { + leaf status { + type enumeration { + enum ACCEPTED { + description "O-RU has accepted the predefind beamtilt offset configuration"; + } + enum REJECTED { + description + "O-RU has rejected the predefind beamtilt offset configuration."; + } + } + mandatory true; + description "Status of acceptance of pre-defined beamtilt offset configuration"; + } + leaf error-message { + when "../status='REJECTED'"; + type string; + description + "Detailed error message when the pre-defined beam tilt configuration + is rejected, e.g., used when 'run-time-tilt-offset-supported' is FALSE and the + NETCONF client is attempting to modify the beam tilt on a band where + one or more array-carriers are still ACTIVE."; + } + } + } + + + //notification statement + notification beamforming-information-update { + uses band-num; + description + "this notification indicates that the beamforming properties are updated for particular band"; + } + + notification capability-group-beamforming-information-update { + uses cap-group; + description + "this notification indicates that the beamforming properties are updated for particular band + or capability group"; + } + + notification predefined-beam-tilt-offset-complete { + if-feature BEAM-TILT; + uses beam-tilt-report; + description + "this notification indicates that the re-generation of the predefined + beams is completed"; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-compression-factors@2020-08-10.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-compression-factors@2020-08-10.yang new file mode 100644 index 0000000..5816b5e --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-compression-factors@2020-08-10.yang @@ -0,0 +1,368 @@ +module o-ran-compression-factors { + yang-version 1.1; + namespace "urn:o-ran:compression-factors:1.0"; + prefix "o-ran-compression-factors"; + + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the module capabilities for + the O-RAN Radio Unit U-Plane configuration. + + Copyright 2020 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 "2020-08-10" { + description + "version 4.0.0 + + 1) supporting compression types per endpoint + 2) adding feature for configurable fs-offset for compression"; + + reference "ORAN-WG4.M.0-v04.00"; + } + + revision "2020-04-17" { + description + "version 3.0.0 + + 1) adding selective RE sending compression types"; + + reference "ORAN-WG4.M.0-v03.00"; + } + + revision "2019-07-03" { + description + "version 1.1.0 + + 1) changes related to compression bitwidth presentation"; + + 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"; + } + + feature CONFIGURABLE-FS-OFFSET { + description + "Presence of this feature means that O-RU supports configurable fs-offset for compression."; + } + + grouping compression-method-grouping { + description + "Grouping for compression method."; + + leaf iq-bitwidth { + type uint8; + description + "Bitwidth to be used in compression"; + } + + leaf compression-method { + type enumeration { + enum NO_COMPRESSION { + description + "No compression will be used"; + } + enum BLOCK_FLOATING_POINT { + description + "Block floating point compression and decompression will be used"; + } + + enum BLOCK_SCALING { + description + "Block scaling compression and decompresion will be used"; + } + + enum U_LAW { + description + "u-Law compression and decompresion method will be used"; + } + + enum BEAMSPACE { + description + "Beamspace compression and decompression will be used"; + } + + enum MODULATION { + description + "Modulation compression and decompression will be used"; + } + enum BLOCK-FLOATING-POINT-SELECTIVE-RE-SENDING { + description + "block floating point with selective re sending + compression and decompression will be used"; + } + enum MODULATION-COMPRESSION-SELECTIVE-RE-SENDING { + description + "modulation compression with selective re sending + compression and decompression will be used"; + } + } + description + "Compresion method which can be supported by the O-RU"; + } + } + + grouping compression-formats { + description + "Grouping deicated to list compression formats as choice"; + + choice compression-format { + description + "Choice of compression format for particular element"; + + case no-compresison { + description "Compression for beam weights is not supported."; + } + case block-floating-point { + description "Block floating point compression and decompression is supported."; + + leaf exponent { + type uint8 { + range "4"; + } + description "Exponent bit width size in number of bits used when encoding in udCompParam."; + } + } + + case block-floating-point-selective-re-sending { + description + "Block floating point with selective re sending compression and decompression is supported."; + + leaf sres-exponent { + type uint8 { + range "4"; + } + description "Exponent bit width size in number of bits used when encoding in udCompParam."; + } + } + + case block-scaling { + description "Block scaling compression and decompresion is supported."; + leaf block-scalar { + type uint8; + description + "Common scaler for compressed PRB"; + } + } + + case u-law { + description "u-Law compression and decompresion method is supported."; + leaf comp-bit-width { + type uint8 { + range "0..15"; + } + description "Bit with for u-law compression"; + } + leaf comp-shift { + type uint8 { + range "0..15"; + } + description + "the shift applied to the entire PRB"; + } + } + + case beam-space-compression { + description "Beamspace compression and decompression is supported. Applies to beamforming weights only."; + leaf-list active-beam-space-coeficient-mask { + type uint8; + description + "active beamspace coefficient indices associated with the compressed beamforming vector"; + } + leaf block-scaler { + type uint8; + description + "Common scaler for compressed beamforming coefficients"; + } + } + + case modulation-compression { + description "Modulation compression and decompression is supported."; + leaf csf { + type uint8 { + range "0..1"; + } + description "Constallation shift flag"; + } + + leaf mod-comp-scaler { + type uint16 { + range "0..32767"; + } + description "Modulation compression scaler value."; + } + } + + case modulation-compression-selective-re-sending { + description "Modulation compression with selective re sending and decompression is supported."; + leaf sres-csf { + type uint8 { + range "0..1"; + } + description "Constallation shift flag"; + } + + leaf sres-mod-comp-scaler { + type uint16 { + range "0..32767"; + } + description "Modulation compression scaler value."; + } + } + + } + } + + grouping compression-params { + description + "Parameters to define compression"; + + leaf compression-type { + type enumeration { + enum STATIC { + description + "Indicates that static compression method will be used (both compression and IQ bitwidth)"; + } + enum DYNAMIC { + description + "Indicates that dynamic compression method will be used"; + } + } + mandatory true; + description + "Compression type that O-DU wants to be supported"; + } + +// *********** TO BE REMOVED *********** + leaf bitwidth { + when "../compression-type = 'STATIC'"; + type uint8; + status deprecated; + description + "Bitwidth to be used in compression. + This has since been replaced in M-Plane version + 2.0.0 with the iq-bitwidth schema node"; + } +// ************************************* + + uses compression-formats; + } + + grouping compression-parameters { + description + "Parameters used to define description type"; + + leaf iq-bitwidth { + type uint8; + description + "Bitwidth to be used in compression"; + } + + uses compression-formats; + } + + grouping format-of-iq-sample { + description + "Indicates module capabilities about IQ samples"; + + leaf dynamic-compression-supported { + type boolean; + + description + "Informs if radio supports dynamic compression method"; + } + + leaf realtime-variable-bit-width-supported { + type boolean; + + description + "Informs if O-RU supports realtime variable bit with"; + } + + list compression-method-supported { + uses compression-parameters; + + description + "List of supported compression methods by O-RU + Note: if O-RU supports different compression methods per endpoint + then please refer do endpoints to have information what + exactly is supported on a paticular endpoint"; + } + + leaf syminc-supported { + type boolean; + + description + "Informs if symbol number increment command in a C-Plane is + supported or not"; + } + + leaf regularization-factor-se-supported { + type boolean; + + description + "Informs if regularizationFactor in section type 5 is + supported(true) or not(false)"; + } + + leaf little-endian-supported { + type boolean; + default false; + + description + "All O-RUs support bigendian byte order. This node informs if module supports the + the optional capability for little endian byte order for C/U plane data flows. + + Note - little endian support does not invalidate bigendian support."; + } + } + + + grouping compression-details { + description ""; + + leaf iq-bitwidth { + type uint8; + description + "Bitwidth to be used in compression"; + } + + uses compression-params; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-delay-management@2020-08-10.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-delay-management@2020-08-10.yang new file mode 100644 index 0000000..6e64c49 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-delay-management@2020-08-10.yang @@ -0,0 +1,354 @@ +module o-ran-delay-management { + yang-version 1.1; + namespace "urn:o-ran:delay:1.0"; + prefix "o-ran-delay"; + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module covers off aspects of O-DU to O-RU delay management, + including config data related to O-RU transmission and reception + windows. + + Copyright 2020 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 "2020-08-10" { + description + "version 4.0.0 + + 1) introduction of new t1a-max-cp-dl leaf to enable decoupled timing between C- and U-Plane"; + + reference "ORAN-WG4.M.0-v04.00"; + } + + revision "2019-07-03" { + description + "version 1.1.0 + + 1) fixing descriptions of ta3-min and ta3-max. + 2) introducing grouping/uses to enable model re-use by WG5"; + + 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"; + } + + + feature ADAPTIVE-RU-PROFILE { + description + "This feature indicates that the O-RU supports adaptive O-RU delay profile + based on information provided by the NETCONF client."; + } + + typedef bandwidth { + type uint32 { + range "200 | 1400 | 3000 | 5000 | 10000 | 15000 | 20000 | 25000 | + 30000 | 40000 | 50000 | 60000 | 70000 | 80000 | 90000 | 100000 + | 200000 | 400000" ; + } + units kilohertz; + description + "transmission bandwidth configuration in units of kHz - + covering NBIoT through to New Radio - see 38.104"; + } + + grouping bandwidth-configuration { + description + "Grouping for bandwidth and scs configuration"; + + leaf bandwidth { + type bandwidth; + description + "transmission bandwidth configuration in units of kHz - + covering NBIoT through to New Radio - see 38.104"; + } + leaf subcarrier-spacing { + type uint32 { + range "0 .. 240000 "; + } + units Hertz; + description "subcarrier spacing in Hz"; + } + } + + grouping t2a-up { + description + "configuration of t2a for uplink"; + + leaf t2a-min-up { + type uint32; + units nanoseconds; + mandatory true; + description + "the minimum O-RU data processing delay between receiving IQ data + message over the fronthaul interface and transmitting + the corresponding first IQ sample at the antenna"; + } + leaf t2a-max-up { + type uint32; + units nanoseconds; + mandatory true; + description + "the earliest allowable time when a data packet is received before + the corresponding first IQ sample is transmitted at the antenna"; + } + } + + grouping t2a-cp-dl { + description + "Grouping for t2a CP for downlink"; + + leaf t2a-min-cp-dl { + type uint32; + units nanoseconds; + mandatory true; + description + "the minimum O-RU data processing delay between receiving downlink + real time control plane message over the fronthaul interface and + transmitting the corresponding first IQ sample at the antenna"; + } + leaf t2a-max-cp-dl { + type uint32; + units nanoseconds; + mandatory true; + description + "the earliest allowable time when a downlink real time control message + is received before the corresponding first IQ sample is transmitted at + the antenna"; + } + } + + grouping ta3 { + description + "Grouping for ta3 configuration"; + + leaf ta3-min { + type uint32; + units nanoseconds; + mandatory true; + description + "the minimum O-RU data processing delay between receiving an IQ sample + at the antenna and transmitting the first data sample over the + fronthaul interface"; + } + leaf ta3-max { + type uint32; + units nanoseconds; + mandatory true; + description + "the maximum O-RU data processing delay between receiving an IQ sample + at the antenna and transmitting the last data sample over the + fronthaul interface"; + } + } + + grouping t2a-cp-ul { + description + "Grouping for t2a CP uplink"; + + leaf t2a-min-cp-ul { + type uint32; + units nanoseconds; + mandatory true; + description + "the minimum O-RU data processing delay between receiving real time + up-link control plane message over the fronthaul interface and + recieving the first IQ sample at the antenna"; + } + leaf t2a-max-cp-ul { + type uint32; + units nanoseconds; + mandatory true; + description + "the earliest allowable time when a real time up-link control message + is received before the corresponding first IQ sample is received at + the antenna"; + } + } + + grouping ru-delay-profile { + description + "Grouping for ru delay profile"; + + uses t2a-up; + uses t2a-cp-dl; + + leaf tcp-adv-dl { + type uint32; + units nanoseconds; + mandatory true; + description + "the time difference (advance) between the reception window for + downlink real time Control messages and reception window for the + corresponding IQ data messages."; + } + + uses ta3; + uses t2a-cp-ul; + } + + grouping o-du-delay-profile { + description + "Grouping for O-DU delay profile"; + + leaf t1a-max-up { + type uint32; + units nanoseconds; + description + "the earliest possible time which the O-DU can support transmiting + an IQ data message prior to transmission of the corresponding IQ + samples at the antenna"; + } + leaf tx-max { + type uint32; + units nanoseconds; + description + "The maximum amount of time which the O-DU requires to transmit + all downlink user plane IQ data message for a symbol"; + } + leaf ta4-max { + type uint32; + units nanoseconds; + description + "the latest possible time which the O-DU can support receiving the + last uplink user plane IQ data message for a symbol."; + } + leaf rx-max { + type uint32; + units nanoseconds; + description + "The maximum time difference the O-DU can support between + receiving the first user plane IQ data message for a symbol and + receiving the last user plane IQ data message for the same symbol"; + } + leaf t1a-max-cp-dl { + type uint32; + units nanoseconds; + description + "The earliest possible time which the O-DU can support transmitting the + downlink real time control message prior to transmission of the + corresponding IQ samples at the antenna."; + } + } + + grouping t12 { + description + "Grouping for t12"; + + leaf t12-min { + type uint32; + units nanoseconds; + description + "the minimum measured delay between DU port-ID and O-RU port-ID"; + } +// additional leaf added by Samsung + leaf t12-max { + type uint32; + units nanoseconds; + description + "the maximum measured delay between CU port-ID and O-RU port-ID"; + } + } + + grouping t34 { + description + "Grouping for t34"; + + leaf t34-min { + type uint32; + units nanoseconds; + description + "the minimum measured delay between O-RU port-ID and CU port-ID"; + } +// additional leaf added by Samsung + leaf t34-max { + type uint32; + units nanoseconds; + description + "the maximum measured delay between O-RU port-ID and CU port-ID"; + } + } + + grouping delay-management-group { + list bandwidth-scs-delay-state { + key "bandwidth subcarrier-spacing"; + description + "Array of structures containing sets of parameters for delay management."; + + uses bandwidth-configuration; + + container ru-delay-profile { + config false; + description "container for O-RU delay parameters"; + + uses ru-delay-profile; + } + } + + container adaptive-delay-configuration { + if-feature ADAPTIVE-RU-PROFILE; + description "container for adaptive delay parameters"; + list bandwidth-scs-delay-state { + key "bandwidth subcarrier-spacing"; + description + "Array of structures containing sets of parameters for delay management."; + + uses bandwidth-configuration; + + container o-du-delay-profile { + description + "O-DU provided delay profile for adaptive delay configuration"; + + uses o-du-delay-profile; + } + } + + container transport-delay { + description + "O-DU provided transport-delay parameters"; + uses t12; + uses t34; + } + } + } + container delay-management { + description "top level tree covering off O-DU to O-RU delay management"; + + uses delay-management-group; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-dhcp@2020-12-10.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-dhcp@2020-12-10.yang new file mode 100644 index 0000000..00b556b --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-dhcp@2020-12-10.yang @@ -0,0 +1,331 @@ +module o-ran-dhcp { + yang-version 1.1; + namespace "urn:o-ran:dhcp:1.0"; + prefix "o-ran-dhcp"; + + import ietf-interfaces { + prefix "if"; + } + + import ietf-inet-types { + prefix "inet"; + } + + import ietf-dhcpv6-types { + prefix dhcpv6-type; + // checkAS + // revision-date 2018-09-04; + } + + import o-ran-wg4-features { + prefix or-feat; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the YANG definitions for managng the DHCP client. + + 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 "2020-12-10" { + description + "version 5.0.0 + + 1) added new leafs for reporting discovered event-collectors + used"; + + reference "ORAN-WG4.O1.0-v05.00"; +//update reference + } + + revision "2019-07-03" { + description + "version 1.1.0 + + 1) backward compatible changes to fix pen number which always + should have been 32 bits + 2) backward compatible changes to introduce reporting of 3GPP + discovered MV-PnP information, including CA/RA Servers and SeGW + 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"; + } + + typedef netconf-client-id { + type union { + type inet:ip-address; + type inet:uri; + } + description "A NETCONF client identifier"; + } + + typedef ca-ra-server-id { + type union { + type inet:ip-address; + type inet:uri; + } + description "A CA/RA Server identifier"; + } + + typedef segw-id { + type union { + type inet:ip-address; + type inet:uri; + } + description "A SeGW identifier"; + } + + typedef event-collector-id { + type union { + type inet:ip-address; + type inet:uri; + } + description "An event collector identifier"; + } + + grouping ca-ra-servers { + description + "The CA/RA servers discovered using DHCP, discovered using the 3GPP + defined options in 3GPP 32.509 in vendor specific option 43/17"; + list ca-ra-servers { + key servers; + description "A list of IP addresses or URIs for CA/RA Servers"; + + leaf servers{ + type ca-ra-server-id; + description "the server identifier"; + } + leaf port-number { + type inet:port-number; + description "an optional (non-default) port"; + } + leaf ca-ra-path { + type string; + description + "ASCII string representing the path to the CMP server directory. + A CMP server may be located in an arbitrary path other than root."; + } + leaf subject-name { + type string; + description + "ASCII string representing the subject name of the CA/RA. "; + } + leaf protocol { + type enumeration { + enum HTTP; + enum HTTPS; + } + } + } + } + + grouping security-gateways { + description + "The security gateways discovered using DHCP, discovered using the 3GPP + defined options in 3GPP 32.509 in vendor specific option 43/17"; + list segw { + key gateways; + description "A list of IP addresses or URIs for SeGW"; + + leaf gateways{ + type segw-id; + description "the SeGW identifier"; + } + } + + } + + grouping netconf-clients { + description + "The netconf clients discovered using DHCP, discovered using the IANA + defined options or O-RAN defined syntax for encoding IP adresses or FQDNs + in vendor specific option 43/17"; + list netconf-clients{ + key client; + description "A list of IP addresses or URIs for NETCONF clients"; + leaf client{ + type netconf-client-id; + description "the client identifier"; + } + leaf optional-port { + type inet:port-number; + description "an optional (non-default) port"; + } + } + } + + grouping event-collectors { + description + "The event-collectors discovered using DHCP, discovered using the O-RAN + defined syntax for encoding IP adresses or FQDNs in vendor specific + option 43/17"; + leaf-list event-collectors{ + if-feature "or-feat:NON-PERSISTENT-MPLANE"; + max-elements 1; + type event-collector-id; + description + "An event-collector discovered using DHCP that can be used by the O-RU to + send pnfRegistration notification messages. + + The O-RU behaviour when discovering more than one event-collector is not defined."; + } + leaf event-collector-format{ + if-feature "or-feat:NON-PERSISTENT-MPLANE"; + type enumeration { + enum ONAP; + } + description "the event-collector notification format"; + } + } + + grouping dhcpv4-option { + description "DHCPv4 Configuration options"; + + leaf dhcp-server-identifier { + type inet:ip-address; + description "DHCP server identifier"; + } + leaf domain-name { + type string; + description "Name of the domain"; + } + leaf-list domain-name-servers { + type inet:ip-address; + description "A list of DNS servers"; + } + leaf interface-mtu { + type uint32 { + range "0..65535"; + } + description "Minimum Transmission Unit (MTU) of the interface"; + } + leaf-list default-gateways{ + type inet:ip-address; + description "the list of default gateways on the O-RUs subnet"; + } + uses netconf-clients; + uses ca-ra-servers; + uses security-gateways; + uses event-collectors; + } + + grouping dhcpv6-option { + description "DHCPv6 Configuration options"; + + container dhcp-server-identifier{ + description "dhcpv6 server identifief"; + uses dhcpv6-type:duid; + } + leaf domain-name { + type string; + description "Name of the domain"; + } + leaf-list domain-name-servers { + type inet:ip-address; + description "A list of DNS servers"; + } + uses netconf-clients; + uses ca-ra-servers; + uses security-gateways; + uses event-collectors; + } + + grouping dhcp-group { + list interfaces { + key "interface"; + description "Interface configuration"; + + leaf interface { + type if:interface-ref; + description "Name of the interface"; + } + + container dhcpv4 { + description "DHCPv4 information"; + leaf client-id { + type string; + description "DHCP client identifier"; + } + uses dhcpv4-option; + } + container dhcpv6 { + description "DHCPv6 information"; + container dhcp-client-identifier{ + description "dhcpv6 client identifief"; + uses dhcpv6-type:duid; + } + uses dhcpv6-option; + } + } + + container m-plane-dhcp { + description "leafs covering off DHCP aspects of m-plane operations"; + leaf private-enterprise-number { + status deprecated; + type uint16; + default 53148; + description "the private enteprise number allocated to O-RAN Alliance"; + } + leaf private-enterprise-num { + type uint32; + default 53148; + description "the private enterprise number allocated to O-RAN Alliance"; + } + leaf vendor-class-data { + type string; + description + "The string used in DHCPv4 option 60 or DHCPv4 option 124 and + DHCPv6 option 16"; + } + } + } + + + // Top Level Container + + container dhcp { + config false; + description + "DHCP client configuration"; + + uses dhcp-group; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ecpri-delay@2019-02-04.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ecpri-delay@2019-02-04.yang new file mode 100644 index 0000000..88f1678 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ecpri-delay@2019-02-04.yang @@ -0,0 +1,135 @@ +module o-ran-ecpri-delay { + yang-version 1.1; + namespace "urn:o-ran:message5:1.0"; + prefix "o-ran-msg5"; + + import o-ran-processing-element { + prefix "element"; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module is an optional module for supporting eCPRI message 5 handling + used for eCPRI based delay measurements. + + 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-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"; + } + +// groupings + + grouping msg5-group { + + container ru-compensation { + config false; + description + "leafs for ru timing compensation based on message 5 handling"; + leaf tcv2 { + type uint32; + units nanoseconds; + description + "a compensation value to account for expected delay from packet + receipt at R2 to timestamping in the O-RU"; + } + leaf tcv1 { + type uint32; + units nanoseconds; + description + "a compensation value to account for expected processing time from + timestamping in the O-RU until actual packet transmission at R3"; + } + } + + leaf enable-message5 { + type boolean; + default false; + description + "whether O-RU's eCPRI message 5 handling is enabled."; + } + + container message5-sessions { + description "session information for eCPRI message 5"; + + list session-parameters { + key "session-id"; + description "list of MSG5 session information"; + leaf session-id { + type uint32; + description "Session ID for MSG5 responder"; + } + leaf processing-element-name { + type leafref { + path "/element:processing-elements/element:ru-elements/element:name"; + } + description "the name of the processing element used for MSG5"; + } + container flow-state { + config false; + description "MSG5 flow state"; + leaf responses-transmitted { + type uint32; + description + "The total number of eCPRI mesage 5 response messages transmitted by + the O-RU."; + } + leaf requests-transmitted { + type uint32; + description + "The total number of eCPRI mesage 5 request messages transmitted by + the O-RU."; + } + leaf followups-transmitted { + type uint32; + description + "The total number of eCPRI mesage 5 follow up messages transmitted by + the O-RU."; + } + } + } + } + } + +// top level container + + container ecpri-delay-message { + description "top level tree covering off O-DU to O-RU msg5 delay measurement"; + + uses msg5-group; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ethernet-forwarding@2020-04-17.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ethernet-forwarding@2020-04-17.yang new file mode 100644 index 0000000..8c67b63 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ethernet-forwarding@2020-04-17.yang @@ -0,0 +1,126 @@ +module o-ran-ethernet-forwarding { + yang-version 1.1; + namespace "urn:o-ran:ethernet-fwd:1.0"; + prefix "o-ran-eft"; + + import ietf-yang-types { + prefix "yang"; + } + + import o-ran-interfaces { + prefix "or-if"; + } + + import ietf-interfaces { + prefix "if"; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the Ethernet forwarding table of an O-RU. + This is an option capability used when supporting 'shared cell' operation. + + Copyright 2020 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 "2020-04-17" { + description + "version 3.0.0 + + 1. Initial version"; + + reference "ORAN-WG4.M.0-v03.00"; + } + + grouping ethernet-ft { + description + "Ethernet forwarding table."; + + leaf aging-time { + type uint32 { + range "10..10000000"; + } + units "seconds"; + default "300"; + description + "The timeout period in seconds for aging out + dynamically-learned forwarding information."; + } + + list filtering-entry { + key "address vlan-id"; + config false; + description + "List of the entries within the Ethernet forwarding table. + This list is keyed by the MAC address and VLAN of the Ethernet frame."; + + leaf address { + type yang:mac-address; + description + "A MAC address (unicast, multicast, broadcast) for + which the device has forwarding and/or filtering + information."; + } + + leaf vlan-id { + type uint16 { + range "0..4094"; + } + description + "VLAN-ID entry in the forwarding table, used during the + look-up when receiving an in-coming Ethernet frame to determine + how to forward. + + A value of 0 indicates that the filtering entry is for an un-tagged + frame/MAC address"; + } + + list port-map { + key "port-ref"; + description + "The list of entries composing the port map."; + leaf port-ref { + type leafref { + path "/if:interfaces/if:interface/or-if:port-reference/or-if:port-number"; + } + description + "The interface port reference associated with this map."; + } + } + } + } + + container ethernet-forwarding-table { + description "Top level container defining forwarding tables for Ethernet"; + + uses ethernet-ft; + } + +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-externalio@2019-07-03.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-externalio@2019-07-03.yang new file mode 100644 index 0000000..8779f71 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-externalio@2019-07-03.yang @@ -0,0 +1,183 @@ +module o-ran-externalio { + yang-version 1.1; + namespace "urn:o-ran:external-io:1.0"; + prefix "o-ran-io"; + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the input state and output configuration for + external IO. + + 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 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 external-io-group { + list input { + key "name"; + config false; + description + "Leaf nodes describing external line inputs"; + leaf name { + type string { + length "1..255"; + } + description + "A unique name that identifies an input port instance. + This name may be used in fault management to refer to a fault source + or affected object"; + } + leaf port-in { + type uint8; + description + "A number which identifies an external input port."; + } + + leaf line-in { + type boolean; + default true; + description + "Value TRUE indicates that circuit is open. + Value FALSE indicates that circuit is closed. + + Usually when nothing is connected to the line the value is TRUE. + The details of external line-in implementation are HW specific."; + } + } + + list output { + key "name"; + config false; + description + "Leaf nodes describing external line outputs"; + leaf name { + type string { + length "1..255"; + } + description + "A name that is unique that identifies an output port instance. + This name may be used in fault management to refer to a fault source + or affected object"; + } + leaf port-out { + type uint8; + mandatory true; + description + "A number which identifies an external output port."; + } + } + + list output-setting { + key "name"; + + description + "List allowing to set output line state"; + + leaf name { + type leafref { + path "/external-io/output/name"; + require-instance false; + } + mandatory true; + + description + "Name derived from unmodifiable list external-io"; + } + + leaf line-out { + type boolean; + default true; + description + "Value TRUE indicates that circuit is in its natural state. + Value FALSE indicates that circuit is not in its natural state."; + } + } + } + + grouping notification-group { + container current-input-notification { + description "a container for the state of the input ports"; + list external-input { + key "name"; + description "a list of the input ports and their state"; + leaf name{ + type leafref{ + path "/external-io/input/name"; + } + description "the name of the ald-port"; + } + leaf io-port { + type leafref{ + path "/external-io/input/port-in"; + } + description "the external input port"; + } + leaf line-in { + type leafref{ + path "/external-io/input/line-in"; + } + description "the state of the external input port"; + } + } + } + } + +// Top Level Container + + container external-io { + description + "External IO information."; + uses external-io-group; + } + + notification external-input-change { + description + "Notification used to indicate that external line input has changed state"; + uses notification-group; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-fan@2019-07-03.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-fan@2019-07-03.yang new file mode 100644 index 0000000..79fb588 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-fan@2019-07-03.yang @@ -0,0 +1,125 @@ +module o-ran-fan { + yang-version 1.1; + namespace "urn:o-ran:fan:1.0"; + prefix "o-ran-fan"; + + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the state of the O-RAN equipment's fans. + + 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 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"; + } + + typedef percent { + type uint16 { + range "0 .. 100"; + } + description "Percentage"; + } + + grouping fan-grouping { + list fan-state { + key name; + description "a list of the fans based on their unique names"; + leaf name { + type string { + length "1..255"; + } + description + "A name that is unique that identifies a fan instance. + This name may be used in fault management to refer to a fault source + or affected object"; + } + leaf fan-location { + type uint8; + description "A number indicating the location of the FAN in the fan tray"; + } + leaf present-and-operating { + type boolean; + mandatory true; + description + "Indicates if a fan is present and operating in the location"; + } + leaf vendor-code { + when "../present-and-operating = 'true'"; + type uint8 { + range "0..7"; + } + description + "Indicates fan vendor code. Fan vendors are detected with ID pins + using 3 bits digital inputs. + + Optional node included when the NETCONF Server has determined + the fan vendor code."; + } + leaf fan-speed { + when "../present-and-operating = 'true'"; + type percent; + description + "Measured fan speed. Expressed as percentage of max fan speed. + + Optional node included when the fan speed can be measured."; + } + leaf target-speed { + when "../present-and-operating = 'true'"; + type uint16; + units rpm; + description "the target speed of the fan"; + } + } + } + + container fan-tray { + config false; + description "top level tree covering off operational state of the fans"; + + uses fan-grouping; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-file-management@2019-07-03.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-file-management@2019-07-03.yang new file mode 100644 index 0000000..ee07645 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-file-management@2019-07-03.yang @@ -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://@[: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 ""; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-fm@2019-02-04.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-fm@2019-02-04.yang new file mode 100644 index 0000000..5142418 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-fm@2019-02-04.yang @@ -0,0 +1,166 @@ +module o-ran-fm { + yang-version 1.1; + namespace "urn:o-ran:fm:1.0"; + prefix "o-ran-fm"; + + import ietf-yang-types { + prefix yang; + revision-date 2013-07-15; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines alarm reporting mechanism. + + 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-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 alarm { + description + "Gropuping which can uniquely identify alarm"; + + leaf fault-id { + type uint16; + mandatory true; + + description + "Fault specific Id that identifies the fault."; + } + + leaf fault-source { + type string { + length "1..255"; + } + mandatory true; + + description + "Represents the Object or source that is suspected to be faulty."; + } + + list affected-objects { + leaf name { + type string { + length "1..255"; + } + mandatory true; + + description + "Represents the Object or source that is suspected to be affected by this fault"; + } + min-elements 1; + max-elements 100; + + description + "List of affected-objects"; + } + + leaf fault-severity { + type enumeration { + enum CRITICAL { + description + "Critical alarm means that this device is not able to perform any further service"; + } + enum MAJOR { + description + "Major alarm appeared on the device"; + } + enum MINOR { + description + "Minor alarm appeared on the device"; + } + enum WARNING { + description + "Warning is being reported by the device"; + } + } + mandatory true; + + description + "Fault severity defines the severity level of the fault. A notification, whose fault severity has the value 'warning', + is a special type of an alarm notification. For these alarm notifications, + the Master Agent does not expect to receive a clear alarm notification."; + } + + leaf is-cleared { + type boolean; + mandatory true; + + description + "Fault state determines the type of the event. Not used if faultSeverity is WARNING."; + } + + leaf fault-text { + type string { + length "0..255"; + } + + description + "Textual description of the fault."; + } + + leaf event-time { + type yang:date-and-time; + mandatory true; + + description + "Timestamp to indicate the time when the fault is detected/cleared."; + } + } + + container active-alarm-list { + list active-alarms { + uses alarm; + + description + "List of currenty active alarms"; + } + config false; + + description + "List of currently active alarms. An alarm is removed from this table when the state transitions to clear."; + } + + notification alarm-notif { + uses alarm; + + description + "Notification sent on initial alarm creation, as well as any time the alarm changes state, including clear"; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-hardware@2020-12-10.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-hardware@2020-12-10.yang new file mode 100644 index 0000000..f62a405 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-hardware@2020-12-10.yang @@ -0,0 +1,330 @@ +module o-ran-hardware { + yang-version 1.1; + namespace "urn:o-ran:hardware:1.0"; + prefix "o-ran-hw"; + + import ietf-hardware { + prefix hw; + } + import iana-hardware { + prefix ianahw; + } + import ietf-yang-types { + prefix yang; + } + import o-ran-wg4-features { + prefix or-feat; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the YANG definitions for managng the O-RAN hardware. + + Copyright 2020 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 "2020-12-10" { + description + "version 5.0.0 + + 1) added date-last-service leaf used in pnfRegistration"; + + reference "ORAN-WG4.O1.0-v05.00"; +//update reference + } + + revision "2020-04-17" { + description + "version 3.0.0 + + 1) added new leaf to indicate whether O-RU supports dying gasp + 2) added new identities for PA and FPGA"; + + reference "ORAN-WG4.M.0-v03.00"; + } + + revision "2019-07-03" { + description + "version 1.1.0 + + 1) added new identities to accommodate cross working group use of + o-ran-hardware and assoicated set of augmentations that are backwards + compatible to version 1.0.0"; + + 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"; + } + + feature ENERGYSAVING { + description + "Indicates that the Radio Unit supports energy saving state."; + } + + // identity statements + identity O-RAN-RADIO { + base ianahw:module; + description + "Module used as it represents a self-contained sub-system + used in /hw:/hardware/hw:component/hw:class to represent + an O-RAN RU"; + } + + identity O-RAN-HW-COMPONENT { + base ianahw:module; + description + "Module used as it represents a self-contained sub-system + used in /hw:/hardware/hw:component/hw:class to represent + any O-RAN hardware component"; + } + + identity O-DU-COMPONENT { + base O-RAN-HW-COMPONENT; + description + "Used in /hw:/hardware/hw:component/hw:class to represent + any O-RAN defined O-DU hardware component"; + } + + identity O-RU-COMPONENT { + base O-RAN-HW-COMPONENT; + description + "Used in /hw:/hardware/hw:component/hw:class to represent + any O-RAN defined O-RU hardware component, including a stand-alone + O-RU or an O-RU component integrated into a multi-module system."; + } + + identity O-RU-POWER-AMPLIFIER { + base O-RU-COMPONENT; + description + "Used in /hw:/hardware/hw:component/hw:class to represent + an O-RU's power amplifier, and may be used for reporting + measurements on a per class basis"; + } + + identity O-RU-FPGA { + base O-RU-COMPONENT; + description + "Used in /hw:/hardware/hw:component/hw:class to represent + an FPGA in an O-RU, and may be used for reporting + measurements on a per class basis"; + } + + // typedef statements + typedef energysaving-state { + type enumeration { + enum UNKNOWN { + description "The Radio Unit is unable to report energy saving state."; + } + enum SLEEPING { + description + "The Radio Unit is in a sleep state. The NETCONF management plane + connection is functioning. Other functions and hardware which are + not needed for management plane may be in energy saving mode."; + } + enum AWAKE { + description + "The Radio Unit is not in an energy saving state."; + } + } + description + "new typedef since ietf-hardware only covers pwer-state + for redundancy purposes and not power saving operations."; + } + + typedef availability-type { + type enumeration { + enum UNKNOWN { + description "The Radio Unit is unable to report its availability state."; + } + enum NORMAL { + description + "The equipment is functioning correctly."; + } + enum DEGRADED { + description + "The equipment may be reporting a major alarm or may be reporting a critical + alarm that is only impacting one or more subcomponent, but where the + equipment's implementation permit it to continue operation (server traffic) + in a degraded state. + + Used for example, when the equipment has M identical sub-components and + when a critical alarm is imapcting only N subcomponents, where N@[:]/path"; + } + + uses o-ran-fm:credential-information; + } + +// transceiver measurements applicable to all O-RAN HW functions + + leaf transceiver-measurement-interval { + type uint16; + units seconds; + description + "measurement interval to measure the performance of transceiver + measurement objects periodically."; + } + +// EPE measurements applicable to all O-RAN HW functions + + leaf epe-measurement-interval { + type uint16; + units seconds; + description + "measurement interval to measure the energy, power and environmental + measurement objects periodically."; + } + +// RX Window measurements applicable to O-RAN WG4 defined functions + + leaf rx-window-measurement-interval { + type uint16; + units seconds; + description + "measurement interval to measure the performance of reception + window measurement objects periodically."; + } + + leaf tx-measurement-interval { + type uint16; + units seconds; + description + "measurement interval to measure the tx (outbound) + window measurement objects periodically."; + } + + leaf notification-interval { + type uint16; + units seconds; + description + "notification interval for the measurement result to be notified + periodically."; + } + + leaf file-upload-interval { + type uint16; + units seconds; + description + "file upload interval for the measurement result file to be + uploaded periodically."; + } + + leaf max-bin-count{ + type uint16; + config false; + mandatory true; + description + "indicates the maximum value of configurable bin-count for frequency + table in transceiver-measurement-objects as one of module + capabilities."; + } + + list transceiver-measurement-objects { + key "measurement-object"; + description + "optional list used to report transceiver measurements + applicable to any O-RAN defined hardware function"; + leaf measurement-object { + type enumeration { + enum RX_POWER { + description + "Measured Rx input power in mW for SFP or lane 1 of QSFP"; + } + enum RX_POWER_LANE_2 { + description + "Measured Rx input power in mW for lane 2 of QSFP"; + } + enum RX_POWER_LANE_3 { + description + "Measured Rx input power in mW for lane 3 of QSFP"; + } + enum RX_POWER_LANE_4 { + description + "Measured Rx input power in mW for lane 4 of QSFP"; + } + enum TX_POPWER { + status deprecated; + description + "Measured Tx input power in mW."; + } + enum TX_POWER { + description + "Measured Tx input power in mW."; + } + enum TX_POWER_LANE_2 { + description + "Measured Tx input power in mW for lane 2 of QSFP"; + } + enum TX_POWER_LANE_3 { + description + "Measured Tx input power in mW for lane 3 of QSFP"; + } + enum TX_POWER_LANE_4 { + description + "Measured Tx input power in mW for lane 4 of QSFP"; + } + enum TX_BIAS_COUNT { + description + "Internally measured Tx Bias Current in mA for SFP or lane 1 of QSFP"; + } + enum TX_BIAS_COUNT_LANE_2 { + description + "Internally measured Tx Bias Current in mA for lane 2 of QSFP"; + } + enum TX_BIAS_COUNT_LANE_3 { + description + "Internally measured Tx Bias Current in mA for lane 3 of QSFP"; + } + enum TX_BIAS_COUNT_LANE_4 { + description + "Internally measured Tx Bias Current in mA for lane 4 of QSFP"; + } + enum VOLTAGE { + description + "Internally measured transceiver supply voltage in mV"; + } + enum TEMPERATURE { + description + "Internally measured optional laser temperature in degrees Celsius."; + } + } + description "Target metric to measure the performance"; + } + + leaf active { + type boolean; + default false; + description + "Enable/disable the performance measurement per Object"; + } + + leaf-list report-info { + type enumeration { + enum MAXIMUM { + description + "to report maximum value and its recorded time within the + measurement-interval for the measurement-object."; + } + enum MINIMUM { + description + "to report minimum value and its recorded time within the + measurement-interval for the measurement-object."; + } + enum FIRST { + description + "to report first value and its recorded time within the + measurement-interval for the measurement-object."; + } + enum LATEST { + description + "to report latest value and its recorded time within the + measurement-interval for the measurement-object."; + } + enum FREQUENCY_TABLE { + description + "to report frequency bin table within the + measurement-interval for the measurement-object."; + } + } + description "The reporting info to the measurement object."; + } + + leaf object-unit { + type enumeration { + enum PORT_NUMBER { + description + "unit to measure the performance per object-id"; + } + } + mandatory true; + description "unit to measure the performance per object-id."; + } + + leaf function { + type enumeration { + enum RAW { + description + "the value is expressed by real value."; + } + enum LOG_10 { + description + "the value is expressed by logarithm with base 10."; + } + } + + description + "the value to be recorded for transceiver-measurement + by real value or log 10."; + } + + leaf bin-count { + type uint16; + + description + "the number of bin for the frequency table. + This value shall be less than max-bin-count"; + } + + leaf lower-bound { + type decimal64 { + fraction-digits 4; + } + + description + "the lower value of the first bin of frequency table."; + } + + leaf upper-bound { + type decimal64 { + fraction-digits 4; + } + + description + "the upper value of the last bin of frequency table."; + } + uses transceiver-measurement-result-grouping; +// configuration and measurement result for the transceiver-measurement + + } + + list rx-window-measurement-objects { + key "measurement-object"; + description + "optional list used to report RX Window measurements + applicable to O-RAN WG4 define O-RU functions"; + leaf measurement-object { + type enumeration { + enum RX_ON_TIME { + description + "the number of data packets, received on time within + the reception window."; + } + enum RX_EARLY { + description + "the number of data packets, received before + the reception window."; + } + enum RX_LATE { + description + "the number of data packets, received after + the reception window."; + } + enum RX_CORRUPT { + description + "the number of data packets, which are corrupt or whose header + is incorrect."; + } + enum RX_DUPL { + status deprecated; + description + "the number of data packets, which is duplicated with other packets, + received within the measurement period."; + } + enum RX_TOTAL { + description + "the total number of received packets (data and control) within the measurement period."; + } + enum RX_ON_TIME_C { + description + "the number of control packets, received on time within + the reception window."; + } + enum RX_EARLY_C { + description + "the number of control packets, received before + the reception window."; + } + enum RX_LATE_C { + description + "the number of control packets, received after + the reception window."; + } + enum RX_SEQID_ERR { + description + "the number of data packets, received with an erroneous sequence ID."; + } + enum RX_SEQID_ERR_C { + description + "the number of control packets, received with an erroneous sequence ID."; + } + enum RX_ERR_DROP { + description + "The total number of inbound messages which are discarded by the receiving + O-RAN entity for any reason."; + } + } + description + "target reception window metric to measure the performance."; + } + + leaf active { + type boolean; + default false; + description + "Enable/disable the performance measurement per reception window + measurement object."; + } + + leaf object-unit { + type enumeration { + enum RU { + description + "the reception window stats are counted per hardware component. + This may be the parent 'module' or child 'port' component."; + } + enum TRANSPORT { + if-feature GRANULARITY-TRANSPORT-MEASUREMENT; + description + "the reception window stats are counted per transport flow. + When there are multiple transport flows between O-DU and O-RU, + e.g. multiple sets of o-du mac address, ru mac address and + vlan-id, the reception window stats per transport flow + are counted in this case. + This configuration is allowed only when O-RU supports + a feature GRANULARITY-TRANSPORT-MEASUREMENT."; + } + enum EAXC_ID { + if-feature GRANULARITY-EAXC-ID-MEASUREMENT; + + description + "the reception window stats are counted per eAxC ID, which is + used in the header of receivd data packet. + This configuration is allowed only when O-RU supports + a feature GRANULARITY-EAXC-ID-MEASUREMENT."; + } + } + description + "unit to measure the performance per object-id."; + } + + leaf report-info { + type enumeration { + enum COUNT { + description + "the number of data packet are counted for the reception + window stats."; + } + } + description + "The reporting info to the measurement object."; + } + + uses rx-window-measurement-result-grouping; +// configuration and measurement result for the reception window stats + + } + + + list tx-measurement-objects { + key "measurement-object"; + description + "optional list used to report TX measurements + applicable to O-RAN WG4 define O-RU functions"; + leaf measurement-object { + type enumeration { + enum TX_TOTAL { + description + "the number of outbound packets (data and control), transmitted within + the measurement period"; + } + enum TX_TOTAL_C { + description + "the number of outbound control packets, transmitted within + the measurement period. + This counter is required only if RU supports LAA/LBT capabilities."; + } + } + description + "CU-plane transmission counters"; + } + + leaf active { + type boolean; + default false; + description + "Enable/disable the measurement per measurement object."; + } + + leaf object-unit { + type enumeration { + enum RU { + description + "the transmission stats are counted per hardware component. + This may be the parent 'module' or child 'port' component."; + } + enum TRANSPORT { + if-feature GRANULARITY-TRANSPORT-MEASUREMENT; + description + "the transmission stats are counted per transport flow. + When there are multiple transport flows between O-DU and O-RU, + e.g. multiple sets of o-du mac address, ru mac address and + vlan-id, the transmission stats per transport flow + are counted in this case. + This configuration is allowed only when O-RU supports + a feature GRANULARITY-TRANSPORT-MEASUREMENT."; + } + enum EAXC_ID { + if-feature GRANULARITY-EAXC-ID-MEASUREMENT; + + description + "the transmission stats are counted per eAxC ID, which is + used in the header of receivd data packet. + This configuration is allowed only when O-RU supports + a feature GRANULARITY-EAXC-ID-MEASUREMENT."; + } + } + description + "unit to measure the performance per object-id."; + } + + leaf report-info { + type enumeration { + enum COUNT { + description + "the number of data packet are counted for the reception + window stats."; + } + } + description + "The reporting info to the measurement object."; + } + + uses tx-measurement-result-grouping; + // configuration and measurement result for the tx stats + + } + + list epe-measurement-objects { + key "measurement-object"; + description + "optional list used to report energy, power and environmental + measurements applicable to any O-RAN defined hardware function"; + leaf measurement-object { + type enumeration { + enum TEMPERATURE { + description + "Measured temperature in degrees celcius"; + } + enum POWER { + description + "Measured power consumed, in watts (W)"; + } + } + description "Target metric to measure the performance"; + } + + leaf active { + type boolean; + default false; + description + "Enable/disable the performance measurement per Object"; + } + + leaf-list report-info { + type enumeration { + enum MAXIMUM { + description + "to report maximum value and its recorded time within the + measurement-interval for the measurement-object."; + } + enum MINIMUM { + description + "to report minimum value and its recorded time within the + measurement-interval for the measurement-object."; + } + enum AVERAGE { + description + "to report average value within the + measurement-interval for the measurement-object."; + } + } + description "The reporting info to the measurement object."; + } + + + uses epe-measurement-result-grouping; + // configuration and measurement result for the epe-measurement + + } + + + } + + grouping measurement-capabilities { + container measurement-capabilitites { + config false; + description "the type of measurement objects supported by the O-RU"; + + list transceiver-objects { + key measurement-object; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/transceiver-measurement-objects/measurement-object"; + } + } + } + list rx-window-objects { + key measurement-object; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/rx-window-measurement-objects/measurement-object"; + } + } + } + list tx-stats-objects { + key measurement-object; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/tx-measurement-objects/measurement-object"; + } + } + } + list epe-stats-objects { + key "measurement-object"; + description + "An optional list describing the energy, power and environmental measurements supported + by the O-RU. Measurements are defined per hardware component."; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/epe-measurement-objects/measurement-object"; + } + } + leaf-list component-class { + type identityref { + base ianahw:hardware-class; + } + description + "An indication of the general hardware type of the + component for which EPE measurements are supported."; + + } + } + } + } + + grouping measurement-notification { + + description + "notification may contain measurement result for transceiver-stats + and/or rx-window-stats and/or tx-stats and/or epe-stats"; + list transceiver-stats { + key "measurement-object"; + + description + "measurement result of transceiver-measurement per measurement-object"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/transceiver-measurement-objects/measurement-object"; + } + + description + "measurement-object for the transceiver-measurement"; + } + + uses start-and-end-time; + uses transceiver-measurement-result-grouping; + } + + list rx-window-stats { + key "measurement-object"; + + description + "measurement result for the reception window measurement per + measurement-object"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/rx-window-measurement-objects/measurement-object"; + } + + description + "measurement-object for the reception window measurement"; + } + uses start-and-end-time; + uses rx-window-measurement-result-grouping; + + } + + list tx-stats { + key "measurement-object"; + + description + "measurement result for the tx stats measurement per + measurement-object"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/tx-measurement-objects/measurement-object"; + } + + description + "measurement-object for the tx stats measurement"; + } + uses start-and-end-time; + uses tx-measurement-result-grouping; + + } + + container epe-stats { + description + "container for the epe stats measurement - deprecated because measurement object + isn't included"; + status deprecated; + + uses start-and-end-time; + uses epe-measurement-result-grouping; + + + } + + list epe-statistics { + key "measurement-object"; + + description + "measurement result for the epe stats measurement per + measurement-object"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/epe-measurement-objects/measurement-object"; + } + + description + "measurement-object for the epe stats measurement"; + } + uses start-and-end-time; + uses epe-measurement-result-grouping; + + } + } + + // Top level container + + container performance-measurement-objects { + description + "configuration for performance management and measurement-result are + included"; + uses measurement-group; + } + +// Notifications + + notification measurement-result-stats { + description + "Notification may contain measurement results for transceiver-stats + and/or rx-window-stats"; + uses measurement-notification; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-processing-element@2020-04-17.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-processing-element@2020-04-17.yang new file mode 100644 index 0000000..06dacbb --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-processing-element@2020-04-17.yang @@ -0,0 +1,360 @@ +module o-ran-processing-element { + yang-version 1.1; + namespace "urn:o-ran:processing-element:1.0"; + prefix "o-ran-elements"; + + import ietf-yang-types { + prefix yang; + } + + import ietf-inet-types { + prefix "inet"; + } + + import ietf-interfaces { + prefix "if"; + } + + import ietf-ip { + prefix "ip"; + } + + import o-ran-interfaces { + prefix "o-ran-int"; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the YANG definitions for mapping of transport flows to + processing elements. Three options are supported: + i) virtual MAC based mapping + ii) MAC addrress + VLAN-ID based mapping + iii) UDP/IP based mapping + + Copyright 2020 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 "2020-04-17" { + description + "version 3.0.0 + + 1) added new enum SHARED-CELL-ETH-INTERFACE in + transport-session-type and new containers north-eth-flow and + south-eth-flow to enable Shared cell scenario."; + + reference "ORAN-WG4.M.0-v03.00"; + } + + revision "2019-07-03" { + description + "version 1.1.0 + + 1) added new leaf to enable O-RU to report the maximum number of + transport flows it can support, e.g., due to restrictions on number + of VLAN-IDs when ethernet type transport is used."; + + 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"; + } + + feature SHARED_CELL { + description + "Presence of feature indicates that this O-RU is capable to support + shared cell."; + } +// groupings + + grouping pe-group { + leaf maximum-number-of-transport-flows { + type uint16 { + range "1..4094"; + } + config false; + default 4094; + description + "The maximum number of transport flows that can be supported by an O-RU"; + } + leaf transport-session-type { + type enumeration { + enum ETH-INTERFACE { + description "VLAN based CUS Transport "; + } + enum UDPIP-INTERFACE { + description "UDP/IP based CUS Transport "; + } + enum ALIASMAC-INTERFACE{ + description "Alias MAC address based CUS Transport "; + } + enum SHARED-CELL-ETH-INTERFACE { + if-feature "SHARED_CELL"; + description "VLAN based CUS Transport used for Shared Cell scenario"; + } + } + default ETH-INTERFACE; + description + "the type of transport session used for identifying different processing + elements"; + } + container enhanced-uplane-mapping { + presence "indicates that enhanced uplane mapping is used"; + description "a mapping table for enhanced user plane marking"; + list uplane-mapping { + key "up-marking-name"; + description + "a mapping between up-link name and o-ran-interfaces:up-marking-name"; + leaf up-marking-name { + type string; + description "a unique up marking name that is used for enhanced up marking"; + } + choice up-markings { + description + "U-Plane markings"; + case ethernet { + when "(../../transport-session-type = 'ALIASMAC-INTERFACE') or + (../../transport-session-type = 'ETH-INTERFACE') or + (../../transport-session-type = 'SHARED-CELL-ETH-INTERFACE')"; + leaf up-cos-name { + type leafref { + path "/if:interfaces/if:interface/o-ran-int:class-of-service/o-ran-int:enhanced-uplane-markings/o-ran-int:up-marking-name"; + } + description "the Ethernet U-plane transport marking as defined in o-ran-interfaces"; + } + } + case ipv4 { + when "(../../transport-session-type = 'UDPIP-INTERFACE')"; + leaf upv4-dscp-name { + type leafref { + path "/if:interfaces/if:interface/ip:ipv4/o-ran-int:diffserv-markings/o-ran-int:enhanced-uplane-markings/o-ran-int:up-marking-name"; + } + description "the IPv4 U-plane transport marking as defined in o-ran-interfaces"; + } + } + case ipv6 { + when "(../../transport-session-type = 'UDPIP-INTERFACE')"; + leaf upv6-dscp-name { + type leafref { + path "/if:interfaces/if:interface/ip:ipv6/o-ran-int:diffserv-markings/o-ran-int:enhanced-uplane-markings/o-ran-int:up-marking-name"; + } + description "the IPv6 U-plane transport marking as defined in o-ran-interfaces"; + } + } + } + } + } + list ru-elements { + key "name"; + description + "the list of transport definitions for each processing element"; + leaf name { + type string { + length "1..255"; + } + description + "A name that is unique across the O-RU that identifies a processing + element instance. + + This name may be used in fault management to refer to a fault source + or affected object"; + } + container transport-flow { + description + "container for the transport-flow used for CU plane"; + leaf interface-name { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + description "the interface name "; + } + container aliasmac-flow { + when "../../../transport-session-type = 'ALIASMAC-INTERFACE'"; + if-feature o-ran-int:ALIASMAC-BASED-CU-PLANE; + description "leafs for virtual mac type data flows"; + leaf ru-aliasmac-address { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:alias-macs"; + } + mandatory true; + description + "O-RU's alias MAC address used for alias MAC based flow"; + } + leaf vlan-id { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:vlan-id"; + } + description + "O-RU's VLAN-ID used for alias MAC based flow"; + } + leaf o-du-mac-address { + type yang:mac-address; + mandatory true; + description + "O-DU's MAC address used for alias MAC based flow"; + } + } + container eth-flow { + when "../../../transport-session-type = 'ETH-INTERFACE'"; + description "leafs for mac + vlan-id type data flows"; + leaf ru-mac-address { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:mac-address"; + } + mandatory true; + description + "O-RU's MAC address used for Ethernet based flow"; + } + leaf vlan-id { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:vlan-id"; + } + mandatory true; + description + "O-RU's VLAN-ID used for Ethernet based flow"; + } + leaf o-du-mac-address { + type yang:mac-address; + mandatory true; + description + "O-DU's MAC address used for Ethernet based flow"; + } + } + container udpip-flow { + when "../../../transport-session-type = 'UDPIP-INTERFACE'"; + description "leafs for UDP/IP type data flows"; + choice address { + leaf ru-ipv4-address { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/ip:ipv4/ip:address/ip:ip"; + } + description "O-RU's IPv4 address"; + } + leaf ru-ipv6-address { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/ip:ipv6/ip:address/ip:ip"; + } + description "O-RU's IPv6 address"; + } + mandatory true; + description "choice of O-RU IPv4 or IPv6 address"; + } + leaf o-du-ip-address { + type inet:ip-address; + mandatory true; + description "O-DU's IPv address"; + } + leaf ru-ephemeral-udp-port { + type inet:port-number; + mandatory true; + description + "ephemeral port used by O-RU"; + } + leaf o-du-ephemeral-udp-port { + type inet:port-number; + mandatory true; + description + "ephemeral port used by O-DU"; + } + leaf ecpri-destination-udp { + type inet:port-number; + mandatory true; + description "the well known UDP port number used by eCPRI"; + // fixme - add in a default when allocated by IANA + } + } + container north-eth-flow { + when "../../../transport-session-type = 'SHARED-CELL-ETH-INTERFACE'"; + if-feature "SHARED_CELL"; + description "leafs for mac + vlan-id type data flows"; + leaf ru-mac-address { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:mac-address"; + } + description + "O-RU's MAC address used for Ethernet based flow"; + } + leaf vlan-id { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:vlan-id"; + } + description + "O-RU's VLAN-ID used for Ethernet based flow"; + } + leaf north-node-mac-address { + type yang:mac-address; + description + "North-node's MAC address used for Ethernet based flow"; + } + } + container south-eth-flow { + when "../../../transport-session-type = 'SHARED-CELL-ETH-INTERFACE'"; + if-feature "SHARED_CELL"; + description "leafs for mac + vlan-id type data flows"; + leaf ru-mac-address { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:mac-address"; + } + description + "O-RU's MAC address used for Ethernet based flow"; + } + leaf vlan-id { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:vlan-id"; + } + description + "O-RU's VLAN-ID used for Ethernet based flow"; + } + leaf south-node-mac-address { + type yang:mac-address; + description + "south-node's MAC address used for Ethernet based flow"; + } + } + } + } + } + +// top level container + + container processing-elements { + description + "a model defining the mapping between transport flows and arbitrary + O-RAN processing elements. A processing element may be then defined for + handling connectivity or delay procedures, or defined with a corresponding + eaxcid for CU plane operations"; + uses pe-group; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-shared-cell@2020-12-10.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-shared-cell@2020-12-10.yang new file mode 100644 index 0000000..3c4d2a4 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-shared-cell@2020-12-10.yang @@ -0,0 +1,564 @@ +module o-ran-shared-cell { + yang-version 1.1; + namespace "urn:o-ran:shared-cell:1.0"; + prefix "o-ran-sc"; + + import o-ran-compression-factors { + prefix "cf"; + } + import o-ran-processing-element { + prefix "o-ran-pe"; + revision-date 2020-04-17; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the YANG definitions for shared cell capable O-RU (Cascade and FHM). + + Copyright 2020 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 "2020-12-10" { + description + "version 5.0.0 + + 1) added selective combining using beamId."; + + reference "ORAN-WG4.M.0-v05.00"; + } + + revision "2020-04-17" { + description + "version 3.0.0 + + 1) initial version for shared cell O-RU related yang module."; + + reference "ORAN-WG4.M.0-v03.00"; + } + + feature FHM { + description + "Presence of feature indicates that O-RU acts as FHM and doesn't have + the capability of radio transmission and reception. Absence of feature + indicates that O-RU does not act as FHM and supports radio transmission + and reception function."; + } + + feature SELECTIVE-BEAM-ID { + description + "Presence of feature indicates that FHM supports the selective combining + function by using beamId"; + } + + // radio offsets + grouping radio-offset { + description + "shared cell FHM mode needs the configuration for radio related offset"; + leaf downlink-radio-frame-offset { + type uint32 { + range 0..12288000; + } + mandatory true; + + description + "This parameter is used for offsetting the starting position of + 10ms radio frame. + Note: Unit is 1/1.2288e9 sec."; + } + + leaf downlink-sfn-offset { + type int16 { + range -32768..32767; + } + mandatory true; + + description + "This parameter is used for offsetting SFN value. + Unit is 10ms."; + } + } + + // shared cell capability + grouping shared-cell-module-capability{ + description + "shared cell related module capability of O-RU"; + container shared-cell-module-cap { + config false; + description + "indicates shared cell specific module capability"; + + leaf t-copy { + type uint32; + units nanoseconds; + mandatory true; + description + "Corresponding to the maximum FHM or cascade O-RU processing delay + between receiving an IQ sample over the fronthaul interface from + the north-node, coping it and transmitting it over the fronthaul + interface to the south-node."; + } + + leaf t-combine { + type uint32; + units nanoseconds; + mandatory true; + description + "Corresponding to the maximum FHM or cascade O-RU processing delay + between receiving an IQ sample over the fronthaul interface from + the south-node(s), combing them and transmitting it over the + fronthaul interface to the north-node."; + } + + leaf ta3-prime-max-upper-range { + type uint32; + units nanoseconds; + mandatory true; + description + "The upper limit for the configurable ta3-prime-max value. + This is the capability information of O-RU that comes from + the O-RU internal memory for the combine operation."; + } + + leaf max-number-node-copy-and-combine { + type uint8{ + range "1..max"; + } + mandatory true; + description + "Indicates the maximum number of south-node for the copy-and-combine + functions of cascade O-RU or FHM. + For cascade mode, this value is one. It means + O-RU copies the stream of eCPRI messages only once for the connected + south-node and copied stream are forwarded to the south-node. + Similarly, the cascade O-RU combines once for the streams of + eCPRI messages received from the south node and the streams of radio + reception function. + For FHM mode, FHM is able to copy the stream of eCPRI messages + according to this parameter and forward each copied stream + to each south-node. FHM is able to combine the streams of eCPRI + messages received from the multiple south-nodes corresponding to + this parameter at most."; + } + + leaf max-number-eaxcid-copy { + type uint8{ + range "1..max"; + } + mandatory true; + description + "Indicates the maximum number of eaxc-ids for the copy functions + of cascade O-RU or FHM. + For Cascade, it is same number of static-low-level-tx-endpoints plus + static-low-level-rx-endpoints, for which low-level-tx(rx)-endpoints + are configured with eaxc-id in u-plane configuration. + For FHM, it is max configurable number of eaxc-ids in + tx-eaxc-id and rx-eaxc-id in shared-cell-copy-uplane-config."; + } + + leaf max-number-eaxcid-combine { + type uint8{ + range "1..max"; + } + mandatory true; + description + "Indicates the maximum number of eaxc-ids for the combine functions + of cascade O-RU or FHM. + For Cascade, it is same number of static-low-level-rx-endpoints, + for which low-level-rx-endpoints are configured with eaxc-id in + u-plane configuration. + For FHM, it is max configurable number of eaxc-ids in rx-eaxc-id + in shared-cell-combine-uplane-config."; + } + + list compression-method-supported { + if-feature FHM; + description + "List of supported compression methods for FHM"; + uses cf:compression-details; + } + } + } + + // shared cell mode configuration + grouping shared-cell-mode{ + description + "A grouping defining the schema nodes for shared cell configuration"; + choice shared-cell-copy-combine-mode { + case COMMON { + description + "all eCPRI payload are the target for copy and combine functions. + Common set of eaxc-ids are used in O-RU in the shared cell network. + For cascade mode, eaxc-ids of low-level-tx(rx)-links in + o-ran-uplane-configuration that has relation to the + processing-element are used. + For FHM mode, eaxc-ids of shared-cell-copy-uplane-config and + those of shared-cell-combine-config are used."; + + uses shared-cell-copy-configuration; + uses shared-cell-combine-configuration; + } + case SELECTIVE-BEAM-ID { + if-feature "FHM and SELECTIVE-BEAM-ID"; + description + "Case that FHM has selective transmission and reception fucntion + by using beamId"; + + uses shared-cell-copy-configuration-for-selective-beam-id; + uses shared-cell-combine-configuration-for-selective-beam-id; + } + case SELECTIVE { + description "for future use"; + } + description + "configuration mode can be selected."; + } + } + + // processing elements set + grouping processing-element-set{ + description + "shared-cell-copy/combine-configuration refers the pair of processing + element set of a north-node and a south-node."; + + leaf north-node-processing-element{ + type leafref { + path "/o-ran-pe:processing-elements/o-ran-pe:ru-elements/o-ran-pe:name"; + } + description + "north-node processing element indicates the set of + 'north-node-mac-address', 'ru-mac-address' and 'vlan-id' in case + north-eth-flow is selected for the transport flow."; + } + + leaf-list south-node-processing-elements{ + type leafref { + path "/o-ran-pe:processing-elements/o-ran-pe:ru-elements/o-ran-pe:name"; + } + description + "south-node processing elements indicate the sets of + 'south-node-mac-address', 'ru-mac-address' and 'vlan-id' in case + south-eth-flow is selected for the transport flow."; + } + } // processing-element-set + + // processing elements set for SELECTIVE-BEAM-ID + grouping processing-element-set-for-selective-beam-id{ + description + "shared-cell-copy/combine-configuration refers the pair of processing + element set of a north-node and a south-node."; + + leaf north-node-processing-element{ + type leafref { + path "/o-ran-pe:processing-elements/o-ran-pe:ru-elements/o-ran-pe:name"; + } + description + "north-node processing element indicates the set of + 'north-node-mac-address', 'ru-mac-address' and 'vlan-id' in case + north-eth-flow is selected for the transport flow."; + } + + leaf-list south-node-processing-elements{ + type leafref { + path "/o-ran-pe:processing-elements/o-ran-pe:ru-elements/o-ran-pe:name"; + } + description + "south-node processing elements indicate the sets of + 'south-node-mac-address', 'ru-mac-address' and 'vlan-id' in case + south-eth-flow is selected for the transport flow."; + } + + list mapping-table-for-selective-beam-id { + key "global-beam-id south-node-processing-elements"; + description "the mapping information between global-beam-id and local-beam-id"; + + leaf global-beam-id{ + type uint16; + description + "This parameter indicates the beam ID to be applied to the U-Plane data + on O-DU as same as existing beamId. One global beamId can be mapped + to one or multiple local beamId. + The mapping information between each global beamId, O-RU(s), + and local beamId is configured to the FHM during M-Plane start-up procedure."; + } + leaf south-node-processing-elements { + type leafref { + path "/o-ran-pe:processing-elements/o-ran-pe:ru-elements/o-ran-pe:name"; + } + description + "south-node processing elements indicate the sets of + 'south-node-mac-address', 'ru-mac-address' and 'vlan-id' in case + south-eth-flow is selected for the transport flow."; + } + leaf local-beam-id { + type uint16; + description "This parameter indicates the beam ID to be applied to + the U-Plane data on O-RU as same as existing beamId. + In one O-RU, different beams can not map to one global beamId. + Local beamId shall be unique within O-RU."; + } + } + } // processing-element-set for SELECTIVE-BEAM-ID + + // shared cell copy and combine config + grouping shared-cell-copy-configuration{ + description + "shared-cell-copy-configuration"; + list shared-cell-copy-entities{ + key name; + description + "copy entity. The north-node is an O-DU or an O-RU. + The south-nodes are O-RUs. + The number of south-nodes is at most one for cascade O-RU and + more than one for FHM"; + + leaf name{ + type string; + description + "the name of shared-cell-copy-entity."; + } + + uses processing-element-set; + + container shared-cell-copy-uplane-config { + if-feature FHM; + description + "Container consists of uplane-info for copy-configuration for FHM."; + + list tx-eaxc-id { + key eaxc-id; + description + "used for low-level-tx-endpoints to copy"; + + leaf eaxc-id { + type uint16; + description + "encoded value of eaxcid to be read by CU-Plane"; + } + } + list rx-eaxc-id { + key eaxc-id; + description + "used for low-level-rx-endpoints to copy"; + + leaf eaxc-id { + type uint16; + description + "encoded value of eaxcid to be read by CU-Plane"; + } + } + uses radio-offset; + } + + } // shared-cell-copy-entities + } // shared-cell-copy-configuration (groupings) + + grouping shared-cell-copy-configuration-for-selective-beam-id{ + description + "shared-cell-copy-configuration for selective function by beam id"; + list shared-cell-copy-entities-selective-beam-id{ + key name; + description + "copy entity. The north-node is an O-DU or an O-RU. + The south-nodes are O-RUs. + The number of south-nodes is at most one for cascade O-RU and + more than one for FHM"; + + leaf name{ + type string; + description + "the name of shared-cell-copy-entity."; + } + + uses processing-element-set-for-selective-beam-id; + + container shared-cell-copy-uplane-config { + if-feature FHM; + description + "Container consists of uplane-info for copy-configuration for FHM."; + + list tx-eaxc-id { + key eaxc-id; + description + "used for low-level-tx-endpoints to copy"; + + leaf eaxc-id { + type uint16; + description + "encoded value of eaxcid to be read by CU-Plane"; + } + } + list rx-eaxc-id { + key eaxc-id; + description + "used for low-level-rx-endpoints to copy"; + + leaf eaxc-id { + type uint16; + description + "encoded value of eaxcid to be read by CU-Plane"; + } + } + uses radio-offset; + } + + } // shared-cell-copy-entities for SELECTIVE-BEAM-ID + } // shared-cell-copy-configuration (groupings) for SELECTIVE-BEAM-ID + + grouping shared-cell-combine-configuration{ + description + "shared-cell-combine-configuration"; + + list shared-cell-combine-entities{ + key name; + description + "combine configuration. The north-node is O-DU or O-RU. + The south-nodes are O-RUs. + The number of south-nodes is at most one for cascade O-RU and + more than one for FHM"; + + leaf name{ + type string; + description + "name of shared-cell-combine-entity"; + } + + uses processing-element-set; + + leaf ta3-prime-max { + type uint32; + units nanoseconds; + description + "indicates the latest time that FHM or cascade O-RU is allowed to + send UL U-plane message to north-node relative to reception + timing at O-RU antenna."; + } + + uses shared-cell-combine-uplane-config; + } + } + + grouping shared-cell-combine-configuration-for-selective-beam-id{ + description + "shared-cell-combine-configuration for selective function by beam id"; + + list shared-cell-combine-entities-for-selective-beam-id{ + key name; + description + "combine configuration. The north-node is O-DU or O-RU. + The south-nodes are O-RUs. + The number of south-nodes is at most one for cascade O-RU and + more than one for FHM"; + + leaf name{ + type string; + description + "name of shared-cell-combine-entity"; + } + + uses processing-element-set; + + leaf ta3-prime-max { + type uint32; + units nanoseconds; + description + "indicates the latest time that FHM or cascade O-RU is allowed to + send UL U-plane message to north-node relative to reception + timing at O-RU antenna."; + } + + uses shared-cell-combine-uplane-config; + } + } + + + grouping shared-cell-combine-uplane-config{ + description + "shared cell related uplane configuration applicable to O-RU which + doesn't have radio transmisison capability"; + container shared-cell-combine-uplane-config { + if-feature FHM; + description + "when O-RU doesn't have radio transmisison availability for FHM mode, + the required u-plane configuration for copy and combine function + are defined, instead of the lists of o-ran-uplane-conf.yang"; + + list rx-eaxc-id { + key eaxc-id; + description + "used for low-level-rx-endpoints to combine"; + leaf eaxc-id { + type uint16; + description + "encoded value of eaxc-id to be read by CU-Plane"; + } + container comression-method { + description + "for combine mechanism, compression method per eaxc-id applied in + south-node is known to FHM "; + uses cf:compression-details; + } + } + + uses radio-offset; + + leaf n-ta-offset { + type uint32; + units Tc; + mandatory true; + description + "Value of configurable N-TA offset + units are Tc=~0.5ns=1/1.96608GHz"; + } + + leaf number-of-prb { + type uint16; + mandatory true; + description + "Determines max number of PRBs that will be used in all sections + per one symbol. + This value is used only when uplink C-plane message indicates that + all PRB is used in the field of numPrbc"; + } + } + } + +// top level container + container shared-cell{ + description + "This container for shared-cell consists of capability information and + configurable parameters"; + uses shared-cell-module-capability; + + container shared-cell-config { + description "configuration for shared cell."; + uses shared-cell-mode; + } + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-software-management@2019-07-03.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-software-management@2019-07-03.yang new file mode 100644 index 0000000..e9f3448 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-software-management@2019-07-03.yang @@ -0,0 +1,595 @@ +module o-ran-software-management { + yang-version 1.1; + namespace "urn:o-ran:software-management:1.0"; + prefix o-ran-swm; + + import ietf-inet-types { + prefix "inet"; + revision-date 2013-07-15; + } + + import ietf-hardware { + prefix "hw"; + } + + import o-ran-hardware { + prefix "o-ran-hw"; + } + + import o-ran-file-management { + prefix "o-ran-fm"; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines operations and configuration for the management of software packages. + This module is derived out of opencpe-firmware-mgmt@2014-02-06.yang + + 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.0.2 + + 1) backward compatible changes to correct sFTP Server Authentication . + 2) simplifying file management and authentication to reuse from o-ran-file-management module + 3) minor fixes according to lack of descriptions + 4) removal of not used grouping + 5) 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"; + } + + // groupings + + grouping slot-group { + description + "Contains information about each software slot and its content."; + list software-slot { + key name; + min-elements 2; + + description + "Information about available software-slots and their software."; + + leaf name { + type string; + + description + "Name of the software package. This shall be unique to identify the software-slot."; + } + + leaf status { + type enumeration { + enum VALID { + description + "Slot Contains software build considered as proven valid"; + } + enum INVALID { + description + "software build is not currently used by O-RU. The software is considered by O-RU as damaged (e.g. wrong CRC)"; + } + enum EMPTY { + description + "W slot does not contain software package."; + } + } + config false; + mandatory true; + + description "Indicates the status of the software slot"; + } + + leaf active { + type boolean; + must "../status = 'VALID'"; + config false; + description + "informs if software stored in particular slot is activated at the moment"; + } + + leaf running { + type boolean; + must "../status = 'VALID'"; + config false; + description + "informs if software stored in particular slot is used at the moment"; + } + + leaf access { + type enumeration { + enum READ_ONLY { + description + "slot intended only for factory software, + activation of such software slot means getting back to factory defaults"; + } + enum READ_WRITE { + description + "slot used for updating software"; + } + } + default READ_WRITE; + config false; + + description + "Indicates the writability of the slot. + A Read-Only software slot is one which has a factory installed software-slot"; + } + + leaf product-code { + type leafref { + path "/hw:hardware/hw:component/o-ran-hw:product-code"; + } + config false; + + description "product code provided by the vendor, specific to the product. This is derived from manifest file."; + } + + leaf vendor-code { + type string { + length 1..2; + } + config false; + + description + "Unique code of the vendor. This is derived from manifest file."; + } + + leaf build-id { + type string; + config false; + + description + "Identity associated with the software build. This is derived from manifest file."; + } + + leaf build-name { + type string; + config false; + + description + "Name of the build. This is derived from manifest file."; + } + + leaf build-version { + type string; + description "The vendor-specific version string of the software build."; + } + + list files { + key "name"; + config false; + + description "List of all the files present in the software package."; + + leaf name { + type string; + + description + "Name of the file installed in the slot."; + } + + leaf version { + type string; + + description + "Version of the file installed in the slot"; + } + leaf local-path { + type string; + mandatory true; + + description + "Complete path of the file stored locally"; + } + + leaf integrity { + type enumeration { + enum OK { + description "OK - indicates that file integrity is correct"; + } + enum NOK { + description "NOK - indicates corrupted file"; + } + } + config false; + + description + "Result of the file integrity check (checksum calculation) during installation."; + } + } + } + } + + grouping download-input { + description + "Grouping for sw download rpc input"; + leaf remote-file-path { + type inet:uri; + mandatory true; + description + "URI of the software image including username. + The following format is possible: + sftp://@[:]/path"; + } + + uses o-ran-fm:credential-information; + } + + grouping download-output { + description + "Grouping for sw download rpc output"; + leaf status { + type enumeration { + enum STARTED { + description + "Operation has been started without error."; + } + enum FAILED { + description + "Operation cannot be started because of error, more detailed information can be found in error-message."; + } + } + mandatory true; + + description + "Status of the software files download"; + } + leaf error-message { + when "../status = 'FAILED'"; + type string; + + description + "Detailed error Message when the status is failed."; + } + + leaf notification-timeout { + type int32; + units seconds; + default 30; + + description + "Notification timeout is the time NETCONF client shall + wait for a 'download-event' notification from O-RU. If there is no + 'download-event' notification received within notification-timeout, + NETCONF client shall assume the download timeout/failure, and follow necessary steps."; + } + } + + grouping install-input { + description + "Grouping for sw installation rpc input"; + leaf slot-name { + type leafref { + path "/software-inventory/software-slot/name"; + } + must "/software-inventory/software-slot[name = current()][active = 'false' and running = 'false']" { + error-message "software-install may be requested only against active::false and running::false slot!"; + } + mandatory true; + + description + "software-slot to which the software shall be installed to."; + } + + leaf-list file-names { + type string; + + description + "Names of the files within software package to be installed"; + } + } + + grouping install-output { + description + "Grouping for sw installation rpc output"; + leaf status { + type enumeration { + enum STARTED { + description + "Operation has been started without error."; + } + enum FAILED { + description + "Operation cannot be started because of error, more detailed information can be found in error-message."; + } + } + mandatory true; + + description + "Status of the software package install."; + } + leaf error-message { + when "../status = 'FAILED'"; + type string; + + description + "Detailed error Message when the status is failed."; + } + } + + grouping activate-input { + description + "Grouping for sw activation rpc input"; + leaf slot-name { + type leafref { + path "/software-inventory/software-slot/name"; + } + must "/software-inventory/software-slot[name = current()][status = 'VALID']" { + error-message "software activation may be requested only on VALID slot!"; + } + mandatory true; + + description + "Slot name on which software has to be activated."; + } + } + + grouping activate-output { + description + "Grouping for sw activation rpc output"; + leaf status { + type enumeration { + enum STARTED { + description + "Operation has been started without error."; + } + enum FAILED { + description + "Operation cannot be started because of error, more detailed information can be found in error-message."; + } + } + mandatory true; + + description + "Status of the software files activation"; + } + leaf error-message { + when "../status = 'FAILED'"; + type string; + + description + "Detailed error Message when the status is failed."; + } + + leaf notification-timeout { + type int32; + units seconds; + default 30; + + description + "Timeout on client waiting for the activate event"; + } + } + + grouping download-notification { + description + "Grouping for notification event structure for download completion"; + leaf file-name { + type string; + mandatory true; + + description + "File name of downloaded software package"; + } + + leaf status { + type enumeration { + enum COMPLETED { + description + "Operation completed succesfully"; + } + enum AUTHENTICATION_ERROR { + description "source available, wrong credentials"; + } + enum PROTOCOL_ERROR { + description "SFTP errors"; + } + enum FILE_NOT_FOUND { + description "source not available."; + } + enum APPLICATION_ERROR { + description "Application related errors"; + } + enum TIMEOUT { + description "Timeout waiting for download"; + } + } + + description + "Status of finished operation execution"; + } + leaf error-message { + when "../status != 'COMPLETED'"; + type string; + + description + "Detailed description of faulty situation"; + } + } + + grouping install-notification { + description + "Grouping for notification event structure for installation completion"; + leaf slot-name { + type leafref { + path "/software-inventory/software-slot/name"; + } + + description + "Name of the slot to which software was installed."; + } + leaf status { + type enumeration { + enum COMPLETED { + description + "Operation completed succesfully"; + } + enum FILE_ERROR { + description "operation on the file resulted in in error, disk failure, not enough disk space, + incompatible file format"; + } + enum INTEGRITY_ERROR { + description "file is corrupted"; + } + enum APPLICATION_ERROR { + description "operation failed due to internal reason"; + } + } + + description + "Status of finished operation execution"; + } + leaf error-message { + when "../status != 'COMPLETED'"; + type string; + + description + "Detailed description of faulty situation"; + } + } + + grouping activation-notification { + description + "Grouping for notification event structure for activation completion"; + leaf slot-name { + type leafref { + path "/software-inventory/software-slot/name"; + } + + description + "Name of the slot which was activated"; + } + + leaf status { + type enumeration { + enum COMPLETED { + description + "Operation completed succesfully"; + } + enum APPLICATION_ERROR { + description + "Operation finished with error, more details can by found in error-message"; + } + } + + description + "Status of finished operation execution"; + } + leaf return-code { + type uint8; + + description + "status code return when the software is tried to activate"; + } + leaf error-message { + when "../status != 'COMPLETED'"; + type string; + + description + "Detailed description of faulty situation"; + } + } + + // top level container + + container software-inventory { + config false; + description + "Contains information about each software slot and its content."; + + uses slot-group; + + } + // rpc statements + + rpc software-download { + description + "Rpc needed to perform software download operation."; + + input { + uses download-input; + } + output { + uses download-output; + } + } + + rpc software-install { + description + "Install a previously downloaded software package."; + + input { + uses install-input; + } + output { + uses install-output; + } + } + + rpc software-activate { + description + "Activate a previously installed software."; + input { + uses activate-input; + } + output { + uses activate-output; + } + } + + // notification definitions + notification download-event { + description "Notification event structure for download completion"; + uses download-notification; + + } + + notification install-event { + description "Notification event structure for installation completion"; + uses install-notification; + } + + notification activation-event { + description "Notification event structure for activation completion"; + uses activation-notification; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-supervision@2020-12-10.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-supervision@2020-12-10.yang new file mode 100644 index 0000000..4956f9b --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-supervision@2020-12-10.yang @@ -0,0 +1,228 @@ +module o-ran-supervision { + yang-version 1.1; + namespace "urn:o-ran:supervision:1.0"; + prefix "o-ran-supervision"; + + import ietf-yang-types { + prefix yang; + } + + import o-ran-wg4-features { + prefix or-feat; + } + + import ietf-inet-types { + prefix "inet"; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the configuration data and supervision RPCs that are + used to detect loss M-Plane connectivity. + + Copyright 2020 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 "2020-12-10" { + description + "version 5.0.0 + + 1) added Event Producer-Collector supervision"; + + reference "ORAN-WG4.M.0-v05.00"; + } + + revision "2020-04-17" { + description + "version 3.0.0 + + 1) added output string to enable indication if config modification change has failed + 2) corrected model description + 3) removed erroneous text in notification description"; + + reference "ORAN-WG4.M.0-v03.00"; + } + + revision "2019-07-03" { + description + "version 2.0.0 + + 1) added leafs for CU plane monitoring + 2) 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"; + } + + typedef event-collector-id { + type union { + type inet:ip-address; + type inet:uri; + } + description "An Event Collector identifier"; + } + + grouping watchdog-input { + leaf supervision-notification-interval { + type uint16; + units seconds; + default 60; + description + "The interval in seconds at which supervision notifications are sent. + If not specified the default value of 60 seconds shall apply."; + } + leaf guard-timer-overhead { + type uint16; + units seconds; + default 10; + description + "This is overhead added to the supervision timer used to calculate the + supervision wathcdog timer. i.e., + + supervision timer = notification timer + guard-timer-overhead + + If not specified the default value of 10 seconds shall apply. + + Failure to send this rpc again within the timeout sets the radio into + 'loss of supervision' state. + + NOTE - The supervision timer MUST not be less that the confimed + timeout timer (when the feature is supported). + + This type of constraint (using an RPCs input) cannot be formally + expressed in YANG."; + } + } + + grouping watchdog-output { + leaf next-update-at { + type yang:date-and-time; + description + "Indicates the time when the next supervision notification is expected."; + } + leaf error-message { + type string; + + description + "An optional error message, e.g., used when the RPC input attempts to + modify a locked running configuration. + + Take note, the supervision-notification-interval and guard-timer-overhead + have default values and so their values can be modified even when a leaf is + not included in the RPC input."; + } + } + + grouping supervision-group { + container cu-plane-monitoring { + description "container describing operation of CU plane monitoring"; + presence + "Indicates O-RU supports timer based cu-plane monitoring interval. If + this container is NOT present, the opertaion of the O-RU is undefined."; + + leaf configured-cu-monitoring-interval { + type uint8 { + range "0..160"; + } + default 160; + units milliseconds; + description + "This value corresponds to the configured value of the timer used by + the O-RU to monitor the C/U plane connection. + + A value of 0 means that the O-RU's shall disable its CU plane + monitoring. + + A NETCONF client should configure the value according to the + configuration of the PHY layer and/or C/U plane section types + supported and/or any fault tolerant operation. For example, + + i) when opertaing with an O-DU supporting non-LAA LTE, this value can + be configured to a value according to the repetition time of + transmitted reference symbols across the fronthaul interface + ii) when opertaing with an O-DU supporting C-Plane Section Type 0, + this value can configured to a value according to the minimum + repetition interval of section type 0. + iii) when operating with an O-DU supporting fault tolerant operation, + this value can be configured according to the fault tolerant heartbeat + interval "; + } + } + container event-collector-monitoring { + if-feature "or-feat:NON-PERSISTENT-MPLANE"; + description "container describing operation of Event Collector monitoring"; + + leaf heartbeat-interval { + type uint8; + default 60; + units seconds; + description "the heartbeat interval"; + } + + leaf-list heartbeat-recipient-id { + type event-collector-id; + description + "A configured Event collector identity, to which the O-RU shall send heartbeat notifications"; + } + } + } + + container supervision { + uses supervision-group; + // other WG specific monitoring containers follow here + } + + rpc supervision-watchdog-reset { + description + "rpc to reset the watchdog timer"; + input { + uses watchdog-input; + } + + output { + uses watchdog-output; + } + } + + notification supervision-notification { + description + "Notification to indicate that NETCONF management interface is up."; + + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-sync@2020-08-10.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-sync@2020-08-10.yang new file mode 100644 index 0000000..c8d8a74 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-sync@2020-08-10.yang @@ -0,0 +1,988 @@ +module o-ran-sync { + yang-version 1.1; + namespace "urn:o-ran:sync:1.0"; + prefix "o-ran-sync"; + + import ietf-interfaces { + prefix "if"; + } + + import o-ran-interfaces { + prefix "o-ran-int"; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines synchronization mechanism for the O-RAN Equipment. + + Copyright 2020 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 "2020-08-10" { + description + "version 1.3.0 + + 1) Update description of ENCHANCED under container sync-capability leaf sync-t-tsc with + correct reference to IEEE 802.1CM sections. + 2) Add description that CLASS_B and ENHANCED are as per IEEE802.1CM. + 3) Add freq-error and time-error leafs under container sync-status. This allows an O-DU to + query the O-RU using NETCONF procedure about the phase and frequency errors at + any time. + 4) Move delay-assymmetry outside of container g-8275-1-config as the delay assymetry + is applicable to G.8275.2 as well + 5) Add gnss-rx-error in gnss-data for LLS-C4 configuration + 6) Correct the description of state enumerations under synce-status. The earlier + descriptions were copy paste from ptp-status"; + + reference "ORAN-WG4.M.0-v04.00"; + } + + revision "2020-04-17" { + description + "version 1.2.0 + + 1) enable O-RU to only support GNSS and not 802.1CM."; + + reference "ORAN-WG4.M.0-v03.00"; + } + + revision "2019-07-03" { + description + "version 1.1.0 + + 1) 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"; + } + + typedef geographic-coordinate-degree { + type decimal64 { + fraction-digits 8; + } + description + "Decimal degree (DD) used to express latitude and longitude + geographic coordinates."; + } + + feature GNSS { + description + "This feature indicates that the equipment supports integrated GNSS functionality."; + } + + feature ANTI-JAM { + description + "This feature indicates that the equipment supports Anti-jam fuctionality"; + } + + grouping sync-group { + description "This group represents the state and status of timing and synchronization of the O-RU"; + container sync-status { + config false; + + description + "Object of this class provides synchronization state of the module."; + + leaf sync-state { + type enumeration { + enum LOCKED { + description + "equipment is in the locked mode, as defined in ITU-T G.810"; + } + enum HOLDOVER { + description + "equipment clock is in holdover mode"; + } + enum FREERUN { + description + "equipment clock isn't locked to an input reference, and is not in the holdover mode"; + } + } + mandatory true; + description + "State of DU synchronization"; + } + leaf time-error { + type decimal64 { + fraction-digits 3; + } + units nanoseconds; + description + "An optional leaf indicating an estimate of the current time error in the O-RU, + e.g., derived from a low pass filtering of the residual error of the PLL. + The definition of the filtering and updating is left to O-RU implementation."; + } + leaf frequency-error { + type decimal64 { + fraction-digits 3; + } + units parts-per-billion; + description + "An optional leaf indicating an estimate of the current frequency error in the O-RU, + e.g., derived from a low pass filtering of the residual error of the PLL. + The definition of the filtering and updating is left to O-RU implementation."; + } + + list supported-reference-types { + key item; + min-elements 1; + description + "Type of a synchronization supported source."; + leaf item { + type enumeration { + enum GNSS { + description + "GPS can be taken as a synchronization source"; + } + enum PTP { + description + "Precision Time Protocol can be taken as a synchronization source"; + } + enum SYNCE { + description + "Synchronous Ethernet can be taken as a synchronization source"; + } + } + mandatory true; + + description + "supported reference-type"; + } + } + } + + container sync-capability { + config false; + + description + "Object of this class provides synchronization capabilities of the module."; + + leaf sync-t-tsc { + type enumeration { + enum CLASS_B { + description + "Regular accuracy (previously referred to class B) for synchronization + is supported by the device as per IEEE802.1CM clause 6.4.1, Case 1.1"; + } + enum ENCHANCED { + description + "Enhanced accuracy for synchronization is supported by the device as per + IEEE802.1CM clause 6.4.1, Case 1.2. + + The typo in the name of the enumeration (ENCHANCED instead of ENHANCED) + is kept as is for backwards compatibility"; + } + } + description + "When the O-RU supports 802.1CM, this leaf provides information about + T-TSC capability"; + + reference "IEEE 802.1CM"; + } + } + + container ptp-config { + description + "This MO defines configuration of Precise Time Protocol."; + leaf domain-number { + type uint8; + default 24; + description + "This parameter indicates Domain Number for PTP announce messages."; + } + + list accepted-clock-classes { + key clock-classes; + leaf clock-classes { + type uint8; + description + "PTP Clock Class accepted by the O-RU"; + } + description + "Contains list of PTP acceptable Clock Classes, sorted in the descending order."; + } + + leaf ptp-profile { + type enumeration { + enum G_8275_1 { + description + "Usage of multicast over ethernet"; + } + + enum G_8275_2 { + description + "Usage of unicast over IP"; + } + } + default "G_8275_1"; + description + "Type of profile to be used in ptp setting"; + } + leaf delay-asymmetry { + type int16 { + range "-10000..10000"; + } + default 0; + description + "Defines static phase error in the recovered PTP timing signal to be compensated at the O-RU. + The error is defined in units of nanoseconds in the range ±10 000 ns. + + If the deprecated delay-asymmetry schema node in the g-8275-1-config container is configured + together with this schema node, then the O-RU shall use this schema node and ignore the + value in the g-8275-1-config container."; + } + + container g-8275-1-config { + when "../ptp-profile='G_8275_1'"; + + description + "Container allowing for configuration of G8275.1"; + + leaf multicast-mac-address { + type enumeration { + enum FORWARDABLE { + description + "means, that PTP shall use 01-1B-19-00-00-00 destination MAC address"; + } + enum NONFORWARDABLE { + description + "means, that PTP shall use 01-80-C2-00-00-0E destination MAC address"; + } + } + default FORWARDABLE; + description + "The parameter defines destination MAC address, used by the DU in the egress PTP messages."; + } + + leaf delay-asymmetry { + type int16 { + range -10000..10000; + } + default 0; + status deprecated; + description + "Defines static phase error in the recovered PTP timing signal to be compensated at the O-RU. + The error is defined in units of nanoseconds in the range ±10 000 ns."; + } + } + + container g-8275-2-config { + when "../ptp-profile='G_8275_2'"; + + description + "Container used for configuration of G8275.2 profile"; + + leaf local-ip-port { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + description + "Reference to interface name corresponding to IP interface + used for G.8275.2"; + } + + list master-ip-configuration { + key local-priority; + description + "The parameter defines list of ip configuration of devices acting as ptp signal source."; + leaf local-priority { + type uint8; + description + "The parameter defines local priority or underlying master IP address."; + } + + leaf ip-address { + type string; + description + "the parameter defines master IP address."; + } + } + + leaf log-inter-sync-period { + type int8 { + range "-7..0"; + } + + description + "The parameter defines number of sync message during 1 second"; + } + + leaf log-inter-announce-period { + type int8 { + range "-3..0"; + } + + description + "The parameter defines number of announce message during 1 second"; + } + } + } + + container ptp-status { + description + "ptp status container"; + leaf reporting-period { + type uint8; + default 10; + description + "This parameter defines minimum period in seconds between reports, + sent by the NETCONF Client, for parameters in this container."; + } + leaf lock-state { + type enumeration { + enum LOCKED { + description + "The integrated ordinary clock is synchronizing to the reference, recovered from PTP flow"; + } + enum UNLOCKED { + description + "The integrated ordinary clock is not synchronizing to the reference, recovered from PTP flow"; + } + } + config false; + description + "This parameter indicates, whether the integrated ordinary clock is + synchronizing to the reference, recovered from PTP signal. + The exact definition when to indicate locked or unlocked is up to specific + implementation."; + } + + leaf clock-class { + type uint8; + config false; + description + "This parameter contains the clock class of the clock, controlled by the O-RU"; + } + + leaf clock-identity { + type string { + length 18; + pattern "0[xX][0-9a-fA-F]{16}"; + } + config false; + description + "This parameter contains identity of the clock, + according to IEEE 1588-2008 defintion, controlled by the O-RU. + The string shall be formatted as an 8-octet hex value with the '0x' prefix."; + } + + leaf partial-timing-supported { + type boolean; + config false; + description + "Provides information wheter G.8275.2 (partial timing support from network) is supported."; + } + + list sources { + key local-port-number; + config false; + + description + "Synchronisation sources"; + + leaf local-port-number { + type leafref { + path "/if:interfaces/if:interface/o-ran-int:port-reference/o-ran-int:port-number"; + } + description + "This is reference to portNumber of ExternalEthernetPort to identify the port, + where the PTP signal is located."; + } + + leaf state { + type enumeration { + enum PARENT { + description + "Indicates that this source is the current master clock, i.e. the clock, + which the clock, controlled by the Netconf Server, is synchronized to"; + } + enum OK { + description + "Indicates that this source is an alternate master, which the clock, + controlled by the Netconf Server, can potentially synchronize to, + i.e. clock class and priority, announced by the master clock is lower, + compared to those of the clock, controlled by the Netconf Server, + and and the clock class is accepted"; + } + enum NOK { + description + "Indicates that this source is an alternate master, which the clock, + controlled by the Netconf Server, has an operational connection to, + but the class or priority of the master clock is higher or equal + to those of the clock, controlled by the Netconf Server, + or the clock class is not accepted"; + } + enum DISABLED { + description + "Indicates that this source is an alternate master, which the clock, + controlled by the Netconf Server, has no operational connection to"; + } + } + description + "This parameter indicates status of the PTP source"; + } + + leaf two-step-flag { + type boolean; + description + "This parameter reflects status of the twoStepFlag attribute in Sync messages, + received from the PTP source."; + } + + leaf leap61 { + type boolean; + description + "This parameter reflects status of the leap61 flag in Announce messages, + received from the PTP source. + When true, the last minute of the current UTC day contains 61 seconds."; + } + + leaf leap59 { + type boolean; + description + "This parameter reflects status of the leap59 flag in Announce messages, + received from the PTP source. + When true, the last minute of the current UTC day contains 59 seconds."; + } + + leaf current-utc-offset-valid { + type boolean; + description + "This parameter reflects status of the currentUtcOffsetValid flag in + Announce messages, received from the PTP source. + When true, the current UTC offset is valid."; + } + + leaf ptp-timescale { + type boolean; + description + "This parameter reflects status of the ptpTimescale flag in Announce + messages, received from the PTP source. + + When set, the clock timescale of the grandmaster clock is PTP; + otherwise, the timescale is ARB (arbitrary)"; + } + + leaf time-traceable { + type boolean; + description + "This parameter reflects status of the timeTraceable flag in Announce + messages, received from the PTP source. + + When true, the timescale and the currentUtcOffset are traceable to a + primary reference"; + } + + leaf frequency-traceable { + type boolean; + description + "This parameter reflects status of the frequencyTraceable flag in + Announce messages, received from the PTP source. + + When true, the frequency determining the timescale is traceable to a + primary reference"; + } + + leaf source-clock-identity { + type string { + length 18; + pattern "0[xX][0-9a-fA-F]{16}"; + } + description + "This parameter reflects value of the sourceClockIdentity attribute in + Announce messages, received from the PTP source. + + The string shall be formatted as an 8-octet hex value with the '0x' + prefix."; + } + + leaf source-port-number { + type uint16; + description + "This parameter reflects value of the sourcePortNumber attribute in + Announce messages, received from the PTP source."; + } + + leaf current-utc-offset { + type int16; + description + "The offset between TAI and UTC when the epoch of the PTP system is + the PTP epoch, i.e., when ptp-timescale is TRUE; otherwise, the value + has no meaning"; + } + + leaf priority1 { + type uint8; + description + "This parameter reflects value of the priority1 attribute in Announce + messages, received from the PTP source."; + } + + leaf clock-class { + type uint8; + description + "This parameter reflects value of the clockClass attribute in + Announce messages, received from the PTP source."; + } + + leaf clock-accuracy { + type uint8; + description + "This parameter reflects value of the clockAccuracy attribute in + Announce messages, received from the PTP source."; + } + + leaf offset-scaled-log-variance { + type uint16; + description + "This parameter reflects value of the offsetScaledLogVariance + attribute in Announce messages, received from the PTP source."; + } + + leaf priority2 { + type uint8; + description + "This parameter reflects value of the priority2 attribute in Announce + messages, received from the PTP source."; + } + + leaf grandmaster-clock-identity { + type string { + length 18; + pattern "0[xX][0-9a-fA-F]{16}"; + } + description + "This parameter reflects value of the grandmasterClockIdentity + attribute in Announce messages, received from the PTP source. + + The string shall be formatted as an 8-octet hex value with the '0x' + prefix."; + } + + leaf steps-removed { + type uint16; + description + "This parameter reflects value of the stepsRemoved attribute in + Announce messages, received from the PTP source. + + It indicates the number of communication paths traversed + between the local clock and the grandmaster clock."; + } + + leaf time-source { + type uint8; + description + "This parameter reflects value of the timeSource attribute in + Announce messages, received from the PTP source."; + } + } + } + + container synce-config { + description + "This container defines the configuration of SyncE"; + + leaf-list acceptance-list-of-ssm { + type enumeration { + enum PRC { + description + "PRC"; + } + enum PRS { + description + "PRS"; + } + enum SSU_A { + description + "SSU_A"; + } + enum SSU_B { + description + "SSU_B"; + } + enum ST2 { + description + "ST2"; + } + enum ST3 { + description + "ST3"; + } + enum ST3E { + description + "ST3E"; + } + enum EEC1 { + description + "EEC1"; + } + enum EEC2 { + description + "EEC2"; + } + enum DNU { + description + "DNU"; + } + enum NONE { + description + "NONE"; + } + } + + default "PRC"; + + description + "The parameter contains the list of SyncE acceptable SSMs."; + } + + leaf ssm-timeout { + type uint16; + + description + "The parameter contains the value of maximum duration in seconds for which the actual SSM value may be different than configured values."; + } + } + + container synce-status { + description + "SyncE status container"; + + leaf reporting-period { + type uint8; + default 10; + description + "This parameter defines minimum period in seconds between reports, + sent by the NETCONF client, for parameters in this container."; + } + + leaf lock-state { + type enumeration { + enum LOCKED { + description + "The integrated ordinary clock is synchronizing to the reference, recovered from SyncE signal"; + } + enum UNLOCKED { + description + "The integrated ordinary clock is not synchronizing to the reference, recovered from SyncE signal"; + } + } + config false; + description + "This parameter indicates, whether the integrated ordinary clock is + synchronizing to the reference, recovered from SyncE signal. + + The exact definition when to indicate locked or unlocked is up to + specific implementation."; + } + + list sources { + key local-port-number; + config false; + leaf local-port-number { + type leafref { + path "/if:interfaces/if:interface/o-ran-int:port-reference/o-ran-int:port-number"; + } + description + "This is reference to portNumber of ExternalEthernetPort to identify + the port, where the SyncE signal is located."; + } + + leaf state { + type enumeration { + enum PARENT { + description + "Indicates this is the primary SyncE source recovering SyncE signal"; + } + enum OK { + description + "Indicates that this source is an alternate SyncE source, which the clock, + controlled by the Netconf Server, can potentially synchronize to, when the + clock quality of the primary SyncE signal advertised in ESMC packets is + lower than the expected or configured clock quality; or when this source + clock quality is better than the primary SyncE source clock quality"; + } + enum NOK { + description + "Indicates that this source is an alternate SyncE source, and the O-RU + has an operational connection to this alternate SyncE source, but the + clock quality is not in the configured acceptable range"; + } + enum DISABLED { + description + "Indicates that this source is an alternate SyncE clock, and the O-RU has an + operational connection to this alternate SyncE source"; + } + } + description + "This parameter indicates status of the SyncE source"; + } + + leaf quality-level { + type uint8 { + range 0..15; + } + description + "This parameter contains value of the SSM clock quality level, + received in SSM messages from the SyncE source."; + } + min-elements 1; + description + "This parameter contains characteristics of SyncE sources of the clock, controlled by the O-RU."; + } + } + + container gnss-config { + if-feature GNSS; + description + "This container defines the configuration of Global Navigation Satellite System (GNSS)."; + + leaf enable { + type boolean; + + description + "This parameter defines if GNSS receiver shall be enabled or not."; + } + + leaf-list satellite-constelation-list { + type enumeration { + enum GPS { + description + "GPS"; + } + enum GLONASS { + description + "GLONASS should not be used alone but always along with GPS or BEIDOU because of missing leap second information"; + } + enum GALILEO { + description + "GALILEO"; + } + enum BEIDOU { + description + "BEIDOU"; + } + } + + description + "This parameter defines list of constellations to be used to acquire synchronization."; + } + + leaf polarity { + type enumeration { + enum POSITIVE { + description + "POSITIVE"; + } + enum NEGATIVE { + description + "NEGATIVE"; + } + } + default POSITIVE; + + description + "This parameter defines pulse polarity"; + } + + leaf cable-delay { + type uint16 { + range "0..1000"; + } + default 5; + + description + "This parameter is used to compensate cable delay."; + } + + leaf anti-jam-enable { + if-feature ANTI-JAM; + type boolean; + default false; + description + "This parameter is used to enable or disable anti-jamming."; + } + } + + container gnss-status { + if-feature GNSS; + description + "Provides information about state of gps receiver"; + leaf reporting-period { + type uint8; + default 10; + description + "This parameter defines minimum period in seconds between reports, + sent by the NETCONF Client, for parameters in this container."; + } + leaf name { + type string { + length "1..255"; + } + config false; + description + "A name that is unique that identifies a GNSS instance. + This name may be used in fault management to refer to a + fault source or affected object"; + } + leaf gnss-sync-status { + type enumeration { + enum SYNCHRONIZED { + description "GNSS functionality is synchronized"; + } + enum ACQUIRING-SYNC { + description "GNSS functionality is acquiring sync"; + } + enum ANTENNA-DISCONNECTED { + description "GNSS functionality has its antenna disconnected"; + } + enum BOOTING { + description "GNSS functionality is booting"; + } + enum ANTENNA-SHORT-CIRCUIT { + description "GNSS functionality has an antenna short circuit"; + } + } + config false; + description "when available, indicates the status of the gnss receiver."; + } + container gnss-data { + when "../gnss-sync-status='SYNCHRONIZED'"; + config false; + description + "GPS data contained"; + leaf satellites-tracked { + type uint8; + description "Number of satellites tracked"; + } + container location { + description + "Containes information about geo location"; + leaf altitude { + type int64; + units millimeter; + description + "Distance above the sea level."; + } + leaf latitude { + type geographic-coordinate-degree { + range "-90..90"; + } + description + "Relative position north or south on the Earth's surface."; + } + leaf longitude { + type geographic-coordinate-degree { + range "-180..180"; + } + description + "Angular distance east or west on the Earth's surface."; + } + } + leaf gnss-rx-time-error { + type decimal64 { + fraction-digits 3; + } + units nanoseconds; + description + "An optional leaf, representing the estimate of current GNSS receiver time error "; + } + } + } + } + container sync { + description + "Main containter for sync related parameters"; + + uses sync-group; + } + + //notification statement + notification synchronization-state-change { + description + "Notification used to inform about synchronization state change"; + + leaf sync-state { + type leafref { + path "/sync/sync-status/sync-state"; + } + description + "State of equipment synchronization is notified at state change"; + } + } + + notification ptp-state-change { + description + "Notification used to inform about ptp synchronization state change"; + + leaf ptp-state{ + type leafref{ + path "/sync/ptp-status/lock-state"; + } + description + "ptp-state-change notification is signalled from equipment at state change"; + } + } + notification synce-state-change { + description + "Notification used to inform about synce synchronization state change"; + + leaf synce-state{ + type leafref{ + path "/sync/synce-status/lock-state"; + } + description + "synce-state change notification is signalled from equipment at state change"; + } + } + notification gnss-state-change { + if-feature GNSS; + description + "Notification used to inform about gnss synchronization state change"; + + leaf gnss-state{ + type leafref{ + path "/sync/gnss-status/gnss-sync-status"; + } + description + "gnss-state-change notification is signalled from equipment at state change"; + } + } + +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-trace@2019-07-03.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-trace@2019-07-03.yang new file mode 100644 index 0000000..5bfead9 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-trace@2019-07-03.yang @@ -0,0 +1,102 @@ +module o-ran-trace { + yang-version 1.1; + namespace "urn:o-ran:trace:1.0"; + prefix "o-ran-trace"; + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the operations for the trace logs. + + 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.0.0 + + 1) Initial module definition."; + + reference "ORAN-WG4.M.0-v01.00"; + } + + + grouping trace-status-grouping { + description "grouping used for trace RPCs"; + leaf status { + type enumeration { + enum SUCCESS { + description "rpc completed correctly"; + } + enum FAILURE { + description "rpc failed"; + } + } + description "result of rpc operation"; + } + leaf failure-reason { + when "../status = 'FAILURE'"; + type string; + description "free form text description why error occurred"; + } + } + + rpc start-trace-logs { + description + "Management plane triggered to start collecting the trace logs files of O-RU."; + output { + uses trace-status-grouping; + } + } + + rpc stop-trace-logs { + description + "Management plane triggered to stop collecting the trace logs files of O-RU."; + output { + uses trace-status-grouping; + } + } + + notification trace-log-generated { + description + "When new log file generated, send this notification."; + leaf-list log-file-name { + type string; + description + "The list of trace log file names on the O-RU."; + } + + leaf is-notification-last { + type boolean; + default false; + description + "Informs if notification is last - the one after receiving stop-trace-logs rpc."; + } + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-transceiver@2019-07-03.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-transceiver@2019-07-03.yang new file mode 100644 index 0000000..93d83d8 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-transceiver@2019-07-03.yang @@ -0,0 +1,513 @@ +module o-ran-transceiver { + yang-version 1.1; + namespace "urn:o-ran:transceiver:1.0"; + prefix "o-ran-transceiver"; + + import o-ran-interfaces { + prefix "o-ran-int"; + } + + import ietf-interfaces { + prefix "if"; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the operational state data for SFP transceivers used in + an O-RAN Radio Unit. + + 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 2.0.0 + + 1) introduction of reporting for QSFP. + 2) backward compatible changes to introduce groupings."; + + reference "ORAN-WG4.M.0-v02.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"; + } + + + // Groupings + + grouping transceiver-group { + list port-transceiver-data { + key "interface-name port-number"; + description "data recovered from port transceivers"; + leaf interface-name { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + description "Name of interface"; + } + leaf port-number { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../interface-name]" + "/o-ran-int:port-reference/o-ran-int:port-number"; + } + description + "A number which identifies a port. In case of SFP/SFP+ + port, port number value is 0 to N-1 where N is number of ports + in the device. Numbers 0 to N-1 are assigned to ports in order + following order of labels on the device (labels for ports are + not necessarily numbers starting from zero)"; + } + + leaf name { + type string { + length "1..255"; + } + description + "A name that is unique across the O-RU that identifies a transceiver instance. + This name may be used in fault management to refer to a fault source + or affected object"; + } + + leaf present { + type boolean; + config false; + mandatory true; + description + "Indicates if pluggable transceiver module is present."; + } + + leaf vendor-id { + type string { + length 1..16; + } + config false; + description + "Name of the transciever vendor Full name of transceiver vendor, + that contains ASCII characters, left-aligned with + any padding on the right with ASCII spaces (20h), or ASCII nul + (00h) removed, and ASCII less-than (3Ch) replaced with ASCII + open-brace (7Bh) and ASCII more-than (3Eh) replaced with ASCII + close-brace (7Dh). + + Optional node included when the NETCONF Server has determined + the vendor ID."; + } + + leaf vendor-part { + type string { + length 1..16; + } + config false; + description + "Transceiver vendors part number, that contains ASCII characters, + left-aligned with any padding on the right with ASCII spaces + (20h), or ASCII nul (00h) removed, and ASCII less-than (3Ch) + replaced with ASCII open-brace (7Bh) and ASCII more-than (3Eh) + replaced with ASCII close-brace (7Dh). + + Optional node included when the NETCONF Server has determined + the vendor part number."; + } + + leaf vendor-rev { + type string { + length 1..2; + } + config false; + description + "Transceiver vendors revision number. 2-octet field that + contains ASCII characters. + + Optional node included when the NETCONF Server has determined + the vendor revision number"; + } + + leaf serial-no { + type string { + length 1..16; + } + config false; + description + "Transceiver serial number encoded using ASCII characters, + left-aligned with any padding on the right with ASCII spaces + (20h), or ASCII nul (00h) removed, and ASCII less-than (3Ch) + replaced with ASCII open-brace (7Bh) and ASCII more-than (3Eh) + replaced with ASCII close-brace (7Dh). + + Optional node included when the NETCONF Server has determined + the serial number."; + } + + leaf SFF8472-compliance-code { + type enumeration { + enum diagnostics-undefined { + description "undefined compliance code"; + } + enum rev9.3-diagnostics { + description "diagnostics published 08-01-02"; + } + enum rev9.5-diagnostics{ + description "diagnostics published 06-01-04"; + } + enum rev10.2-diagnostics{ + description "diagnostics published 06-01-07"; + } + enum rev11.0-diagnostics{ + description "diagnostics published 05-21-10"; + } + enum rev11.3-diagnostics{ + description "diagnostics published 06-11-13"; + } + enum rev11.4-diagnostics{ + description "diagnostics published 07-24-14"; + } + enum rev12.0-diagnostics{ + description "diagnostics published 08-28-14"; + } + } + config false; + description + "Indication of which feature set(s) are + implemented in the transceiver from Byte 94 of address A0h + https://ta.snia.org/higherlogic/ws/public/download/294/SFF-8472.PDF + + Optional node included when the NETCONF Server has determined + the compliance code."; + + reference "https://ta.snia.org/higherlogic/ws/public/download/294/SFF-8472.PDF"; + } + + leaf connector-type { + type enumeration { + enum unknown { + description "encoded as 00h in Table 4-3 of SFF-8024"; + } + enum subscrber-connector { + description "encoded as 01h in Table 4-3 of SFF-8024"; + } + enum fiber-jack { + description "encoded as 06h in Table 4-3 of SFF-8024"; + } + enum lucent-connector { + description "encoded as 07h in Table 4-3 of SFF-8024"; + } + enum mt-rj { + description "encoded as 08h in Table 4-3 of SFF-8024"; + } + enum multiple-optical { + description "encoded as 09h in Table 4-3 of SFF-8024"; + } + enum sg { + description "encoded as 0Ah in Table 4-3 of SFF-8024"; + } + enum optical-pigtail { + description "encoded as 0Bh in Table 4-3 of SFF-8024"; + } + enum multi-fiber-parralel-optic-1x12 { + description "encoded as 0Ch in Table 4-3 of SFF-8024"; + } + enum multi-fiber-parralel-optic-2x16 { + description "encoded as 0Dh in Table 4-3 of SFF-8024"; + } + enum hssdc_2{ + description "encoded as 20h in Table 4-3 of SFF-8024"; + } + enum copper-pigtail{ + description "encoded as 21h in Table 4-3 of SFF-8024"; + } + enum rj45{ + description "encoded as 22h in Table 4-3 of SFF-8024"; + } + enum no-separable-connector{ + description "encoded as 23h in Table 4-3 of SFF-8024"; + } + enum mxc-2x16{ + description "encoded as 24h in Table 4-3 of SFF-8024"; + } + } + config false; + // TOCHECK: Remove any enumerations which are not applicable + description + "Connector-type indicates the external optical or electrical cable + connector provided as the media interface as defined in the connector + types derived from table 4-3 in SFF-8024. + + Optional node included when the NETCONF Server has determined + the connector type."; + reference "https://ta.snia.org/higherlogic/ws/public/document?document_id=944"; + } + + leaf identifier { + type enumeration { + enum unknown { + description "encoded as 00h in Table 4-1 of SFF-8024"; + } + enum gbic { + description "encoded as 01h in Table 4-1 of SFF-8024"; + } + enum soldered { + description "encoded as 02h in Table 4-1 of SFF-8024"; + } + enum sfp { + description "encoded as 03h in Table 4-1 of SFF-8024"; + } + enum xbi { + description "encoded as 04h in Table 4-1 of SFF-8024"; + } + enum xenpack { + description "encoded as 05h in Table 4-1 of SFF-8024"; + } + enum xfp { + description "encoded as 06h in Table 4-1 of SFF-8024"; + } + enum xff { + description "encoded as 07h in Table 4-1 of SFF-8024"; + } + enum xfp-e { + description "encoded as 08h in Table 4-1 of SFF-8024"; + } + enum xpak { + description "encoded as 09h in Table 4-1 of SFF-8024"; + } + enum x2 { + description "encoded as 0Ah in Table 4-1 of SFF-8024"; + } + enum dwdm-sfp { + description "encoded as 0Bh in Table 4-1 of SFF-8024"; + } + enum qsfp { + description "encoded as 0Ch in Table 4-1 of SFF-8024"; + } + enum qsfp+ { + description "encoded as 0Dh in Table 4-1 of SFF-8024"; + } + } + config false; + description + "Connector identifier as defined in the identifer + types derived from table 4-1 in SFF-8024. + + Optional node included when the NETCONF Server has determined + the identifier type."; + reference "https://members.snia.org/document/dl/26423"; + } + + leaf nominal-bitrate { + type uint32; + config false; + description + "Nominal bitrate in Mb/s (10^6 bits per second). + If needed actual value is rounded to nearest integer. + + Optional node included when the NETCONF Server has determined + the nominal bit rate."; + } + + leaf low-bitrate-margin { + type uint8; + config false; + description + "Minimum supported bitrate as percentage of nominal bitrate + below nominal bitrate. + + Optional node included when the NETCONF Server has determined + the low bit rate margin"; + } + + leaf high-bitrate-margin { + type uint8; + config false; + description + "Maximum supported bitrate as percentage of nominal bitrate + above nominal bitrate. + + Optional node included when the NETCONF Server has determined + the high bitrate margin."; + } + + leaf rx-power-type { + type enumeration { + enum oma { + description "oma = optical modulation amplitude"; + } + enum avp{ + description "avp = average power"; + } + } + config false; + description + "Receieved power measurement type + oma = optical modulation amplitude + avp = average power + + Optional node included when the NETCONF Server has determined + the rx power type."; + } + + leaf rx-power { + type decimal64{ + fraction-digits 4; + } + config false; + description + "Measured RX input power in mW. + + Optional node included when the NETCONF Server has determined + the measured RX power. + + If operating with QSFP, this power corresponds to that of + Lane/Channel 1."; + } + + leaf tx-power { + type decimal64{ + fraction-digits 4; + } + config false; + description + "Measured coupled TX output power in mW. + + Optional node included when the NETCONF Server has determined + the measured coupled TX power."; + } + + leaf tx-bias-current { + type decimal64{ + fraction-digits 4; + } + config false; + description + "Measured transmitter laser bias current in mA. + + Optional node included when the NETCONF Server has determined + the tx bias current. + + If operating with QSFP, this bias current corresponds to that of + Lane/Channel 1."; + } + + leaf voltage { + type decimal64{ + fraction-digits 4; + } + config false; + description + "Internally measured supply voltage in mV. + + Optional node included when the NETCONF Server has determined + the internally measured voltage."; + } + + leaf temperature { + type decimal64 { + fraction-digits 4; + } + config false; + description + "Internally measured module temperature in degrees Celcius. + + Optional node included when the NETCONF Server has determined + the temperature."; + } + + list additional-multi-lane-reporting { + when "(../identifier ='qsfp')or(../identifier ='qsfp+')"; + config false; + description + "Additional reporting according to SFF8436 which specifies real time + channel monitoring for each transmit and receive channel and includes + optical input power and Tx bias current. "; + key lane; + leaf lane { + type uint8 { + range "2..4"; + } + description + "the specific lane/channel associated with the report parameters"; + } + leaf rx-power { + type decimal64{ + fraction-digits 4; + } + config false; + description + "Measured RX input power in mW. + + Optional node included when the NETCONF Server has determined + the measured RX power for a particular lane/channel + - see tabel 7-10 of SFF-8636."; + } + leaf tx-bias-current { + type decimal64{ + fraction-digits 4; + } + config false; + description + "Measured transmitter laser bias current in mA. + + Optional node included when the NETCONF Server has determined + the tx bias current for a particular lane/channel + - see tabel 7-10 of SFF-8636."; + } + leaf tx-power { + type decimal64{ + fraction-digits 4; + } + config false; + description + "Measured coupled TX output power in mW. + + Optional node included when the NETCONF Server has determined + the measured coupled TX power or a particular lane/channel + - see tabel 7010 of SFF-8636."; + } + } + } + + } + + // Top Level Container + + container port-transceivers { + description + "Container for Port transceiver information. + Leaf nodes providing parameters status and diagnostic + information for pluggable transceiver module (like SFP, + SFP+, SFP28)"; + + uses transceiver-group; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-troubleshooting@2019-02-04.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-troubleshooting@2019-02-04.yang new file mode 100644 index 0000000..ae09f8c --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-troubleshooting@2019-02-04.yang @@ -0,0 +1,96 @@ +module o-ran-troubleshooting { + yang-version 1.1; + namespace "urn:o-ran:troubleshooting:1.0"; + prefix "o-ran-trblsht"; + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the operations for the troubleshooting logs. + + 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-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 troubleshooting-status-grouping { + description "grouping used for troubleshooting RPCs"; + leaf status { + type enumeration { + enum SUCCESS { + description "rpc completed correctly"; + } + enum FAILURE { + description "rpc failed"; + } + } + description "result of rpc operation"; + } + leaf failure-reason { + when "../status = 'FAILURE'"; + type string; + description "free form text description why error occurred"; + } + } + + rpc start-troubleshooting-logs { + description + "Management plane triggered to start collecting the troubleshooting logs files of O-RU."; + output { + uses troubleshooting-status-grouping; + } + } + + rpc stop-troubleshooting-logs { + description + "Management plane triggered to stop collecting the troubleshooting logs files of O-RU."; + output { + uses troubleshooting-status-grouping; + } + } + + notification troubleshooting-log-generated { + description + "When new log file generated, send this notification."; + leaf-list log-file-name { + type string; + description + "The list of troubleshooting log file names on the O-RU."; + } + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-udp-echo@2019-02-04.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-udp-echo@2019-02-04.yang new file mode 100644 index 0000000..b65c453 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-udp-echo@2019-02-04.yang @@ -0,0 +1,95 @@ +module o-ran-udp-echo { + yang-version 1.1; + namespace "urn:o-ran:udpecho:1.0"; + prefix "o-ran-echo"; + + import o-ran-interfaces { + prefix "o-ran-int"; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module covers off aspects of interface transport + verification for UDP/IP based C/U plane connections based on UDP Echo. + + 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-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"; + } + +// groupings + + grouping udp-echo-group { + leaf enable-udp-echo { + type boolean; + default false; + description + "whether O-RU's UDP ech server is enabled"; + } + + leaf dscp-config { + type enumeration { + enum REFLECTIVE { + description + "DSCP in echoed datagrams is copied from received datagram"; + } + enum EF { + description + "DSCP in echoed datagrams is always be set to expeditied + forwarding Per Hop Behaviour."; + } + } + default EF; + description "configuration of UDP echo DSCP"; + } + + leaf echo-replies-transmitted { + type uint32; + config false; + description + "The total number of UDP echo replies transmitted by the O-RU."; + } + } + + container udp-echo { + if-feature o-ran-int:UDPIP-BASED-CU-PLANE; + description "container for udp echo"; + + uses udp-echo-group; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-uplane-conf@2020-12-10.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-uplane-conf@2020-12-10.yang new file mode 100644 index 0000000..57177f5 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-uplane-conf@2020-12-10.yang @@ -0,0 +1,2744 @@ +module o-ran-uplane-conf { + yang-version 1.1; + namespace "urn:o-ran:uplane-conf:1.0"; + prefix "o-ran-uplane-conf"; + + import o-ran-processing-element { + prefix "o-ran-pe"; + } + + import ietf-interfaces { + prefix "if"; + } + + import o-ran-module-cap { + prefix "mcap"; + revision-date 2020-12-10; + } + + import o-ran-compression-factors { + prefix "cf"; + revision-date 2020-08-10; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the module capabilities for + the O-RAN Radio Unit U-Plane configuration. + + Copyright 2020 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 "2020-12-10" { + description + "version 5.0.0 + + 1) introduces new coupling method coupling-via-frequency-and-time-with-priorities-optimized + 2) introduces new max-highest-priority-sections-per-slot parameter"; + + reference "ORAN-WG4.M.0-v05.00"; + } + + revision "2020-08-10" { + description + "version 4.0.0 + + 1) parameters allowing for static PRACH configuration introduced + 2) parameters allowing for static SRS configuration introduced + 3) parameters allowing for configuration of TDD pattern introduced + 4) Backward compatible change to introduce new parameter 'coupling-method' related + to Section Description Priority to serve for CUS-Plane CR"; + + reference "ORAN-WG4.M.0-v04.00"; + } + + revision "2020-04-17" { + description + "version 3.0.0 + + 1) Adding optional little endian support + 2) Adding a new capability parameter to indicate that the O-RU + supports regularizationFactor in section type 5 + 3) Added support for Dynamic Spectrum Sharing feature + 4) Clarify the supported number of reMasks in RU side + 5) Section extension for grouping multiple ports + 6) adding PRACH formats to endpoint capabilities"; + + reference "ORAN-WG4.M.0-v03.00"; + } + + revision "2019-07-03" { + description + "version 1.1.0 + + 1) added new leaf multiple-numerology-supported to enable O-RU to report + whether it supports multiple numerologies. + + 2) fixing broken constraints (configuration cannot be dependent on + operational state). This is a backwards incompatible revision. + + As these constraints only apply when the LAA feature is used, and also + when considering the limited number of implementation that need to be + taken into consideration for backwards compatibility, it has been + agreed to NOT increment the namespace integer. + + 3) added frequency related capabilities for tx-arrays and rx-array + + 4) removed redundant LAA import"; + + 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"; + } + + feature EAXC-GAIN-CORRECTION { + description + "Presence of feature indicates that O-RU supports eAxC specific gain correction."; + } + + feature TX-REFERENCE-LEVEL { + description + "Presence of feature indicates that O-RU supports TX gain reference level control"; + } + + typedef prach-preamble-format { + type enumeration { + enum LTE-0 { + description + "LTE PRACH Preamble format 0"; + } + enum LTE-1 { + description + "LTE PRACH Preamble format 1"; + } + enum LTE-2 { + description + "LTE PRACH Preamble format 2"; + } + enum LTE-3 { + description + "LTE PRACH Preamble format 3"; + } + enum LTE-4 { + description + "LTE PRACH Preamble format 4"; + } + enum LTE-NB0 { + description + "LTE Narrowband PRACH format 0"; + } + enum LTE-NB1 { + description + "LTE Narrowband PRACH format 1"; + } + enum NR-0 { + description + "5GNR PRACH Preamble format 0"; + } + enum NR-1 { + description + "5GNR PRACH Preamble format 1"; + } + enum NR-2 { + description + "5GNR PRACH Preamble format 2"; + } + enum NR-3 { + description + "5GNR PRACH Preamble format 3"; + } + enum NR-A1 { + description + "5GNR PRACH Preamble format A1"; + } + enum NR-A2 { + description + "5GNR PRACH Preamble format A2"; + } + enum NR-A3 { + description + "5GNR PRACH Preamble format A3"; + } + enum NR-B1 { + description + "5GNR PRACH Preamble format B1"; + } + enum NR-B2 { + description + "5GNR PRACH Preamble format B2"; + } + enum NR-B3 { + description + "5GNR PRACH Preamble format B3"; + } + enum NR-B4 { + description + "5GNR PRACH Preamble format B4"; + } + enum NR-C0 { + description + "5GNR PRACH Preamble format C0"; + } + enum NR-C2 { + description + "5GNR PRACH Preamble format C2"; + } + } + + description + "PRACH preamble format definition"; + } + + typedef polarisation_type { + type enumeration { + enum MINUS_45 { + description "MINUS_45"; + } + enum ZERO { + description "ZERO"; + } + enum PLUS_45 { + description "PLUS_45"; + } + enum PLUS_90 { + description "PLUS_90"; + } + } + description "Type definition for polarisations"; + } + + grouping general-config { + description "a group for general configuration"; + + container general-config { + description "a container for general configuration"; + + leaf regularization-factor-se-configured { + type boolean; + default false; + description + "Informs if regularizationfactor in section extension is configured(true) or not(false), this + leaf indicates whether the O-DU will send the regularizationfactor in section extension. + + If the O-RU does not support regularization-factor-se-supported in o-ran-module-cap.yang, + this leaf is ignored."; + } + + leaf little-endian-byte-order { + type boolean; + default false; + + description + "If little endian byte order for C/U plane data flows is supported by + the O-RU, indicates if the O-RU should use little endian byte order + for all UL and DL C/U plane data flows. + + If little endian byte order is NOT supported, this node is ignored + (and the default bigendian byte order used)"; + } + } + } + + grouping laa-carrier-config { + description "Carrier Configuration for support of LAA. "; + leaf ed-threshold-pdsch { + type int8; + units dBm; + description + "This value indicates Energy Detection(ED) threshold for LBT for PDSCH and for measurements in dBm."; + } + + leaf ed-threshold-drs { + type int8; + units dBm; + description + "This value indicates Energy Detection(ED) threshold for LBT for DRS in dBm."; + } + + leaf tx-antenna-ports { + type uint8; + description + "This value indicates Tx antenna ports for DRS (1, 2, 4)"; + } + + leaf transmission-power-for-drs { + type int8; + units decibels; + description + "This value indicates offset of Cell specific reference Signal(CRS) power to reference signal power (dB). + DRS signal consists of CRS, PSS, SSS, and optionally CSI-RS."; + } + + leaf dmtc-period { + type enumeration { + enum FORTY { + description + "40 ms"; + } + enum EIGHTY { + description + "80 ms"; + } + enum ONE-HUNDRED-SIXTY { + description + "160 ms"; + } + } + units milliseconds; + description + "This value indicates DRS measurement timing configuration (DMTC) period in ms"; + } + + leaf dmtc-offset { + type uint8; + units subframes; + description + "This value indicates dmtc offset in Subframes."; + } + + leaf lbt-timer { + type uint16; + units milliseconds; + description + "This value indicates LBT Timer in milliseconds."; + } + + list max-cw-usage-counter { + when "/mcap:module-capability/mcap:rw-sub-band-info/mcap:rw-self-configure = 'true'"; + key "priority"; + description ""; + leaf priority { + type enumeration { + enum P1 { + description "priority 1"; + } + enum P2 { + description "priority 2"; + } + enum P3 { + description "priority 3"; + } + enum P4 { + description "priority 4"; + } + } + description "This value provides the priority class traffic for which the counter is calculated."; + } + + leaf counter-value { + type uint8 { + range "1..8"; + } + description "This value indicates the maximum value of counter + which shows how many max congestion window value is used for backoff + number of priority class traffic. This value is defined at 3GPP 36.213 + section 15.1.3 as K."; + } + } + } + + grouping coupling-methods { + description + "Grouping for configuration of desired C-Plane / U-Plane coupling methods (if supported)"; + leaf coupling-to { + type leafref { + path "/mcap:module-capability/mcap:ru-capabilities/mcap:coupling-methods/mcap:coupling-via-frequency-and-time"; + require-instance false; + } + + description + "RW instance of RO parameter."; + } + leaf coupling-method { + when "../coupling-to = 'true'"; + type enumeration{ + enum NORMAL { + description "Coupling via sectionId value. This value can be used always."; + } + enum FREQUENCY_AND_TIME { + description "Coupling via frequency and time. Can be used when coupling-via-frequency-and-time = true + or coupling-via-frequency-and-time-with-priorities = true in o-ran-module-cap.yang"; + } + enum FREQUENCY_AND_TIME_WITH_PRIORITIES { + description "Coupling via frequency and time with priorities. Can be used when + coupling-via-frequency-and-time-with-priorities = true in o-ran-module-cap.yang"; + } + enum FREQUENCY_AND_TIME_WITH_PRIORITIES_OPTIMIZED { + description "Coupling via frequency and time with priorities optimized. Can be used when + coupling-via-frequency-and-time-with-priorities-optimized = true in o-ran-module-cap.yang"; + } + } + default NORMAL; + description + "Method of coupling between C-Plane and U-Plane messages; see methods of coupling + of C-Plane and U-Plane in CUS-Plane specification. If an O-RU doesn't support the + necessary capability as defined in o-ran-module-cap.yang, the O-RU shall respond + with rpc-error including an error-message describing the error condition"; + } + } + + grouping eaxc { + description + "One eAxC identifier (eAxC ID) comprises a band and sector + identifier (BandSector_ID), a component-carrier identifier (CC_ID) and a + spatial stream identifier (RU_Port_ID). + + In this version of the specification, one eAxC contains only one spatial + stream (i.e. one beam per subcarrier) at a time. + + Bit allocation is subdivided as follows: + * O_DU_Port_ID: Used to differentiate processing units at O-DU + * BandSector_ID: Aggregated cell identifier + * CC_ID: distinguishes Carrier Components + * RU_Port_ID: Used to differentiate spatial streams or beams on the O-RU + + The bitwidth of each of the above fields is variable this model is supposed to check + if we are occpying bits continuously but we do not have to occupy all 16 bits"; + + + leaf o-du-port-bitmask { + type uint16; + mandatory true; + description + "mask for eaxc-id bits used to encode O-DU Port ID"; + } + + leaf band-sector-bitmask { + type uint16; + mandatory true; + description + "mask for eaxc-id bits used to encode the band sector ID"; + } + + leaf ccid-bitmask { + type uint16; + mandatory true; + description + "mask for eaxc-id bits used to encode the component carrier id"; + } + + leaf ru-port-bitmask { + type uint16; + mandatory true; + description + "mask for eaxc-id bits used to encode the O-RU Port ID"; + } + + leaf eaxc-id { + type uint16; + mandatory true; + description + "encoded value of eaxcid to be read by CU-Plane"; + } + } + + grouping parameters { + description + "Grouping of all parameters common between UL and DL"; + + leaf name { + type string; + mandatory true; + description "Unique name of array antenna"; + } + + leaf number-of-rows { + type uint16; + mandatory true; + description "Number of rows array elements are shaped into - M"; + } + + leaf number-of-columns { + type uint16; + mandatory true; + description "Number of columns array elements are shaped into - N"; + } + + leaf number-of-array-layers { + type uint8; + mandatory true; + description "Number of array layers array elements are shaped into - Q"; + } + + leaf horizontal-spacing { + type decimal64 { + fraction-digits 5; + } + units Meter; + + description "Average distance between centers of nearby AE in horizontal direction (in array coordinates system)"; + } + + leaf vertical-spacing{ + type decimal64 { + fraction-digits 5; + } + units Meter; + + description "Average distance between centers of nearby AE in vertical direction (in array coordinates system)"; + } + + container normal-vector-direction { + description + "Counter-clockwise rotation around z and y axis."; + + leaf azimuth-angle{ + type decimal64 { + fraction-digits 4; + } + units Degrees; + + description "Azimuth angle, counter-clockwise rotation around z-axis. Value 'zero' points to broad-side, value '90' points to y-axis"; + } + leaf zenith-angle{ + type decimal64 { + fraction-digits 4; + } + units Degrees; + + description "Zenith angle, counter-clockwise rotation around y-axis. Value 'zero' points to zenith, value '90' points to horizon"; + } + } + + container leftmost-bottom-array-element-position { + description "Structure describing position of leftmost, bottom array element."; + leaf x { + type decimal64 { + fraction-digits 4; + } + units Meter; + + description "X dimension of position of leftmost, bottom array element"; + } + + leaf y { + type decimal64 { + fraction-digits 4; + } + units Meter; + + description "Y dimension of position of leftmost, bottom array element"; + } + + leaf z { + type decimal64 { + fraction-digits 4; + } + units Meter; + + description "Z dimension of position of leftmost, bottom array element"; + } + } + list polarisations { + key "p"; + min-elements 1; + max-elements 2; + + description + "List of supported polarisations."; + + leaf p { + type uint8; + mandatory true; + description + "Polarisation index. See CUS-plane"; + } + + leaf polarisation { + type polarisation_type; + mandatory true; + description "Type of polarisation supported by array."; + } + } + leaf band-number { + type leafref { + path "/mcap:module-capability/mcap:band-capabilities/mcap:band-number"; + } + mandatory true; + description + "This parameter informing which frequency band particular antenna + array is serving for. + Intended use is to deal with multiband solutions."; + } + } + + grouping array-choice { + choice antenna-type { + case tx { + leaf tx-array-name { + type leafref { + path "/o-ran-uplane-conf:user-plane-configuration/o-ran-uplane-conf:tx-arrays/o-ran-uplane-conf:name"; + } + + description + "Leafref to tx array if such is choosen"; + } + } + case rx { + leaf rx-array-name { + type leafref { + path "/o-ran-uplane-conf:user-plane-configuration/o-ran-uplane-conf:rx-arrays/o-ran-uplane-conf:name"; + } + + description + "Leafref to rx array if such is choosen"; + } + } + description + "Choice for antenna type"; + } + description + "Elements which groups choice for antenna type"; + } + + grouping scs-config { + description + "It groups all parameters related to SCS configuration"; + + leaf frame-structure { + type uint8; + + description + "This parameter defines the frame structure. The first 4 bits define the FFT/iFFT size + being used for all IQ data processing related to this message. + The second 4 bits define the sub carrier spacing as well as the number of slots per 1ms sub-frame + according to 3GPP TS 38.211, taking for completeness also 3GPP TS 36.211 into account"; + } + + leaf cp-type { + type enumeration { + enum NORMAL { + description + "Normal cyclic prefix"; + } + + enum EXTENDED { + description + "Extended cyclic prefix"; + } + } + + description + "Provides type of CP (cyclic prefix) if section type 3 is not used or type of CP cannot be determined from cpLength."; + } + + leaf cp-length { + type uint16; + units Ts; + mandatory true; + description + "Used for symbol 0 for NR & LTE, and symbol 7*2u for NR. + See CUS-plane"; + } + + leaf cp-length-other { + type uint16; + units Ts; + mandatory true; + description + "Used for other symbols than by cp-length above"; + } + + leaf offset-to-absolute-frequency-center { + type int32; + mandatory true; + description + "This provides value of freqOffset to be used if section type 3 is not used. See freqOffset in CUS-plane. + offset-to-absolute-frequency-center defines the relative spacing between the center of RE#0 of RB#0 to the center-of-channel-bandwidth. + If offset-to-absolute-frequency-center for NR with SCS=15kHz is odd, + it implies that 7.5kHz shift as indicated by the parameter frequencyShift7p5khz for UL is applied. + When type (in tx/rx-array-carrier) is DSS, “offset-to-absolute-frequency-center” indicates the 1st RE of 1st RB of NR."; + } + + list number-of-prb-per-scs { + key scs; + description + "List of configured for each SCS that will be used."; + + leaf scs { + type mcap:scs-config-type; + description + "Value corresponds to SCS values defined for frameStructure in C-plane. + Note: set of allowed values is restricted by SCS derived from values in supported-frame-structures."; + } + + leaf number-of-prb { + type uint16; + mandatory true; + description + "Determines max number of PRBs that will be used in all sections per one symbol. + This is affecting allocation of resources to endpoint. Value shall not exceed constrains + defined by max-prb-per-symbol of endpoint type. In addition sum (over all used epoints + within a group of endpoints sharing resources) of number-of-prb rounded up to + nearest value from prb-capacity-allocation-granularity shall not exceed max-prb-per-symbol of the group."; + } + } + } + + grouping tx-common-array-carrier-elements { + description + "This grouping containes all common parameters for tx-array-carriers and rx-array-carriers"; + + leaf absolute-frequency-center { + type uint32; + status deprecated; + description + "deprecated in version 5.0.0 and replaced with offset-to-absolute-frequency-center + and common FREF translated from absolute-frequency-center (NREF) as defined in 38.104"; + } + + leaf center-of-channel-bandwidth { + type uint64; + units Hz; + mandatory true; + description + "Center frequency of channel bandwidth in Hz. Common for all numerologies. + center-of-channel-bandwidth is the FREF translated from absolute-frequency-center (NREF) as per 3GPP TS 38.104"; + } + + leaf channel-bandwidth { + type uint64; + units Hz; + mandatory true; + + description + "Width of carrier given in Hertz"; + } + + leaf active { + type enumeration { + enum INACTIVE { + description + "carrier does not provide signal - transmission is disabled"; + } + enum SLEEP{ + description + "carrier is fully configured and was active but is energy saving mode"; + } + enum ACTIVE{ + description + "carrier is fully configured and properly providing the signal"; + } + } + default INACTIVE; + + description + "Indicates if transmission is enabled for this array carriers. Note that Netconf server uses state parameter + to indicate actual state of array carriers operation. When array carriers is in sleep status, + Netconf server rejects all other operation request to tx-array-carriers object except either request to change from sleep + to active status or delete MO operation (see 4.8) to the object."; + } + + leaf state { + type enumeration { + enum DISABLED { + description + "array carrier is not active - transmission of signal is disabled."; + } + enum BUSY { + description + "array carrier is processing an operation requested by change of active parameter. + When array carriers is BUSY the transmission of signal is not guaranteed."; + } + enum READY { + description + "array carrier had completed activation operation - is active and transmission of signal is ongoing."; + } + } + config false; + mandatory true; + description + "Indicates state of array carriers activation operation"; + } + + leaf type { + type enumeration { + enum NR { + description + "5G technology"; + } + enum LTE { + description + "LTE technology"; + } + enum DSS_LTE_NR { + if-feature mcap:DSS_LTE_NR; + description + "NR and LTE technologies in Dynamic Spectrum Sharing mode"; + } + } + description + "Type of carrier. Indicates array-carrier technology."; + } + + leaf duplex-scheme { + type enumeration { + enum TDD { + description + "TDD scheme"; + } + enum FDD { + description + "FDD scheme"; + } + } + config false; + + description + "Type of duplex scheme O-RU supports."; + } + leaf rw-duplex-scheme { + type leafref { + path "/user-plane-configuration/tx-array-carriers[name=current()/../name]" + "/duplex-scheme"; + require-instance false; + } + description + "Config true type of duplex scheme."; + } + leaf rw-type { + type leafref { + path "/user-plane-configuration/tx-array-carriers[name=current()/../name]" + "/type"; + require-instance false; + } + description + "Config true type of carrier."; + } + } + + grouping rx-common-array-carrier-elements { + description + "This grouping containes all common parameters for tx-array-carriers and rx-array-carriers"; + + leaf absolute-frequency-center { + type uint32; + status deprecated; + description + "deprecated in version 5.0.0 and replaced with offset-to-absolute-frequency-center + and common FREF translated from absolute-frequency-center (NREF) as defined in 38.104"; + } + + leaf center-of-channel-bandwidth { + type uint64; + units Hz; + mandatory true; + description + "Center frequency of channel bandwidth in Hz. Common for all numerologies. + center-of-channel-bandwidth is the FREF translated from absolute-frequency-center (NREF) as per 3GPP TS 38.104"; + } + + leaf channel-bandwidth { + type uint64; + units Hz; + mandatory true; + + description + "Width of carrier given in Hertz"; + } + + leaf active { + type enumeration { + enum INACTIVE { + description + "carrier does not provide signal - transmission is disabled"; + } + enum SLEEP{ + description + "carrier is fully configured and was active but is energy saving mode"; + } + enum ACTIVE{ + description + "carrier is fully configured and properly providing the signal"; + } + } + default INACTIVE; + + description + "Indicates if transmission is enabled for this array carriers. Note that Netconf server uses state parameter + to indicate actual state of array carriers operation. When array carriers is in sleep status, + Netconf server rejects all other operation request to tx-array-carriers object except either request to change from sleep + to active status or delete MO operation (see 4.8) to the object."; + } + + leaf state { + type enumeration { + enum DISABLED { + description + "array carrier is not active - transmission of signal is disabled."; + } + enum BUSY { + description + "array carrier is processing an operation requested by change of active parameter. + When array carriers is BUSY the transmission of signal is not guaranteed."; + } + enum READY { + description + "array carrier had completed activation operation - is active and transmission of signal is ongoing."; + } + } + config false; + mandatory true; + description + "Indicates state of array carriers activation operation"; + } + + leaf type { + type enumeration { + enum NR { + description + "5G technology"; + } + enum LTE { + description + "LTE technology"; + } + enum DSS_LTE_NR { + if-feature mcap:DSS_LTE_NR; + description + "NR and LTE technologies in Dynamic Spectrum Sharing mode"; + } + } + description + "Type of carrier. Indicates array-carrier technology."; + } + + leaf duplex-scheme { + type enumeration { + enum TDD { + description + "TDD scheme"; + } + enum FDD { + description + "FDD scheme"; + } + } + config false; + + description + "Type of duplex scheme O-RU supports."; + } + } + + grouping endpoint-section-capacity { + leaf max-control-sections-per-data-section { + type uint8 { + range "1..12"; + } + description + "Max number of C-plane sections (C-plane section is part of C-plane message that carries 'section fields') + referring to same U-plane section (U-plane section is part of U-plane message that carries + 'section header fields' and 'PRB fields') that is supported by endpoint. + Note that additional limitations specific for each section type apply on top of this number."; + } + leaf max-sections-per-symbol { + type uint16; + description + "Max number of sections within one symbol that can be processed by endpoint + or processed collectively by group of endpoints sharing capacity"; + } + leaf max-sections-per-slot { + type uint16; + description + "Max number of sections within one slot that can be processed by endpoint + or processed collectively by group of endpoints sharing capacity."; + } + leaf max-highest-priority-sections-per-slot { + must "current()<../max-sections-per-slot" { + error-message "the sectionID for the highest priority needs to be less than the max sectionIds per slot"; + } + type uint16; + description + "Max number of highest priority sections within one slot that can be processed by endpoint or processed collectively by + group of endpoints sharing capacity. This leaf applies only when coupling-via-frequency-and-time-with-priorities-optimized + is true, in other instances this leaf is ignored by the O-RU. The sectionId for highest priority section descriptions shall + start from 0 to specified max value and is a subset of max-sections-per-slot and must be less than max-sections-per-slot."; + } + + leaf max-remasks-per-section-id { + type uint8 { + range "1..12"; + } + default 12; + description + "maximum number of different reMask values that is applied to a PRB + within one section id. This value can be processed by endpoint + or processed collectively by group of endpoints sharing capacity"; + } + + description + "Parameters describing section capacity where section is undestood as number of different sectionId values"; + } + + grouping endpoint-beam-capacity { + leaf max-beams-per-symbol { + type uint16; + description + "Max number of beams within one symbol that can be processed by endpoint + or processed collectively by group of endpoints sharing capacity"; + } + leaf max-beams-per-slot { + type uint16; + description + "Max number of beams within one slot that can be processed by endpoint + or processed collectively by group of endpoints sharing capacity"; + } + + description + "Parameters describing beam capacity where number of beams is understood as number of different beamId values"; + } + + grouping endpoint-prb-capacity { + leaf max-prb-per-symbol { + type uint16; + description + "Max number of prbs within one symbol that can be processed by endpoint + or processed collectively by group of endpoints sharing capacity"; + } + + description + "Attributes presenting processing capacity related to PRB."; + } + + grouping endpoint-numerology-capacity { + leaf max-numerologies-per-symbol { + type uint16; + description + "Max number of numerologies within one symbol that can be processed by endpoint + or processed collectively by group of endpoints sharing capacity"; + } + + description + "Attributes presenting processing capacity related to numerology. + + This leaf contains valid data only when multiple-numerology-supported + is set to true."; + } + + grouping endpoint-static-config-support { + leaf static-config-supported { + type enumeration { + enum NONE { + description + "The endpoint does not support static PRACH / SRS configuration. + Reception of PRACH / SRS is possible through real time C-Plane messages + if other endpoint capabilities allow for that."; + } + enum PRACH { + if-feature mcap:PRACH-STATIC-CONFIGURATION-SUPPORTED; + description + "The endpoint supports statically configured PRACH reception"; + } + enum SRS { + if-feature mcap:SRS-STATIC-CONFIGURATION-SUPPORTED; + description + "The endpoint supports statically configured SRS reception"; + } + } + default NONE; + + description + "The parameter informs if endpoint can be statically configured to process PRACH or SRS reception"; + } + + leaf max-prach-patterns { + when "(/user-plane-configuration/static-low-level-rx-endpoints[name=current()/../name]/static-config-supported = 'PRACH')"; + type uint8; + description + "Maximum number of PRACH patterns the endpoint can handle in PRACH configuration"; + } + + leaf max-srs-patterns { + when "(/user-plane-configuration/static-low-level-rx-endpoints[name=current()/../name]/static-config-supported = 'SRS')"; + type uint8; + description + "Maximum number of SRS patterns the endpoint can handle in SRS configuration"; + } + + description + "Endpoint's capabilities related to static PRACH / SRS configuration."; + } + + grouping endpoint-tdd-pattern-support { + leaf configurable-tdd-pattern-supported { + if-feature mcap:CONFIGURABLE-TDD-PATTERN-SUPPORTED; + type boolean; + default false; + + description + "The parameter informs if endpoint supports configuration for TDD pattern"; + } + + leaf tdd-group { + type uint8; + description + "Parameter is used to group static-low-level-[tr]x-endpoints. + Note: [tr]x-array-carriers using static-low-level-[tr]x-endpoints + having the same value of tdd-group, must have the same TDD switching + points and the same directions to the air interface granted - regardless TDD switching + is controlled by M-Plane or by C-Plane"; + } + + description + "This grouping exposes static-low-level-[tr]x-endpoint's capabilities related to its support for configurable + TDD patterns and limitations regarding common TDD switching per groups of endpoints."; + } + + grouping uplane-conf-group { + description + "Grouping for uplane configuration related parameters"; + + list low-level-tx-links { + key name; + description + "Object model for low-level-tx-link configuration"; + + leaf name { + type string; + description + "Unique name of low-level-tx-link object."; + } + + leaf processing-element { + type leafref { + path "/o-ran-pe:processing-elements/o-ran-pe:ru-elements/o-ran-pe:name"; + } + mandatory true; + description + "Contains name of processing-element to be used as transport by low-level-tx-link"; + } + + leaf tx-array-carrier { + type leafref { + path "/user-plane-configuration/tx-array-carriers/name"; + } + mandatory true; + description + "Contains name of tx-array-carriers MO to be used as transport by low-level-tx-link"; + } + + leaf low-level-tx-endpoint { + type leafref { + path "/user-plane-configuration/low-level-tx-endpoints/name"; + } + mandatory true; + description + "Contains name of low-level-tx-endpoints MO to be used as transport by low-level-tx-link"; + } + } + + list low-level-rx-links { + key name; + description + "Object model for low-level-rx-links configuration"; + + leaf name { + type string; + + description + "Unique name of low-level-rx-links object."; + } + + leaf processing-element { + type leafref { + path "/o-ran-pe:processing-elements/o-ran-pe:ru-elements/o-ran-pe:name"; + } + mandatory true; + description + "Contains name of processing-element to be used as transport by LowLevelTxLink"; + } + + leaf rx-array-carrier { + type leafref { + path "/user-plane-configuration/rx-array-carriers/name"; + } + mandatory true; + + description + "Contains name of rx-array-carriers MO to be used as transport by low-level-rx-links"; + } + + leaf low-level-rx-endpoint { + type leafref { + path "/user-plane-configuration/low-level-rx-endpoints/name"; + } + mandatory true; + + description + "Contains name of low-level-rx-endpoints MO to be used as transport by low-level-rx-links"; + } + + leaf user-plane-uplink-marking { + type leafref { + path "/o-ran-pe:processing-elements/o-ran-pe:enhanced-uplane-mapping/o-ran-pe:uplane-mapping/o-ran-pe:up-marking-name"; + } + description + "Parameter to set the non-default marking for user-plane"; + } + } + + list endpoint-types { + key "id"; + config false; + description + "Properties of endpoint that are common to multiple endpoints if such are identified"; + + leaf id { + type uint16; + description + "Identifies type of endpoints sharing same properties. Values shall start with 0 and shall be allocated without gaps."; + } + + list supported-section-types { + key "section-type"; + description + "Indicates section types and extensions endpoints of this type support"; + + leaf section-type { + type uint8; + + description + "This parameter determines the characteristics of U-plane data to be transferred or received from a beam with one pattern id."; + } + + leaf-list supported-section-extensions { + type uint8; + + description + "This parameter provides the extension types supported by the O-RU + which provides additional parameters specific to the subject data extension"; + } + } + + leaf-list supported-frame-structures { + type uint8; + + description + "List of supported values of frame structure"; + } + + leaf managed-delay-support { + type enumeration { + enum MANAGED { + description + "Time managed delays are supported"; + } + + enum NON_MANAGED { + description + "Non time managed delays are supported"; + } + + enum BOTH { + description + "Both time managed and non time managed delays are supported"; + } + } + + description + "Type of delay supported by the endpoint"; + } + + leaf multiple-numerology-supported { + type boolean; + default true; + description + "Indicates whether the endpoint type supports multiple numerologies"; + } + + leaf max-numerology-change-duration { + type uint16 { + range "0..10000"; + } + + units Ts; + description + "Maximum gap of endpoint operation that will be caused by changing of + numerology. + + This time is required for reconfiguration and flushing of pipes. + + This leaf contains valid data only when multiple-numerology-supported + is set to true."; + } + + uses endpoint-section-capacity; + uses endpoint-beam-capacity; + uses endpoint-prb-capacity; + + leaf-list prb-capacity-allocation-granularity { + type uint16; + + description + "List of capacity allocation steps. O-RU allocates PRB capacity rounding it up to nearest value N + from prb-capacity-allocation-granularity such that M >= number-of-prb-per-scs. + See also number-of-prb-per-scs/number-of-prb."; + } + + uses endpoint-numerology-capacity; + } + + list endpoint-capacity-sharing-groups { + key "id"; + config false; + description + "Represents groups of endpoints that share capacity. Depending on O-RU implementation, + processing resources that handle CU-plane (e.g. memory to keep sections and beams) + could be allocated per endpoint or shared between several endpoints. + To address this O-RU shall reports own capability per endpoint (see endpoint-types) + and per group of endpoints sharing capacity. + If endpoint is in multiple groups then resulting constraint is minimum over all groups. + Note: values of parameters representing capacity that is not shared between endpoints in a group + shall be set to max value of specific parameter; this effectively removes related constraint."; + + leaf id { + type uint16; + description + "Identifies group of endpoints sharing resources. + Values shall start with 0 and shall be allocated without gaps."; + } + uses endpoint-section-capacity; + uses endpoint-beam-capacity; + uses endpoint-prb-capacity; + uses endpoint-numerology-capacity; + + leaf max-endpoints { + type uint16; + description + "Indicates how many endpoints in the group can be used4 simultaneously"; + } + leaf max-managed-delay-endpoints { + type uint16; + description + "Number of endpoints supporting managed delay that can be used (configured for use) at a time"; + } + leaf max-non-managed-delay-endpoints { + type uint16; + description + "Number of endpoints supporting non-managed delay that can be used (configured for use) at a time"; + } + } + + list endpoint-prach-group { + key "id"; + config false; + description + "Represents group of a series of PRACH preamble formats"; + + leaf id { + type uint16; + description + "Identifies group of PRACH preamble formats."; + } + + leaf-list supported-prach-preamble-formats { + type prach-preamble-format; + min-elements 1; + description + "the list of PRACH preamble formats supported by the endpoint-type that is + applicable to static-low-level-rx-endpoints in the O-RU"; + } + + } + + list supported-compression-method-sets { + key "id"; + config false; + description + "List of available compression methods supported by device"; + + leaf id { + type uint16; + description + "Identification number for compression method set"; + } + + list compression-method-supported { + uses cf:compression-parameters; + + leaf-list fs-offset { + if-feature cf:CONFIGURABLE-FS-OFFSET; + type uint8; + default 0; + description + "Adjusts FS (full scale) value of IQ format relative to FS derived from unmodified IQ format. + Please refer to CU-Plane specification for details"; + + } + description + "List of supported compression methods by O-RU + Note: if O-RU supports different compression methods per endpoint + then please refer to endpoints to have information what + exactly is supported on paticular endpoint"; + } + } + + list static-low-level-tx-endpoints { + key name; + config false; + description + "Object model for static-low-level-tx-endpoints configuration"; + + leaf name { + type string; + + description + "Unique name of static-low-level-tx-endpoints object."; + } + + leaf-list restricted-interfaces { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + description + "Optionally used to indicate that a low-level link is constrained to operate only via a subset of the available interfaces."; + } + + leaf array { + type leafref { + path "/user-plane-configuration/tx-arrays/name"; + } + mandatory true; + description + "Contains distname of tx-arrays, particular low-level-tx-endpoints is in hardware dependency with. + Note: single instance of tx-arrays can be referenced by many instances of low-level-tx-endpoints + (e.g. to allow DU to handle multiple fronthauls and multiple component carriers)."; + } + + leaf endpoint-type { + type leafref { + path "../../endpoint-types/id"; + } + + description + "Reference to endpoint type capabilities list element supported by this endpoint"; + } + + leaf-list capacity-sharing-groups { + type leafref { + path "../../endpoint-capacity-sharing-groups/id"; + } + + description + "Reference to capacities of sharing-groups supported by this endpoint"; + } + + list supported-reference-level { + if-feature TX-REFERENCE-LEVEL; + key "id"; + description + "Informs about supported ranges for gain reference level."; + + leaf id { + type uint16; + description + "Identification number for particular range"; + } + + leaf min { + type decimal64 { + fraction-digits 4; + } + units dB; + mandatory true; + description + "Minimum of supported gain reference level"; + } + + leaf max { + type decimal64 { + fraction-digits 4; + } + units dB; + mandatory true; + description + "Maximum of supported gain reference level"; + } + } + + container compression { + description + "Container collecting compression related parameters."; + + leaf dynamic-compression-supported { + type boolean; + + description + "Informs if endpoint supports dynamic compression method"; + } + + leaf realtime-variable-bit-width-supported { + type boolean; + + description + "Informs if endpoint supports realtime variable bit with"; + } + + leaf supported-compression-set-id { + type leafref { + path "../../../supported-compression-method-sets/id"; + } + + description + "Id of supported compression set for this endpoint"; + } + } + + uses endpoint-tdd-pattern-support; + + } + + list static-low-level-rx-endpoints { + key name; + config false; + description + "Object model for static-low-level-rx-endpoints configuration"; + + leaf name { + type string; + + description + "Unique name of static-low-level-rx-endpoints object."; + } + + leaf-list restricted-interfaces { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + description + "Optionally used to indicate that a low-level link is constrained to operate only via a subset of the available interfaces."; + } + + leaf array { + type leafref { + path "/user-plane-configuration/rx-arrays/name"; + } + mandatory true; + description + "Contains distname of rx-arrays, particular low-level-rx-endpoints is in hardware dependency with. + Note: single instance of rx-arrays can be referenced by many instances of low-level-rx-endpoints + (e.g. to allow DU to handle multiple fronthauls and multiple component carriers)."; + } + + leaf endpoint-type { + type leafref { + path "../../endpoint-types/id"; + } + + description + "Reference to endpoint type capabilities list element supported by this endpoint"; + } + + leaf-list capacity-sharing-groups { + type leafref { + path "../../endpoint-capacity-sharing-groups/id"; + } + + description + "Reference to capacities of sharing-groups supported by this endpoint"; + } + + leaf prach-group { + type leafref { + path "../../endpoint-prach-group/id"; + require-instance false; + } + description + "An optional leaf used for those rx endpoints that support PRACH, indicating + the group id describing the set of of PRACH preambles supported"; + } + + container compression { + description + "Container collecting compression related parameters."; + + leaf dynamic-compression-supported { + type boolean; + + description + "Informs if endpoint supports dynamic compression method"; + } + + leaf realtime-variable-bit-width-supported { + type boolean; + + description + "Informs if endpoint supports realtime variable bit with"; + } + + leaf supported-compression-set-id { + type leafref { + path "../../../supported-compression-method-sets/id"; + } + + description + "Id of supported compression set for this endpoint"; + } + } + + uses endpoint-static-config-support; + + uses endpoint-tdd-pattern-support; + + } + + list low-level-tx-endpoints { + key "name"; + + description + "Object model for low-level-tx-endpoints configuration - augmented static-low-level-tx-endpoints by local-address + which cannot be added to static low-level-tx-endpoints as we cannot have modificable element in static object"; + + leaf name { + type leafref { + path "/user-plane-configuration/static-low-level-tx-endpoints/name"; + require-instance false; + } + mandatory true; + + description + "Unique name of low-level-tx-endpoint object. Reference to static object"; + } + + container compression { + presence + "This container shall exists to avoid missaligned compression + methods between devices"; + + description + "Container which consists of global configurable parameters for compression"; + + uses cf:compression-details; + + leaf fs-offset { + if-feature cf:CONFIGURABLE-FS-OFFSET; + type uint8; + default 0; + description + "Adjusts FS (full scale) value of IQ format relative to FS derived from unmodified IQ format. + Please refer to CU-Plane specification for details"; + } + + list dynamic-compression-configuration { + when "../compression-type = 'DYNAMIC'"; + key "id"; + unique "compression-method iq-bitwidth fs-offset"; + description + "List of possible configuration in case dynamic configuration is used + Note: In case of empty list all available compressions can be choosen dynamically + and default fs-offset is taken (0)."; + + leaf id { + type uint16; + description + "Identification number for particular compression"; + } + + uses cf:compression-method-grouping; + + leaf fs-offset { + if-feature cf:CONFIGURABLE-FS-OFFSET; + type uint8; + default 0; + description + "Adjusts FS (full scale) value of IQ format relative to FS derived from unmodified IQ format. + Please refer to CU-Plane specification for details"; + } + } + } + + uses scs-config; + + container e-axcid { + uses eaxc; + + description + "Contains local address of low level TX endpoint offered by Netconf server."; + } + + uses coupling-methods; + + leaf configurable-tdd-pattern-supported { + if-feature mcap:CONFIGURABLE-TDD-PATTERN-SUPPORTED; + type leafref { + //checkAS added if-feature + path "/user-plane-configuration/static-low-level-rx-endpoints[name=current()/../name]/configurable-tdd-pattern-supported"; + require-instance false; + } + description "RO to RW parameter mapping - needed for conditional under tx-array-carrier"; + } + } + + list low-level-rx-endpoints { + key name; + + description + "Object model for low-level-rx-endpoint configuration - augmented static-low-level-rx-endpoints by local-address + which cannot be added to static low-level-rx-endpoints as we cannot have modificable element in static object"; + + leaf name { + type leafref { + path "/user-plane-configuration/static-low-level-rx-endpoints/name"; + require-instance false; + } + mandatory true; + + description + "Unique name of low-level-rx-endpoint object. Reference to static object"; + } + + container compression { + description + "Container which consists of global configurable parameters for compression"; + + uses cf:compression-details; + + leaf fs-offset { + if-feature cf:CONFIGURABLE-FS-OFFSET; + type uint8; + default 0; + description + "Adjusts FS (full scale) value of IQ format relative to FS derived from unmodified IQ format. + Please refer to CU-Plane specification for details"; + } + + list dynamic-compression-configuration { + when "../compression-type = 'DYNAMIC'"; + key "id"; + unique "compression-method iq-bitwidth fs-offset"; + description + "List of possible configuration in case dynamic configuration is used + Note: In case of empty list all available compressions can be choosen dynamically + and default fs-offset is taken (0)."; + + leaf id { + type uint16; + description + "Identification number for particular compression"; + } + + uses cf:compression-method-grouping; + + leaf fs-offset { + if-feature cf:CONFIGURABLE-FS-OFFSET; + type uint8; + default 0; + description + "Adjusts FS (full scale) value of IQ format relative to FS derived from unmodified IQ format. + Please refer to CU-Plane specification for details"; + } + } + } + + uses scs-config; + + list ul-fft-sampling-offsets { + key scs; + description + "List of FFT sampling offsets configured for each SCS that will be used. + Client shall configure one element for each SCS that will be used."; + + leaf scs { + type mcap:scs-config-type; + description + "Value corresponds to SCS values defined for frameStructure in C-plane + Note: set of allowed values is restricted by SCS derived from values in supported-frame-structures."; + } + + leaf ul-fft-sampling-offset { + type uint16; + + units Ts; + description + "Determines time advance of capture window for FFT. + Value represents time advance of capture window start in relation to the end of CP. Unit is Ts. + Note: value of this parameter is usually set to '0' (zero) for PRACH channels. + Any phase offset resulting from the non-zero value of this parameter is handled in O-DU."; + } + } + + container e-axcid { + uses eaxc; + + description + "Contains local address of low level RX endpoint offered by Netconf server."; + } + + leaf eaxc-gain-correction { + if-feature EAXC-GAIN-CORRECTION; + type decimal64 { + fraction-digits 4; + } + units dB; + default 0; + description + "eAxC specifc part of overall gain_correction. + gain_correction = common array-carrier gain-correction + eAxC-gain-correction."; + } + + leaf non-time-managed-delay-enabled { + type boolean; + default false; + description + "Tells if non time managed delay shall be enabled"; + } + + uses coupling-methods; + + leaf static-config-supported { + type leafref { + path "/user-plane-configuration/static-low-level-rx-endpoints[name=current()/../name]/static-config-supported"; + require-instance false; + } + description "RO to RW parameter mapping - for further conditionals"; + } + + leaf static-prach-configuration { + if-feature mcap:PRACH-STATIC-CONFIGURATION-SUPPORTED; + when "(/user-plane-configuration/low-level-rx-endpoints[name=current()/../name]/static-config-supported = 'PRACH')"; + type leafref { + //checkAS added if-feature + path "/user-plane-configuration/static-prach-configurations/static-prach-config-id"; + } + description + "This parameter creates reference to static PRACH configuration applicable for particular endpoint"; + } + + leaf static-srs-configuration { + when "(/user-plane-configuration/low-level-rx-endpoints[name=current()/../name]/static-config-supported = 'SRS')"; + if-feature mcap:SRS-STATIC-CONFIGURATION-SUPPORTED; + type leafref { + //checkAS added if-feature + path "/user-plane-configuration/static-srs-configurations/static-srs-config-id"; + } + description + "This parameter creates reference to static SRS configuration applicable for particular endpoint"; + } + + leaf configurable-tdd-pattern-supported { + if-feature mcap:CONFIGURABLE-TDD-PATTERN-SUPPORTED; + type leafref { + //checkAS added if-feature + path "/user-plane-configuration/static-low-level-rx-endpoints[name=current()/../name]/configurable-tdd-pattern-supported"; + require-instance false; + } + description "RO to RW parameter mapping - needed for conditional under rx-array-carrier"; + } + } + + list tx-array-carriers { + key name; + description + "Object model for tx-array-carriers configuration"; + + leaf name { + type string; + + description + "Unique name of tx-array-carriers object."; + } + + uses tx-common-array-carrier-elements; + + leaf band-number { + if-feature mcap:LAA; + type leafref { + path "/mcap:module-capability/mcap:band-capabilities/mcap:band-number"; + require-instance false; + } + description + "This parameter informing which frequency band particular antenna + array is serving for. + Intended use is to deal with multiband solutions."; + } + + container lte-tdd-frame { + when "(/user-plane-configuration/tx-array-carriers/rw-type = 'LTE') and (/user-plane-configuration/tx-array-carriers/rw-duplex-scheme = 'TDD')"; + status deprecated; + description + "Container which consists of global configurable parameters for tdd Frame. + This contained is deprecated due to introduction of TDD pattern configuration + applicable in a common way for LTE and NR."; + + leaf subframe-assignment { + type enumeration { + enum SAO { + description "subframe assignment configuration 0"; + } + enum SA1 { + description "subframe assignment configuration 1"; + } + enum SA2 { + description "subframe assignment configuration 2"; + } + enum SA3 { + description "subframe assignment configuration 3"; + } + enum SA4 { + description "subframe assignment configuration 4"; + } + enum SA5 { + description "subframe assignment configuration 5"; + } + enum SA6 { + description "subframe assignment configuration 6"; + } + } + mandatory true; + description + "Indicates DL/UL subframe configuration as specified in + 3GPP TS 36.211 [v15.3.0, table 4.2-2]"; + } + leaf special-subframe-pattern { + type enumeration { + enum SPP0 { + description "special subframe pattern configuration 0"; + } + enum SPP1 { + description "special subframe pattern configuration 1"; + } + enum SPP2 { + description "special subframe pattern configuration 2"; + } + enum SPP3 { + description "special subframe pattern configuration 3"; + } + enum SPP4 { + description "special subframe pattern configuration 4"; + } + enum SPP5 { + description "special subframe pattern configuration 5"; + } + enum SPP6 { + description "special subframe pattern configuration 6"; + } + enum SPP7 { + description "special subframe pattern configuration 7"; + } + enum SPP8 { + description "special subframe pattern configuration 8"; + } + enum SPP9 { + description "special subframe pattern configuration 9"; + } + enum SPP10 { + description "special subframe pattern configuration 10"; + } + } + mandatory true; + description + "Indicates TDD special subframe configuration as in TS 36.211 + [v15.3.0, table 4.2-1] "; + } + } + + container laa-carrier-configuration { + when "../band-number = 46"; + if-feature mcap:LAA; + description "Container to specify LAA feature related carrier configuration."; + uses laa-carrier-config; + } + + leaf gain { + type decimal64 { + fraction-digits 4; + } + units dB; + mandatory true; + + description + "Transmission gain in dB. Value applicable to each array element carrier belonging to array carrier."; + } + + leaf downlink-radio-frame-offset { + type uint32 { + range 0..12288000; + } + mandatory true; + + description + "This parameter is used for offsetting the starting position of 10ms radio frame. + Note: The value should have same value within DU to all tx-array-carrierss that have same frequency and bandwidth. + Note2: Unit is 1/1.2288e9 s. Then, its range is calculated 0..12288000."; + } + + leaf downlink-sfn-offset { + type int16 { + range -32768..32767; + } + mandatory true; + + description + "This parameter is used for offsetting SFN value. + Unit is in 10ms. + Note: The value should have same value within DU to all tx-array-carrierss that have same frequency and bandwidth."; + } + + leaf reference-level { + if-feature TX-REFERENCE-LEVEL; + type decimal64 { + fraction-digits 4; + } + units dB; + default 0; + description + "Allows to adjust reference level for sum of IQ signal power over eAxCs in this array-carrier."; + } + + leaf configurable-tdd-pattern { + when "not(/user-plane-configuration/low-level-tx-endpoints[name = string(/user-plane-configuration/low-level-tx-links[tx-array-carrier = current()/../name]/tx-array-carrier)]/configurable-tdd-pattern-supported = 'false')"; + if-feature mcap:CONFIGURABLE-TDD-PATTERN-SUPPORTED; + type leafref { + path "/user-plane-configuration/configurable-tdd-patterns/tdd-pattern-id"; + } + description + "This parameter creates reference to configuration for TDD pattern applicable for particular tx-array-carrier. + The leaf may exist under tx-array-carrier only in case O-RU supports feature 'CONFIGURABLE-TDD-PATTERN-SUPPORTED' + AND all low-level-tx-endpoints linked to this tx-array-carrier have configurable-tdd-pattern-supported = 'true'"; + } + } + + list rx-array-carriers { + key name; + description + "Object model for rx-array-carriers configuration"; + + leaf name { + type string; + description + "Unique name of rx-array-carriers object."; + } + + uses rx-common-array-carrier-elements; + + leaf downlink-radio-frame-offset { + type uint32 { + range 0..12288000; + } + mandatory true; + + description + "This parameter is used for offsetting the starting position of 10ms radio frame. + Note: The value should have same value within DU to all tx-array-carrierss that have same frequency and bandwidth. + Note2: Unit is 1/1.2288e9 s. Then, its range is calculated 0..12288000."; + } + + leaf downlink-sfn-offset { + type int16 { + range -32768..32767; + } + mandatory true; + + description + "This parameter is used for offsetting SFN value. + Unit is in 10ms. + Note: The value should have same value within DU to all tx-array-carrierss that have same frequency and bandwidth."; + } + + leaf gain-correction { + type decimal64 { + fraction-digits 4; + + } + units dB; + mandatory true; + description + "Gain correction of RF path linked with array element or array layers. + Common part of overall gain_correction. + gain_correction = common array-carrier gain-correction + eAxC gain correction."; + } + + leaf n-ta-offset { + type uint32; + units Tc; + mandatory true; + description + "Value of configurable N-TA offset + units are Tc=~0.5ns=1/1.96608GHz"; + } + + leaf configurable-tdd-pattern { + when "not(/user-plane-configuration/low-level-rx-endpoints[name = string(/user-plane-configuration/low-level-rx-links[rx-array-carrier = current()/../name]/rx-array-carrier)]/configurable-tdd-pattern-supported = 'false')"; + if-feature mcap:CONFIGURABLE-TDD-PATTERN-SUPPORTED; + type leafref { + path "/user-plane-configuration/configurable-tdd-patterns/tdd-pattern-id"; + } + description + "This parameter creates reference to configuration for TDD pattern applicable for particular rx-array-carrier. + The leaf may exist under rx-array-carrier only in case O-RU supports feature 'CONFIGURABLE-TDD-PATTERN-SUPPORTED' + AND all low-level-rx-endpoints linked to this rx-array-carrier have configurable-tdd-pattern-supported = 'true'"; + } + } + + list tx-arrays { + key "name"; + config false; + description + "Structure describing TX array parameters"; + + uses parameters; + + leaf max-gain { + type decimal64 { + fraction-digits 4; + + } + units dB; + mandatory true; + description + "Max gain of RF path linked with array element (minimum over elements of array) or array layers"; + } + + leaf independent-power-budget { + type boolean; + mandatory true; + description + "If true then every element of array has own, power budget independent from power budget of other elements. + Else all elements of array that are at same row and column and have same polarization share power budget"; + } + + list capabilities { + description + "List of capabilities related to this tx-array"; + uses mcap:support-for-dl; + } + } + + list rx-arrays { + key "name"; + config false; + description "Structure describing RX array parameters"; + + uses parameters; + container gain-correction-range { + leaf max { + type decimal64 { + fraction-digits 4; + } + units dB; + mandatory true; + description "Array gain correction factor - maximum allowed value"; + } + leaf min { + type decimal64 { + fraction-digits 4; + } + units dB; + mandatory true; + description "Array gain correction factor - minimum allowed value"; + } + + description + "Array gain correction factor"; + } + + list capabilities { + description + "List of capabilities related to this rx-array"; + uses mcap:support-for-ul; + } + } + + list relations { + key "entity"; + config false; + description "Structure describing relations between array elements"; + + leaf entity { + type uint16; + + description + "Relation entity. Used as a key for list of relations."; + } + + container array1 { + uses array-choice; + + description + "Defnes name for first array"; + } + container array2 { + uses array-choice; + + description + "Defnes name for second array"; + } + list types { + key "relation-type"; + description + "Defines relation type and pairs for array elements for given arrays"; + + leaf relation-type { + type enumeration { + enum SHARED { + description "SHARED"; + } + enum COALOCATED { + description "COALOCATED"; + } + } + description "Type of relation between array elements"; + } + list pairs { + key "element-array1"; + description + "defines related array elements"; + + leaf element-array1 { + type uint16; + + description + "Tells about id of element from array1"; + } + leaf element-array2 { + type uint16; + + description + "Tells about id of element from array2"; + } + } + } + } + + container eaxc-id-group-configuration { + if-feature mcap:EAXC-ID-GROUP-SUPPORTED; + description + "This is the container for eAxC ID group configuration."; + leaf max-num-tx-eaxc-id-groups { + type leafref { + path "/mcap:module-capability/mcap:ru-capabilities/mcap:eaxcid-grouping-capabilities/mcap:max-num-tx-eaxc-id-groups"; + require-instance false; + } + description "eaxc-id-group-configuration"; + } + leaf max-num-tx-eaxc-ids-per-group { + type leafref { + path "/mcap:module-capability/mcap:ru-capabilities/mcap:eaxcid-grouping-capabilities/mcap:max-num-tx-eaxc-ids-per-group"; + require-instance false; + } + description "max-num-tx-eaxc-ids-per-group"; + } + leaf max-num-rx-eaxc-id-groups { + type leafref { + path "/mcap:module-capability/mcap:ru-capabilities/mcap:eaxcid-grouping-capabilities/mcap:max-num-rx-eaxc-id-groups"; + require-instance false; + } + description "max-num-rx-eaxc-id-groups"; + } + leaf max-num-rx-eaxc-ids-per-group { + type leafref { + path "/mcap:module-capability/mcap:ru-capabilities/mcap:eaxcid-grouping-capabilities/mcap:max-num-rx-eaxc-ids-per-group"; + require-instance false; + } + description "max-num-rx-eaxc-ids-per-group"; + } + + list tx-eaxc-id-group { + must "count(../tx-eaxc-id-group) <= ../max-num-tx-eaxc-id-groups" { + error-message "too many tx-eaxcid-id groups"; + } + key "representative-tx-eaxc-id"; + description + "This is a list of the groups of the eAxC IDs assigned to low-level-tx-endpoints. + Each group is a union of the 'member-tx-eaxc-id's and a 'representative-tx-eaxc-id'. + The low-level-tx-endpoint associated to 'representative-tx-eaxc-id' is able to + process the DL C-plane information for all the low-level-tx-endpoints associated + to 'member-tx-eaxc-id's. + + Take Note: This list should only contain eAxC IDs assigned to a tx-endpoint."; + + + leaf representative-tx-eaxc-id { + type uint16; + description + "This parameter contains eAxC_ID that populates content of C-Plane section + extension 11 to eAxC_IDs configured in the group as 'member-tx-eaxc-id'(s)."; + } + leaf-list member-tx-eaxc-id { + type uint16; + must "count(../member-tx-eaxc-id) <= ../../max-num-tx-eaxc-ids-per-group" { + error-message "too many tx-eaxcid-id members"; + } + must "current()!=../representative-tx-eaxc-id" { + error-message "the representative eaxcid does not need to be a list member"; + } + description + "This is a list of member eAxC IDs, which together with the representative-tx-eaxc-id, + are assigned to low-level-tx-endpoints in the group."; + } + } + + list rx-eaxc-id-group { + must "count(../rx-eaxc-id-group) <= ../max-num-rx-eaxc-id-groups" { + error-message "too many rx-eaxcid-id groups"; + } + key "representative-rx-eaxc-id"; + description + "This is a list of the groups of the eAxC IDs assigned to low-level-rx-endpoints. + Each group is a union of 'member-rx-eaxc-id's and a 'representative-rx-eaxc-id'. + The low-level-rx-endpoint associated to 'representative-rx-eaxc-id' is able to + process the UL C-plane information for all the low-level-rx-endpoints associated + to 'member-rx-eaxc-id's. + + Take Note: This list should only contain eAxC IDs assigned to a rx-endpoint."; + + leaf representative-rx-eaxc-id { + type uint16; + description + "This parameter contains eAxC_ID that populates content of C-Plane section + extension 11 to eAxC_IDs configured in the group as 'member-rx-eaxc-id'(s)."; + } + + leaf-list member-rx-eaxc-id { + type uint16; + must "count(../member-rx-eaxc-id) <= ../../max-num-rx-eaxc-ids-per-group" { + error-message "too many rx-eaxcid-id members"; + } + must "current()!=../representative-rx-eaxc-id" { + error-message "the representative eaxcid does not need to be a list member"; + } + description + "This is a list of member eAxC IDs assigned to low-level-rx-endpoints in the group."; + } + } + } + + list static-prach-configurations { + if-feature mcap:PRACH-STATIC-CONFIGURATION-SUPPORTED; + key static-prach-config-id; + description + "List of static PRACH configurations. An O-RU shall reject any configuration + modification which exceed the maximum permitted configurations supported by + the O-RU"; + + leaf static-prach-config-id { + type uint8; + description + "Supplementary parameter acting as key in list of static PRACH configurations."; + } + + uses static-prach-configuration; + } + + grouping static-prach-configuration { + description + "Set of parameters related to static PRACH configuration"; + + leaf pattern-period { + type uint16 { + range 1..1024; + } + mandatory true; + description + "Period after which static PRACH patterns are repeated. Unit: number of frames."; + } + + leaf guard-tone-low-re { + type uint32; + mandatory true; + description + "Number of REs occupied by the low guard tones."; + } + + leaf num-prach-re { + type uint32; + mandatory true; + description + "Number of contiguous PRBs per data section description"; + } + + leaf guard-tone-high-re { + type uint32; + mandatory true; + description + "Number of REs occupied by the high guard tones."; + } + + leaf sequence-duration { + type uint32 { + range 256..24576; + } + units Ts; + mandatory true; + description + "Duration of single sequence of the PRACH. Sequence may be considered as 'single PRACH symbol'"; + } + + list prach-patterns { + key prach-pattern-id; + min-elements 1; + description + "Provides a PRACH pattern. Each record in the list represents a single PRACH occasion. Number of list entries cannot exceed max-prach-patterns"; + + leaf prach-pattern-id { + type uint16; + mandatory true; + description + "Supplementary parameter acting as key for prach-pattern list."; + } + + leaf number-of-repetitions { + type uint8{ + range 1..14; + } + mandatory true; + description + "This parameter defines number of PRACH repetitions in PRACH occasion, + to which the section control is applicable."; + } + + leaf number-of-occasions { + type uint8; + mandatory true; + description + "This parameter informs how many consecutive PRACH occasions is described by the PRACH pattern."; + } + + leaf re-offset { + type uint32; + mandatory true; + description + "Offset between the start of lowest-frequency RE of lowest-frequency PRB + and the start of lowest-frequency RE belonging to the PRACH occasion. + The re-offset is configured as number of PRACH REs."; + } + + list occasion-parameters { + key occasion-id; + min-elements 1; + description + "This is list of cp-lengths, gp-lengths and beam-ids applicable + per each PRACH occasion in PRACH pattern. + Note: the number of records in this list MUST be equal + to value of parameter number-of-occasions."; + + leaf occasion-id { + type uint8; + mandatory true; + description + "Supplementary parameter acting as key in 'occasion-parameters' list"; + } + + leaf cp-length { + type uint16; + units Ts; + mandatory true; + description + "Cyclic prefix length. See CUS-plane specification for detailed description."; + } + + leaf gp-length { + type uint16; + units Ts; + description + "Guard period length."; + } + + leaf beam-id { + type uint16; + mandatory true; + description + "This parameter defines the beam pattern to be applied to the U-Plane data. + beamId = 0 means no beamforming operation will be performed."; + } + } + + leaf frame-number { + type uint16{ + range 0..1023; + } + mandatory true; + description + "This parameter is an index inside the pattern-length, such that + PRACH occasion is happening for SFN which fulfills following equation: + [SFN mod pattern-length = frame-id]"; + } + + leaf sub-frame-id { + type uint16; + mandatory true; + description + "Identifier of sub-frame of the PRACH occasion. Value is interpreted in the same way + as subframeId field in a section description of a C-Plane message."; + } + + leaf time-offset { + type uint16; + units Ts; + mandatory true; + description + "This parameter defines the time-offset from the start of the sub-frame + to the start of the first Cyclic Prefix of PRACH pattern"; + } + } + } + + grouping static-srs-configuration { + description + "Set of parameters related to static PRACH configuration"; + + leaf pattern-period { + type uint16 { + range 1..1024; + } + mandatory true; + description + "Period after which static SRS patterns are repeated. Unit: number of frames."; + } + + list srs-patterns { + key srs-pattern-id; + min-elements 1; + description + "Provides a SRS pattern. Each record in the list represents a single PRACH occasion. Number of list entries cannot exceed max-srs-patterns."; + + leaf srs-pattern-id { + type uint16; + mandatory true; + description + "Supplementary parameter acting as key for srs-pattern list."; + } + + leaf sub-frame-id { + type uint16; + mandatory true; + description + "Identifier of sub-frame of the Raw SRS occasion. Value is interpreted in the same way + as subframeId field in a section description of a C-Plane message."; + } + + leaf slot-id { + type uint16; + mandatory true; + description + "Identifier of slot of the Raw SRS occasion. Value is interpreted in the same way + as slotId field in a section description of a C-Plane message."; + } + + leaf start-symbol-id { + type uint16; + mandatory true; + description + "Identifier of first symbol of the Raw SRS occasion. Value is interpreted in the same way + as startSymbolId field in a section description of a C-Plane message."; + } + + leaf beam-id { + type uint16; + mandatory true; + description + "This parameter defines the beam pattern to be applied to the U-Plane data. + beamId = 0 means no beamforming operation will be performed."; + } + + leaf num-symbol { + type uint16; + mandatory true; + description + "This parameter defines number of consecutive symbols covered by specific srs-pattern. + Single srs-pattern may address at least one symbol. However, possible optimizations + could allow for several (up to 14) symbols."; + } + + leaf start-prbc { + type uint16 { + range 0..1023; + } + mandatory true; + description + "Identifier of first PRB of the Raw SRS occasion. Value is interpreted in the same way + as startPrbc field in a section description of a C-Plane message."; + } + + leaf num-prbc { + type uint16; + mandatory true; + description + "Number of PRBs of the Raw SRS occasion. Value is interpreted in the same way + as numPrbc field in a section description of a C-Plane message."; + } + } + } + + grouping configurable-tdd-pattern { + description + "Set of parameters related to configurable TDD pattern. + Note: configurable-tdd-pattern shall not be used in case the usage would collide with + deprecated 'lte-tdd-pattern'."; + + list switching-points { + key switching-point-id; + description + "List of switching points within frame, related to configurable TDD pattern. + An O-RU shall reject any configuration modification which exceeds the maximum + number of switching-points supported by the O-RU"; + + leaf switching-point-id { + type uint16; + description + "Supplementary parameter acting as key for switching-points list."; + } + + leaf direction { + type enumeration { + enum UL { + description "Uplink"; + } + enum DL { + description "Downlink"; + } + enum GP { + description "Guard period"; + } + } + mandatory true; + description + "Parameter provides information regarding desired signal direction at the moment switching point occurs."; + } + + leaf frame-offset { + type uint32; + mandatory true; + description + "Offset from DL air frame boundary transmitted at RF connector to the point in time that is characteristic to the operation on RF switches. Unit is 1/1.2288e9 s."; + } + } + } + + list static-srs-configurations { + if-feature mcap:SRS-STATIC-CONFIGURATION-SUPPORTED; + key static-srs-config-id; + description + "List of static SRS configurations"; + + leaf static-srs-config-id { + type uint8; + description + "Supplementary parameter acting as key in the list of static SRS configurations."; + } + + uses static-srs-configuration; + } + + list configurable-tdd-patterns { + if-feature mcap:CONFIGURABLE-TDD-PATTERN-SUPPORTED; + key tdd-pattern-id; + description + "List of configured TDD patterns"; + + leaf tdd-pattern-id { + type uint8; + description + "Supplementary parameter acting as key in the list of configured TDD patterns."; + } + + uses configurable-tdd-pattern; + } + } + + grouping tx-array-notification-group { + description + "Grouping for tx-array for notification"; + + list tx-array-carriers{ + key name; + description "notification of state change for tx-array-carriers"; + + leaf name{ + type leafref{ + path "/user-plane-configuration/tx-array-carriers/name"; + } + description + "name of tx-array-carriers is notified at state change"; + } + leaf state{ + type leafref{ + path "/user-plane-configuration/tx-array-carriers/state"; + } + description + "state of tx-array-carriers is notified at state change"; + } + } + } + + grouping rx-array-notification-group { + description + "Grouping for rx-array for notification"; + + list rx-array-carriers{ + key name; + description + "Notification used to inform about state change of rx-array-carriers"; + leaf name{ + type leafref{ + path "/user-plane-configuration/rx-array-carriers/name"; + } + description + "name of rx-array-carriers is notified at state change"; + } + leaf state{ + type leafref{ + path "/user-plane-configuration/rx-array-carriers/state"; + } + description + "state of rx-array-carriers is notified at state change"; + } + } + } + +// top level container + + container user-plane-configuration { + description "top level container for user plane configuration"; + + uses uplane-conf-group; + uses general-config; + } + + //notification statement + notification tx-array-carriers-state-change { + description + "Notification used to inform about state change of tx-array-carriers"; + uses tx-array-notification-group; + } + notification rx-array-carriers-state-change { + description + "Notification used to inform about state change of tx-array-carriers"; + + uses rx-array-notification-group; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-usermgmt@2020-12-10.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-usermgmt@2020-12-10.yang new file mode 100644 index 0000000..ed6f39a --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-usermgmt@2020-12-10.yang @@ -0,0 +1,206 @@ +module o-ran-usermgmt { + yang-version 1.1; + namespace "urn:o-ran:user-mgmt:1.0"; + prefix "o-ran-usermgmt"; + + import ietf-netconf-acm { + prefix nacm; + reference + "RFC 8341: Network Configuration Access Control Model"; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the user management model for the O-RAN Equipment. + + 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 "2020-12-10" { + description + "version 1.2.0 + + 1) updated description for enabled leaf"; + + reference "ORAN-WG4.M.0-v01.00"; + } + + revision "2019-07-03" { + description + "version 1.1.0 + + 1) change name leaf to type nacm:user-name-type + 2) added account-type to qualify when password is required "; + + 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"; + } + + typedef password-type { + type string { + length "8..128"; + pattern "[a-zA-Z0-9!$%\\^()\\[\\]_\\-~{}.+]*" { + error-message "Password content does not meet the requirements"; + } + } + description + "The password for this entry. This shouldn't be in clear text + The Password must contain at least 2 characters from + each of the following groups: + a) Lower case alphabetic (a-z) + b) Upper case alphabetic (A-Z) + c) Numeric 0-9 + d) Special characters Allowed !$%^()[]_-~{}.+ + Password must not contain Username."; + } + + grouping user-list { + list user { + key "name"; + description + "The list of local users configured on this device."; + leaf name { + type nacm:user-name-type; + description + "The user name string identifying this entry. + + NOTE: o-ran-usermgmt:user-profile/user/name is + identical to nacm:nacm/groups/group/user-name + but the current schema is preserved for backwards + compatibility."; + } + leaf account-type { + type enumeration { + enum PASSWORD { + description "the user-name is for password based authentication"; + } + enum CERTIFICATE { + description "the user-name is for certificate based authentciation"; + } + } + default "PASSWORD"; + } + + leaf password { + nacm:default-deny-all; + type password-type; + description + "The password for this entry. + + This field is only valid when account-type is NOT set to CERTIFICATE, + i.e., when account-type is NOT present or present and set to + PASSWORD."; + } + leaf enabled { + type boolean; + description + "Indicates whether an account is enabled or disabled. + + A NETCONF Server shall reject a configuration that attempts to + enable a Password account for an account where the password leaf + is not configured. + + This validation statement is included in the YANG description and + not in a MUST statement to preserve backwards compatibility."; + } + } + } + + container users { + // checkAS + // must "user/enabled='true'" { + // error-message "At least one account needs to be enabled."; + // } + + //TAKE NOTE - any configuration with zero enabled users is invalid. + //This will typically be the case when using a simulated NETCONF Server + //and so this constraint should be removed when operating in those scenarios + + //The config data base of the O-RAN equipment should ensure that the user + //default account is enabled on factory restart + + description "list of user accounts"; + uses user-list; + } + + rpc chg-password { + nacm:default-deny-all; + input { + leaf currentPassword { + type password-type; + mandatory true; + description + "provide the current password"; + } + leaf newPassword { + type password-type; + mandatory true; + description + "provide a new password"; + } + leaf newPasswordConfirm { + type password-type; + mandatory true; + description + "re-enter the new password "; + } + } + output { + leaf status { + type enumeration { + enum "Successful" { + value 1; + } + enum "Failed" { + value 2; + } + } + mandatory true; + description + "Successful or Failed"; + } + leaf status-message { + type string; + description + "Gives a more detailed reason for success / failure"; + } + } + } + +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ves-subscribed-notifications@2020-12-10.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ves-subscribed-notifications@2020-12-10.yang new file mode 100644 index 0000000..3a08e15 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ves-subscribed-notifications@2020-12-10.yang @@ -0,0 +1,87 @@ +module o-ran-ves-subscribed-notifications { + yang-version 1.1; + namespace "urn:o-ran:ves-sn:1.0"; + prefix o-ran-vsn; + + import ietf-subscribed-notifications { + prefix sn; + } + import ietf-inet-types { + prefix inet; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines augmentations to ietf-subscribed-notifications to + enable support of configured notifications sent using VNF Event Stream + notifications. + + Copyright 2020 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 "2020-12-10" { + description + "version 5.0.0 + + 1) initial version"; + + reference "ORAN-WG4.M.0-v05.00"; + } + + // identity statements + identity o-ran-ves-connectionless { + base sn:transport; + description + "A transport type used to indicate that notifications should be sent using an + ONAP VES Notification using RESTful connectionless transport"; + } + + grouping event-collector { + description + "Provides a reusable description of an event-collector."; + leaf notification-recipient { + type inet:uri; + mandatory true; + description + "This URI specifies the address of the notification receiver + HTTPS endpoint. Additional path elements may be added as required by the + protocol, i. e. it configures the server root. + E.g. https://myserver.mydomain.com:8443/notifications."; + } + } + + augment "/sn:subscriptions/sn:subscription/sn:receivers/sn:receiver" { + when "(derived-from-or-self(../../sn:transport, 'o-ran-vsn:o-ran-ves-connectionless'))"; + description + "This augmentation allows VES-specific receiver parameters to be + configured."; + uses event-collector; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-wg4-features@2020-12-10.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-wg4-features@2020-12-10.yang new file mode 100644 index 0000000..5b183a3 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-wg4-features@2020-12-10.yang @@ -0,0 +1,57 @@ +module o-ran-wg4-features { + yang-version 1.1; + namespace "urn:o-ran:wg4feat:1.0"; + prefix "o-ran-feat"; + + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the a set of re-usable type definitions for WG4 specific + features. + + Copyright 2020 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 "2020-12-10" { + description + "version 5.0.0 + + 1) initial version."; + + reference "ORAN-WG4.M.0-v05.00"; + } + + feature NON-PERSISTENT-MPLANE { + description + "Indicates that the Radio Unit supports the optional + capability to improve the operation with a SMO using a non- + persistent NETCONF session."; + } +} diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/onap-system.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/onap-system.yang new file mode 100644 index 0000000..3e19429 --- /dev/null +++ b/ntsimulator/deploy/o-ran-ru-fh/yang/onap-system.yang @@ -0,0 +1,59 @@ +module onap-system { + yang-version 1.1; + namespace "urn:onap:system"; + prefix os; + + import ietf-inet-types { + prefix inet; + } + import ietf-system { + prefix sys; + } + + organization + "ONAP - Open Network Automation Platform"; + contact + "Web: + Editors: + Alex Stancu + Adrian Lita + Martin Skorupski "; + description + "This module augments ietf-system with ONAP details. + + Copyright 2020 the O-RAN Alliance. + + Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + + 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."; + + revision 2020-10-26 { + description + "Initial revision for the ietf-system augmentation for ONAP."; + reference + "https://jira.onap.org/browse/SDNC-1396"; + } + + augment "/sys:system" { + leaf name { + type string; + description + "The name of the system."; + } + leaf web-ui { + type inet:uri; + description + "The URI of the system Web UI."; + } + description + "Enhancing the system information."; + } +} diff --git a/ntsimulator/deploy/o-ran/Dockerfile b/ntsimulator/deploy/o-ran/Dockerfile new file mode 100644 index 0000000..1888fb3 --- /dev/null +++ b/ntsimulator/deploy/o-ran/Dockerfile @@ -0,0 +1,39 @@ +# +# Copyright 2020 highstreet technologies GmbH and others +# +# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +# +# 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. + +################ +#### DEVICE #### +################ + +FROM nexus3.o-ran-sc.org:10004/o-ran-sc/nts-ng-base:latest +LABEL maintainer="alexandru.stancu@highstreet-technologies.com / adrian.lita@highstreet-technologies.com" + +# ntsim-ng configuration and deployment +COPY ./yang /opt/dev/deploy/yang +COPY ./data /opt/dev/deploy/data +COPY ./config.json /opt/dev/ntsim-ng/config/config.json + +# ntsim-ng init docker +RUN /opt/dev/ntsim-ng/ntsim-ng --container-init -w /opt/dev/ntsim-ng + +# add exposed ports +EXPOSE 830-929 +EXPOSE 21-22 + +ENV NTS_FUNCTION_TYPE=NTS_FUNCTION_TYPE_O_RAN_FH + +# run +WORKDIR /opt/dev/workspace +CMD ["/opt/dev/ntsim-ng/ntsim-ng", "-w/opt/dev/ntsim-ng", "--supervisor"] diff --git a/ntsimulator/deploy/o-ran/config.json b/ntsimulator/deploy/o-ran/config.json index 59166db..eb45979 100644 --- a/ntsimulator/deploy/o-ran/config.json +++ b/ntsimulator/deploy/o-ran/config.json @@ -1,10 +1,34 @@ { - "docker-rules": { + "container-rules": { "excluded-modules": [], "excluded-features": [] }, + + "supervisor-rules": { + "netopeer": { + "path": "/usr/local/bin/netopeer2-server", + "args": ["-d", "-v2"], + "autorestart": true, + "stdout": "log/netopeer-stdout.log", + "stderr": "log/netopeer-stderr.log" + }, + + "sshd": { + "path": "/usr/sbin/sshd", + "args": ["-D"], + "autorestart": true, + "stdout": "log/sshd-stdout.log", + "stderr": "log/sshd-stderr.log" + }, - "populate-rules" : { + "ntsim-network-function": { + "path": "/opt/dev/ntsim-ng/ntsim-ng", + "args": ["-w/opt/dev/ntsim-ng", "-f"], + "nomanual": true + } + }, + + "datastore-random-generation-rules" : { "excluded-modules": [ "sysrepo", "sysrepo-monitoring", @@ -16,41 +40,110 @@ "ietf-truststore", "ietf-system", "ietf-netconf-server", + "ietf-alarms", + "ietf-network-instance", + "ietf-restconf", + "ietf-yang-schema-mount", + "ietf-subscribed-notifications", + "o-ran-uplane-conf", + "o-ran-performance-management", + "o-ran-transceiver", + "o-ran-mplane-int", + "o-ran-processing-element", "nts-network-function" ], - "default-list-instances": 2, + "default-list-instances": 8, "custom-list-instances" : [] }, + "datastore-populate-rules": { + "random-generation-enabled": true, + + "pre-generated-operational-data": [], + "pre-generated-running-data": [] + }, + "fault-rules" : { "yang-notif-template" : "$$uint16_counter$$%%object%%%%affected-object%%%%fault-severity%%%%cleared%%%%text%%%%date-time%%", "choosing-method" : "linear", "faults" : [ { - "condition" : "cod1", - "object" : "obj1", + "condition" : "CPRI Port Down", + "object" : "Slot-0-Port-A", + "severity" : "MAJOR", + "date-time" : "$$time$$", + "specific-problem" : "CPRI Port Down", + + "fault-severity" : "MAJOR", + "affected-object" : "%%object%%", + "cleared" : "false", + "text" : "CPRI Port Down" + }, + + { + "condition" : "CPRI Port Down", + "object" : "Slot-0-Port-A", + "severity" : "NORMAL", + "date-time" : "$$time$$", + "specific-problem" : "CPRI Port Down", + + "fault-severity" : "MAJOR", + "affected-object" : "%%object%%", + "cleared" : "true", + "text" : "CPRI Port Down" + }, + + { + "condition" : "CPRI Port Down", + "object" : "Slot-0-Port-C", + "severity" : "MAJOR", + "date-time" : "$$time$$", + "specific-problem" : "CPRI Port Down", + + "fault-severity" : "MAJOR", + "affected-object" : "%%object%%", + "cleared" : "false", + "text" : "CPRI Port Down" + }, + + { + "condition" : "CPRI Port Down", + "object" : "Slot-0-Port-C", + "severity" : "NORMAL", + "date-time" : "$$time$$", + "specific-problem" : "CPRI Port Down", + + "fault-severity" : "MAJOR", + "affected-object" : "%%object%%", + "cleared" : "true", + "text" : "CPRI Port Down" + }, + + { + "condition" : "CPRI Port Down", + "object" : "Slot-2-Port-B", "severity" : "MAJOR", "date-time" : "$$time$$", - "specific-problem" : "sp1", + "specific-problem" : "CPRI Port Down", - "fault-severity" : "WARNING", + "fault-severity" : "MAJOR", "affected-object" : "%%object%%", "cleared" : "false", - "text" : "ana n-are mere" + "text" : "CPRI Port Down" }, { - "condition" : "cod2", - "object" : "obj1", + "condition" : "CPRI Port Down", + "object" : "Slot-2-Port-B", "severity" : "NORMAL", "date-time" : "$$time$$", - "specific-problem" : "sp2", + "specific-problem" : "CPRI Port Down", - "fault-severity" : "WARNING", + "fault-severity" : "MAJOR", "affected-object" : "%%object%%", "cleared" : "true", - "text" : "ana are mere" + "text" : "CPRI Port Down" } ] } diff --git a/ntsimulator/deploy/o-ran/container-tag.yaml b/ntsimulator/deploy/o-ran/container-tag.yaml index e0c7ce8..ee93a5d 100644 --- a/ntsimulator/deploy/o-ran/container-tag.yaml +++ b/ntsimulator/deploy/o-ran/container-tag.yaml @@ -1,2 +1,2 @@ --- -tag: 1.0.6 \ No newline at end of file +tag: 1.2.0 \ No newline at end of file diff --git a/ntsimulator/deploy/o-ran/data/README.md b/ntsimulator/deploy/o-ran/data/README.md new file mode 100644 index 0000000..7b501f4 --- /dev/null +++ b/ntsimulator/deploy/o-ran/data/README.md @@ -0,0 +1,2 @@ +This folder should contain XML/JSON data for pre-populating running/operational. +Data files by themselves are not taken into account until added to config.json diff --git a/ntsimulator/deploy/nts-manager/ubuntu.Dockerfile b/ntsimulator/deploy/o-ran/local.Dockerfile similarity index 71% rename from ntsimulator/deploy/nts-manager/ubuntu.Dockerfile rename to ntsimulator/deploy/o-ran/local.Dockerfile index 4978e0d..765bace 100644 --- a/ntsimulator/deploy/nts-manager/ubuntu.Dockerfile +++ b/ntsimulator/deploy/o-ran/local.Dockerfile @@ -17,18 +17,16 @@ #### DEVICE #### ################ -FROM nexus3.o-ran-sc.org:10004/o-ran-sc/nts-ng-base:latest +FROM o-ran-sc/nts-ng-base:latest LABEL maintainer="alexandru.stancu@highstreet-technologies.com / adrian.lita@highstreet-technologies.com" # ntsim-ng configuration and deployment COPY ./yang /opt/dev/deploy/yang +COPY ./data /opt/dev/deploy/data COPY ./config.json /opt/dev/ntsim-ng/config/config.json # ntsim-ng init docker -RUN /opt/dev/ntsim-ng/ntsim-ng --docker-init -w /opt/dev/ntsim-ng - -# supervisor configuration -COPY ./supervisord.conf /etc/supervisord.conf +RUN /opt/dev/ntsim-ng/ntsim-ng --container-init -w /opt/dev/ntsim-ng # finishing container build ARG BUILD_DATE @@ -38,13 +36,8 @@ LABEL build-date=$BUILD_DATE EXPOSE 830-929 EXPOSE 21-22 -# host IP address to bind to -ENV NETCONF_NTS_HOST_IP=127.0.0.1 -# starting port for host allocation -ENV NETCONF_NTS_HOST_BASE_PORT=50000 - -ENV DOCKER_ENGINE_VERSION=1.40 +ENV NTS_FUNCTION_TYPE=NTS_FUNCTION_TYPE_O_RAN_FH # run WORKDIR /opt/dev/workspace -CMD ["sh", "-c", "/usr/bin/supervisord -c /etc/supervisord.conf"] +CMD ["/opt/dev/ntsim-ng/ntsim-ng", "-w/opt/dev/ntsim-ng", "--supervisor"] diff --git a/ntsimulator/deploy/o-ran/supervisord.conf b/ntsimulator/deploy/o-ran/supervisord.conf deleted file mode 100644 index cd7eb88..0000000 --- a/ntsimulator/deploy/o-ran/supervisord.conf +++ /dev/null @@ -1,22 +0,0 @@ -[supervisord] -nodaemon=true -logfile=/var/log/supervisord.log -loglevel=debug - -[program:netopeer2-server] -command=/usr/local/bin/netopeer2-server -d -autorestart=true -redirect_stderr=true -priority=2 - -[program:sshd] -command=/usr/sbin/sshd -D -autorestart=true -redirect_stderr=true -priority=3 - -[program:ntsim-ng] -command=/opt/dev/ntsim-ng/ntsim-ng -w /opt/dev/ntsim-ng -n -f -autorestart=false -redirect_stderr=true -priority=4 diff --git a/ntsimulator/deploy/x-ran/Dockerfile b/ntsimulator/deploy/x-ran/Dockerfile new file mode 100644 index 0000000..f8883d3 --- /dev/null +++ b/ntsimulator/deploy/x-ran/Dockerfile @@ -0,0 +1,39 @@ +# +# Copyright 2020 highstreet technologies GmbH and others +# +# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +# +# 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. + +################ +#### DEVICE #### +################ + +FROM nexus3.o-ran-sc.org:10004/o-ran-sc/nts-ng-base:latest +LABEL maintainer="alexandru.stancu@highstreet-technologies.com / adrian.lita@highstreet-technologies.com" + +# ntsim-ng configuration and deployment +COPY ./yang /opt/dev/deploy/yang +COPY ./data /opt/dev/deploy/data +COPY ./config.json /opt/dev/ntsim-ng/config/config.json + +# ntsim-ng init docker +RUN /opt/dev/ntsim-ng/ntsim-ng --container-init -w /opt/dev/ntsim-ng + +# add exposed ports +EXPOSE 830-929 +EXPOSE 21-22 + +ENV NTS_FUNCTION_TYPE=NTS_FUNCTION_TYPE_X_RAN + +# run +WORKDIR /opt/dev/workspace +CMD ["/opt/dev/ntsim-ng/ntsim-ng", "-w/opt/dev/ntsim-ng", "--supervisor"] diff --git a/ntsimulator/deploy/x-ran/config.json b/ntsimulator/deploy/x-ran/config.json index 72bac1d..aec6853 100644 --- a/ntsimulator/deploy/x-ran/config.json +++ b/ntsimulator/deploy/x-ran/config.json @@ -1,10 +1,34 @@ { - "docker-rules": { + "container-rules": { "excluded-modules": [], "excluded-features": [] }, + + "supervisor-rules": { + "netopeer": { + "path": "/usr/local/bin/netopeer2-server", + "args": ["-d", "-v2"], + "autorestart": true, + "stdout": "log/netopeer-stdout.log", + "stderr": "log/netopeer-stderr.log" + }, - "populate-rules" : { + "sshd": { + "path": "/usr/sbin/sshd", + "args": ["-D"], + "autorestart": true, + "stdout": "log/sshd-stdout.log", + "stderr": "log/sshd-stderr.log" + }, + + "ntsim-network-function": { + "path": "/opt/dev/ntsim-ng/ntsim-ng", + "args": ["-w/opt/dev/ntsim-ng", "-f"], + "nomanual": true + } + }, + + "datastore-random-generation-rules" : { "excluded-modules": [ "sysrepo", "sysrepo-monitoring", @@ -19,7 +43,14 @@ "nts-network-function" ], - "default-list-instances": 2, + "default-list-instances": 1, "custom-list-instances" : [] + }, + + "datastore-populate-rules": { + "random-generation-enabled": true, + + "pre-generated-operational-data": [], + "pre-generated-running-data": [] } } \ No newline at end of file diff --git a/ntsimulator/deploy/x-ran/container-tag.yaml b/ntsimulator/deploy/x-ran/container-tag.yaml index e0c7ce8..ee93a5d 100644 --- a/ntsimulator/deploy/x-ran/container-tag.yaml +++ b/ntsimulator/deploy/x-ran/container-tag.yaml @@ -1,2 +1,2 @@ --- -tag: 1.0.6 \ No newline at end of file +tag: 1.2.0 \ No newline at end of file diff --git a/ntsimulator/deploy/x-ran/data/README.md b/ntsimulator/deploy/x-ran/data/README.md new file mode 100644 index 0000000..7b501f4 --- /dev/null +++ b/ntsimulator/deploy/x-ran/data/README.md @@ -0,0 +1,2 @@ +This folder should contain XML/JSON data for pre-populating running/operational. +Data files by themselves are not taken into account until added to config.json diff --git a/ntsimulator/deploy/x-ran/local.Dockerfile b/ntsimulator/deploy/x-ran/local.Dockerfile new file mode 100644 index 0000000..6cf773e --- /dev/null +++ b/ntsimulator/deploy/x-ran/local.Dockerfile @@ -0,0 +1,43 @@ +# +# Copyright 2020 highstreet technologies GmbH and others +# +# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +# +# 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. + +################ +#### DEVICE #### +################ + +FROM o-ran-sc/nts-ng-base:latest +LABEL maintainer="alexandru.stancu@highstreet-technologies.com / adrian.lita@highstreet-technologies.com" + +# ntsim-ng configuration and deployment +COPY ./yang /opt/dev/deploy/yang +COPY ./data /opt/dev/deploy/data +COPY ./config.json /opt/dev/ntsim-ng/config/config.json + +# ntsim-ng init docker +RUN /opt/dev/ntsim-ng/ntsim-ng --container-init -w /opt/dev/ntsim-ng + +# finishing container build +ARG BUILD_DATE +LABEL build-date=$BUILD_DATE + +# add exposed ports +EXPOSE 830-929 +EXPOSE 21-22 + +ENV NTS_FUNCTION_TYPE=NTS_FUNCTION_TYPE_X_RAN + +# run +WORKDIR /opt/dev/workspace +CMD ["/opt/dev/ntsim-ng/ntsim-ng", "-w/opt/dev/ntsim-ng", "--supervisor"] diff --git a/ntsimulator/deploy/x-ran/supervisord.conf b/ntsimulator/deploy/x-ran/supervisord.conf deleted file mode 100644 index cd7eb88..0000000 --- a/ntsimulator/deploy/x-ran/supervisord.conf +++ /dev/null @@ -1,22 +0,0 @@ -[supervisord] -nodaemon=true -logfile=/var/log/supervisord.log -loglevel=debug - -[program:netopeer2-server] -command=/usr/local/bin/netopeer2-server -d -autorestart=true -redirect_stderr=true -priority=2 - -[program:sshd] -command=/usr/sbin/sshd -D -autorestart=true -redirect_stderr=true -priority=3 - -[program:ntsim-ng] -command=/opt/dev/ntsim-ng/ntsim-ng -w /opt/dev/ntsim-ng -n -f -autorestart=false -redirect_stderr=true -priority=4 diff --git a/ntsimulator/docker-compose.yaml b/ntsimulator/docker-compose.yaml index 6cf95b5..45f9ebf 100644 --- a/ntsimulator/docker-compose.yaml +++ b/ntsimulator/docker-compose.yaml @@ -1,34 +1,106 @@ -version: '2.4' +version: '3.7' services: ntsim-ng: - image: "${DOCKER_REPO}nts-ng-manager:${BUILD_VERSION}" + image: "${DOCKER_REPO}nts-ng-manager:${NTS_BUILD_VERSION}" container_name: nts-ng-manager + stop_grace_period: 5m ports: - "::${NTS_MANAGER_PORT}:830" volumes: - "/var/run/docker.sock:/var/run/docker.sock" - "/usr/bin/docker:/usr/bin/docker" environment: - IPv6_ENABLED: "false" + NTS_HOST_IP: "10.20.11.136" + NTS_HOST_BASE_PORT: 50000 + NTS_HOST_NETCONF_SSH_BASE_PORT: 0 + NTS_HOST_NETCONF_TLS_BASE_PORT: 1000 + NTS_HOST_TRANSFER_FTP_BASE_PORT: 2000 + NTS_HOST_TRANSFER_SFTP_BASE_PORT: 2000 + DOCKER_ENGINE_VERSION: "1.40" + IPv6_ENABLED: ${IPv6_ENABLED} + SSH_CONNECTIONS: ${SSH_CONNECTIONS} + TLS_CONNECTIONS: ${TLS_CONNECTIONS} + + SDN_CONTROLLER_PROTOCOL: ${SDN_CONTROLLER_PROTOCOL} + SDN_CONTROLLER_IP: ${SDN_CONTROLLER_IP} + SDN_CONTROLLER_PORT: ${SDN_CONTROLLER_PORT} + SDN_CONTROLLER_CALLHOME_PORT: ${SDN_CONTROLLER_CALLHOME_PORT} + SDN_CONTROLLER_USERNAME: ${SDN_CONTROLLER_USERNAME} + SDN_CONTROLLER_PASSWORD: ${SDN_CONTROLLER_PASSWORD} - NETCONF_NTS_HOST_IP: "10.20.11.121" - NETCONF_NTS_HOST_BASE_PORT: 50000 - SSH_CONNECTIONS: 1 - TLS_CONNECTIONS: 0 + VES_COMMON_HEADER_VERSION: ${VES_COMMON_HEADER_VERSION} + VES_ENDPOINT_PROTOCOL: ${VES_ENDPOINT_PROTOCOL} + VES_ENDPOINT_IP: ${VES_ENDPOINT_IP} + VES_ENDPOINT_PORT: ${VES_ENDPOINT_PORT} + VES_ENDPOINT_AUTH_METHOD: ${VES_ENDPOINT_AUTH_METHOD} + VES_ENDPOINT_USERNAME: ${VES_ENDPOINT_USERNAME} + VES_ENDPOINT_PASSWORD: ${VES_ENDPOINT_PASSWORD} + # networks: + # app_net: - SDN_CONTROLLER_IP: "10.20.11.131" - SDN_CONTROLLER_PORT: 8181 - SDN_CONTROLLER_CALLHOME_PORT: 6666 - SDN_CONTROLLER_USERNAME: "admin" - SDN_CONTROLLER_PASSWORD: "admin" + ntsim-ng-o-ru: + image: "${DOCKER_REPO}nts-ng-o-ran-ru-fh:${NTS_BUILD_VERSION}" + cap_add: + - SYS_ADMIN + stop_grace_period: 5m + hostname: "O-RAN-O-RU-1" + ports: + - "::18300:830" + environment: + IPv6_ENABLED: ${IPv6_ENABLED} + SSH_CONNECTIONS: ${SSH_CONNECTIONS} + TLS_CONNECTIONS: ${TLS_CONNECTIONS} + + NTS_NF_STANDALONE_START_FEATURES: "datastore-populate ves-heartbeat ves-file-ready ves-pnf-registration netconf-call-home web-cut-through" + + SDN_CONTROLLER_PROTOCOL: ${SDN_CONTROLLER_PROTOCOL} + SDN_CONTROLLER_IP: ${SDN_CONTROLLER_IP} + SDN_CONTROLLER_PORT: ${SDN_CONTROLLER_PORT} + SDN_CONTROLLER_CALLHOME_PORT: ${SDN_CONTROLLER_CALLHOME_PORT} + SDN_CONTROLLER_USERNAME: ${SDN_CONTROLLER_USERNAME} + SDN_CONTROLLER_PASSWORD: ${SDN_CONTROLLER_PASSWORD} + + VES_COMMON_HEADER_VERSION: ${VES_COMMON_HEADER_VERSION} + VES_ENDPOINT_PROTOCOL: ${VES_ENDPOINT_PROTOCOL} + VES_ENDPOINT_IP: ${VES_ENDPOINT_IP} + VES_ENDPOINT_PORT: ${VES_ENDPOINT_PORT} + VES_ENDPOINT_AUTH_METHOD: ${VES_ENDPOINT_AUTH_METHOD} + VES_ENDPOINT_USERNAME: ${VES_ENDPOINT_USERNAME} + VES_ENDPOINT_PASSWORD: ${VES_ENDPOINT_PASSWORD} + + networks: + app_net: + + ntsim-ng-o-du: + image: "${DOCKER_REPO}nts-ng-o-ran-du:${NTS_BUILD_VERSION}" + cap_add: + - SYS_ADMIN + stop_grace_period: 5m + hostname: "O-RAN-O-DU-1" + ports: + - "::18301:830" + environment: + IPv6_ENABLED: ${IPv6_ENABLED} + SSH_CONNECTIONS: ${SSH_CONNECTIONS} + TLS_CONNECTIONS: ${TLS_CONNECTIONS} - VES_ENDPOINT_PROTOCOL: "https" - VES_ENDPOINT_IP: "127.0.0.1" - VES_ENDPOINT_PORT: 1234 - VES_ENDPOINT_AUTH_METHOD: "no-auth" - VES_ENDPOINT_USERNAME: "admin" - VES_ENDPOINT_PASSWORD: "admin" + NTS_NF_STANDALONE_START_FEATURES: "datastore-populate ves-heartbeat ves-file-ready ves-pnf-registration netconf-call-home web-cut-through" + + SDN_CONTROLLER_PROTOCOL: ${SDN_CONTROLLER_PROTOCOL} + SDN_CONTROLLER_IP: ${SDN_CONTROLLER_IP} + SDN_CONTROLLER_PORT: ${SDN_CONTROLLER_PORT} + SDN_CONTROLLER_CALLHOME_PORT: ${SDN_CONTROLLER_CALLHOME_PORT} + SDN_CONTROLLER_USERNAME: ${SDN_CONTROLLER_USERNAME} + SDN_CONTROLLER_PASSWORD: ${SDN_CONTROLLER_PASSWORD} + + VES_COMMON_HEADER_VERSION: ${VES_COMMON_HEADER_VERSION} + VES_ENDPOINT_PROTOCOL: ${VES_ENDPOINT_PROTOCOL} + VES_ENDPOINT_IP: ${VES_ENDPOINT_IP} + VES_ENDPOINT_PORT: ${VES_ENDPOINT_PORT} + VES_ENDPOINT_AUTH_METHOD: ${VES_ENDPOINT_AUTH_METHOD} + VES_ENDPOINT_USERNAME: ${VES_ENDPOINT_USERNAME} + VES_ENDPOINT_PASSWORD: ${VES_ENDPOINT_PASSWORD} networks: app_net: @@ -37,3 +109,9 @@ networks: driver: bridge ipam: driver: default + +# We can attach to any other docker network, like in the example below +# networks: +# default: +# external: +# name: smo_integration \ No newline at end of file diff --git a/ntsimulator/nts-ng-docker-image-build-ubuntu.yaml b/ntsimulator/nts-ng-docker-image-build-ubuntu.yaml index 051da85..23ea07d 100644 --- a/ntsimulator/nts-ng-docker-image-build-ubuntu.yaml +++ b/ntsimulator/nts-ng-docker-image-build-ubuntu.yaml @@ -19,7 +19,7 @@ services: ####### Base docker image containing the framework ################################################### nts-ng-base: - image: o-ran-sc/nts-ng-base + image: ${DOCKER_REPO}nts-ng-base build: context: . dockerfile: ./deploy/base/ubuntu.Dockerfile @@ -28,31 +28,53 @@ services: ####### NTS-NG Manager ################################################### nts-ng-manager: - image: o-ran-sc/nts-ng-manager + image: ${DOCKER_REPO}nts-ng-manager:${NTS_BUILD_VERSION} build: context: ./deploy/nts-manager - dockerfile: ubuntu.Dockerfile - args: - - BUILD_DATE + labels: + - "description=nts-ng" + dockerfile: local.Dockerfile + + ################################################### + ####### X-RAN + ################################################### + nts-ng-x-ran: + image: ${DOCKER_REPO}nts-ng-x-ran:${NTS_BUILD_VERSION} + build: + context: ./deploy/x-ran + labels: + - "description=nts-ng" + dockerfile: local.Dockerfile ################################################### ####### O-RAN FH ################################################### nts-ng-o-ran-fh: - image: o-ran-sc/nts-ng-o-ran-fh + image: ${DOCKER_REPO}nts-ng-o-ran-fh:${NTS_BUILD_VERSION} build: context: ./deploy/o-ran - dockerfile: ubuntu.Dockerfile - args: - - BUILD_DATE + labels: + - "description=nts-ng" + dockerfile: local.Dockerfile ################################################### - ####### X-RAN + ####### O-RAN RU FH November Train ################################################### - nts-ng-x-ran: - image: o-ran-sc/nts-ng-x-ran + nts-ng-o-ran-ru-fh: + image: ${DOCKER_REPO}nts-ng-o-ran-ru-fh:${NTS_BUILD_VERSION} build: - context: ./deploy/x-ran - dockerfile: ubuntu.Dockerfile - args: - - BUILD_DATE + context: ./deploy/o-ran-ru-fh + labels: + - "description=nts-ng" + dockerfile: local.Dockerfile + + ################################################### + ####### O-RAN DU + ################################################### + nts-ng-o-ran-du: + image: ${DOCKER_REPO}nts-ng-o-ran-du:${NTS_BUILD_VERSION} + build: + context: ./deploy/o-ran-du + labels: + - "description=nts-ng" + dockerfile: local.Dockerfile diff --git a/ntsimulator/nts-start.sh b/ntsimulator/nts-start.sh new file mode 100755 index 0000000..3b4541b --- /dev/null +++ b/ntsimulator/nts-start.sh @@ -0,0 +1 @@ +docker-compose up -d --scale ntsim-ng=0 --scale ntsim-ng-o-ru=1 --scale ntsim-ng-o-du=1 \ No newline at end of file diff --git a/ntsimulator/nts-stop.sh b/ntsimulator/nts-stop.sh new file mode 100755 index 0000000..58694d0 --- /dev/null +++ b/ntsimulator/nts-stop.sh @@ -0,0 +1 @@ +docker-compose down \ No newline at end of file diff --git a/ntsimulator/nts_build.sh b/ntsimulator/nts_build.sh new file mode 100755 index 0000000..62619e1 --- /dev/null +++ b/ntsimulator/nts_build.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +source .env +docker-compose -f nts-ng-docker-image-build-ubuntu.yaml build --build-arg NTS_BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') --build-arg NTS_BUILD_VERSION=$NTS_BUILD_VERSION diff --git a/ntsimulator/ntsim-ng/core/app/app_common.c b/ntsimulator/ntsim-ng/core/app/app_common.c new file mode 100644 index 0000000..35bcef5 --- /dev/null +++ b/ntsimulator/ntsim-ng/core/app/app_common.c @@ -0,0 +1,69 @@ +/************************************************************************* +* +* Copyright 2020 highstreet technologies GmbH and others +* +* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +* +* 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. +***************************************************************************/ + +#define _GNU_SOURCE + +#include "supervisor.h" +#include "utils/log_utils.h" +#include "utils/sys_utils.h" +#include +#include + +#include "core/session.h" +#include "core/framework.h" + +#define SYSREPO_BUILD_TIME_XPATH "/nts-network-function:info/build-time" +#define SYSREPO_VERSION_XPATH "/nts-network-function:info/version" + +static int app_common_populate_info(void); + +int app_common_init(void) { + assert_session(); + + int rc = app_common_populate_info(); + if(rc != NTS_ERR_OK) { + log_error("app_common_populate_info() failed\n"); + return NTS_ERR_FAILED; + } + + return NTS_ERR_OK; +} + +static int app_common_populate_info(void) { + int rc; + if (framework_environment.nts.build_time && strlen(framework_environment.nts.build_time) > 0) { + rc = sr_set_item_str(session_operational, SYSREPO_BUILD_TIME_XPATH, framework_environment.nts.build_time, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + } + + rc = sr_set_item_str(session_operational, SYSREPO_VERSION_XPATH, framework_environment.nts.version, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + rc = sr_apply_changes(session_operational, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_apply_changes failed: %s\n", sr_strerror(rc)); + return NTS_ERR_FAILED; + } + + return NTS_ERR_OK; +} diff --git a/ntsimulator/ntsim-ng/core/app/app_common.h b/ntsimulator/ntsim-ng/core/app/app_common.h new file mode 100644 index 0000000..3dec9c5 --- /dev/null +++ b/ntsimulator/ntsim-ng/core/app/app_common.h @@ -0,0 +1,21 @@ +/************************************************************************* +* +* Copyright 2020 highstreet technologies GmbH and others +* +* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +* +* 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. +***************************************************************************/ + +#pragma once + +int app_common_init(void); + diff --git a/ntsimulator/ntsim-ng/core/app/manager.c b/ntsimulator/ntsim-ng/core/app/manager.c index 4881661..cc522dc 100644 --- a/ntsimulator/ntsim-ng/core/app/manager.c +++ b/ntsimulator/ntsim-ng/core/app/manager.c @@ -29,568 +29,261 @@ #include "core/framework.h" #include "core/session.h" #include "core/context.h" -#include "core/docker.h" -#define NTS_MANAGER_MODULE "nts-manager" -#define NTS_SIMULATION_SCHEMA_XPATH "/nts-manager:simulation" -#define NTS_FUNCTION_LIST_SCHEMA_XPATH "/nts-manager:simulation/network-functions/network-function" -#define NTS_SDN_CONTROLLER_CONFIG_XPATH "/nts-manager:simulation/sdn-controller" -#define NTS_VES_ENDPOINT_CONFIG_XPATH "/nts-manager:simulation/ves-endpoint" +#include "app_common.h" -#define NTS_NETWORK_FUNCTION_FTYPE_SCHEMA_XPATH "/nts-network-function:simulation/network-function/function-type" - -static manager_network_function_type *manager_context = 0; -static int manager_installed_function_types_count = 0; - -static int manager_populate_sysrepo_network_function_list(void); -static int manager_populate_static_status(void); - -static void manager_context_free(manager_network_function_type *context); - -static int manager_process_change(int context_index, manager_network_function_type *new_context); static int manager_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *private_data); static int manager_instances_get_items_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data); -static int manager_stats_get_items_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data); int manager_run(void) { assert_session(); - log_message(1, LOG_COLOR_BOLD_YELLOW"\nrunning as MANAGER daemon...\n"LOG_COLOR_RESET); - - manager_operations_init(); - docker_device_init(); - - //get installed function types - struct lys_node_leaf *elem = (struct lys_node_leaf *)ly_ctx_get_node(session_context, 0, NTS_FUNCTION_LIST_SCHEMA_XPATH"/function-type", 0); - if(elem == 0) { - log_error("ly_ctx_get_node failed for xpath: %s", NTS_FUNCTION_LIST_SCHEMA_XPATH"/function-type"); - return NTS_ERR_FAILED; - } + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"starting MANAGER...\n"LOG_COLOR_RESET); - struct lys_ident **found = 0; - manager_installed_function_types_count = context_get_identity_leafs_of_type(elem->type.info.ident.ref[0], &found); - if(!manager_installed_function_types_count) { - log_error("error network functions"); - return NTS_ERR_FAILED; - } - - //initial list population - manager_context = (manager_network_function_type *)malloc(sizeof(manager_network_function_type) * manager_installed_function_types_count); - for(int i = 0; i < manager_installed_function_types_count; i++) { - manager_context[i].instance = 0; - - manager_context[i].function_type = found[i]; - asprintf(&manager_context[i].function_type_string, "%s:%s", found[i]->module->name, found[i]->name); - manager_context[i].docker_image_name = manager_context[i].function_type->ref; - manager_context[i].started_instances = 0; - manager_context[i].mounted_instances = 0; - manager_context[i].mount_point_addressing_method = strdup("docker-mapping"); - manager_context[i].docker_instance_name = strdup(manager_context[i].function_type->name); - manager_context[i].docker_version_tag = strdup("latest"); - manager_context[i].docker_repository = strdup("local"); - } - free(found); - - //do initial sysrepo list population - int rc = manager_populate_sysrepo_network_function_list(); + int rc = app_common_init(); if(rc != NTS_ERR_OK) { - log_error("manager_populate_sysrepo_network_function_list failed"); - return NTS_ERR_FAILED; - } - - rc = manager_populate_static_status(); - if(rc != NTS_ERR_OK) { - log_error("manager_populate_static_status failed"); + log_error("app_common_init failed\n"); return NTS_ERR_FAILED; } - //subscribe to any changes on the list - rc = sr_module_change_subscribe(session_running, NTS_MANAGER_MODULE, NTS_SIMULATION_SCHEMA_XPATH, manager_change_cb, NULL, 0, SR_SUBSCR_CTX_REUSE, &session_subscription); - if(rc != SR_ERR_OK) { - log_error("could not subscribe to simulation changes"); + //init manager context + rc = manager_context_init(); + if(rc != NTS_ERR_OK) { + log_error("manager_context_init failed\n"); return NTS_ERR_FAILED; } - rc = sr_oper_get_items_subscribe(session_running, NTS_MANAGER_MODULE, NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_instances_get_items_cb, NULL, SR_SUBSCR_CTX_REUSE, &session_subscription); - if(rc != SR_ERR_OK) { - log_error("could not subscribe to oper faults"); - return 0; - } - - rc = sr_oper_get_items_subscribe(session_running, NTS_MANAGER_MODULE, NTS_SIMULATION_SCHEMA_XPATH, manager_stats_get_items_cb, NULL, SR_SUBSCR_CTX_REUSE, &session_subscription); - if(rc != SR_ERR_OK) { - log_error("could not subscribe to oper faults"); - return 0; - } - - //daemonize - while(!framework_sigint) { - sleep(1); - } - - for(int i = 0; i < manager_installed_function_types_count; i++) { - while(manager_context[i].started_instances) { - manager_stop_instance(&manager_context[i]); - } - manager_context_free(&manager_context[i]); - } - - free(manager_context); - - return NTS_ERR_OK; -} - -static int manager_populate_sysrepo_network_function_list(void) { - //check whether everything is already populated, read and update (if previously ran) - sr_val_t *values = 0; - size_t value_count = 0; - int rc = sr_get_items(session_running, NTS_FUNCTION_LIST_SCHEMA_XPATH, 0, 0, &values, &value_count); - if(rc != SR_ERR_OK) { - log_error("get items failed"); + //init operations + rc = manager_operations_init(); + if(rc != NTS_ERR_OK) { + log_error("manager_operations_init failed\n"); return NTS_ERR_FAILED; } - //either get values, or if data inconclusive, delete everything - if(value_count) { - log_message(2, "nts-manager instances found (%d). cleaning up for fresh start...\n", value_count); - - for(int i = 0; i < value_count; i++) { - rc = sr_delete_item(session_running, values[i].xpath, 0); - if(rc != SR_ERR_OK) { - log_error("sr_delete_item failed"); - return NTS_ERR_FAILED; - } - } - rc = sr_apply_changes(session_running, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_apply_changes failed"); - return NTS_ERR_FAILED; - } - } - - //populate everything if needed - for(int i = 0; i < manager_installed_function_types_count; i++) { - char *xpath = 0; - - asprintf(&xpath, "%s[function-type='%s']/function-type", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type_string); - rc = sr_set_item_str(session_running, xpath, (const char *)manager_context[i].function_type_string, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; - } - free(xpath); - - asprintf(&xpath, "%s[function-type='%s']/started-instances", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type_string); - rc = sr_set_item_str(session_running, xpath, "0", 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; - } - free(xpath); - - asprintf(&xpath, "%s[function-type='%s']/mounted-instances", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type_string); - rc = sr_set_item_str(session_running, xpath, "0", 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; - } - free(xpath); - - asprintf(&xpath, "%s[function-type='%s']/mount-point-addressing-method", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type_string); - rc = sr_set_item_str(session_running, xpath, (const char*)manager_context[i].mount_point_addressing_method, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; - } - free(xpath); - - asprintf(&xpath, "%s[function-type='%s']/docker-instance-name", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type_string); - rc = sr_set_item_str(session_running, xpath, (const char*)manager_context[i].docker_instance_name, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; - } - free(xpath); - - asprintf(&xpath, "%s[function-type='%s']/docker-version-tag", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type_string); - rc = sr_set_item_str(session_running, xpath, (const char*)manager_context[i].docker_version_tag, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; - } - free(xpath); - - asprintf(&xpath, "%s[function-type='%s']/docker-repository", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type_string); - rc = sr_set_item_str(session_running, xpath, (const char*)manager_context[i].docker_repository, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; - } - free(xpath); - } - - char int_to_str[30]; - - //setup sdn-controller defaults - if(strlen(framework_environment.sdn_controller_ip)) { - rc = sr_set_item_str(session_running, NTS_SDN_CONTROLLER_CONFIG_XPATH"/controller-ip", (const char*)framework_environment.sdn_controller_ip, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; + //print everything on the manager's screen + log_add_verbose(1, LOG_COLOR_BOLD_CYAN"Available images: \n"LOG_COLOR_RESET); + for(int i = 0; i < docker_context_count; i++) { + log_add_verbose(1, LOG_COLOR_BOLD_CYAN"- %s\n"LOG_COLOR_RESET, docker_context[i].image); + for(int j = 0; j < docker_context[i].available_images_count; j++) { + log_add_verbose(1, " - "LOG_COLOR_RED"%s/"LOG_COLOR_CYAN"%s"LOG_COLOR_RESET":"LOG_COLOR_YELLOW"%s\n"LOG_COLOR_RESET, docker_context[i].available_images[j].repo, docker_context[i].image, docker_context[i].available_images[j].tag); } } - - sprintf(int_to_str, "%d", framework_environment.sdn_controller_port); - rc = sr_set_item_str(session_running, NTS_SDN_CONTROLLER_CONFIG_XPATH"/controller-port", (const char*)int_to_str, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; - } - - sprintf(int_to_str, "%d", framework_environment.sdn_controller_callhome_port); - rc = sr_set_item_str(session_running, NTS_SDN_CONTROLLER_CONFIG_XPATH"/controller-netconf-call-home-port", (const char*)int_to_str, 0, 0); + + // subscribe to any changes on the list + rc = sr_module_change_subscribe(session_running, NTS_MANAGER_MODULE, NTS_SIMULATION_SCHEMA_XPATH, manager_change_cb, NULL, 0, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_UPDATE, &session_subscription); if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); + log_error("could not subscribe to simulation changes\n"); return NTS_ERR_FAILED; } - if(strlen(framework_environment.sdn_controller_username)) { - rc = sr_set_item_str(session_running, NTS_SDN_CONTROLLER_CONFIG_XPATH"/controller-username", (const char*)framework_environment.sdn_controller_username, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; - } - } - - if(strlen(framework_environment.sdn_controller_password)) { - rc = sr_set_item_str(session_running, NTS_SDN_CONTROLLER_CONFIG_XPATH"/controller-password", (const char*)framework_environment.sdn_controller_password, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; - } - } - - //setup ves-endpoint details - if(strlen(framework_environment.ves_endpoint_protocol)) { - rc = sr_set_item_str(session_running, NTS_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-protocol", (const char*)framework_environment.ves_endpoint_protocol, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; - } - } - - if(strlen(framework_environment.ves_endpoint_ip)) { - rc = sr_set_item_str(session_running, NTS_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-ip", (const char*)framework_environment.ves_endpoint_ip, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; - } - } - - sprintf(int_to_str, "%d", framework_environment.ves_endpoint_port); - rc = sr_set_item_str(session_running, NTS_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-port", (const char*)int_to_str, 0, 0); + //subscribe to stats + rc = sr_oper_get_items_subscribe(session_running, NTS_MANAGER_MODULE, NTS_SIMULATION_SCHEMA_XPATH, manager_sr_stats_get_items_cb, NULL, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_OPER_MERGE, &session_subscription); if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); + log_error("could not subscribe to oper faults\n"); return NTS_ERR_FAILED; } - if(strlen(framework_environment.ves_endpoint_auth_method)) { - rc = sr_set_item_str(session_running, NTS_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-auth-method", (const char*)framework_environment.ves_endpoint_auth_method, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; - } - } - - if(strlen(framework_environment.ves_endpoint_username)) { - rc = sr_set_item_str(session_running, NTS_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-username", (const char*)framework_environment.ves_endpoint_username, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; - } - } - - if(strlen(framework_environment.ves_endpoint_password)) { - rc = sr_set_item_str(session_running, NTS_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-password", (const char*)framework_environment.ves_endpoint_password, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; - } - } - - if(strlen(framework_environment.ves_endpoint_certificate)) { - rc = sr_set_item_str(session_running, NTS_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-certificate", (const char*)framework_environment.ves_endpoint_certificate, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; - } - } - - rc = sr_set_item_str(session_running, NTS_NETWORK_FUNCTION_FTYPE_SCHEMA_XPATH, "NTS_FUNCTION_TYPE_MANAGER", 0, 0); + //subscribe to instances oper change + rc = sr_oper_get_items_subscribe(session_running, NTS_MANAGER_MODULE, NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_instances_get_items_cb, NULL, SR_SUBSCR_CTX_REUSE, &session_subscription); if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; + log_error("could not subscribe to oper faults\n"); + return 0; } - - //apply all changes - rc = sr_apply_changes(session_running, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_apply_changes failed: %s", sr_strerror(rc)); + rc = manager_sr_update_static_stats(); + if(rc != NTS_ERR_OK) { + log_error("manager_sr_update_static_stats failed\n"); return NTS_ERR_FAILED; } - return NTS_ERR_OK; -} - -static int manager_populate_static_status(void) { - assert_session(); - - char int_to_str[30]; - - //setup sdn-controller defaults - sprintf(int_to_str, "%d", framework_environment.host_base_port); - int rc = sr_set_item_str(session_operational, NTS_SIMULATION_SCHEMA_XPATH"/base-port", (const char*)int_to_str, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"nts-ng manager"LOG_COLOR_RESET" v%s build %s\n", framework_environment.nts.version, framework_environment.nts.build_time); + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"Host IP:"LOG_COLOR_RESET" %s\n", framework_environment.host.ip); + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"Host ports"LOG_COLOR_RESET": "); + if(framework_environment.settings.ssh_connections) { + log_add(1, "NETCONF SSH: %d (%d)", framework_environment.host.ssh_base_port, framework_environment.settings.ssh_connections); } - - sprintf(int_to_str, "%d", framework_environment.ssh_connections); - rc = sr_set_item_str(session_operational, NTS_SIMULATION_SCHEMA_XPATH"/ssh-connections", (const char*)int_to_str, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; + else { + log_add(1, "NETCONF SSH: disabled"); } - - sprintf(int_to_str, "%d", framework_environment.tls_connections); - rc = sr_set_item_str(session_operational, NTS_SIMULATION_SCHEMA_XPATH"/tls-connections", (const char*)int_to_str, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; + if(framework_environment.settings.tls_connections) { + log_add(1, " | NETCONF TLS: %d (%d)", framework_environment.host.tls_base_port, framework_environment.settings.tls_connections); } - - //apply all changes - rc = sr_apply_changes(session_operational, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_apply_changes failed"); - return NTS_ERR_FAILED; + else { + log_add(1, " | NETCONF TLS: disabled"); } - - return NTS_ERR_OK; -} - -static void manager_context_free(manager_network_function_type *context) { - assert(context); - - free(context->function_type_string); - free(context->mount_point_addressing_method); - free(context->docker_instance_name); - free(context->docker_version_tag); - free(context->docker_repository); -} - -//take note that this happens in the sysrepo thread -static int manager_process_change(int context_index, manager_network_function_type *new_context) { - assert(context_index < manager_installed_function_types_count); - assert(new_context); - - manager_network_function_type *current_context = &manager_context[context_index]; - int rc = 0; - - current_context->data_changed |= new_context->data_changed; - - //process changes, and update data in current_context to resemble new_context - if(new_context->docker_instance_name != 0) { - free(current_context->docker_instance_name); - current_context->docker_instance_name = strdup(new_context->docker_instance_name); + if(framework_environment.settings.ftp_connections) { + log_add(1, " | FTP: %d (%d)", framework_environment.host.ftp_base_port, framework_environment.settings.ftp_connections); } - - if(new_context->docker_version_tag != 0) { - free(current_context->docker_version_tag); - current_context->docker_version_tag = strdup(new_context->docker_version_tag); + else { + log_add(1, " | FTP: disabled"); } - - if(new_context->docker_repository != 0) { - free(current_context->docker_repository); - current_context->docker_repository = strdup(new_context->docker_repository); + if(framework_environment.settings.sftp_connections) { + log_add(1, " | SFTP: %d (%d)", framework_environment.host.sftp_base_port, framework_environment.settings.sftp_connections); } - - if(new_context->mount_point_addressing_method != 0) { - free(current_context->mount_point_addressing_method); - current_context->mount_point_addressing_method = strdup(new_context->mount_point_addressing_method); + else { + log_add(1, " | SFTP: disabled"); } + log_add(1,"\n"); + log_add_verbose(1, LOG_COLOR_BOLD_GREEN"started!\n"LOG_COLOR_RESET); - if(new_context->started_instances != -1) { - if(new_context->started_instances < current_context->started_instances) { - //remove started instances - while(current_context->started_instances > new_context->started_instances) { - log_message(2, "stopping instance of type %s\n", current_context->function_type_string); - rc = manager_stop_instance(current_context); - if(rc != NTS_ERR_OK) { - log_error("manager_stop_instance failed"); - return NTS_ERR_FAILED; - break; - } - } - } - else if(new_context->started_instances > current_context->started_instances) { - //add started instances - while(current_context->started_instances < new_context->started_instances) { - log_message(2, "staring instance of type %s\n", current_context->function_type_string); - rc = manager_start_instance(current_context); - if(rc != NTS_ERR_OK) { - log_error("manager_start_instance failed"); - return NTS_ERR_FAILED; - break; - } - } - } + //daemonize + while(!framework_sigint) { + manager_operations_loop(); //caution - this function time-waits (1sec) on manager_operation_sem } - if(new_context->mounted_instances != -1) { - if(new_context->mounted_instances < current_context->mounted_instances) { - //remove mounted instances - while(current_context->mounted_instances > new_context->mounted_instances) { - log_message(2, "unmounting instance of type %s\n", current_context->function_type_string); - rc = manager_unmount_instance(current_context); - if(rc != NTS_ERR_OK) { - log_error("manager_unmount_instance failed"); - break; - } - } - } - else if(new_context->mounted_instances > current_context->mounted_instances) { - //add mounted instances - while(current_context->mounted_instances < new_context->mounted_instances) { - log_message(2, "mouting instance of type %s\n", current_context->function_type_string); - rc = manager_mount_instance(current_context); - if(rc != NTS_ERR_OK) { - log_error("manager_mount_instance failed"); - break; - } - } - } - } + manager_operations_free(); + manager_context_free(); return NTS_ERR_OK; } static int manager_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *private_data) { sr_change_iter_t *it = 0; - int rc = SR_ERR_OK; sr_change_oper_t oper; sr_val_t *old_value = 0; sr_val_t *new_value = 0; + int rc = SR_ERR_OK; - if(event == SR_EV_CHANGE) { - manager_network_function_type new_context; - new_context.function_type = 0; //not to be used. use only from current_context - new_context.function_type_string = 0; //not to be used. use only from current_context - int index = -1; + if(manager_sr_get_context_sync()) { + return SR_ERR_OK; + } + if(event == SR_EV_UPDATE) { rc = sr_get_changes_iter(session, NTS_FUNCTION_LIST_SCHEMA_XPATH"//.", &it); if(rc != SR_ERR_OK) { - log_error("sr_get_changes_iter failed"); + log_error("sr_get_changes_iter failed\n"); return SR_ERR_VALIDATION_FAILED; } + manager_operation_t *new_oper = 0; while((rc = sr_get_change_next(session, it, &oper, &old_value, &new_value)) == SR_ERR_OK) { - char *ov = sr_val_to_str(old_value); - char *nv = sr_val_to_str(new_value); - - //get function type and index - char *function_type_string = strdup(strstr(new_value->xpath, "function-type='") + 15); - *strchr(function_type_string, '\'') = 0; - - //if context is new - if((new_context.function_type_string == 0) || (strcmp(new_context.function_type_string, function_type_string) != 0)) { - - if(new_context.function_type_string != 0) { - if(manager_process_change(index, &new_context) != NTS_ERR_OK) { - manager_context_free(&new_context); - return SR_ERR_VALIDATION_FAILED; + if(new_value) { + //get function type and index + char *nv = sr_val_to_str(new_value); + + char function_type[512]; + strncpy(function_type, strstr(new_value->xpath, "function-type='") + 15, 510); + *strchr(function_type, '\'') = 0; + + //if context is new + if((new_oper == 0) || (strcmp(new_oper->function_type, function_type) != 0)) { + + if(new_oper == 0) { + manager_operations_begin(); + } + else { + //validate and add the operation + if(manager_operations_validate(new_oper) != NTS_ERR_OK) { + manager_operations_free_oper(new_oper); + manager_operations_finish_with_error(); + return SR_ERR_VALIDATION_FAILED; + } + + manager_operations_add(new_oper); + } + + new_oper = manager_operations_new_oper(MANAGER_OPERATION_EDIT); + new_oper->function_type = strdup(function_type); + + //get ft_idnex + for(int i = 0; i < docker_context_count; i++) { + if(strcmp(new_oper->function_type, manager_context[i].function_type) == 0) { + new_oper->ft_index = i; + break; + } } - manager_context_free(&new_context); + if(new_oper->ft_index == -1) { + log_error("function-type not found: %s\n", new_oper->function_type); + return SR_ERR_VALIDATION_FAILED; + } } - //-1 means no change - new_context.function_type_string = function_type_string; - new_context.started_instances = -1; - new_context.mounted_instances = -1; - new_context.mount_point_addressing_method = 0; - new_context.docker_instance_name = 0; - new_context.docker_version_tag = 0; - new_context.docker_repository = 0; - - new_context.data_changed = false; - - //find intex in manager_context[] - for(int i = 0; i < manager_installed_function_types_count; i++) { - if(strcmp(function_type_string, manager_context[i].function_type_string) == 0) { - index = i; - break; + char *leaf_path = strdup(strstr(new_value->xpath, "']/") + 3); + if(strcmp(leaf_path, "started-instances") == 0) { + new_oper->started_instances = new_value->data.uint16_val; + rc = sr_set_item(session, old_value->xpath, old_value, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item failed\n"); + return SR_ERR_VALIDATION_FAILED; + } + } + else if(strcmp(leaf_path, "mounted-instances") == 0) { + new_oper->mounted_instances = new_value->data.uint16_val; + rc = sr_set_item(session, old_value->xpath, old_value, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item failed\n"); + return SR_ERR_VALIDATION_FAILED; + } + } + else if(strcmp(leaf_path, "docker-instance-name") == 0) { + new_oper->docker_instance_name = strdup(nv); + free(manager_context[new_oper->ft_index].docker_instance_name); + manager_context[new_oper->ft_index].docker_instance_name = strdup(nv); + } + else if(strcmp(leaf_path, "docker-version-tag") == 0) { + new_oper->docker_version_tag = strdup(nv); + free(manager_context[new_oper->ft_index].docker_version_tag); + manager_context[new_oper->ft_index].docker_version_tag = strdup(nv); + } + else if(strcmp(leaf_path, "docker-repository") == 0) { + new_oper->docker_repository = strdup(nv); + free(manager_context[new_oper->ft_index].docker_repository); + manager_context[new_oper->ft_index].docker_repository = strdup(nv); + } + else if(strcmp(leaf_path, "mount-point-addressing-method") == 0) { + //update conetxt + free(manager_context[new_oper->ft_index].mount_point_addressing_method); + manager_context[new_oper->ft_index].mount_point_addressing_method = strdup(nv); + } + else { + //mark each instance for reconfiguration + for(int i = 0; i < manager_context[new_oper->ft_index].started_instances; i++) { + manager_context[new_oper->ft_index].instance[i].is_configured = false; } } - } - char *leaf_path = strdup(strstr(new_value->xpath, "']/") + 3); - if(strcmp(leaf_path, "started-instances") == 0) { - new_context.started_instances = new_value->data.uint16_val; - } - else if(strcmp(leaf_path, "mounted-instances") == 0) { - new_context.mounted_instances = new_value->data.uint16_val; - } - else if(strcmp(leaf_path, "mount-point-addressing-method") == 0) { - new_context.mount_point_addressing_method = strdup(nv); - } - else if(strcmp(leaf_path, "docker-instance-name") == 0) { - new_context.docker_instance_name = strdup(nv); - } - else if(strcmp(leaf_path, "docker-version-tag") == 0) { - new_context.docker_version_tag = strdup(nv); - } - else if(strcmp(leaf_path, "docker-repository") == 0) { - new_context.docker_repository = strdup(nv); - } - else { - new_context.data_changed = true; + free(leaf_path); + free(nv); } - free(leaf_path); - free(ov); - free(nv); sr_free_val(old_value); sr_free_val(new_value); } sr_free_change_iter(it); - - if(index != -1) { - if(manager_process_change(index, &new_context) != NTS_ERR_OK) { - manager_context_free(&new_context); + + //validate and add the operation, if any; can be 0 if no modifications to NF list + if(new_oper) { + if(manager_operations_validate(new_oper) != NTS_ERR_OK) { + manager_operations_free_oper(new_oper); + manager_operations_finish_with_error(); return SR_ERR_VALIDATION_FAILED; } - manager_context_free(&new_context); + manager_operations_add(new_oper); } } + else if(event == SR_EV_CHANGE) { + } else if(event == SR_EV_DONE) { - bool global_change = true; + bool global_change = false; + // go throughout all the changes, not just NF list rc = sr_get_changes_iter(session, NTS_SIMULATION_SCHEMA_XPATH"//.", &it); if(rc != SR_ERR_OK) { - log_error("sr_get_changes_iter failed"); + log_error("sr_get_changes_iter failed\n"); return SR_ERR_VALIDATION_FAILED; } while((rc = sr_get_change_next(session, it, &oper, &old_value, &new_value)) == SR_ERR_OK) { - if(strstr(new_value->xpath, NTS_FUNCTION_LIST_SCHEMA_XPATH) == new_value->xpath) { - global_change = false; - sr_free_val(old_value); - sr_free_val(new_value); - break; + if(new_value) { + if(strstr(new_value->xpath, NTS_FUNCTION_LIST_SCHEMA_XPATH) != new_value->xpath) { + global_change = true; + sr_free_val(old_value); + sr_free_val(new_value); + break; + } } sr_free_val(old_value); @@ -599,124 +292,56 @@ static int manager_change_cb(sr_session_ctx_t *session, const char *module_name, sr_free_change_iter(it); - // commit all updates - for(int i = 0; i < manager_installed_function_types_count; i++) { - for(int j = 0; j < manager_context[i].started_instances; j++) { - if(global_change || manager_context[i].data_changed || (manager_context[i].instance[j].is_configured == false)) { - log_message(2, "configuring instance %d of type %s\n", j, manager_context[i].function_type_string); - rc = manager_config_instance(&manager_context[i], &manager_context[i].instance[j]); - if(rc != NTS_ERR_OK) { - log_error("manager_config_instance failed"); - } + if(global_change) { + //mark each instance for reconfiguration + for(int i = 0; i < docker_context_count; i++) { + for(int j = 0; j < manager_context[i].started_instances; j++) { + manager_context[i].instance[j].is_configured = false; } } - - manager_context[i].data_changed = false; } - global_change = false; + + manager_operations_finish_and_execute(); //from this point on, manager_operations_loop will take over } return SR_ERR_OK; } static int manager_instances_get_items_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data) { - - char value[100]; *parent = lyd_new_path(NULL, sr_get_context(sr_session_get_connection(session)), NTS_FUNCTION_LIST_SCHEMA_XPATH, 0, 0, 0); if(*parent == 0) { - log_error("lyd_new_path failed"); + log_error("lyd_new_path failed\n"); return SR_ERR_OPERATION_FAILED; } - for(int i = 0; i < manager_installed_function_types_count; i++) { - char *ftype_path = 0; - asprintf(&ftype_path, "%s[function-type='%s']/instances/instance", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type_string); + for(int i = 0; i < docker_context_count; i++) { + char ftype_path[512]; + sprintf(ftype_path, "%s[function-type='%s']/instances/instance", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type); for(int j = 0; j < manager_context[i].started_instances; j++) { - char *instance_path = 0; - asprintf(&instance_path, "%s[name='%s']", ftype_path, manager_context[i].instance[j].name); + char instance_path[1024]; + sprintf(instance_path, "%s[name='%s']", ftype_path, manager_context[i].instance[j].container.name); - char *full_path = 0; + char full_path[2048]; - asprintf(&full_path, "%s/mount-point-addressing-method", instance_path); + sprintf(full_path, "%s/mount-point-addressing-method", instance_path); if(lyd_new_path(*parent, NULL, full_path, manager_context[i].instance[j].mount_point_addressing_method, 0, 0) == 0) { - log_error("lyd_new_path failed"); - return SR_ERR_OPERATION_FAILED; - } - free(full_path); - - asprintf(&full_path, "%s/networking/docker-ip", instance_path); - if(lyd_new_path(*parent, NULL, full_path, manager_context[i].instance[j].docker_ip, 0, 0) == 0) { - log_error("lyd_new_path failed"); - return SR_ERR_OPERATION_FAILED; - } - free(full_path); - - asprintf(&full_path, "%s/networking/docker-port", instance_path); - sprintf(value, "%d", manager_context[i].instance[j].docker_port); - if(lyd_new_path(*parent, NULL, full_path, value, 0, 0) == 0) { - log_error("lyd_new_path failed"); + log_error("lyd_new_path failed\n"); return SR_ERR_OPERATION_FAILED; } - free(full_path); - asprintf(&full_path, "%s/networking/host-ip", instance_path); - if(lyd_new_path(*parent, NULL, full_path, manager_context[i].instance[j].host_ip, 0, 0) == 0) { - log_error("lyd_new_path failed"); + sprintf(full_path, "%s/is-mounted", instance_path); + struct lyd_node *is_mounted = lyd_new_path(*parent, NULL, full_path, manager_context[i].instance[j].is_mounted ? "true" : "false", 0, LYD_PATH_OPT_NOPARENTRET); + if(is_mounted == 0) { + log_error("lyd_new_path failed\n"); return SR_ERR_OPERATION_FAILED; } - free(full_path); - asprintf(&full_path, "%s/networking/host-port", instance_path); - sprintf(value, "%d", manager_context[i].instance[j].host_port); - if(lyd_new_path(*parent, NULL, full_path, value, 0, 0) == 0) { - log_error("lyd_new_path failed"); + if(manager_sr_populate_networking(is_mounted->parent, &manager_context[i].instance[j]) != NTS_ERR_OK) { + log_error("manager_sr_populate_networking failed\n"); return SR_ERR_OPERATION_FAILED; } - free(full_path); - - free(instance_path); } - free(ftype_path); - } - - return SR_ERR_OK; -} - -static int manager_stats_get_items_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data) { - char value[128]; - - *parent = lyd_new_path(NULL, sr_get_context(sr_session_get_connection(session)), NTS_SIMULATION_SCHEMA_XPATH, 0, 0, 0); - if(*parent == 0) { - return SR_ERR_OPERATION_FAILED; - } - - docker_usage_t usage = docker_usage_get(manager_context, manager_installed_function_types_count); - - sprintf(value, "%.2f", usage.cpu); - if(lyd_new_path(*parent, NULL, NTS_SIMULATION_SCHEMA_XPATH"/cpu-usage", value, 0, 0) == 0) { - return SR_ERR_OPERATION_FAILED; - } - - sprintf(value, "%.0f", usage.mem); - if(lyd_new_path(*parent, NULL, NTS_SIMULATION_SCHEMA_XPATH"/mem-usage", value, 0, 0) == 0) { - return SR_ERR_OPERATION_FAILED; - } - - //setup sdn-controller defaults - sprintf(value, "%d", framework_environment.host_base_port); - if(lyd_new_path(*parent, NULL, NTS_SIMULATION_SCHEMA_XPATH"/base-port", value, 0, 0) == 0) { - return SR_ERR_OPERATION_FAILED; - } - - sprintf(value, "%d", framework_environment.ssh_connections); - if(lyd_new_path(*parent, NULL, NTS_SIMULATION_SCHEMA_XPATH"/ssh-connections", value, 0, 0) == 0) { - return SR_ERR_OPERATION_FAILED; - } - - sprintf(value, "%d", framework_environment.tls_connections); - if(lyd_new_path(*parent, NULL, NTS_SIMULATION_SCHEMA_XPATH"/tls-connections", value, 0, 0) == 0) { - return SR_ERR_OPERATION_FAILED; } return SR_ERR_OK; diff --git a/ntsimulator/ntsim-ng/core/app/manager.h b/ntsimulator/ntsim-ng/core/app/manager.h index ad1f0a9..50ee1f3 100644 --- a/ntsimulator/ntsim-ng/core/app/manager.h +++ b/ntsimulator/ntsim-ng/core/app/manager.h @@ -19,52 +19,138 @@ #include #include -#include +#include +#include +#include +#include "core/docker.h" + +#define NTS_MANAGER_MODULE "nts-manager" +#define NTS_SIMULATION_SCHEMA_XPATH "/nts-manager:simulation" +#define NTS_FUNCTION_LIST_SCHEMA_XPATH "/nts-manager:simulation/network-functions/network-function" typedef struct { //meta-data - char *docker_id; + const struct lys_ident *ft; + const char *function_type; + bool is_init; bool is_configured; bool is_mounted; - //yang data - char *name; + docker_container_t container; char *mount_point_addressing_method; - char *docker_ip; - uint16_t docker_port; - char *host_ip; - uint16_t host_port; } manager_network_function_instance_t; typedef struct { //manager_docker data + const struct lys_ident *ft; + char *function_type; manager_network_function_instance_t *instance; - bool data_changed; - - //meta-data, constant - struct lys_ident *function_type; - char *function_type_string; - const char *docker_image_name; + docker_context_t *docker; //yang data int started_instances; int mounted_instances; + + char *mount_point_addressing_method; char *docker_instance_name; char *docker_version_tag; char *docker_repository; +} manager_context_t; + +typedef enum { + MANAGER_OPERATION_EDIT = 0, + MANAGER_OPERATION_RPC = 1, +} manager_operation_type_t; + +typedef struct manager_operation { + manager_operation_type_t type; + + int ft_index; + char *function_type; + + int started_instances; + int mounted_instances; + + char *docker_instance_name; + char *docker_repository; + char *docker_version_tag; char *mount_point_addressing_method; -} manager_network_function_type; + + //not used by EDIT, as datastore will be automatically updated + struct { + int *delay_period; + int delay_period_count; + } fault_generation; + + struct { + int faults_enabled; + int call_home; + } netconf; + + struct { + int faults_enabled; + int pnf_registration; + int heartbeat_period; + } ves; + + char *errmsg; + struct manager_operation *next; +} manager_operation_t; + +extern manager_context_t *manager_context; +extern docker_context_t *docker_context; +extern int docker_context_count; + +typedef enum { + MANAGER_PROTOCOL_UNUSED = 0, + MANAGER_PROTOCOL_UNAVAILABLE, + + MANAGER_PROTOCOL_NETCONF_SSH, + MANAGER_PROTOCOL_NETCONF_TLS, + MANAGER_PROTOCOL_FTP, + MANAGER_PROTOCOL_SFTP, + MANAGER_PROTOCOL_HTTP, + MANAGER_PROTOCOL_HTTPS, +} manager_protocol_type_t; + +extern manager_protocol_type_t manager_port[65536]; //manager.c int manager_run(void); +//manager_context.c +int manager_context_init(void); +void manager_context_free(void); + //manager_operations.c -void manager_operations_init(void); +int manager_operations_init(void); +void manager_operations_loop(void); +void manager_operations_free(void); + +manager_operation_t *manager_operations_new_oper(manager_operation_type_t type); +int manager_operations_free_oper(manager_operation_t *oper); + +int manager_operations_begin(void); +int manager_operations_add(manager_operation_t *oper); +void manager_operations_finish_and_execute(void); +void manager_operations_finish_with_error(void); + +int manager_operations_validate(manager_operation_t *oper); + +//manager_actions.c +int manager_actions_start(manager_context_t *ctx); +int manager_actions_config_instance(manager_context_t *ctx, manager_network_function_instance_t *instance); +int manager_actions_stop(manager_context_t *ctx); +int manager_actions_mount(manager_context_t *ctx); +int manager_actions_unmount(manager_context_t *ctx); -int manager_start_instance(manager_network_function_type *function_type); -int manager_config_instance(manager_network_function_type *function_type, manager_network_function_instance_t *instance); -int manager_stop_instance(manager_network_function_type *function_type); -int manager_mount_instance(manager_network_function_type *function_type); -int manager_unmount_instance(manager_network_function_type *function_type); +//manager_sysrepo.c +int manager_sr_get_context_sync(void); +int manager_sr_update_context(manager_context_t *ctx); +int manager_sr_on_last_operation_status(const char *status, const char *errmsg); +int manager_sr_notif_send_instance_changed(const char *status, const char *function_type, const char *name, const manager_network_function_instance_t* instance); +int manager_sr_update_static_stats(void); +int manager_sr_stats_get_items_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data); +int manager_sr_populate_networking(struct lyd_node *parent, const manager_network_function_instance_t* instance); diff --git a/ntsimulator/ntsim-ng/core/app/manager_actions.c b/ntsimulator/ntsim-ng/core/app/manager_actions.c new file mode 100644 index 0000000..a681e0b --- /dev/null +++ b/ntsimulator/ntsim-ng/core/app/manager_actions.c @@ -0,0 +1,583 @@ +/************************************************************************* +* +* Copyright 2020 highstreet technologies GmbH and others +* +* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +* +* 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. +***************************************************************************/ + +#define _GNU_SOURCE + +#include "manager.h" +#include "utils/log_utils.h" +#include "utils/sys_utils.h" +#include +#include +#include +#include + +#include "core/framework.h" +#include "core/docker.h" +#include "core/session.h" +#include "core/nc_config.h" +#include "utils/nc_client.h" +#include "utils/http_client.h" +#include "utils/nts_utils.h" + +int manager_actions_start(manager_context_t *ctx) { + assert(ctx); + + int started_instances = ctx->started_instances; + char instance_name[512]; + sprintf(instance_name, "%s-%d", ctx->docker_instance_name, started_instances); + + uint16_t netconf_ssh_port = framework_environment.host.ssh_base_port; + uint16_t netconf_tls_port = framework_environment.host.tls_base_port; + uint16_t ftp_port = framework_environment.host.ftp_base_port; + uint16_t sftp_port = framework_environment.host.sftp_base_port; + + if(framework_environment.settings.ssh_connections) { + while((netconf_ssh_port) && (manager_port[netconf_ssh_port] != MANAGER_PROTOCOL_UNUSED)) { + netconf_ssh_port++; + } + + for(int i = 0; i < framework_environment.settings.ssh_connections; i++) { + if(manager_port[i + netconf_ssh_port] != MANAGER_PROTOCOL_UNUSED) { + log_error("no ports available for operation for ssh\n"); + manager_sr_notif_send_instance_changed("start FAILED - no ports available for ssh", ctx->function_type, instance_name, 0); + return NTS_ERR_FAILED; + } + } + + for(int i = 0; i < framework_environment.settings.ssh_connections; i++) { + manager_port[i + netconf_ssh_port] = MANAGER_PROTOCOL_NETCONF_SSH; + } + } + + if(framework_environment.settings.tls_connections) { + while((netconf_tls_port) && (manager_port[netconf_tls_port] != MANAGER_PROTOCOL_UNUSED)) { + netconf_tls_port++; + } + + for(int i = 0; i < framework_environment.settings.tls_connections; i++) { + if(manager_port[i + netconf_tls_port] != MANAGER_PROTOCOL_UNUSED) { + log_error("no ports available for operation for tls\n"); + manager_sr_notif_send_instance_changed("start FAILED - no ports available for tls", ctx->function_type, instance_name, 0); + + for(int i = 0; i < framework_environment.settings.ssh_connections; i++) { + manager_port[i + netconf_ssh_port] = MANAGER_PROTOCOL_UNUSED; + } + return NTS_ERR_FAILED; + } + } + + for(int i = 0; i < framework_environment.settings.tls_connections; i++) { + manager_port[i + netconf_tls_port] = MANAGER_PROTOCOL_NETCONF_TLS; + } + } + + if(framework_environment.settings.ftp_connections) { + while((ftp_port) && (manager_port[ftp_port] != MANAGER_PROTOCOL_UNUSED)) { + ftp_port++; + } + + for(int i = 0; i < framework_environment.settings.ftp_connections; i++) { + if(manager_port[i + ftp_port] != MANAGER_PROTOCOL_UNUSED) { + log_error("no ports available for operation for ftp\n"); + manager_sr_notif_send_instance_changed("start FAILED - no ports available for ftp", ctx->function_type, instance_name, 0); + + for(int i = 0; i < framework_environment.settings.ssh_connections; i++) { + manager_port[i + netconf_ssh_port] = MANAGER_PROTOCOL_UNUSED; + } + + for(int i = 0; i < framework_environment.settings.tls_connections; i++) { + manager_port[i + netconf_tls_port] = MANAGER_PROTOCOL_UNUSED; + } + return NTS_ERR_FAILED; + } + } + + for(int i = 0; i < framework_environment.settings.ftp_connections; i++) { + manager_port[i + ftp_port] = MANAGER_PROTOCOL_FTP; + } + } + + if(framework_environment.settings.sftp_connections) { + while((sftp_port) && (manager_port[sftp_port] != MANAGER_PROTOCOL_UNUSED)) { + sftp_port++; + } + + for(int i = 0; i < framework_environment.settings.sftp_connections; i++) { + if(manager_port[i + sftp_port] != MANAGER_PROTOCOL_UNUSED) { + log_error("no ports available for operation for sftp\n"); + manager_sr_notif_send_instance_changed("start FAILED - no ports available for sftp", ctx->function_type, instance_name, 0); + + for(int i = 0; i < framework_environment.settings.ssh_connections; i++) { + manager_port[i + netconf_ssh_port] = MANAGER_PROTOCOL_UNUSED; + } + + for(int i = 0; i < framework_environment.settings.tls_connections; i++) { + manager_port[i + netconf_tls_port] = MANAGER_PROTOCOL_UNUSED; + } + + for(int i = 0; i < framework_environment.settings.ftp_connections; i++) { + manager_port[i + ftp_port] = MANAGER_PROTOCOL_UNUSED; + } + return NTS_ERR_FAILED; + } + } + + for(int i = 0; i < framework_environment.settings.sftp_connections; i++) { + manager_port[i + sftp_port] = MANAGER_PROTOCOL_SFTP; + } + } + + ctx->instance = (manager_network_function_instance_t *)realloc(ctx->instance, sizeof(manager_network_function_instance_t) * (started_instances + 1)); + if(ctx->instance == 0) { + log_error("realloc failed\n"); + manager_sr_notif_send_instance_changed("start FAILED - realloc error", ctx->function_type, instance_name, 0); + for(int i = 0; i < framework_environment.settings.ssh_connections; i++) { + manager_port[i + netconf_ssh_port] = MANAGER_PROTOCOL_UNUSED; + } + + for(int i = 0; i < framework_environment.settings.tls_connections; i++) { + manager_port[i + netconf_tls_port] = MANAGER_PROTOCOL_UNUSED; + } + + for(int i = 0; i < framework_environment.settings.ftp_connections; i++) { + manager_port[i + ftp_port] = MANAGER_PROTOCOL_UNUSED; + } + + for(int i = 0; i < framework_environment.settings.sftp_connections; i++) { + manager_port[i + sftp_port] = MANAGER_PROTOCOL_UNUSED; + } + return NTS_ERR_FAILED; + } + + manager_network_function_instance_t *instance = &ctx->instance[started_instances]; + instance->is_init = false; + instance->is_configured = false; + instance->is_mounted = false; + instance->mount_point_addressing_method = strdup(ctx->mount_point_addressing_method); + + int rc = docker_start(instance_name, ctx->docker_version_tag, ctx->docker->image, ctx->docker_repository, netconf_ssh_port, netconf_tls_port, ftp_port, sftp_port, &instance->container); + if(rc != NTS_ERR_OK) { + log_error("docker_start failed\n"); + manager_sr_notif_send_instance_changed("start FAILED - Docker start error", ctx->function_type, instance_name, 0); + for(int i = 0; i < framework_environment.settings.ssh_connections; i++) { + manager_port[i + netconf_ssh_port] = MANAGER_PROTOCOL_UNUSED; + } + + for(int i = 0; i < framework_environment.settings.tls_connections; i++) { + manager_port[i + netconf_tls_port] = MANAGER_PROTOCOL_UNUSED; + } + + for(int i = 0; i < framework_environment.settings.ftp_connections; i++) { + manager_port[i + ftp_port] = MANAGER_PROTOCOL_UNUSED; + } + + for(int i = 0; i < framework_environment.settings.sftp_connections; i++) { + manager_port[i + sftp_port] = MANAGER_PROTOCOL_UNUSED; + } + return NTS_ERR_FAILED; + } + + ctx->started_instances++; + manager_sr_notif_send_instance_changed("start SUCCESS", ctx->function_type, instance_name, instance); + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET" started (%s); ports host(docker): ", instance_name, instance->mount_point_addressing_method); + if(framework_environment.settings.ssh_connections > 1) { + log_add(1, "NETCONF SSH: %d-%d(%d-%d)", instance->container.host_netconf_ssh_port, (instance->container.host_netconf_ssh_port + framework_environment.settings.ssh_connections - 1), instance->container.docker_netconf_ssh_port, (instance->container.docker_netconf_ssh_port + framework_environment.settings.ssh_connections - 1)); + } + else if(framework_environment.settings.ssh_connections == 1) { + log_add(1, "NETCONF SSH: %d(%d)", instance->container.host_netconf_ssh_port, instance->container.docker_netconf_ssh_port); + } + else { + log_add(1, "NETCONF SSH: disabled"); + } + + if(framework_environment.settings.tls_connections > 1) { + log_add(1, " | NETCONF TLS: %d-%d(%d-%d)", instance->container.host_netconf_tls_port, (instance->container.host_netconf_tls_port + framework_environment.settings.tls_connections - 1), instance->container.docker_netconf_tls_port, (instance->container.docker_netconf_tls_port + framework_environment.settings.tls_connections - 1)); + } + else if(framework_environment.settings.tls_connections == 1) { + log_add(1, " | NETCONF TLS: %d(%d)", instance->container.host_netconf_tls_port, instance->container.docker_netconf_tls_port); + } + else { + log_add(1, " | NETCONF TLS: disabled"); + } + + if(framework_environment.settings.ftp_connections > 1) { + log_add(1, " | FTP: %d-%d(%d-%d)", instance->container.host_ftp_port, (instance->container.host_ftp_port + framework_environment.settings.ftp_connections - 1), instance->container.docker_ftp_port, (instance->container.docker_ftp_port + framework_environment.settings.ftp_connections - 1)); + } + else if(framework_environment.settings.ftp_connections == 1) { + log_add(1, " | FTP: %d(%d)", instance->container.host_ftp_port, instance->container.docker_ftp_port); + } + else { + log_add(1, " | FTP: disabled"); + } + + if(framework_environment.settings.sftp_connections > 1) { + log_add(1, " | SFTP: %d-%d(%d-%d)", instance->container.host_sftp_port, (instance->container.host_sftp_port + framework_environment.settings.sftp_connections - 1), instance->container.docker_sftp_port, (instance->container.docker_sftp_port + framework_environment.settings.sftp_connections - 1)); + } + else if(framework_environment.settings.sftp_connections == 1) { + log_add(1, " | SFTP: %d(%d)", instance->container.host_sftp_port, instance->container.docker_sftp_port); + } + else { + log_add(1, " | SFTP: disabled"); + } + + log_add(1, "\n"); + + + return NTS_ERR_OK; +} + +int manager_actions_config_instance(manager_context_t *ctx, manager_network_function_instance_t *instance) { + assert(ctx); + assert(instance); + + //first wait for the nc server to be up and running + int retries = 0; + while(check_port_open(instance->container.docker_ip, CLIENT_CONFIG_TLS_PORT) == false) { + usleep(50000); + retries++; + if(retries >= 200) { + log_error("manager_actions_config_instance() could not connect to %s, as port is not open\n", instance->container.name); + return NTS_ERR_FAILED; + } + } + + //populate sdn-controller and ves-endpoint + struct lyd_node *local_tree = 0; + int rc = lyd_utils_dup(session_running, "/nts-manager:simulation/sdn-controller", "/nts-network-function:simulation/sdn-controller", &local_tree); + if(rc != NTS_ERR_OK) { + log_error("lyd_utils_dup failed\n"); + manager_sr_notif_send_instance_changed("config FAILED - libyang", ctx->function_type, instance->container.name, instance); + return NTS_ERR_FAILED; + } + + rc = lyd_utils_dup(session_running, "/nts-manager:simulation/ves-endpoint", "/nts-network-function:simulation/ves-endpoint", &local_tree); + if(rc != NTS_ERR_OK) { + log_error("lyd_utils_dup failed\n"); + manager_sr_notif_send_instance_changed("config FAILED - libyang", ctx->function_type, instance->container.name, instance); + lyd_free_withsiblings(local_tree); + return NTS_ERR_FAILED; + } + + char xpath_s[512]; + sprintf(xpath_s, "/nts-manager:simulation/network-functions/network-function[function-type='%s']", ctx->function_type); + rc = lyd_utils_dup(session_running, xpath_s, "/nts-network-function:simulation/network-function", &local_tree); + if(rc != NTS_ERR_OK) { + log_error("lyd_utils_dup failed\n"); + manager_sr_notif_send_instance_changed("config FAILED - libyang", ctx->function_type, instance->container.name, instance); + lyd_free_withsiblings(local_tree); + return NTS_ERR_FAILED; + } + + nc_client_t *nc_client = nc_client_tls_connect(instance->container.docker_ip, CLIENT_CONFIG_TLS_PORT); + // nc_client_t *nc_client = nc_client_ssh_connect(instance->container.docker_ip, instance->container.docker_port, "netconf", "netconf!"); + if(nc_client == 0) { + log_error("nc_client_tls_connect\n"); + manager_sr_notif_send_instance_changed("config FAILED - netconf client connect", ctx->function_type, instance->container.name, instance); + lyd_free_withsiblings(local_tree); + return NTS_ERR_FAILED; + } + + rc += nc_client_edit_batch(nc_client, local_tree, 5000); + lyd_free_withsiblings(local_tree); + if(rc != NTS_ERR_OK) { + log_error("nc_client_edit_batch failed %d\n", rc); + manager_sr_notif_send_instance_changed("config FAILED - netconf edit batch", ctx->function_type, instance->container.name, instance); + nc_client_disconnect(nc_client); + return NTS_ERR_FAILED; + } + + if(instance->is_init == false) { + //run datastore-populate rpc + struct lyd_node *rpc_node = 0; + struct lyd_node *rpcout = 0; + rpc_node = lyd_new_path(0, session_context, "/nts-network-function:datastore-populate", 0, 0, 0); + if(rpc_node == 0) { + log_error("failed to create rpc node\n"); + manager_sr_notif_send_instance_changed("config FAILED - populate RPC", ctx->function_type, instance->container.name, instance); + nc_client_disconnect(nc_client); + return NTS_ERR_FAILED; + } + + rpcout = nc_client_send_rpc(nc_client, rpc_node, 10000); + if(rpcout == 0) { + log_error("datastore-populate rpc failed\n"); + manager_sr_notif_send_instance_changed("config FAILED - datastore populate RPC", ctx->function_type, instance->container.name, instance); + nc_client_disconnect(nc_client); + lyd_free_withsiblings(rpc_node); + return NTS_ERR_FAILED; + } + else { + lyd_free_withsiblings(rpcout); + } + lyd_free_withsiblings(rpc_node); + + //run feature-control rpc + rpc_node = lyd_new_path(0, session_context, "/nts-network-function:feature-control/start-features", "ves-file-ready ves-heartbeat ves-pnf-registration manual-notification-generation netconf-call-home web-cut-through", 0, 0); + if(rpc_node == 0) { + log_error("failed to create rpc node\n"); + manager_sr_notif_send_instance_changed("config FAILED - feature-control RPC", ctx->function_type, instance->container.name, instance); + nc_client_disconnect(nc_client); + return NTS_ERR_FAILED; + } + + rpcout = nc_client_send_rpc(nc_client, rpc_node, 10000); + if(rpcout == 0) { + log_error("feature-control rpc failed\n"); + manager_sr_notif_send_instance_changed("config FAILED - feature-control RPC", ctx->function_type, instance->container.name, instance); + nc_client_disconnect(nc_client); + lyd_free_withsiblings(rpc_node); + return NTS_ERR_FAILED; + } + else { + lyd_free_withsiblings(rpcout); + } + lyd_free_withsiblings(rpc_node); + } + + instance->is_init = true; + instance->is_configured = true; + nc_client_disconnect(nc_client); + manager_sr_notif_send_instance_changed("config SUCCESS", ctx->function_type, instance->container.name, instance); + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET" configured via netconf\n", instance->container.name); + + return NTS_ERR_OK; +} + +int manager_actions_stop(manager_context_t *ctx) { + assert(ctx); + + manager_network_function_instance_t *instance = &ctx->instance[ctx->started_instances - 1]; + char instance_name[512]; + strcpy(instance_name, instance->container.name); + + if(instance->is_mounted) { + if(manager_actions_unmount(ctx) != NTS_ERR_OK) { + log_error("failed to unmount instance\n"); + } + } + + int rc = docker_stop(&instance->container); + if(rc != NTS_ERR_OK) { + log_error("docker_device_stop failed\n"); + manager_sr_notif_send_instance_changed("stop FAILED - Docker error", ctx->function_type, instance_name, 0); + return NTS_ERR_FAILED; + } + + //free ports + for(int i = 0; i < framework_environment.settings.ssh_connections; i++) { + manager_port[i + ctx->instance[ctx->started_instances - 1].container.host_netconf_ssh_port] = MANAGER_PROTOCOL_UNUSED; + } + + for(int i = 0; i < framework_environment.settings.tls_connections; i++) { + manager_port[i + ctx->instance[ctx->started_instances - 1].container.host_netconf_tls_port] = MANAGER_PROTOCOL_UNUSED; + } + + for(int i = 0; i < framework_environment.settings.ftp_connections; i++) { + manager_port[i + ctx->instance[ctx->started_instances - 1].container.host_ftp_port] = MANAGER_PROTOCOL_UNUSED; + } + + for(int i = 0; i < framework_environment.settings.sftp_connections; i++) { + manager_port[i + ctx->instance[ctx->started_instances - 1].container.host_sftp_port] = MANAGER_PROTOCOL_UNUSED; + } + + free(instance->mount_point_addressing_method); + + if(ctx->started_instances > 1) { + ctx->instance = (manager_network_function_instance_t *)realloc(ctx->instance, sizeof(manager_network_function_instance_t) * ctx->started_instances); + if(ctx->instance == 0) { + log_error("realloc failed\n"); + manager_sr_notif_send_instance_changed("stop FAILED - realloc", ctx->function_type, instance_name, 0); + return NTS_ERR_FAILED; + } + } + else { + free(ctx->instance); + ctx->instance = 0; + } + ctx->started_instances--; + manager_sr_notif_send_instance_changed("stop SUCCESS", ctx->function_type, instance_name, 0); + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET" stopped\n", instance_name); + + + return NTS_ERR_OK; +} + +int manager_actions_mount(manager_context_t *ctx) { + assert(ctx); + + manager_network_function_instance_t *instance = &ctx->instance[ctx->mounted_instances]; + + if(instance->is_mounted == true) { + manager_sr_notif_send_instance_changed("mount SUCCESS - already mounted", ctx->function_type, instance->container.name, instance); + return NTS_ERR_OK; + } + + controller_details_t *controller; + controller = controller_details_get(0); + if(controller == 0) { + log_error("could not get controller details\n"); + manager_sr_notif_send_instance_changed("mount FAILED - no controller details", ctx->function_type, instance->container.name, instance); + return NTS_ERR_FAILED; + } + + for(int i = 0; i < (framework_environment.settings.ssh_connections + framework_environment.settings.tls_connections); i++) { + char *protocol; + char *protocol_data; + + char *ip = 0; + uint16_t port = 0; + if(instance->mount_point_addressing_method[0] == 'd') { + ip = instance->container.docker_ip; + } + else { + ip = instance->container.host_ip; + } + + + if(i < framework_environment.settings.ssh_connections) { + protocol = "SSH"; + protocol_data = "\ + \"network-topology:netconf-node-topology:username\": \"netconf\",\ + \"network-topology:netconf-node-topology:password\": \"netconf\""; + + if(instance->mount_point_addressing_method[0] == 'd') { + port = instance->container.docker_netconf_ssh_port + i; + } + else { + port = instance->container.host_netconf_ssh_port + i; + } + } + else { + protocol = "TLS"; + protocol_data = "\ + \"netconf-node-topology:key-based\" : {\ + \"netconf-node-topology:username\" : \"netconf\",\ + \"netconf-node-topology:key-id\" : \""KS_KEY_NAME"\"\ + }"; + + if(instance->mount_point_addressing_method[0] == 'd') { + port = instance->container.docker_netconf_tls_port + i - framework_environment.settings.ssh_connections; + } + else { + port = instance->container.host_netconf_tls_port + i - framework_environment.settings.ssh_connections; + } + } + + char *json_template = "\ + {\ + \"network-topology:node\": [{\ + \"network-topology:node-id\": \"%s\",\ + \"network-topology:netconf-node-topology:host\": \"%s\",\ + \"network-topology:netconf-node-topology:port\": \"%d\",\ + \"network-topology:netconf-node-topology:tcp-only\": \"false\",\ + \"network-topology:netconf-node-topology:protocol\": {\ + \"network-topology:netconf-node-topology:name\": \"%s\"\ + },\ + %s,\ + \"network-topology:netconf-node-topology:connection-timeout-millis\": \"20000\",\ + \"network-topology:netconf-node-topology:default-request-timeout-millis\": \"60000\",\ + \"network-topology:netconf-node-topology:max-connection-attempts\": \"3\"\ + }]\ + }"; + + char node_id[128]; + char json[4096]; + sprintf(node_id, "%s-%d", instance->container.name, port); + sprintf(json, json_template, node_id, ip, port, protocol, protocol_data); + + char url[512]; + sprintf(url, "%s/rests/data/network-topology:network-topology/topology=topology-netconf/node=%s", controller->base_url, node_id); + int rc = http_request(url, controller->username, controller->password, "PUT", json, 0, 0); + if(rc != NTS_ERR_OK) { + log_error("http_request failed\n"); + controller_details_free(controller); + manager_sr_notif_send_instance_changed("mount FAILED - REST request", ctx->function_type, instance->container.name, instance); + return NTS_ERR_FAILED; + } + } + + controller_details_free(controller); + + instance->is_mounted = true; + ctx->mounted_instances++; + manager_sr_notif_send_instance_changed("mount SUCCESS", ctx->function_type, instance->container.name, instance); + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET" mounted\n", instance->container.name); + + return NTS_ERR_OK; +} + +int manager_actions_unmount(manager_context_t *ctx) { + assert(ctx); + + int ret = NTS_ERR_OK; + + manager_network_function_instance_t *instance = &ctx->instance[ctx->mounted_instances - 1]; + + if(instance->is_mounted == false) { + log_error("tried to unmount an unmounted instance\n"); + manager_sr_notif_send_instance_changed("unmount FAILED - already unmounted", ctx->function_type, instance->container.name, instance); + return NTS_ERR_OK; + } + + controller_details_t *controller; + controller = controller_details_get(0); + if(controller == 0) { + log_error("could not get controller details\n"); + manager_sr_notif_send_instance_changed("unmount FAILED - no controller details", ctx->function_type, instance->container.name, instance); + return NTS_ERR_FAILED; + } + + for(int i = 0; i < (framework_environment.settings.ssh_connections + framework_environment.settings.tls_connections); i++) { + uint16_t port = 0; + if(i < framework_environment.settings.ssh_connections) { + if(instance->mount_point_addressing_method[0] == 'd') { + port = instance->container.docker_netconf_ssh_port + i; + } + else { + port = instance->container.host_netconf_ssh_port + i; + } + } + else { + if(instance->mount_point_addressing_method[0] == 'd') { + port = instance->container.docker_netconf_tls_port + i - framework_environment.settings.ssh_connections; + } + else { + port = instance->container.host_netconf_tls_port + i - framework_environment.settings.ssh_connections; + } + } + char node_id[128]; + sprintf(node_id, "%s-%d", instance->container.name, port); + + char url[512]; + sprintf(url, "%s/rests/data/network-topology:network-topology/topology=topology-netconf/node=%s", controller->base_url, node_id); + int rc = http_request(url, controller->username, controller->password, "DELETE", "", 0, 0); + if(rc != NTS_ERR_OK) { + log_error("http_request failed\n"); + manager_sr_notif_send_instance_changed("unmount FAILED - REST request", ctx->function_type, instance->container.name, instance); + ret = NTS_ERR_FAILED; + } + } + + controller_details_free(controller); + + ctx->mounted_instances--; + ctx->instance[ctx->mounted_instances].is_mounted = false; + manager_sr_notif_send_instance_changed("unmount SUCCESS", ctx->function_type, instance->container.name, instance); + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET" unmounted\n", instance->container.name); + + return ret; +} diff --git a/ntsimulator/ntsim-ng/core/app/manager_context.c b/ntsimulator/ntsim-ng/core/app/manager_context.c new file mode 100644 index 0000000..d61cb96 --- /dev/null +++ b/ntsimulator/ntsim-ng/core/app/manager_context.c @@ -0,0 +1,361 @@ +/************************************************************************* +* +* Copyright 2020 highstreet technologies GmbH and others +* +* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +* +* 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. +***************************************************************************/ + +#define _GNU_SOURCE + +#include "manager.h" +#include "utils/log_utils.h" +#include "utils/sys_utils.h" +#include "utils/nts_utils.h" +#include +#include + +#include +#include + +#include "core/framework.h" +#include "core/session.h" +#include "core/context.h" + +#define NTS_AVAILABLE_IMAGES_SCHEMA_XPATH "/nts-manager:simulation/available-images" + + +manager_context_t *manager_context = 0; +docker_context_t *docker_context = 0; +int docker_context_count = 0; + +static int manager_populate_sysrepo_network_function_list(void); +static int manager_populate_available_simulations(void); + +int manager_context_init(void) { + + //get installed function types + struct lys_node_leaf *elem = (struct lys_node_leaf *)ly_ctx_get_node(session_context, 0, NTS_FUNCTION_LIST_SCHEMA_XPATH"/function-type", 0); + if(elem == 0) { + log_error("ly_ctx_get_node failed for xpath: %s\n", NTS_FUNCTION_LIST_SCHEMA_XPATH"/function-type"); + return NTS_ERR_FAILED; + } + + struct lys_ident **function_types = 0; + docker_context_count = context_get_identity_leafs_of_type(elem->type.info.ident.ref[0], &function_types); + if(!docker_context_count) { + log_error("context_get_identity_leafs_of_type() error\n"); + return NTS_ERR_FAILED; + } + + docker_context_count = docker_context_count; + + const char **docker_filter = malloc(sizeof(char *) * docker_context_count); + if(docker_filter == 0) { + log_error("bad malloc\n"); + free(function_types); + return NTS_ERR_FAILED; + } + + for(int i = 0; i < docker_context_count; i++) { + docker_filter[i] = function_types[i]->ref; + } + + int rc = docker_init(docker_filter, docker_context_count, "1.2.0", &docker_context); + free(docker_filter); + if(rc != NTS_ERR_OK) { + log_error("docker_init() failed\n"); + free(function_types); + return NTS_ERR_FAILED; + } + + + //remove non-present network functions + int new_context_count = 0; + docker_context_t *new_context = malloc(sizeof(docker_context_t) * docker_context_count); + struct lys_ident **new_function_types = (struct lys_ident **)malloc(sizeof(struct lys_ident *) * docker_context_count); + for(int i = 0; i < docker_context_count; i++) { + if(docker_context[i].available_images_count) { + new_context[new_context_count].image = docker_context[i].image; + new_context[new_context_count].available_images = docker_context[i].available_images; + new_context[new_context_count].available_images_count = docker_context[i].available_images_count; + new_function_types[new_context_count] = function_types[i]; + + new_context_count++; + + } + else { + free(docker_context[i].image); + } + } + + free(function_types); + function_types = new_function_types; + + free(docker_context); + docker_context = new_context; + docker_context_count = new_context_count; + + //initial list population + manager_context = (manager_context_t *)malloc(sizeof(manager_context_t) * docker_context_count); + if(manager_context == 0) { + log_error("malloc failed\n"); + free(function_types); + return NTS_ERR_FAILED; + } + + for(int i = 0; i < docker_context_count; i++) { + manager_context[i].ft = function_types[i]; + + asprintf(&manager_context[i].function_type, "%s:%s", manager_context[i].ft->module->name, manager_context[i].ft->name); + manager_context[i].instance = 0; + manager_context[i].docker = &docker_context[i]; + + manager_context[i].started_instances = 0; + manager_context[i].mounted_instances = 0; + manager_context[i].mount_point_addressing_method = strdup("docker-mapping"); + + if(docker_context[i].available_images_count) { + manager_context[i].docker_instance_name = strdup(strstr(manager_context[i].function_type, ":") + 1); + manager_context[i].docker_version_tag = strdup(docker_context[i].available_images[0].tag); + manager_context[i].docker_repository = strdup(docker_context[i].available_images[0].repo); + } + else { + manager_context[i].docker_instance_name = strdup("no-image-installed"); + manager_context[i].docker_version_tag = strdup("no-image-installed"); + manager_context[i].docker_repository = strdup("no-image-installed"); + } + } + free(function_types); + + //do initial sysrepo list population + rc = manager_populate_sysrepo_network_function_list(); + if(rc != NTS_ERR_OK) { + log_error("manager_populate_sysrepo_network_function_list failed\n"); + return NTS_ERR_FAILED; + } + + rc = manager_populate_available_simulations(); + if(rc != NTS_ERR_OK) { + log_error("manager_populate_available_simulations failed\n"); + return NTS_ERR_FAILED; + } + + rc = nts_utils_populate_info(session_running, framework_environment.nts.function_type); + if(rc != NTS_ERR_OK) { + log_error("nts_utils_populate_info failed\n"); + return NTS_ERR_FAILED; + } + + return NTS_ERR_OK; +} + +void manager_context_free(void) { + for(int i = 0; i < docker_context_count; i++) { + free(manager_context[i].docker_instance_name); + free(manager_context[i].docker_version_tag); + free(manager_context[i].docker_repository); + free(manager_context[i].function_type); + } + + free(manager_context); +} + +static int manager_populate_sysrepo_network_function_list(void) { + //check whether everything is already populated, read and update (if previously ran) + sr_val_t *values = 0; + size_t value_count = 0; + int rc = sr_get_items(session_running, NTS_FUNCTION_LIST_SCHEMA_XPATH, 0, 0, &values, &value_count); + if(rc != SR_ERR_OK) { + log_error("get items failed\n"); + return NTS_ERR_FAILED; + } + + //either get values, or if data inconclusive, delete everything + if(value_count) { + log_add_verbose(2, "nts-manager instances found (%d). cleaning up for fresh start...\n", value_count); + + for(int i = 0; i < value_count; i++) { + rc = sr_delete_item(session_running, values[i].xpath, 0); + if(rc != SR_ERR_OK) { + log_error("sr_delete_item failed\n"); + return NTS_ERR_FAILED; + } + } + rc = sr_apply_changes(session_running, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_apply_changes failed\n"); + return NTS_ERR_FAILED; + } + } + + //populate everything if needed + for(int i = 0; i < docker_context_count; i++) { + char *xpath = 0; + + asprintf(&xpath, "%s[function-type='%s']/function-type", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type); + rc = sr_set_item_str(session_running, xpath, (const char *)manager_context[i].function_type, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + free(xpath); + + asprintf(&xpath, "%s[function-type='%s']/started-instances", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type); + rc = sr_set_item_str(session_running, xpath, "0", 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + free(xpath); + + asprintf(&xpath, "%s[function-type='%s']/mounted-instances", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type); + rc = sr_set_item_str(session_running, xpath, "0", 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + free(xpath); + + asprintf(&xpath, "%s[function-type='%s']/docker-instance-name", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type); + rc = sr_set_item_str(session_running, xpath, (const char*)manager_context[i].docker_instance_name, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + free(xpath); + + asprintf(&xpath, "%s[function-type='%s']/docker-version-tag", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type); + rc = sr_set_item_str(session_running, xpath, (const char*)manager_context[i].docker_version_tag, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + free(xpath); + + asprintf(&xpath, "%s[function-type='%s']/docker-repository", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type); + rc = sr_set_item_str(session_running, xpath, (const char*)manager_context[i].docker_repository, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + free(xpath); + + asprintf(&xpath, "%s[function-type='%s']/mount-point-addressing-method", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type); + rc = sr_set_item_str(session_running, xpath, (const char *)manager_context[i].mount_point_addressing_method, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + free(xpath); + + //presence containers + asprintf(&xpath, "%s[function-type='%s']/fault-generation", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type); + rc = sr_set_item_str(session_running, xpath, 0, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + free(xpath); + + asprintf(&xpath, "%s[function-type='%s']/netconf", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type); + rc = sr_set_item_str(session_running, xpath, 0, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + free(xpath); + + asprintf(&xpath, "%s[function-type='%s']/ves", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type); + rc = sr_set_item_str(session_running, xpath, 0, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + free(xpath); + } + + //apply all changes + rc = sr_apply_changes(session_running, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_apply_changes failed: %s\n", sr_strerror(rc)); + return NTS_ERR_FAILED; + } + + return NTS_ERR_OK; +} + +static int manager_populate_available_simulations(void) { + assert_session(); + + struct lyd_node *container = lyd_new_path(0, session_context, NTS_AVAILABLE_IMAGES_SCHEMA_XPATH, 0, LYD_ANYDATA_CONSTSTRING, LYD_PATH_OPT_NOPARENTRET); + if(container == 0) { + log_error("lyd_new_path failed\n"); + return NTS_ERR_FAILED; + } + + for(int i = 0; i < docker_context_count; i++) { + for(int j = 0; j < docker_context[i].available_images_count; j++) { + struct lyd_node *list = lyd_new(container, container->schema->module, "network-function-image"); + if(!list) { + log_error("lyd_new failed\n"); + return NTS_ERR_FAILED; + } + + struct lyd_node *rc = lyd_new_leaf(list, list->schema->module, "function-type", (const char *)manager_context[i].function_type); + if(rc == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + + rc = lyd_new_leaf(list, list->schema->module, "docker-image-name", docker_context[i].image); + if(rc == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + + rc = lyd_new_leaf(list, list->schema->module, "docker-version-tag", docker_context[i].available_images[j].tag); + if(rc == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + + rc = lyd_new_leaf(list, list->schema->module, "docker-repository", docker_context[i].available_images[j].repo); + if(rc == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + + } + } + + //find top level container + struct lyd_node *root = container; + while(root->parent) { + root = root->parent; + } + + int rc = sr_edit_batch(session_operational, root, "replace"); + if(rc != SR_ERR_OK) { + log_error("sr_edit_batch failed\n"); + return NTS_ERR_FAILED; + } + + //apply all changes + rc = sr_apply_changes(session_operational, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_apply_changes failed: %s\n", sr_strerror(rc)); + return NTS_ERR_FAILED; + } + + return NTS_ERR_OK; +} diff --git a/ntsimulator/ntsim-ng/core/app/manager_operations.c b/ntsimulator/ntsim-ng/core/app/manager_operations.c index e382b02..c847a6c 100644 --- a/ntsimulator/ntsim-ng/core/app/manager_operations.c +++ b/ntsimulator/ntsim-ng/core/app/manager_operations.c @@ -23,357 +23,347 @@ #include #include #include +#include #include "core/framework.h" -#include "core/docker.h" #include "core/session.h" -#include "utils/nc_client.h" -#include "utils/http_client.h" -#include "utils/nts_utils.h" -static uint16_t manager_start_port = 0; -static uint8_t manager_port[65536]; +static manager_operation_t *manager_operations; +static pthread_mutex_t manager_operations_mutex; +static sem_t manager_operations_sem; -void manager_operations_init(void) { - manager_start_port = framework_environment.host_base_port; - for(int i = 0; i < 65536; i++) { - manager_port[i] = 0; - } -} +manager_protocol_type_t manager_port[65536]; -int manager_start_instance(manager_network_function_type *function_type) { - assert(function_type); - assert_session(); +static int manager_operations_execute(manager_operation_t *oper); - function_type->started_instances++; - function_type->instance = (manager_network_function_instance_t *)realloc(function_type->instance, sizeof(manager_network_function_instance_t) * function_type->started_instances); - if(function_type->instance == 0) { - log_error("realloc failed"); - function_type->started_instances--; - return NTS_ERR_FAILED; +int manager_operations_init(void) { + manager_operations = 0; + if(pthread_mutex_init(&manager_operations_mutex, NULL) != 0) { + log_error("mutex init has failed\n"); + return NTS_ERR_FAILED; } - manager_network_function_instance_t *instance = &function_type->instance[function_type->started_instances - 1]; - instance->is_configured = false; - instance->is_mounted = false; - - asprintf(&instance->name, "%s-%d", function_type->docker_instance_name, function_type->started_instances - 1); - - instance->mount_point_addressing_method = strdup(function_type->mount_point_addressing_method); - instance->docker_port = STANDARD_NETCONF_PORT; - instance->host_ip = strdup(framework_environment.host_ip); - instance->host_port = 0; - - //find start host port - for(int i = manager_start_port; i < 65536 - (framework_environment.ssh_connections + framework_environment.tls_connections + framework_environment.ftp_connections + framework_environment.sftp_connections); i += (framework_environment.ssh_connections + framework_environment.tls_connections + framework_environment.ftp_connections + framework_environment.sftp_connections)) { - if(manager_port[i] == 0) { - manager_port[i] = 1; - instance->host_port = i; - break; - } + if(sem_init(&manager_operations_sem, 0, 0) != 0) { + log_error("sem init has failed\n"); + return NTS_ERR_FAILED; } - if(instance->host_port == 0) { - log_error("no ports available for operation"); - free(instance->name); - free(instance->mount_point_addressing_method); - free(instance->host_ip); - function_type->started_instances--; - return NTS_ERR_FAILED; + //checkAL ar fi misto sa stim ce porturi sunt si ce porturi nu sunt available... + for(int i = 0; i < 1000; i++) { + manager_port[i] = MANAGER_PROTOCOL_UNAVAILABLE; } - int rc = docker_device_start(function_type, instance); - if(rc != NTS_ERR_OK) { - log_error("docker_device_start failed"); - free(instance->name); - free(instance->mount_point_addressing_method); - free(instance->host_ip); - manager_port[instance->host_port] = 0; - function_type->started_instances--; - return NTS_ERR_FAILED; + for(int i = 1000; i < 65536; i++) { + manager_port[i] = MANAGER_PROTOCOL_UNUSED; } return NTS_ERR_OK; } -int manager_config_instance(manager_network_function_type *function_type, manager_network_function_instance_t *instance) { - assert(function_type); - assert(instance); +void manager_operations_loop(void) { + int rc; + + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += 1; + + if(sem_timedwait(&manager_operations_sem, &ts) == 0) { + int retries = 10; + while(retries) { + rc = sr_lock(session_running, NTS_MANAGER_MODULE); + if(rc == SR_ERR_OK) { + break; + } + else { + sleep(1); + } + retries--; + } - //first wait for the nc server to be up and running - while(check_port_open(instance->docker_ip, instance->docker_port) == false) { - usleep(10000); - } + if(retries == 0) { + log_error("sr_lock failed\n"); + //checkAL ce facem acum ? + } - //populate sdn-controller and ves-endpoint - struct lyd_node *local_tree = 0; - int rc = lyd_utils_dup(session_running, "/nts-manager:simulation/sdn-controller", "/nts-network-function:simulation/sdn-controller", &local_tree); - if(rc != NTS_ERR_OK) { - log_error("lyd_utils_dup failed"); - return NTS_ERR_FAILED; + pthread_mutex_lock(&manager_operations_mutex); + + const char *status = "SUCCESS"; + char errmsg[256]; + errmsg[0] = 0; + + while(manager_operations) { + //pop operation from list + manager_operation_t *oper = manager_operations; + manager_operations = manager_operations->next; + + //if operation is RPC first update any *other* fields + + rc = manager_operations_execute(oper); + if(rc != NTS_ERR_OK) { + log_error("manager_operations_execute failed\n"); + status = "FAILED"; + strcpy(errmsg, oper->errmsg); + manager_operations_free_oper(oper); + break; + } + + manager_operations_free_oper(oper); + } + + for(int i = 0; i < docker_context_count; i++) { + //do any reconfig necesarry + for(int j = 0; j < manager_context[i].started_instances; j++) { + if(manager_context[i].instance[j].is_configured == false) { + rc = manager_actions_config_instance(&manager_context[i], &manager_context[i].instance[j]); + if(rc != NTS_ERR_OK) { + status = "reconfig FAILED"; + sprintf(errmsg, "reconfig FAILED - instance %s", manager_context[i].instance[j].container.name); + log_error("%s\n", errmsg); + } + } + } + } + + rc = manager_sr_on_last_operation_status(status, errmsg); + if(rc != NTS_ERR_OK) { + log_error("manager_sr_on_last_operation_status failed\n"); + } + + pthread_mutex_unlock(&manager_operations_mutex); + rc = sr_unlock(session_running, NTS_MANAGER_MODULE); //release datastore + if(rc != SR_ERR_OK) { + log_error("sr_unlock failed\n"); + } } +} - rc = lyd_utils_dup(session_running, "/nts-manager:simulation/ves-endpoint", "/nts-network-function:simulation/ves-endpoint", &local_tree); - if(rc != NTS_ERR_OK) { - log_error("lyd_utils_dup failed"); - lyd_free_withsiblings(local_tree); - return NTS_ERR_FAILED; +void manager_operations_free(void) { + //terminate all containers + for(int i = 0; i < docker_context_count; i++) { + while(manager_context[i].started_instances) { + manager_actions_stop(&manager_context[i]); + } } - char *xpath_s = 0; - asprintf(&xpath_s, "/nts-manager:simulation/network-functions/network-function[function-type='%s']", function_type->function_type_string); - rc = lyd_utils_dup(session_running, xpath_s, "/nts-network-function:simulation/network-function", &local_tree); - free(xpath_s); - if(rc != NTS_ERR_OK) { - log_error("lyd_utils_dup failed"); - lyd_free_withsiblings(local_tree); - return NTS_ERR_FAILED; - } + sem_destroy(&manager_operations_sem); + pthread_mutex_destroy(&manager_operations_mutex); +} - nc_client_t *nc_client = nc_client_ssh_connect(instance->docker_ip, instance->docker_port, "netconf", "netconf"); - if(nc_client == 0) { - log_error("nc_client_ssh_connect"); - lyd_free_withsiblings(local_tree); - return NTS_ERR_FAILED; +manager_operation_t *manager_operations_new_oper(manager_operation_type_t type) { + manager_operation_t *new_oper = malloc(sizeof(manager_operation_t)); + if(new_oper == 0) { + log_error("malloc failed\n"); + return 0; } - rc += nc_client_edit_batch(nc_client, local_tree, 1000); - lyd_free_withsiblings(local_tree); - if(rc != NTS_ERR_OK) { - log_error("nc_client_edit_batch failed %d\n", rc); - nc_client_disconnect(nc_client); - return NTS_ERR_FAILED; - } + new_oper->type = type; + + new_oper->ft_index = -1; + new_oper->function_type = 0; + + new_oper->started_instances = -1; + new_oper->mounted_instances = -1; - if(instance->is_configured == false) { - //run datastore-random-populate rpc - struct lyd_node *rpc_node = 0; - struct lyd_node *rpcout = 0; - rpc_node = lyd_new_path(0, session_context, "/nts-network-function:datastore-random-populate", 0, 0, 0); - if(rpc_node == 0) { - log_error("failed to create rpc node"); - nc_client_disconnect(nc_client); - return NTS_ERR_FAILED; - } + new_oper->docker_instance_name = 0; + new_oper->docker_version_tag = 0; + new_oper->docker_repository = 0; - rpcout = nc_client_send_rpc(nc_client, rpc_node, 5000); - if(rpcout == 0) { - log_error("datastore-random-populate rpc failed"); - nc_client_disconnect(nc_client); - lyd_free_withsiblings(rpc_node); - return NTS_ERR_FAILED; - } - else { - lyd_free_withsiblings(rpcout); - } - lyd_free_withsiblings(rpc_node); - - //run feature-control rpc - rpc_node = lyd_new_path(0, session_context, "/nts-network-function:feature-control/features", "ves-file-ready ves-heartbeat ves-pnf-registration manual-notification-generation netconf-call-home web-cut-through", 0, 0); - if(rpc_node == 0) { - log_error("failed to create rpc node"); - nc_client_disconnect(nc_client); - return NTS_ERR_FAILED; - } + new_oper->mount_point_addressing_method = 0; - rpcout = nc_client_send_rpc(nc_client, rpc_node, 1000); - if(rpcout == 0) { - log_error("feature-control rpc failed"); - nc_client_disconnect(nc_client); - lyd_free_withsiblings(rpc_node); - return NTS_ERR_FAILED; - } - else { - lyd_free_withsiblings(rpcout); - } - lyd_free_withsiblings(rpc_node); - } + new_oper->fault_generation.delay_period = 0; + new_oper->fault_generation.delay_period_count = -1; - instance->is_configured = true; + new_oper->netconf.faults_enabled = -1; + new_oper->netconf.call_home = -1; - nc_client_disconnect(nc_client); + new_oper->ves.faults_enabled = -1; + new_oper->ves.pnf_registration = -1; + new_oper->ves.heartbeat_period = -1; - return NTS_ERR_OK; + new_oper->errmsg = 0; + new_oper->next = 0; + + return new_oper; } -int manager_stop_instance(manager_network_function_type *function_type) { - assert(function_type); +int manager_operations_free_oper(manager_operation_t *oper) { + assert(oper); - manager_network_function_instance_t *instance = &function_type->instance[function_type->started_instances - 1]; + free(oper->function_type); + free(oper->docker_instance_name); + free(oper->docker_repository); + free(oper->docker_version_tag); + free(oper->mount_point_addressing_method); + free(oper->errmsg); - if(instance->is_mounted) { - if(manager_unmount_instance(function_type) != NTS_ERR_OK) { - log_error("failed to unmount instance"); - } - } + free(oper); + return NTS_ERR_OK; +} - int rc = docker_device_stop(instance); - if(rc != NTS_ERR_OK) { - log_error("docker_device_stop failed"); - return NTS_ERR_FAILED; - } +int manager_operations_begin(void) { + return pthread_mutex_lock(&manager_operations_mutex); +} - //clear unused ports - manager_port[instance->host_port] = 0; - - free(instance->mount_point_addressing_method); - free(instance->docker_id); - free(instance->name); - free(instance->docker_ip); - free(instance->host_ip); - - function_type->started_instances--; - if(function_type->started_instances) { - function_type->instance = (manager_network_function_instance_t *)realloc(function_type->instance, sizeof(manager_network_function_instance_t) * function_type->started_instances); - if(function_type->instance == 0) { - log_error("realloc failed"); - return NTS_ERR_FAILED; - } +int manager_operations_add(manager_operation_t *oper) { + assert(oper); + + if(manager_operations == 0) { + manager_operations = oper; } else { - free(function_type->instance); - function_type->instance = 0; + manager_operation_t *h = manager_operations; + while(h->next) { + h = h->next; + } + h->next = oper; } + return NTS_ERR_OK; } -int manager_mount_instance(manager_network_function_type *function_type) { - assert(function_type); +void manager_operations_finish_and_execute(void) { + pthread_mutex_unlock(&manager_operations_mutex); + sem_post(&manager_operations_sem); +} - manager_network_function_instance_t *instance = &function_type->instance[function_type->mounted_instances]; +void manager_operations_finish_with_error(void) { + while(manager_operations) { + manager_operation_t *h = manager_operations->next; + manager_operations_free_oper(manager_operations); + manager_operations = h; + } + pthread_mutex_unlock(&manager_operations_mutex); + sem_post(&manager_operations_sem); +} - if(instance->is_mounted == true) { - return NTS_ERR_FAILED; + + +int manager_operations_validate(manager_operation_t *oper) { + assert(oper); + + //prepopulate unset values + if(oper->docker_instance_name == 0) { + oper->docker_instance_name = strdup(manager_context[oper->ft_index].docker_instance_name); } - controller_details_t *controller; - controller = controller_details_get(0); - if(controller == 0) { - log_error("could not get controller detailes"); - return NTS_ERR_FAILED; + if(oper->docker_repository == 0) { + oper->docker_repository = strdup(manager_context[oper->ft_index].docker_repository); } - for(int i = 0; i < (framework_environment.ssh_connections + framework_environment.tls_connections); i++) { - char *protocol; - char *protocol_data; - if(i < framework_environment.ssh_connections) { - protocol = "SSH"; - protocol_data = "\ - \"network-topology:netconf-node-topology:username\": \"netconf\",\ - \"network-topology:netconf-node-topology:password\": \"netconf\""; + if(oper->docker_version_tag == 0) { + oper->docker_version_tag = strdup(manager_context[oper->ft_index].docker_version_tag); + } - } - else { - protocol = "TLS"; - protocol_data = "\ - \"netconf-node-topology:key-based\" : {\ - \"netconf-node-topology:username\" : \"netconf\",\ - \"netconf-node-topology:key-id\" : \""KS_KEY_NAME"\"\ - }"; - } + if(oper->started_instances == -1) { + oper->started_instances = manager_context[oper->ft_index].started_instances; + } - char *json_template = "\ - {\ - \"network-topology:node\": [{\ - \"network-topology:node-id\": \"%s\",\ - \"network-topology:netconf-node-topology:host\": \"%s\",\ - \"network-topology:netconf-node-topology:port\": \"%d\",\ - \"network-topology:netconf-node-topology:tcp-only\": \"false\",\ - \"network-topology:netconf-node-topology:protocol\": {\ - \"network-topology:netconf-node-topology:name\": \"%s\"\ - },\ - %s,\ - \"network-topology:netconf-node-topology:connection-timeout-millis\": \"20000\",\ - \"network-topology:netconf-node-topology:default-request-timeout-millis\": \"60000\",\ - \"network-topology:netconf-node-topology:max-connection-attempts\": \"3\"\ - }]\ - }"; - - char *json = 0; - uint16_t port = 0; - char *ip = 0; - if(instance->mount_point_addressing_method[0] == 'd') { - ip = instance->docker_ip; - port = instance->docker_port + i; - } - else { - ip = instance->host_ip; - port = instance->host_port + i; - } - char *node_id = 0; - asprintf(&node_id, "%s-%d", instance->name, port); - asprintf(&json, json_template, node_id, ip, port, protocol, protocol_data); + if(oper->mounted_instances == -1) { + oper->mounted_instances = manager_context[oper->ft_index].mounted_instances; + } - char *url = 0; - asprintf(&url, "%s/rests/data/network-topology:network-topology/topology=topology-netconf/node=%s", controller->base_url, node_id); - int rc = http_request(url, controller->username, controller->password, "PUT", json, 0, 0); - if(rc != NTS_ERR_OK) { - log_error("http_request failed"); - free(url); - free(node_id); - free(json); - controller_details_free(controller); - return NTS_ERR_FAILED; + //check docker image if exists + bool found = false; + for(int i = 0; i < docker_context[oper->ft_index].available_images_count; i++) { + if(strcmp(docker_context[oper->ft_index].available_images[i].repo, oper->docker_repository) == 0) { + if(strcmp(docker_context[oper->ft_index].available_images[i].tag, oper->docker_version_tag) == 0) { + found = true; + break; + } } - - free(url); - free(node_id); - free(json); } - controller_details_free(controller); - - instance->is_mounted = true; - function_type->mounted_instances++; + if(found == false) { + log_error("could not find image: %s/%s:%s\n", oper->docker_repository, docker_context[oper->ft_index].image, oper->docker_version_tag); + return NTS_ERR_FAILED; + } return NTS_ERR_OK; } -int manager_unmount_instance(manager_network_function_type *function_type) { - assert(function_type); - int ret = NTS_ERR_OK; - - manager_network_function_instance_t *instance = &function_type->instance[function_type->mounted_instances - 1]; +static int manager_operations_execute(manager_operation_t *oper) { + assert(oper); + + int k = oper->ft_index; + int rc; + + //operation --> actions + if(manager_context[k].started_instances > oper->started_instances) { + //stop instances + while(manager_context[k].started_instances > oper->started_instances) { + + rc = manager_actions_stop(&manager_context[k]); + if(rc != NTS_ERR_OK) { + asprintf(&oper->errmsg, "stop FAILED - function-type %s", manager_context[k].function_type); + log_error("%s\n", oper->errmsg); + + return NTS_ERR_FAILED; + } + + rc = manager_sr_update_context(&manager_context[k]); + if(rc != NTS_ERR_OK) { + log_error("manager_sr_update_context failed\n"); + } + } - if(instance->is_mounted == false) { - log_error("tried to unmount an unmounted instance"); - return NTS_ERR_FAILED; } - - controller_details_t *controller; - controller = controller_details_get(0); - if(controller == 0) { - log_error("could not get controller detailes"); - return NTS_ERR_FAILED; + else if(manager_context[k].started_instances < oper->started_instances) { + //start instances + while(manager_context[k].started_instances < oper->started_instances) { + + rc = manager_actions_start(&manager_context[k]); + if(rc != NTS_ERR_OK) { + asprintf(&oper->errmsg, "start FAILED - function-type %s", manager_context[k].function_type); + log_error("%s\n", oper->errmsg); + return NTS_ERR_FAILED; + } + + rc = manager_sr_update_context(&manager_context[k]); + if(rc != NTS_ERR_OK) { + log_error("manager_sr_update_context failed\n"); + } + + rc = manager_actions_config_instance(&manager_context[k], &manager_context[k].instance[manager_context[k].started_instances - 1]); + if(rc != NTS_ERR_OK) { + asprintf(&oper->errmsg, "config FAILED - instance %s", manager_context[k].instance[manager_context[k].started_instances - 1].container.name); + log_error("%s\n", oper->errmsg); + } + } } - for(int i = 0; i < (framework_environment.ssh_connections + framework_environment.tls_connections); i++) { - uint16_t port = 0; - if(function_type->mount_point_addressing_method[0] == 'd') { - port = instance->docker_port + i; + if(manager_context[k].mounted_instances > oper->mounted_instances) { + //unmount instances + while(manager_context[k].mounted_instances > oper->mounted_instances) { + rc = manager_actions_unmount(&manager_context[k]); + if(rc != NTS_ERR_OK) { + asprintf(&oper->errmsg, "unmount FAILED - instance %s", manager_context[k].instance[manager_context[k].mounted_instances - 1].container.name); + log_error("%s\n", oper->errmsg); + return NTS_ERR_FAILED; + } + + rc = manager_sr_update_context(&manager_context[k]); + if(rc != NTS_ERR_OK) { + log_error("manager_sr_update_context failed\n"); + } } - else { - port = instance->host_port + i; - } - char *node_id = 0; - asprintf(&node_id, "%s-%d", instance->name, port); - char *url = 0; - asprintf(&url, "%s/rests/data/network-topology:network-topology/topology=topology-netconf/node=%s", controller->base_url, node_id); - int rc = http_request(url, controller->username, controller->password, "DELETE", "", 0, 0); - if(rc != NTS_ERR_OK) { - log_error("http_request failed"); - ret = NTS_ERR_FAILED; + } + else if(manager_context[k].mounted_instances < oper->mounted_instances) { + //mount instances + while(manager_context[k].mounted_instances < oper->mounted_instances) { + rc = manager_actions_mount(&manager_context[k]); + if(rc != NTS_ERR_OK) { + asprintf(&oper->errmsg, "mount FAILED - instance %s", manager_context[k].instance[manager_context[k].mounted_instances].container.name); + log_error("%s\n", oper->errmsg); + return NTS_ERR_FAILED; + } + + rc = manager_sr_update_context(&manager_context[k]); + if(rc != NTS_ERR_OK) { + log_error("manager_sr_update_context failed\n"); + } } - - free(url); - free(node_id); } - controller_details_free(controller); - - function_type->mounted_instances--; - function_type->instance[function_type->mounted_instances].is_mounted = false; - - return ret; + return NTS_ERR_OK; } diff --git a/ntsimulator/ntsim-ng/core/app/manager_sysrepo.c b/ntsimulator/ntsim-ng/core/app/manager_sysrepo.c new file mode 100644 index 0000000..46717df --- /dev/null +++ b/ntsimulator/ntsim-ng/core/app/manager_sysrepo.c @@ -0,0 +1,456 @@ +/************************************************************************* +* +* Copyright 2020 highstreet technologies GmbH and others +* +* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +* +* 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. +***************************************************************************/ + +#define _GNU_SOURCE + +#include "manager.h" +#include "utils/log_utils.h" +#include "utils/sys_utils.h" +#include +#include + +#include "core/framework.h" +#include "core/session.h" + +static int manager_context_sync = 0; + +int manager_sr_get_context_sync(void) { + return manager_context_sync; +} + +int manager_sr_update_context(manager_context_t *ctx) { + assert(ctx); + assert_session(); + + char xpath[512]; + char int_to_str[30]; + + //setup sdn-controller defaults + sprintf(xpath, NTS_FUNCTION_LIST_SCHEMA_XPATH"[function-type='%s']/started-instances", ctx->function_type); + sprintf(int_to_str, "%d", ctx->started_instances); + int rc = sr_set_item_str(session_running, xpath, (const char*)int_to_str, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + sprintf(xpath, NTS_FUNCTION_LIST_SCHEMA_XPATH"[function-type='%s']/mounted-instances", ctx->function_type); + sprintf(int_to_str, "%d", ctx->mounted_instances); + rc = sr_set_item_str(session_running, xpath, (const char*)int_to_str, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + manager_context_sync = 1; + + //apply all changes + rc = sr_apply_changes(session_running, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_apply_changes failed\n"); + return NTS_ERR_FAILED; + } + + manager_context_sync = 0; + + return NTS_ERR_OK; +} + +int manager_sr_on_last_operation_status(const char *status, const char *errmsg) { + assert(status); + + int rc = sr_set_item_str(session_operational, NTS_SIMULATION_SCHEMA_XPATH"/last-operation-status", status, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + //apply all changes + rc = sr_apply_changes(session_operational, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_apply_changes failed\n"); + return NTS_ERR_FAILED; + } + + //push notification + const struct lys_module *manager_module = ly_ctx_get_module(session_context, NTS_MANAGER_MODULE, 0, 0); + if(manager_module == 0) { + log_error("ly_ctx_get_module failed\n"); + return NTS_ERR_FAILED; + } + + struct lyd_node *notif = lyd_new(0, manager_module, "operation-status-changed"); + if(notif == 0) { + log_error("lyd_new failed\n"); + return NTS_ERR_FAILED; + } + + lyd_new_leaf(notif, manager_module, "operation-status", status); + if(errmsg && errmsg[0]) { + lyd_new_leaf(notif, manager_module, "error-message", errmsg); + } + + rc = sr_event_notif_send_tree(session_running, notif); + if(rc != SR_ERR_OK) { + log_error("sr_event_notif_send_tree failed\n"); + return NTS_ERR_FAILED; + } + + return NTS_ERR_OK; +} + +int manager_sr_notif_send_instance_changed(const char *status, const char *function_type, const char *name, const manager_network_function_instance_t* instance) { + assert(status); + assert(function_type); + assert(name); + + //push notification + const struct lys_module *manager_module = ly_ctx_get_module(session_context, NTS_MANAGER_MODULE, 0, 0); + if(manager_module == 0) { + log_error("ly_ctx_get_module failed\n"); + return NTS_ERR_FAILED; + } + + struct lyd_node *notif = lyd_new(0, manager_module, "instance-changed"); + if(notif == 0) { + log_error("lyd_new failed\n"); + return NTS_ERR_FAILED; + } + + if(lyd_new_leaf(notif, manager_module, "change-status", status) == 0) { + log_error("lyd_new_leaf error\n"); + return NTS_ERR_FAILED; + } + + if(lyd_new_leaf(notif, manager_module, "function-type", function_type) == 0) { + log_error("lyd_new_leaf error\n"); + return NTS_ERR_FAILED; + } + + if(lyd_new_leaf(notif, manager_module, "name", name) == 0) { + log_error("lyd_new_leaf error\n"); + return NTS_ERR_FAILED; + } + + if(instance) { + if(manager_sr_populate_networking(notif, instance) != NTS_ERR_OK) { + log_error("manager_sr_populate_networking error\n"); + return NTS_ERR_FAILED; + } + } + + int rc = sr_event_notif_send_tree(session_running, notif); + if(rc != SR_ERR_OK) { + log_error("sr_event_notif_send_tree failed\n"); + return NTS_ERR_FAILED; + } + + return NTS_ERR_OK; +} + + +int manager_sr_update_static_stats(void) { + assert_session(); + char int_to_str[30]; + int rc; + + sprintf(int_to_str, "%d", framework_environment.host.ssh_base_port); + rc = sr_set_item_str(session_operational, NTS_SIMULATION_SCHEMA_XPATH"/ports/netconf-ssh-port", (const char*)int_to_str, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + sprintf(int_to_str, "%d", framework_environment.host.tls_base_port); + rc = sr_set_item_str(session_operational, NTS_SIMULATION_SCHEMA_XPATH"/ports/netconf-tls-port", (const char*)int_to_str, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + sprintf(int_to_str, "%d", framework_environment.host.ftp_base_port); + rc = sr_set_item_str(session_operational, NTS_SIMULATION_SCHEMA_XPATH"/ports/transport-ftp-port", (const char*)int_to_str, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + sprintf(int_to_str, "%d", framework_environment.host.sftp_base_port); + rc = sr_set_item_str(session_operational, NTS_SIMULATION_SCHEMA_XPATH"/ports/transport-sftp-port", (const char*)int_to_str, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + sprintf(int_to_str, "%d", framework_environment.settings.ssh_connections); + rc = sr_set_item_str(session_operational, NTS_SIMULATION_SCHEMA_XPATH"/ssh-connections", (const char*)int_to_str, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + sprintf(int_to_str, "%d", framework_environment.settings.tls_connections); + rc = sr_set_item_str(session_operational, NTS_SIMULATION_SCHEMA_XPATH"/tls-connections", (const char*)int_to_str, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + //apply all changes + rc = sr_apply_changes(session_operational, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_apply_changes failed: %s\n", sr_strerror(rc)); + return NTS_ERR_FAILED; + } + + return NTS_ERR_OK; +} + +int manager_sr_stats_get_items_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data) { + char value[128]; + + *parent = lyd_new_path(NULL, sr_get_context(sr_session_get_connection(session)), NTS_SIMULATION_SCHEMA_XPATH, 0, 0, 0); + if(*parent == 0) { + log_error("lyd_new_path failed\n"); + return SR_ERR_OPERATION_FAILED; + } + + int docker_instances_count = 0; + for(int i = 0; i < docker_context_count; i++) { + docker_instances_count += manager_context[i].started_instances; + } + + const char **instances_id = malloc(sizeof(char *) * docker_instances_count); + if(instances_id == 0) { + log_error("malloc failed\n"); + return SR_ERR_OPERATION_FAILED; + } + + int k = 0; + for(int i = 0; i < docker_context_count; i++) { + for(int j = 0; j < manager_context[i].started_instances; j++) { + instances_id[k] = manager_context[i].instance[j].container.id; + k++; + } + } + + docker_usage_t usage; + int rc = docker_usage_get(instances_id, docker_instances_count, &usage); + free(instances_id); + if(rc != NTS_ERR_OK) { + log_error("docker_usage_get failed\n"); + return SR_ERR_OPERATION_FAILED; + } + + sprintf(value, "%.2f", usage.cpu); + if(lyd_new_path(*parent, NULL, NTS_SIMULATION_SCHEMA_XPATH"/cpu-usage", value, 0, 0) == 0) { + log_error("lyd_new_path failed\n"); + return SR_ERR_OPERATION_FAILED; + } + + sprintf(value, "%.0f", usage.mem); + if(lyd_new_path(*parent, NULL, NTS_SIMULATION_SCHEMA_XPATH"/mem-usage", value, 0, 0) == 0) { + log_error("lyd_new_path failed\n"); + return SR_ERR_OPERATION_FAILED; + } + + return SR_ERR_OK; +} + +int manager_sr_populate_networking(struct lyd_node *parent, const manager_network_function_instance_t* instance) { + assert(instance); + assert(parent); + + + struct lyd_node *networking = lyd_new(parent, parent->schema->module, "networking"); + if(networking == 0) { + log_error("lyd_new failed\n"); + return NTS_ERR_FAILED; + } + + if(lyd_new_leaf(networking, parent->schema->module, "docker-ip", instance->container.docker_ip) == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + + if(lyd_new_leaf(networking, parent->schema->module, "host-ip", instance->container.host_ip) == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + + //netconf ssh ports + for(int k = 0; k < framework_environment.settings.ssh_connections; k++) { + char value[128]; + + struct lyd_node *ports = lyd_new(networking, parent->schema->module, "docker-ports"); + if(ports == 0) { + log_error("lyd_new failed\n"); + return NTS_ERR_FAILED; + } + + sprintf(value, "%d", instance->container.docker_netconf_ssh_port + k); + if(lyd_new_leaf(ports, ports->schema->module, "port", value) == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + + if(lyd_new_leaf(ports, ports->schema->module, "protocol", "NTS_PROTOCOL_TYPE_NETCONF_SSH") == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + + + ports = lyd_new(networking, parent->schema->module, "host-ports"); + if(ports == 0) { + log_error("lyd_new failed\n"); + return NTS_ERR_FAILED; + } + + sprintf(value, "%d", instance->container.host_netconf_ssh_port + k); + if(lyd_new_leaf(ports, ports->schema->module, "port", value) == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + + if(lyd_new_leaf(ports, ports->schema->module, "protocol", "NTS_PROTOCOL_TYPE_NETCONF_SSH") == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + } + + //netconf tls ports + for(int k = 0; k < framework_environment.settings.tls_connections; k++) { + char value[128]; + + struct lyd_node *ports = lyd_new(networking, parent->schema->module, "docker-ports"); + if(ports == 0) { + log_error("lyd_new failed\n"); + return NTS_ERR_FAILED; + } + + sprintf(value, "%d", instance->container.docker_netconf_tls_port + k); + if(lyd_new_leaf(ports, ports->schema->module, "port", value) == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + + if(lyd_new_leaf(ports, ports->schema->module, "protocol", "NTS_PROTOCOL_TYPE_NETCONF_TLS") == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + + + ports = lyd_new(networking, parent->schema->module, "host-ports"); + if(ports == 0) { + log_error("lyd_new failed\n"); + return NTS_ERR_FAILED; + } + + sprintf(value, "%d", instance->container.host_netconf_tls_port + k); + if(lyd_new_leaf(ports, ports->schema->module, "port", value) == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + + if(lyd_new_leaf(ports, ports->schema->module, "protocol", "NTS_PROTOCOL_TYPE_NETCONF_TLS") == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + } + + //ftp ports + for(int k = 0; k < framework_environment.settings.ftp_connections; k++) { + char value[128]; + + struct lyd_node *ports = lyd_new(networking, parent->schema->module, "docker-ports"); + if(ports == 0) { + log_error("lyd_new failed\n"); + return NTS_ERR_FAILED; + } + + sprintf(value, "%d", instance->container.docker_ftp_port + k); + if(lyd_new_leaf(ports, ports->schema->module, "port", value) == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + + if(lyd_new_leaf(ports, ports->schema->module, "protocol", "NTS_PROTOCOL_TYPE_FTP") == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + + + ports = lyd_new(networking, parent->schema->module, "host-ports"); + if(ports == 0) { + log_error("lyd_new failed\n"); + return NTS_ERR_FAILED; + } + + sprintf(value, "%d", instance->container.host_ftp_port + k); + if(lyd_new_leaf(ports, ports->schema->module, "port", value) == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + + if(lyd_new_leaf(ports, ports->schema->module, "protocol", "NTS_PROTOCOL_TYPE_FTP") == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + } + + //sftp ports + for(int k = 0; k < framework_environment.settings.sftp_connections; k++) { + char value[128]; + + struct lyd_node *ports = lyd_new(networking, parent->schema->module, "docker-ports"); + if(ports == 0) { + log_error("lyd_new failed\n"); + return NTS_ERR_FAILED; + } + + sprintf(value, "%d", instance->container.docker_sftp_port + k); + if(lyd_new_leaf(ports, ports->schema->module, "port", value) == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + + if(lyd_new_leaf(ports, ports->schema->module, "protocol", "NTS_PROTOCOL_TYPE_SFTP") == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + + + ports = lyd_new(networking, parent->schema->module, "host-ports"); + if(ports == 0) { + log_error("lyd_new failed\n"); + return NTS_ERR_FAILED; + } + + sprintf(value, "%d", instance->container.host_sftp_port + k); + if(lyd_new_leaf(ports, ports->schema->module, "port", value) == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + + if(lyd_new_leaf(ports, ports->schema->module, "protocol", "NTS_PROTOCOL_TYPE_SFTP") == 0) { + log_error("lyd_new_leaf failed\n"); + return NTS_ERR_FAILED; + } + } + + return NTS_ERR_OK; +} diff --git a/ntsimulator/ntsim-ng/core/app/network_function.c b/ntsimulator/ntsim-ng/core/app/network_function.c index 5a66d18..85d0409 100644 --- a/ntsimulator/ntsim-ng/core/app/network_function.c +++ b/ntsimulator/ntsim-ng/core/app/network_function.c @@ -20,6 +20,7 @@ #include "network_function.h" #include "utils/log_utils.h" #include "utils/sys_utils.h" +#include "utils/nts_utils.h" #include #include #include @@ -42,6 +43,10 @@ #include "features/netconf_call_home/netconf_call_home.h" #include "features/web_cut_through/web_cut_through.h" +#include "app_common.h" + +#define NF_FUNCTION_CONTROL_BUFFER_LENGTH 32 + #define IETF_NETCONF_MONITORING_MODULE "ietf-netconf-monitoring" #define IETF_NETCONF_MONITORING_STATE_SCHEMAS_SCHEMA_XPATH "/ietf-netconf-monitoring:netconf-state/schemas" @@ -51,7 +56,7 @@ #define NTS_NETWORK_FUNCTION_MODULE "nts-network-function" #define NTS_NETWORK_FUNCTION_SCHEMA_XPATH "/nts-network-function:simulation/network-function" -#define POPULATE_RPC_SCHEMA_XPATH "/nts-network-function:datastore-random-populate" +#define POPULATE_RPC_SCHEMA_XPATH "/nts-network-function:datastore-populate" #define FEATURE_CONTROL_SCHEMA_XPATH "/nts-network-function:feature-control" #define FAULTS_CLEAR_SCHEMA_XPATH "/nts-network-function:clear-fault-counters" #define FAULTS_LIST_SCHEMA_XPATH "/nts-network-function:simulation/network-function/fault-generation" @@ -59,6 +64,8 @@ #define FAULTS_NC_ENABLED_SCHEMA_XPATH "/nts-network-function:simulation/network-function/netconf/faults-enabled" #define FAULTS_VES_ENABLED_SCHEMA_XPATH "/nts-network-function:simulation/network-function/ves/faults-enabled" +#define STARTED_FEATURES_LIST_SCHEMA_XPATH "/nts-network-function:info/started-features" + static int netconf_monitoring_state_schemas_cb(sr_session_ctx_t *session, const char *module_name, const char *path, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data); static int notifications_streams_cb(sr_session_ctx_t *session, const char *module_name, const char *path, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data); @@ -68,58 +75,73 @@ static int network_function_faults_clear_cb(sr_session_ctx_t *session, const cha static int network_function_faults_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *private_data); static int network_function_faults_count_get_items_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data); +static int network_function_started_features_get_items_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data); + static int network_function_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *private_data); static int faults_update_config(sr_session_ctx_t *session); //not protected by lock static void *faults_thread_routine(void *arg); static pthread_mutex_t nf_function_control_lock; -static char *nf_function_control_string = 0; +static char *nf_function_control_buffer[NF_FUNCTION_CONTROL_BUFFER_LENGTH]; +static int nf_function_control_buffer_in; +static int nf_function_control_buffer_out; static pthread_t faults_thread; static pthread_mutex_t faults_lock; -static pthread_mutex_t network_function_change_lock; -static char *function_type_default = 0; -static char *function_type_val = 0; -static char *mount_point_addressing_method_default = 0; -static char *mount_point_addressing_method_val = 0; - int network_function_run(void) { assert_session(); - log_message(1, LOG_COLOR_BOLD_YELLOW"\nrunning as NETWORK FUNCTION daemon...\n"LOG_COLOR_RESET); + nf_function_control_buffer_in = 0; + nf_function_control_buffer_out = 0; + + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"running as NETWORK FUNCTION daemon...\n"LOG_COLOR_RESET); + + int rc = app_common_init(); + if(rc != NTS_ERR_OK) { + log_error("app_common_init failed\n"); + return NTS_ERR_FAILED; + } + + if(strlen(framework_environment.nts.nf_standalone_start_features)) { + rc = nts_utils_populate_info(session_running, framework_environment.nts.function_type); + if(rc != NTS_ERR_OK) { + log_error("nts_utils_populate_info failed\n"); + return NTS_ERR_FAILED; + } + } if(pthread_mutex_init(&nf_function_control_lock, NULL) != 0) { - log_error("mutex init has failed"); + log_error("mutex init has failed\n"); return NTS_ERR_FAILED; } //ietf-netconf-monitoring schemas populate with modules and submodules (overwrite default Netopeer2 behaviour) - int rc = sr_oper_get_items_subscribe(session_running, IETF_NETCONF_MONITORING_MODULE, IETF_NETCONF_MONITORING_STATE_SCHEMAS_SCHEMA_XPATH, netconf_monitoring_state_schemas_cb, 0, SR_SUBSCR_DEFAULT, &session_subscription); + rc = sr_oper_get_items_subscribe(session_running, IETF_NETCONF_MONITORING_MODULE, IETF_NETCONF_MONITORING_STATE_SCHEMAS_SCHEMA_XPATH, netconf_monitoring_state_schemas_cb, 0, SR_SUBSCR_DEFAULT, &session_subscription); if(rc != SR_ERR_OK) { - log_error("error from sr_oper_get_items_subscribe: %s", sr_strerror(rc)); + log_error("error from sr_oper_get_items_subscribe: %s\n", sr_strerror(rc)); return 0; } //nc-notifications overwrite rc = sr_oper_get_items_subscribe(session_running, NC_NOTIFICATIONS_MODULE, NC_NOTIFICATIONS_STREAMS_SCHEMA_XPATH, notifications_streams_cb, 0, SR_SUBSCR_DEFAULT, &session_subscription); if(rc != SR_ERR_OK) { - log_error("error from sr_oper_get_items_subscribe: %s", sr_strerror(rc)); + log_error("error from sr_oper_get_items_subscribe: %s\n", sr_strerror(rc)); return 0; } //populate rc = sr_rpc_subscribe(session_running, POPULATE_RPC_SCHEMA_XPATH, network_function_populate_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &session_subscription); if(rc != SR_ERR_OK) { - log_error("error from sr_rpc_subscribe: %s", sr_strerror(rc)); + log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc)); return NTS_ERR_FAILED; } //feature control rc = sr_rpc_subscribe(session_running, FEATURE_CONTROL_SCHEMA_XPATH, network_function_feature_control_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &session_subscription); if(rc != SR_ERR_OK) { - log_error("error from sr_rpc_subscribe: %s", sr_strerror(rc)); + log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc)); return NTS_ERR_FAILED; } @@ -132,122 +154,190 @@ int network_function_run(void) { rc = sr_oper_get_items_subscribe(session_running, NTS_NETWORK_FUNCTION_MODULE, FAULTS_COUNT_LIST_SCHEMA_XPATH, network_function_faults_count_get_items_cb, NULL, SR_SUBSCR_CTX_REUSE, &session_subscription); if(rc != SR_ERR_OK) { - log_error("could not subscribe to oper faults: %s", sr_strerror(rc)); + log_error("could not subscribe to oper faults: %s\n", sr_strerror(rc)); return 0; } rc = sr_rpc_subscribe(session_running, FAULTS_CLEAR_SCHEMA_XPATH, network_function_faults_clear_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &session_subscription); if(rc != SR_ERR_OK) { - log_error("error from sr_rpc_subscribe: %s", sr_strerror(rc)); + log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc)); return NTS_ERR_FAILED; } + rc = sr_oper_get_items_subscribe(session_running, NTS_NETWORK_FUNCTION_MODULE, STARTED_FEATURES_LIST_SCHEMA_XPATH, network_function_started_features_get_items_cb, NULL, SR_SUBSCR_CTX_REUSE, &session_subscription); + if(rc != SR_ERR_OK) { + log_error("could not subscribe to oper started-features: %s\n", sr_strerror(rc)); + return 0; + } + + //subscribe to any changes on the main - rc = sr_module_change_subscribe(session_running, NTS_NETWORK_FUNCTION_MODULE, NTS_NETWORK_FUNCTION_SCHEMA_XPATH, network_function_change_cb, NULL, 0, SR_SUBSCR_CTX_REUSE, &session_subscription); + rc = sr_module_change_subscribe(session_running, NTS_NETWORK_FUNCTION_MODULE, NTS_NETWORK_FUNCTION_SCHEMA_XPATH, network_function_change_cb, NULL, 0, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_UPDATE, &session_subscription); if(rc != SR_ERR_OK) { - log_error("could not subscribe to simulation changes"); + log_error("could not subscribe to simulation changes\n"); return NTS_ERR_FAILED; } rc = faults_init(); if(rc != NTS_ERR_OK) { - log_error("faults_init error", sr_strerror(rc)); + log_error("faults_init error\n", sr_strerror(rc)); return NTS_ERR_FAILED; } if(pthread_mutex_init(&faults_lock, NULL) != 0) { - log_error("mutex init has failed"); + log_error("mutex init has failed\n"); return NTS_ERR_FAILED; } if(pthread_create(&faults_thread, 0, faults_thread_routine, 0)) { - log_error("could not create thread for heartbeat"); + log_error("could not create thread for heartbeat\n"); return NTS_ERR_FAILED; } - if(pthread_mutex_init(&network_function_change_lock, NULL) != 0) { - log_error("mutex init has failed"); - return NTS_ERR_FAILED; - } - - while(!framework_sigint) { - pthread_mutex_lock(&network_function_change_lock); - if(function_type_val) { - rc = sr_set_item_str(session_running, NTS_NETWORK_FUNCTION_SCHEMA_XPATH"/function-type", function_type_val, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - } + //check standalone mode + if(strlen(framework_environment.nts.nf_standalone_start_features)) { + char *start_features = 0; - rc = sr_apply_changes(session_running, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_apply_changes failed"); - } + asprintf(&start_features, "1 %s", framework_environment.nts.nf_standalone_start_features); + nf_function_control_buffer[nf_function_control_buffer_in] = start_features; + nf_function_control_buffer_in++; + if(nf_function_control_buffer_in >= NF_FUNCTION_CONTROL_BUFFER_LENGTH) { + nf_function_control_buffer_in = 0; + } - function_type_val = 0; + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"running in NETWORK FUNCTION STANDALONE mode!\n"LOG_COLOR_RESET); + log_add_verbose(1, "Currently enabled features are: %s\n", framework_environment.nts.nf_standalone_start_features); + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"Docker IP:"LOG_COLOR_RESET" %s\n", framework_environment.settings.ip_v6_enabled ? framework_environment.settings.ip_v6 : framework_environment.settings.ip_v4); + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"Docker ports"LOG_COLOR_RESET": "); + if(framework_environment.settings.ssh_connections) { + log_add(1, "NETCONF SSH: %d (%d)", STANDARD_NETCONF_PORT, framework_environment.settings.ssh_connections); + } + else { + log_add(1, "NETCONF SSH: disabled"); + } + if(framework_environment.settings.tls_connections) { + log_add(1, " | NETCONF TLS: %d (%d)", STANDARD_NETCONF_PORT + framework_environment.settings.ssh_connections, framework_environment.settings.tls_connections); } + else { + log_add(1, " | NETCONF TLS: disabled"); + } + if(framework_environment.settings.ftp_connections) { + log_add(1, " | FTP: %d (%d)", STANDARD_FTP_PORT, framework_environment.settings.ftp_connections); + } + else { + log_add(1, " | FTP: disabled"); + } + if(framework_environment.settings.sftp_connections) { + log_add(1, " | SFTP: %d (%d)", STANDARD_SFTP_PORT, framework_environment.settings.sftp_connections); + } + else { + log_add(1, " | SFTP: disabled"); + } + log_add(1,"\n"); + } - if(mount_point_addressing_method_val) { - rc = sr_set_item_str(session_running, NTS_NETWORK_FUNCTION_SCHEMA_XPATH"/mount-point-addressing-method", mount_point_addressing_method_val, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); + while(!framework_sigint) { + pthread_mutex_lock(&nf_function_control_lock); + while(nf_function_control_buffer_in != nf_function_control_buffer_out) { + //get current function control string + char *nf_function_control_string = nf_function_control_buffer[nf_function_control_buffer_out]; + nf_function_control_buffer_out++; + if(nf_function_control_buffer_out >= NF_FUNCTION_CONTROL_BUFFER_LENGTH) { + nf_function_control_buffer_out = 0; } - rc = sr_apply_changes(session_running, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_apply_changes failed"); + if(strstr(nf_function_control_string, "datastore-populate") != 0) { + rc = datastore_populate(3); + if(rc != NTS_ERR_OK) { + log_error("datastore_populate() failed\n"); + } } - mount_point_addressing_method_val = 0; - } - pthread_mutex_unlock(&network_function_change_lock); - - pthread_mutex_lock(&nf_function_control_lock); - if(nf_function_control_string) { if(strstr(nf_function_control_string, "ves-file-ready") != 0) { - // start feature for handling the fileReady VES message - rc = ves_file_ready_feature_start(session_running); - if(rc != 0) { - log_error("ves_file_ready_feature_start() failed"); + if(nf_function_control_string[0] == '1') { + // start feature for handling the fileReady VES message + rc = ves_file_ready_feature_start(session_running); + if(rc != 0) { + log_error("ves_file_ready_feature_start() failed\n"); + } + } + else if(nf_function_control_string[0] == '0') { + // stop feature for handling the fileReady VES message + rc = ves_file_ready_feature_stop(); + if(rc != 0) { + log_error("ves_file_ready_feature_stop() failed\n"); + } } } if(strstr(nf_function_control_string, "ves-pnf-registration") != 0) { - // check if PNF registration is enabled and send PNF registration message if so - rc = ves_pnf_registration_feature_start(session_running); - if(rc != 0) { - log_error("ves_pnf_registration_feature_start() failed"); + if(nf_function_control_string[0] == '1') { + // check if PNF registration is enabled and send PNF registration message if so + rc = ves_pnf_registration_feature_start(session_running); + if(rc != 0) { + log_error("ves_pnf_registration_feature_start() failed\n"); + } } } if(strstr(nf_function_control_string, "ves-heartbeat") != 0) { - // start feature for handling the heartbeat VES message - rc = ves_heartbeat_feature_start(session_running); - if(rc != 0) { - log_error("ves_heartbeat_feature_start() failed"); + if(nf_function_control_string[0] == '1') { + // start feature for handling the heartbeat VES message + rc = ves_heartbeat_feature_start(session_running); + if(rc != 0) { + log_error("ves_heartbeat_feature_start() failed\n"); + } + } + else if(nf_function_control_string[0] == '0') { + // stop feature for handling the heartbeat VES message + rc = ves_heartbeat_feature_stop(); + if(rc != 0) { + log_error("ves_heartbeat_feature_stop() failed\n"); + } } } if(strstr(nf_function_control_string, "manual-notification-generation") != 0) { - // start feature for manual notification - rc = manual_notification_feature_start(session_running); - if(rc != 0) { - log_error("manual_notification_feature_start() failed"); + if(nf_function_control_string[0] == '1') { + // start feature for manual notification + rc = manual_notification_feature_start(session_running); + if(rc != 0) { + log_error("manual_notification_feature_start() failed\n"); + } + } + else if(nf_function_control_string[0] == '0') { + // stop feature for manual notification + rc = manual_notification_feature_stop(); + if(rc != 0) { + log_error("manual_notification_feature_stop() failed\n"); + } } } if(strstr(nf_function_control_string, "netconf-call-home") != 0) { - // start feature for NETCONF Call Home - rc = netconf_call_home_feature_start(session_running); - if(rc != 0) { - log_error("netconf_call_home_feature_start() failed"); + if(nf_function_control_string[0] == '1') { + // start feature for NETCONF Call Home + rc = netconf_call_home_feature_start(session_running); + if(rc != 0) { + log_error("netconf_call_home_feature_start() failed\n"); + } } } if(strstr(nf_function_control_string, "web-cut-through") != 0) { - // start feature for NETCONF Call Home - rc = web_cut_through_feature_start(session_running); - if(rc != 0) { - log_error("web_cut_through_feature_start() failed"); + if(nf_function_control_string[0] == '1') { + // start feature for web cut-through + rc = web_cut_through_feature_start(session_running); + if(rc != 0) { + log_error("web_cut_through_feature_start() failed\n"); + } + } + else if(nf_function_control_string[0] == '0') { + // stop feature for web cut-through + rc = web_cut_through_feature_stop(session_running); + if(rc != 0) { + log_error("web_cut_through_feature_stop() failed\n"); + } } } @@ -275,6 +365,11 @@ static int netconf_monitoring_state_schemas_cb(sr_session_ctx_t *session, const // get all modules from context while ((mod = ly_ctx_get_module_iter(session_context, &i))) { + // we skip the internal sysrepo modules + if (!strcmp("sysrepo", mod->name) || !strcmp("sysrepo-monitoring", mod->name) || !strcmp("sysrepo-plugind", mod->name)) { + continue; + } + list = lyd_new(root, NULL, "schema"); lyd_new_leaf(list, NULL, "identifier", mod->name); lyd_new_leaf(list, NULL, "version", (mod->rev ? mod->rev[0].date : NULL)); @@ -312,7 +407,7 @@ static int notifications_streams_cb(sr_session_ctx_t *session, const char *modul /* go through all the sysrepo modules */ int rc = sr_get_module_info(session_connection, &sr_data); if(rc != SR_ERR_OK) { - log_error("sr_get_module_info failed"); + log_error("sr_get_module_info failed\n"); return SR_ERR_OPERATION_FAILED; } @@ -370,14 +465,15 @@ static int network_function_populate_cb(sr_session_ctx_t *session, const char *p return rc; } - rc = schema_populate(); - if(rc != NTS_ERR_OK) { - rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "ERROR"); - } - else { - rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS"); + pthread_mutex_lock(&nf_function_control_lock); + nf_function_control_buffer[nf_function_control_buffer_in] = strdup("datastore-populate"); + nf_function_control_buffer_in++; + if(nf_function_control_buffer_in >= NF_FUNCTION_CONTROL_BUFFER_LENGTH) { + nf_function_control_buffer_in = 0; } + pthread_mutex_unlock(&nf_function_control_lock); + rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS"); return rc; } @@ -385,6 +481,55 @@ static int network_function_feature_control_cb(sr_session_ctx_t *session, const int rc; int total_errors = 0; + char start_features[16][64]; + int start_features_cnt = 0; + + char stop_features[16][64]; + int stop_features_cnt = 0; + + char *start_input = 0; + char *stop_input = 0; + + for(int i = 0; i < input_cnt; i++) { + if(input[i].data.bits_val == 0) { + continue; + } + + char *val = strdup(input[i].data.bits_val); + + if(strstr(input[i].xpath, "start")) { + start_input = input[i].data.bits_val; + + const char *tok = " "; + char *token = strtok(val, tok); + while(token) { + strcpy(start_features[start_features_cnt++], token); + token = strtok(0, tok); + } + } + + if(strstr(input[i].xpath, "stop")) { + stop_input = input[i].data.bits_val; + + const char *tok = " "; + char *token = strtok(val, tok); + while(token) { + strcpy(stop_features[stop_features_cnt++], token); + token = strtok(0, tok); + } + } + + free(val); + } + + for(int i = 0; i < start_features_cnt; i++) { + for(int j = 0; j < stop_features_cnt; j++) { + if(strcmp(start_features[i], stop_features[j]) == 0) { + total_errors++; + } + } + } + *output_cnt = 1; rc = sr_new_values(*output_cnt, output); if(SR_ERR_OK != rc) { @@ -401,11 +546,27 @@ static int network_function_feature_control_cb(sr_session_ctx_t *session, const } else { rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS"); + + pthread_mutex_lock(&nf_function_control_lock); + if(start_features_cnt) { + asprintf(&nf_function_control_buffer[nf_function_control_buffer_in], "1 %s", start_input); + nf_function_control_buffer_in++; + if(nf_function_control_buffer_in >= NF_FUNCTION_CONTROL_BUFFER_LENGTH) { + nf_function_control_buffer_in = 0; + } + } + + if(stop_features_cnt) { + asprintf(&nf_function_control_buffer[nf_function_control_buffer_in], "0 %s", stop_input); + nf_function_control_buffer_in++; + if(nf_function_control_buffer_in >= NF_FUNCTION_CONTROL_BUFFER_LENGTH) { + nf_function_control_buffer_in = 0; + } + } + pthread_mutex_unlock(&nf_function_control_lock); } - pthread_mutex_lock(&nf_function_control_lock); - nf_function_control_string = strdup(input[0].data.bits_val); - pthread_mutex_unlock(&nf_function_control_lock); + return rc; } @@ -440,7 +601,7 @@ static int network_function_faults_change_cb(sr_session_ctx_t *session, const ch rc = faults_update_config(session); pthread_mutex_unlock(&faults_lock); if(rc != NTS_ERR_OK) { - log_error("faults_update_config failed"); + log_error("faults_update_config failed\n"); return SR_ERR_VALIDATION_FAILED; } } @@ -456,31 +617,78 @@ static int network_function_faults_count_get_items_cb(sr_session_ctx_t *session, *parent = lyd_new_path(NULL, sr_get_context(sr_session_get_connection(session)), FAULTS_COUNT_LIST_SCHEMA_XPATH, 0, 0, 0); if(*parent == 0) { + log_error("lyd_new_path failed\n"); return SR_ERR_OPERATION_FAILED; } sprintf(value, "%d", counters.normal); if(lyd_new_path(*parent, NULL, FAULTS_COUNT_LIST_SCHEMA_XPATH"/normal", value, 0, 0) == 0) { + log_error("lyd_new_path failed\n"); return SR_ERR_OPERATION_FAILED; } sprintf(value, "%d", counters.warning); if(lyd_new_path(*parent, NULL, FAULTS_COUNT_LIST_SCHEMA_XPATH"/warning", value, 0, 0) == 0) { + log_error("lyd_new_path failed\n"); return SR_ERR_OPERATION_FAILED; } sprintf(value, "%d", counters.minor); if(lyd_new_path(*parent, NULL, FAULTS_COUNT_LIST_SCHEMA_XPATH"/minor", value, 0, 0) == 0) { + log_error("lyd_new_path failed\n"); return SR_ERR_OPERATION_FAILED; } sprintf(value, "%d", counters.major); if(lyd_new_path(*parent, NULL, FAULTS_COUNT_LIST_SCHEMA_XPATH"/major", value, 0, 0) == 0) { + log_error("lyd_new_path failed\n"); return SR_ERR_OPERATION_FAILED; } sprintf(value, "%d", counters.critical); if(lyd_new_path(*parent, NULL, FAULTS_COUNT_LIST_SCHEMA_XPATH"/critical", value, 0, 0) == 0) { + log_error("lyd_new_path failed\n"); + return SR_ERR_OPERATION_FAILED; + } + + return SR_ERR_OK; +} + +static int network_function_started_features_get_items_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data) { + char value[1024]; + value[0] = 0; + + if(ves_file_ready_feature_get_status()) { + strcat(value, "ves-file-ready "); + } + + if(ves_pnf_registration_feature_get_status()) { + strcat(value, "ves-pnf-registration "); + } + + if(ves_heartbeat_feature_get_status()) { + strcat(value, "ves-heartbeat "); + } + + if(manual_notification_feature_get_status()) { + strcat(value, "manual-notification-generation "); + } + + if(netconf_call_home_feature_get_status()) { + strcat(value, "netconf-call-home "); + } + + if(web_cut_through_feature_get_status()) { + strcat(value, "web-cut-through "); + } + + if(strlen(value)) { + value[strlen(value) - 1] = 0; + } + + *parent = lyd_new_path(NULL, sr_get_context(sr_session_get_connection(session)), STARTED_FEATURES_LIST_SCHEMA_XPATH, value, 0, 0); + if(*parent == 0) { + log_error("lyd_new_path failed\n"); return SR_ERR_OPERATION_FAILED; } @@ -497,12 +705,16 @@ static int faults_update_config(sr_session_ctx_t *session) { struct lyd_node *data; rc = sr_get_subtree(session, FAULTS_LIST_SCHEMA_XPATH, 0, &data); if(rc != SR_ERR_OK) { - log_error("sr_get_subtree failed"); - ret = NTS_ERR_FAILED; + log_error("sr_get_subtree failed\n"); + return NTS_ERR_FAILED; } faults_fault_list_clear(); faults_counters_clear(); + if(data == 0) { + return NTS_ERR_OK; + } + if(data->child == 0) { goto faults_update_config_free; } @@ -515,7 +727,7 @@ static int faults_update_config(sr_session_ctx_t *session) { if(strcmp(delay_list_entry->schema->name, "delay-period") == 0) { rc = faults_fault_list_add(((const struct lyd_node_leaf_list *)delay_list_entry)->value.uint16); if(rc != NTS_ERR_OK) { - log_error("faults_fault_list_add failed"); + log_error("faults_fault_list_add failed\n"); ret = NTS_ERR_FAILED; goto faults_update_config_free; } @@ -537,21 +749,21 @@ static void *faults_thread_routine(void *arg) { sr_session_ctx_t *current_session_running = 0; rc = sr_session_start(session_connection, SR_DS_RUNNING, ¤t_session_running); if (rc != SR_ERR_OK) { - log_error("sr_session_start failed"); + log_error("sr_session_start failed\n"); return 0; } sr_session_ctx_t *current_session_operational = 0; rc = sr_session_start(session_connection, SR_DS_OPERATIONAL, ¤t_session_operational); if (rc != SR_ERR_OK) { - log_error("sr_session_start failed"); + log_error("sr_session_start failed\n"); return 0; } pthread_mutex_lock(&faults_lock); rc = faults_update_config(current_session_running); if(rc != NTS_ERR_OK) { - log_error("faults_update_config failed"); + log_error("faults_update_config failed\n"); return 0; } pthread_mutex_unlock(&faults_lock); @@ -563,7 +775,7 @@ static void *faults_thread_routine(void *arg) { fault_details_t *fault = faults_generate_fault(); if(fault == 0) { - log_error("faults_generate_fault failed"); + log_error("faults_generate_fault failed\n"); pthread_mutex_unlock(&faults_lock); sleep(1); continue; @@ -571,7 +783,7 @@ static void *faults_thread_routine(void *arg) { rc = faults_counters_increase(fault->severity); if(rc != NTS_ERR_OK) { - log_error("faults_counters_increase failed"); + log_error("faults_counters_increase failed\n"); } pthread_mutex_unlock(&faults_lock); @@ -593,16 +805,17 @@ static void *faults_thread_routine(void *arg) { if(nc_fault_enabled) { struct lyd_node *notif = 0; + log_add_verbose(1, "[faults] notification is '%s'\n", fault->yang_notif_processed); notif = lyd_parse_mem(session_context, fault->yang_notif_processed, LYD_XML, LYD_OPT_NOTIF, 0); if(notif == 0) { - log_error("lyd_parse_mem failed"); + log_error("lyd_parse_mem failed\n"); goto fault_send_ves; } rc = sr_event_notif_send_tree(current_session_running, notif); lyd_free(notif); if(rc != SR_ERR_OK) { - log_error("sr_event_notif_send_tree failed"); + log_error("sr_event_notif_send_tree failed\n"); } } @@ -610,10 +823,11 @@ static void *faults_thread_routine(void *arg) { if(ves_fault_enabled) { rc = faults_ves_message_send(current_session_running, fault->condition, fault->object, fault->severity, fault->date_time, fault->specific_problem); if(rc != NTS_ERR_OK) { - log_error("faults_ves_message_send failed"); + log_error("faults_ves_message_send failed\n"); } } + log_add_verbose(1, "[faults] delaying %d sec\n", new_delay); sleep(new_delay); } else { @@ -635,44 +849,31 @@ static int network_function_change_cb(sr_session_ctx_t *session, const char *mod sr_val_t *old_value = 0; sr_val_t *new_value = 0; - static bool function_type_set = false; - static bool mount_point_addressing_method_set = false; - - if(event == SR_EV_DONE) { + if(event == SR_EV_UPDATE) { rc = sr_get_changes_iter(session, NTS_NETWORK_FUNCTION_SCHEMA_XPATH"//.", &it); if(rc != SR_ERR_OK) { - log_error("sr_get_changes_iter failed"); + log_error("sr_get_changes_iter failed\n"); return SR_ERR_VALIDATION_FAILED; } while((rc = sr_get_change_next(session, it, &oper, &old_value, &new_value)) == SR_ERR_OK) { if(new_value->xpath && (strcmp(new_value->xpath, NTS_NETWORK_FUNCTION_SCHEMA_XPATH"/function-type") == 0)) { - if(function_type_set == false) { - function_type_set = true; - function_type_default = strdup(new_value->data.string_val); - } - else { - //prevent changing function_type - if(strcmp(new_value->data.string_val, function_type_default) != 0) { - pthread_mutex_lock(&network_function_change_lock); - function_type_val = function_type_default; - pthread_mutex_unlock(&network_function_change_lock); + if(old_value && !old_value->dflt) { + rc = sr_set_item(session, old_value->xpath, old_value, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item failed\n"); + return SR_ERR_VALIDATION_FAILED; } } } if(new_value->xpath && (strcmp(new_value->xpath, NTS_NETWORK_FUNCTION_SCHEMA_XPATH"/mount-point-addressing-method") == 0)) { - if(mount_point_addressing_method_set == false) { - mount_point_addressing_method_set = true; - mount_point_addressing_method_default = strdup(new_value->data.string_val); - } - else { - //prevent changing mount_point_addressing_method - if(strcmp(new_value->data.string_val, mount_point_addressing_method_default) != 0) { - pthread_mutex_lock(&network_function_change_lock); - mount_point_addressing_method_val = mount_point_addressing_method_default; - pthread_mutex_unlock(&network_function_change_lock); + if(old_value && !old_value->dflt) { + rc = sr_set_item(session, old_value->xpath, old_value, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item failed\n"); + return SR_ERR_VALIDATION_FAILED; } } } diff --git a/ntsimulator/ntsim-ng/core/app/supervisor.c b/ntsimulator/ntsim-ng/core/app/supervisor.c new file mode 100644 index 0000000..8612a08 --- /dev/null +++ b/ntsimulator/ntsim-ng/core/app/supervisor.c @@ -0,0 +1,216 @@ +/************************************************************************* +* +* Copyright 2020 highstreet technologies GmbH and others +* +* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +* +* 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. +***************************************************************************/ + +#define _GNU_SOURCE + +#include "supervisor.h" +#include "utils/log_utils.h" +#include "utils/sys_utils.h" +#include +#include + +#include "core/framework.h" +#include +#include +#include +#include +#include +#include + +typedef struct { + char *name; + char *path; + char **args; + bool nomanual; + bool autorestart; + char *stdout_path; + char *stderr_path; + + pid_t pid; + int running; +} supervisor_control_block_t; + +static void supervisor_spawn(supervisor_control_block_t *scb); +static void supervisor_free_scb(int count, supervisor_control_block_t *scb); +static void supervisor_on_signal(int signo); + +static volatile sig_atomic_t supervisor_got_signal_stop = 0; +static bool nts_manual; + +int supervisor_run(void) { + int scb_count = framework_config.supervisor.rules_count; + supervisor_control_block_t *scb = (supervisor_control_block_t*)malloc(sizeof(supervisor_control_block_t) * framework_config.supervisor.rules_count); + if(scb == 0) { + log_error("malloc failed\n"); + return NTS_ERR_FAILED; + } + + for(int i = 0; i < scb_count; i++) { + scb[i].name = strdup(framework_config.supervisor.rules[i].name); + scb[i].path = strdup(framework_config.supervisor.rules[i].path); + scb[i].args = malloc(sizeof(char *) * (framework_config.supervisor.rules[i].args_count + 2)); + scb[i].args[0] = strdup(framework_config.supervisor.rules[i].path); + for(int j = 0; j < framework_config.supervisor.rules[i].args_count; j++) { + scb[i].args[j + 1] = strdup(framework_config.supervisor.rules[i].args[j]); + } + scb[i].args[framework_config.supervisor.rules[i].args_count + 1] = 0; + scb[i].autorestart = framework_config.supervisor.rules[i].autorestart; + scb[i].nomanual = framework_config.supervisor.rules[i].nomanual; + scb[i].stdout_path = framework_config.supervisor.rules[i].stdout_path ? strdup(framework_config.supervisor.rules[i].stdout_path) : 0; + scb[i].stderr_path = framework_config.supervisor.rules[i].stderr_path ? strdup(framework_config.supervisor.rules[i].stderr_path) : 0; + scb[i].pid = 0; + scb[i].running = 0; + } + + nts_manual = framework_environment.nts.manual; + + signal(SIGINT, supervisor_on_signal); + signal(SIGTERM, supervisor_on_signal); + signal(SIGQUIT, supervisor_on_signal); + + for(int i = 0; i < scb_count; i++) { + supervisor_spawn(&scb[i]); + log_add_verbose(1, "[supervisor] spawning %s... with pid %lu\n", scb[i].name, scb[i].pid); + } + + int running = 1; + while(running) { + int defunct_status; + pid_t defunct_pid = waitpid(-1, &defunct_status, WNOHANG); + if(defunct_pid > 0) { + for(int i = 0; i < scb_count; i++) { + if(scb[i].pid == defunct_pid) { + log_add_verbose(1, "[supervisor] process %s (pid=%lu) exited with status %d\n", scb[i].name, defunct_pid, defunct_status); + scb[i].running = 0; + if(scb[i].autorestart) { + supervisor_spawn(&scb[i]); + log_add_verbose(1, "[supervisor] respawned %s (pid=%lu)\n", scb[i].name, scb[i].pid); + } + } + } + } + + if(supervisor_got_signal_stop) { + for(int i = 0; i < scb_count; i++) { + if(scb[i].running) { + log_add_verbose(1, "[supervisor] sending %d to %s (pid=%lu)...\n", supervisor_got_signal_stop, scb[i].name, scb[i].pid); + kill(scb[i].pid, supervisor_got_signal_stop); + } + } + supervisor_got_signal_stop = 0; + running = 0; + } + + sleep(1); + } + + //after SIGTERM was forwarded + running = 1; + while(running) { + int defunct_status; + pid_t defunct_pid = waitpid(-1, &defunct_status, WNOHANG); + if(defunct_pid > 0) { + char *name = 0; + for(int i = 0; i < scb_count; i++) { + if(scb[i].pid == defunct_pid) { + scb[i].running = 0; + name = scb[i].name; + } + } + log_add_verbose(1, "[supervisor] process %s (pid=%d) exited with status %d\n", name, defunct_pid, defunct_status); + } + + running = 0; + for(int i = 0; i < scb_count; i++) { + if(scb[i].running == 1) { + running = 1; + } + } + } + + supervisor_free_scb(scb_count, scb); + framework_free(); + + return NTS_ERR_OK; +} + +static void supervisor_spawn(supervisor_control_block_t *scb) { + if(nts_manual && scb->nomanual) { + return; + } + + scb->running = 1; + scb->pid = fork(); + if(scb->pid == -1) { + log_error("fork() failed\n"); + return; + } + + if(scb->pid == 0) { + //child process + int stdout_fd = 0; + int stderr_fd = 0; + + signal(SIGINT, 0); + signal(SIGTERM, 0); + signal(SIGQUIT, 0); + framework_free(); + setsid(); + + if(scb->stdout_path) { + if(scb->stdout_path[0] == 0) { + free(scb->stdout_path); + scb->stdout_path = strdup("/dev/null"); + } + stdout_fd = open(scb->stdout_path, O_WRONLY | O_CREAT | O_TRUNC, 0666); + dup2(stdout_fd, STDOUT_FILENO); + } + + if(scb->stderr_path) { + if(scb->stderr_path[0] == 0) { + free(scb->stderr_path); + scb->stderr_path = strdup("/dev/null"); + } + stderr_fd = open(scb->stderr_path, O_WRONLY | O_CREAT | O_TRUNC, 0666); + dup2(stderr_fd, STDERR_FILENO); + } + + execv(scb->path, scb->args); + _exit(0); + } +} + +static void supervisor_free_scb(int count, supervisor_control_block_t *scb) { + for(int i = 0; i < count; i++) { + free(scb[i].name); + free(scb[i].path); + int j = 0; + while(scb[i].args[j]) { + free(scb[i].args[j]); + j++; + } + free(scb[i].args); + free(scb[i].stdout_path); + free(scb[i].stderr_path); + } + + free(scb); +} + +static void supervisor_on_signal(int signo) { + supervisor_got_signal_stop = signo; +} diff --git a/ntsimulator/ntsim-ng/core/app/supervisor.h b/ntsimulator/ntsim-ng/core/app/supervisor.h new file mode 100644 index 0000000..a714dee --- /dev/null +++ b/ntsimulator/ntsim-ng/core/app/supervisor.h @@ -0,0 +1,20 @@ +/************************************************************************* +* +* Copyright 2020 highstreet technologies GmbH and others +* +* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +* +* 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. +***************************************************************************/ + +#pragma once + +int supervisor_run(void); diff --git a/ntsimulator/ntsim-ng/core/container.c b/ntsimulator/ntsim-ng/core/container.c new file mode 100644 index 0000000..a3e7b11 --- /dev/null +++ b/ntsimulator/ntsim-ng/core/container.c @@ -0,0 +1,264 @@ +/************************************************************************* +* +* Copyright 2020 highstreet technologies GmbH and others +* +* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +* +* 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. +***************************************************************************/ + +#define _GNU_SOURCE + +#include "container.h" +#include "utils/log_utils.h" +#include "utils/sys_utils.h" +#include "utils/http_client.h" +#include "core/framework.h" +#include "core/session.h" +#include "core/context.h" +#include +#include +#include + +struct installable_module { + char *name; + char *fullpath; + bool installed; + bool submodule; +}; + + +static int get_installable_modules(struct installable_module **modules); //list available modules for install +static void list_yangs(const char *path, struct installable_module **modules, int *total); +static bool container_rules_is_excluded_module(const char *module); +static bool container_rules_is_excluded_feature(const char *feature); + +bool container_self_init(void) { + int rc; + + sr_log_stderr(SR_LL_NONE); + log_add_verbose(1, "Entering container-init mode...\n"); + + // connect to sysrepo + rc = sr_connect(0, &session_connection); + if(SR_ERR_OK != rc) { + log_error("sr_connect failed\n"); + return false; + } + + /* get context */ + session_context = (struct ly_ctx *)sr_get_context(session_connection); + if(session_context == 0) { + log_error("sr_get_context failed\n"); + return false; + } + + /* install yang files */ + log_add_verbose(1, "Installing yang files...\n"); + struct installable_module *modules; + int total_modules = get_installable_modules(&modules); + log_add_verbose(1, "Found total modules: %d\n", total_modules); + + int old_failed_installations = 1; + int failed_installations = 0; + int install_round = 0; + while(failed_installations != old_failed_installations) { + old_failed_installations = failed_installations; + failed_installations = 0; + install_round++; + for(int i = 0; i < total_modules; i++) { + if(!modules[i].installed) { + modules[i].submodule = context_yang_is_module(modules[i].fullpath); + if(!modules[i].submodule) { + if(!container_rules_is_excluded_module(modules[i].name)) { + log_add_verbose(1, "[round %d] trying to install module %s from %s... ", install_round, modules[i].name, modules[i].fullpath); + if(!context_module_install(modules[i].name, modules[i].fullpath)) { + failed_installations++; + log_add(1, LOG_COLOR_BOLD_YELLOW"failed"LOG_COLOR_RESET"\n"); + } + else { + log_add(1, LOG_COLOR_BOLD_GREEN"done"LOG_COLOR_RESET"\n"); + modules[i].installed = true; + } + } + else { + log_add_verbose(1, "[round %d] not installing module %s as it's excluded in config.\n", install_round, modules[i].name); + modules[i].installed = true; + } + } + else { + log_add_verbose(1, "[round %d] %s is a submodule... "LOG_COLOR_BOLD_YELLOW"skipping"LOG_COLOR_RESET"\n", install_round, modules[i].name); + modules[i].installed = true; + } + } + } + } + + if(failed_installations != 0) { + log_error("failed to install all modules in %d rounds...\n", install_round); + return false; + } + else { + log_add_verbose(1, LOG_COLOR_BOLD_GREEN"successfully"LOG_COLOR_RESET" installed "LOG_COLOR_BOLD_GREEN"ALL"LOG_COLOR_RESET" modules in "LOG_COLOR_BOLD_YELLOW"%d"LOG_COLOR_RESET" rounds\n", (install_round - 1)); + } + + //set access for all installed modules + log_add_verbose(1, "Setting access configuration for installed modules... "); + for(int i = 0; i < total_modules; i++) { + if((!container_rules_is_excluded_module(modules[i].name)) && (!modules[i].submodule)) { + if(!context_module_set_access(modules[i].name)) { + log_error("failed to set access to module %s...\n", modules[i].name); + return false; + } + } + } + log_add(1, LOG_COLOR_BOLD_GREEN"done"LOG_COLOR_RESET"\n"); + + //cleanup module-install used memory + for(int i = 0; i < total_modules; i++) { + free(modules[i].name); + free(modules[i].fullpath); + } + free(modules); + + //get context + session_context = (struct ly_ctx *)sr_get_context(session_connection); + if(session_context == 0) { + log_error("sr_get_context failed\n"); + return false; + } + + //init context so we can see all the available modules, features, etc + rc = context_init(session_context); + if(rc != 0) { + log_error("context_init() failed\n"); + return false; + } + + /* enable features */ + log_add_verbose(1, "Enabling yang features...\n"); + char **available_features; + int total_available_features; + total_available_features = context_get_features(&available_features); + log_add_verbose(1, "Found total features: %d\n", total_available_features); + for(int i = 0; i < total_available_features; i++) { + log_add_verbose(1, "feature %s: ", available_features[i]); + + if(!context_get_feature_enabled(available_features[i])) { + if(!container_rules_is_excluded_feature(available_features[i])) { + if(context_feature_enable(available_features[i])) { + log_add(1, "enabling... "LOG_COLOR_BOLD_GREEN"done"LOG_COLOR_RESET"\n"); + } + else { + log_error("enabling... failed\n"); + } + } + else { + log_add(1, "excluded in config, skipping\n"); + } + } + else { + log_add(1, "already "LOG_COLOR_BOLD_GREEN"enabled"LOG_COLOR_RESET", skipping.\n"); + } + } + for(int i = 0; i < total_available_features; i++) { + free(available_features[i]); + } + free(available_features); + + sr_disconnect(session_connection); + context_free(); + + log_add_verbose(1, LOG_COLOR_BOLD_GREEN"ntsim successfully initialized Docker container"LOG_COLOR_RESET"\n"); + return true; +} + +static int get_installable_modules(struct installable_module **modules) { + int total = 0; + *modules = 0; + list_yangs("/opt/dev/deploy/yang", modules, &total); + return total; +} + +static void list_yangs(const char *path, struct installable_module **modules, int *total) { + DIR *d; + struct dirent *dir; + d = opendir(path); + if(d) { + while((dir = readdir(d)) != NULL) { + if(dir->d_type == DT_DIR) { + if(strcmp(dir->d_name, ".") != 0 && strcmp(dir->d_name, "..") != 0) + { + char new_path[1024]; + snprintf(new_path, sizeof(new_path), "%s/%s", path, dir->d_name); + list_yangs(new_path, modules, total); + } + } else { + if(strstr(dir->d_name, ".yang") != 0) { + *modules = (struct installable_module *)realloc(*modules, sizeof(struct installable_module) * (*total + 1)); + if(!*modules) { + log_error("allocation failed\n"); + return; + } + + (*modules)[*total].name = (char*)malloc(sizeof(char) * (strlen(dir->d_name) + 1)); + if(!(*modules)[*total].name) { + log_error("allocation failed\n"); + return; + } + strcpy((*modules)[*total].name, dir->d_name); + (*modules)[*total].name[strlen(dir->d_name) - 5] = 0; //extract ".yang" + char *rev = strstr((*modules)[*total].name, "@"); + if(rev) { //extract revision, if exists + *rev = 0; + } + + (*modules)[*total].fullpath = (char*)malloc(sizeof(char) * (strlen(path) + 1 + strlen(dir->d_name) + 1)); + if(!(*modules)[*total].fullpath) { + log_error("allocation failed\n"); + return; + } + sprintf((*modules)[*total].fullpath, "%s/%s", path, dir->d_name); + + (*modules)[*total].installed = false; + (*modules)[*total].submodule = false; + + (*total)++; + } + } + } + closedir(d); + } +} + +static bool container_rules_is_excluded_module(const char *module) { + assert(module); + + for(int i = 0; i < framework_config.docker.excluded_modules_count; i++) { + if(strstr(module, framework_config.docker.excluded_modules[i]) != 0) { + return true; + } + } + + return false; +} + +static bool container_rules_is_excluded_feature(const char *feature) { + assert(feature); + + for(int i = 0; i < framework_config.docker.excluded_features_count; i++) { + if(strstr(feature, framework_config.docker.excluded_features[i]) != 0) { + return true; + } + } + + return false; +} \ No newline at end of file diff --git a/ntsimulator/ntsim-ng/core/container.h b/ntsimulator/ntsim-ng/core/container.h new file mode 100644 index 0000000..56b0029 --- /dev/null +++ b/ntsimulator/ntsim-ng/core/container.h @@ -0,0 +1,24 @@ +/************************************************************************* +* +* Copyright 2020 highstreet technologies GmbH and others +* +* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +* +* 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. +***************************************************************************/ + +#pragma once + +#include +#include + +//init current container. used *only* with --container-init +bool container_self_init(void); diff --git a/ntsimulator/ntsim-ng/core/context.c b/ntsimulator/ntsim-ng/core/context.c index 8019662..be30e9c 100644 --- a/ntsimulator/ntsim-ng/core/context.c +++ b/ntsimulator/ntsim-ng/core/context.c @@ -47,7 +47,7 @@ static bool check_identity_of_type(const struct lys_ident *ident, const struct l static int identity_get_id(const struct lys_ident *ident); int context_init(const struct ly_ctx *ly_ctx) { - log_message(2, "context_init() begin\n"); + log_add_verbose(2, "context_init() begin\n"); identities = 0; identities_size = 0; @@ -55,30 +55,30 @@ int context_init(const struct ly_ctx *ly_ctx) { features = 0; features_size = 0; - log_message(2, "loading modules\n"); + log_add_verbose(2, "loading modules\n"); uint32_t idx = 0; struct lys_module *module; while((module = (struct lys_module *)ly_ctx_get_module_iter(ly_ctx, &idx)) != 0) { - log_message(2, "MODULE %s\n", module->name); - log_message(2, " prefix: %s\n", module->prefix); - log_message(2, " namespace: %s\n", module->ns); - log_message(2, " imports [%d]", module->imp_size); + log_add_verbose(2, "MODULE %s\n", module->name); + log_add_verbose(2, " prefix: %s\n", module->prefix); + log_add_verbose(2, " namespace: %s\n", module->ns); + log_add_verbose(2, " imports [%d]", module->imp_size); if(module->imp_size) { - log_message(2, ": "); + log_add(2, ": "); for(int i = 0; i < module->imp_size; i++) { - log_message(2, "%s(%s), ", module->imp[i].module->name, module->imp[i].module->prefix); + log_add(2, "%s(%s), ", module->imp[i].module->name, module->imp[i].module->prefix); } } - log_message(2, "\n"); - log_message(2, " implemented: %d\n", module->implemented); + log_add(2, "\n"); + log_add_verbose(2, " implemented: %d\n", module->implemented); if(module->implemented) { - log_message(2, " IDENT count: %d\n", module->ident_size); + log_add_verbose(2, " IDENT count: %d\n", module->ident_size); if(module->ident_size) { //add to list of identities identities = (struct lys_ident_with_childcount *)realloc(identities, sizeof(struct lys_ident_with_childcount) * (identities_size + module->ident_size)); if(!identities) { - log_error("bad realloc"); + log_error("bad realloc\n"); return 1; } @@ -88,50 +88,50 @@ int context_init(const struct ly_ctx *ly_ctx) { identities_size++; if(module->ident[i].base_size) { - log_message(2, " IDENT[%d] %s with base %s:%s\n", i, module->ident[i].name, module->ident[i].base[0]->module->name, module->ident[i].base[0]->name); + log_add_verbose(2, " IDENT[%d] %s with base %s:%s\n", i, module->ident[i].name, module->ident[i].base[0]->module->name, module->ident[i].base[0]->name); int id = identity_get_id(module->ident[i].base[0]); if(id != -1) { identities[id].children++; } } else { - log_message(2, " IDENT[%d] %s as base\n", i, module->ident[i].name); + log_add_verbose(2, " IDENT[%d] %s as base\n", i, module->ident[i].name); } } } - log_message(2, " FEATURES count: %d\n", module->features_size); + log_add_verbose(2, " FEATURES count: %d\n", module->features_size); if(module->features_size) { //add to list of features features = (struct features_with_info *)realloc(features, sizeof(struct features_with_info) * (features_size + module->features_size)); if(!features) { - log_error("bad realloc"); + log_error("bad realloc\n"); return 1; } for(int i = 0; i < module->features_size; i++) { asprintf(&features[features_size].name, "%s:%s", module->name, module->features[i].name); features[features_size].enabled = (lys_features_state(module, module->features[i].name) == 1); - log_message(2, " FEATURE[%d] %s iffeature_size=%d enabled=%d\n", i, module->features[i].name, module->features[i].iffeature_size, features[features_size].enabled); + log_add_verbose(2, " FEATURE[%d] %s iffeature_size=%d enabled=%d\n", i, module->features[i].name, module->features[i].iffeature_size, features[features_size].enabled); features_size++; } } } else { - log_message(2, "Module not implemented, skipping...\n"); + log_add_verbose(2, "-> module not implemented, skipping...\n"); } - log_message(2, " ----\n"); + log_add_verbose(2, " ----\n"); } - log_message(2, "context_init() finished\n"); + log_add_verbose(2, "context_init() finished\n"); return 0; } void context_free(void) { - log_message(2, "context_free()... "); + log_add_verbose(2, "context_free()... "); free(identities); identities_size = 0; @@ -139,14 +139,14 @@ void context_free(void) { free(features[i].name); } free(features); - log_message(2, "done\n"); + log_add(2, "done\n"); } int context_get_identity_leafs_of_type(const struct lys_ident *ident, struct lys_ident ***found) { *found = (struct lys_ident **)malloc(sizeof(struct lys_ident *) * identities_size); if(!*found) { - log_error("bad malloc"); + log_error("bad malloc\n"); } int count = 0; @@ -160,7 +160,7 @@ int context_get_identity_leafs_of_type(const struct lys_ident *ident, struct lys } if(count == 0) { - log_error("no identities found"); + log_error("no identities found\n"); } else { *found = (struct lys_ident **)realloc(*found, sizeof(struct lys_ident *) * count); @@ -172,14 +172,14 @@ int context_get_identity_leafs_of_type(const struct lys_ident *ident, struct lys int context_get_features(char ***found_features) { char **ftrs = (char **)malloc(sizeof(char *) * features_size); if(!ftrs) { - log_error("could not alloc"); + log_error("could not alloc\n"); return 0; } for(int i = 0; i < features_size; i++) { ftrs[i] = (char *)malloc(sizeof(char) * (strlen(features[i].name) + 1)); if(!ftrs) { - log_error("could not alloc"); + log_error("could not alloc\n"); return 0; } @@ -252,7 +252,7 @@ bool context_module_install(const char *name, const char *path) { if(file_exists(data_path)) { rc = sr_install_module_data(session_connection, name, 0, data_path, LYD_XML); if(rc != SR_ERR_OK) { - log_message(1, " xml error "); + log_add(1, " xml error "); sr_remove_module(session_connection, name); context_apply_changes(); return false; @@ -264,7 +264,7 @@ bool context_module_install(const char *name, const char *path) { if(file_exists(data_path)) { rc = sr_install_module_data(session_connection, name, 0, data_path, LYD_JSON); if(rc != SR_ERR_OK) { - log_message(1, " json error "); + log_add(1, " json error "); sr_remove_module(session_connection, name); context_apply_changes(); return false; @@ -302,18 +302,18 @@ bool context_apply_changes(void) { /* get connection count */ if((rc = sr_connection_count(&connection_count)) != SR_ERR_OK) { - log_error("sr_connection_count() failed to get connection count"); + log_error("sr_connection_count() failed to get connection count\n"); return false; } if(connection_count) { - log_error("cannot apply changes because of existing connections"); + log_error("cannot apply changes because of existing connections\n"); return false; } if((rc = sr_connect(SR_CONN_ERR_ON_SCHED_FAIL, &session_connection)) != SR_ERR_OK) { if((rc = sr_connect(0, &session_connection)) != SR_ERR_OK) { - log_error("failed to reconnect to sysrepo"); + log_error("failed to reconnect to sysrepo\n"); } return false; } @@ -321,7 +321,7 @@ bool context_apply_changes(void) { /* get context */ session_context = (struct ly_ctx *)sr_get_context(session_connection); if(session_context == 0) { - log_error("sr_get_context failed"); + log_error("sr_get_context failed\n"); return false; } @@ -334,7 +334,7 @@ bool context_yang_is_module(const char *path) { bool ret = false; struct ly_ctx *ctx = ly_ctx_new(0, 0); if(!ctx) { - log_error("ly_ctx_new failed"); + log_error("ly_ctx_new failed\n"); } char *searchpath = strdup(path); diff --git a/ntsimulator/ntsim-ng/core/datastore/generate.c b/ntsimulator/ntsim-ng/core/datastore/generate.c new file mode 100644 index 0000000..1fa255c --- /dev/null +++ b/ntsimulator/ntsim-ng/core/datastore/generate.c @@ -0,0 +1,1185 @@ +/************************************************************************* +* +* Copyright 2020 highstreet technologies GmbH and others +* +* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +* +* 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. +***************************************************************************/ + +#define _GNU_SOURCE + +#include "generate.h" +#include "utils/log_utils.h" +#include "utils/rand_utils.h" +#include "utils/type_utils.h" +#include "utils/sys_utils.h" +#include +#include +#include +#include + +#include "core/session.h" +#include "core/framework.h" + +#include "schema.h" + +#define LEAFREF_TOTAL_TEST_ENTRIES 11 + +typedef struct { + int init; + + char *xpath; + + const struct lys_module **modules; + int mod_count; + + struct lyd_node *operational; + struct lyd_node *running; +} generate_instance_t; + +typedef struct { + struct lyd_node *operational; + struct lyd_node *running; + bool late_resolving; + + int late_resolve_count; + struct lys_node **late_resolve_schema; + struct lyd_node **late_resolve_parent_o; + struct lyd_node **late_resolve_parent_r; + generate_instance_t **late_resolve_instance; +} generate_job_t; + +static int generate_recursive(generate_job_t *job, generate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r); +static int generate_add_leaf(generate_job_t *job, generate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r); + +static int generate_late_resolve(generate_job_t *job); +static int generate_validate(generate_instance_t *instance, int count); +static int generate_export_data(generate_job_t *job, const char *running_filename, const char *operational_filename); + +static int instance_add_module(generate_instance_t *instance, const struct lys_module *module); +static int generate_late_resolve_add_leaf(generate_job_t *job, generate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r); +static const char* leafref_test_val(int index); + +static int generate_get_instance_count(const char *path); +static char *generate_get_restrict_schema(const char *path); + +struct lyd_node *datastore_load_external(const char *filename, bool operational) { + + struct lyd_node *data_tree = 0; + + if(filename) { + if(file_exists(filename)) { + LYD_FORMAT format = LYD_JSON; + if(strstr(filename, ".xml") != 0) { + format = LYD_XML; + } + + int flags = LYD_OPT_TRUSTED | LYD_OPT_NOSIBLINGS; + if(operational) { + flags |= LYD_OPT_DATA; + } + else { + flags |= LYD_OPT_CONFIG; + } + + data_tree = lyd_parse_path(session_context, filename, format, flags); + if(data_tree == 0) { + log_error("lyd_parse_path failed\n"); + } + } + } + + return data_tree; +} + +int datastore_generate_data(const char *running_filename, const char *operational_filename) { + assert_session(); + + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"datastore_generate_data() begin\n"LOG_COLOR_RESET); + + generate_job_t job; + job.operational = 0; + job.running = 0; + job.late_resolve_count = 0; + job.late_resolve_instance = 0; + job.late_resolve_schema = 0; + job.late_resolve_parent_o = 0; + job.late_resolve_parent_r = 0; + job.late_resolving = false; + + + //load pre-populated data + for(int i = 0; i < framework_config.datastore_populate.preg_running_count; i++) { + char *filename = framework_config.datastore_populate.preg_running[i]; + struct lyd_node *data = datastore_load_external(filename, false); + if(data == 0) { + log_add_verbose(2, "datastore_load_external() could not load %s\n", filename); + } + else { + log_add_verbose(1, "loaded into running %s (%s)\n", filename, data->schema->module->name); + if(job.running) { + int rc = lyd_merge(job.running, data, 0); + if(rc != 0) { + log_error("lyd_merge failed\n"); + } + + lyd_free_withsiblings(data); + } + else { + job.running = data; + } + } + + //also load as operational + data = datastore_load_external(filename, true); + if(data == 0) { + log_add_verbose(2, "datastore_load_external() could not load %s\n", filename); + } + else { + log_add_verbose(1, "loaded into operational %s (%s)\n", filename, data->schema->module->name); + if(job.operational) { + int rc = lyd_merge(job.operational, data, 0); + if(rc != 0) { + log_error("lyd_merge failed\n"); + } + + lyd_free_withsiblings(data); + } + else { + job.operational = data; + } + } + } + + for(int i = 0; i < framework_config.datastore_populate.preg_operational_count; i++) { + char *filename = framework_config.datastore_populate.preg_operational[i]; + struct lyd_node *data = datastore_load_external(filename, true); + if(data == 0) { + log_add_verbose(2, "datastore_load_external() could not load %s\n", filename); + } + else { + log_add_verbose(1, "loaded into operational %s (%s)\n", filename, data->schema->module->name); + if(job.operational) { + int rc = lyd_merge(job.operational, data, 0); + if(rc != 0) { + log_error("lyd_merge failed\n"); + } + + lyd_free_withsiblings(data); + } + else { + job.operational = data; + } + } + } + + char **xpaths = 0; + int instance_count = datastore_schema_get_xpaths(&xpaths); + if(instance_count < 0) { + log_error("datastore_schema_get_xpaths failed\n"); + return NTS_ERR_FAILED; + } + + //exclude pre-populated modules + struct lyd_node *elem; + LY_TREE_FOR(job.operational, elem) { + for(int i = 0; i < instance_count; i++) { + if(strstr(xpaths[i], elem->schema->module->name) == (xpaths[i] + 1)) { //xpaths[i] is "/module:container" + free(xpaths[i]); + + instance_count--; + for(int j = i; j < instance_count; j++) { + xpaths[j] = xpaths[j + 1]; + } + + break; + } + } + } + + generate_instance_t *instance = (generate_instance_t *)malloc(sizeof(generate_instance_t) * instance_count); + if(!instance) { + log_error("bad malloc\n"); + for(int i = 0; i < instance_count; i++) { + free(xpaths[i]); + } + free(xpaths); + return NTS_ERR_FAILED; + } + + if(framework_config.datastore_populate.random_generation_enabled) { + //RANDOM generate everything + for(int i = 0; i < instance_count; i++) { + log_add_verbose(1, "generating "LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET" data...\n", xpaths[i]); + + struct lys_node *schema_node = (struct lys_node *)ly_ctx_get_node(session_context, 0, xpaths[i], 0); + if(schema_node == 0) { + log_error("ly_ctx_get_node failed for %s\n", xpaths[i]); + return NTS_ERR_FAILED; + } + + if(schema_node == 0) { + log_add_verbose(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET); + log_error("ly_ctx_get_node failed for %s\n", xpaths[i]); + return NTS_ERR_FAILED; + } + + if(!schema_node->module->implemented) { + log_add_verbose(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET); + log_error("module is not implemented for %s\n", xpaths[i]); + return NTS_ERR_FAILED; + } + + if((schema_node->flags & LYS_STATUS_DEPRC) != 0) { + log_add_verbose(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET); + log_error("module is deprecated for %s\n", xpaths[i]); + return NTS_ERR_FAILED; + } + + //populate current instance vals + instance[i].init = 0; + instance[i].xpath = strdup(xpaths[i]); + instance[i].modules = 0; + instance[i].mod_count = 0; + instance[i].operational = 0; + instance[i].running = 0; + + //do the actual population + int rc = generate_recursive(&job, &instance[i], schema_node, 0, 0); + if(rc != NTS_ERR_OK) { + log_error("generate_recursive failed instance %d with xpath %s\n", i, instance[i].xpath); + return rc; + } + } + + //link everything so we would be able to find everything in late-resolve + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"datastore_generate_data() done generating, now linking... (%d root nodes)\n"LOG_COLOR_RESET, instance_count); + for(int i = 0; i < instance_count; i++) { + + if(instance[i].operational) { + if(job.operational) { + int rc = lyd_insert_sibling(&job.operational, instance[i].operational); + if(rc != 0) { + log_error("lyd_insert_sibling\n"); + return NTS_ERR_FAILED; + } + } + else { + job.operational = instance[i].operational; + } + } + + if(instance[i].running) { + if(job.running) { + int rc = lyd_insert_sibling(&job.running, instance[i].running); + if(rc != 0) { + log_error("lyd_insert_sibling\n"); + return NTS_ERR_FAILED; + } + } + else { + job.running = instance[i].running; + } + } + } + + //late-resolve + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"datastore_generate_data() starting late-resolve process...\n"LOG_COLOR_RESET); + if(job.late_resolve_count) { + int rc = generate_late_resolve(&job); + if(rc != NTS_ERR_OK) { + log_error("generate_late_resolve failed\n"); + return rc; + } + } + + //validate data and remove invalid nodes + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"datastore_generate_data() validating\n"LOG_COLOR_RESET); + int rc = generate_validate(instance, instance_count); + if(rc != NTS_ERR_OK) { + log_error("generate_validate failed\n"); + return rc; + } + } + + //export generated data + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"datastore_generate_data() exporting data\n"LOG_COLOR_RESET); + int rc = generate_export_data(&job, running_filename, operational_filename); + if(rc != NTS_ERR_OK) { + log_error("generate_export_data failed\n"); + return rc; + } + + //cleanup + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"datastore_generate_data() cleaning up... "LOG_COLOR_RESET); + for(int i = 0; i < instance_count; i++) { + log_add(1, "%d ", i); + + free(instance[i].modules); + free(instance[i].xpath); + + free(xpaths[i]); + } + free(xpaths); + free(job.late_resolve_instance); + free(job.late_resolve_schema); + free(job.late_resolve_parent_o); + free(job.late_resolve_parent_r); + + lyd_free_withsiblings(job.operational); + lyd_free_withsiblings(job.running); + + log_add(1, "\n"); + log_add_verbose(1, LOG_COLOR_BOLD_GREEN"datastore_generate_data() finished\n"LOG_COLOR_RESET); + + return NTS_ERR_OK; +} + +int datastore_generate_external(void) { + char cmd[512]; + sprintf(cmd, "%s --generate", framework_arguments.argv[0]); + system(cmd); + return NTS_ERR_OK; +} + + +static int generate_recursive(generate_job_t *job, generate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r) { + assert(job); + assert(schema); + assert(instance); + + char *resolved_schema_path = lys_path(schema, LYS_PATH_FIRST_PREFIX); + bool schema_operational = ((schema->flags & LYS_CONFIG_W) == 0); + + generate_recursive_rerun_switch: + switch(schema->nodetype) { + //for container, just add it to the xpath, and iterate it's childeren to further traverse the tree + case LYS_CONTAINER: { + //add container + + struct lyd_node *new_parent_o = parent_o; + struct lyd_node *new_parent_r = parent_r; + + new_parent_o = lyd_new(parent_o, schema->module, schema->name); + if(!new_parent_o) { + log_error("error creating container operational -> %s\n", schema->name); + log_error("ly_error: %s\n", ly_errmsg(session_context)); + return NTS_ERR_FAILED; + } + + if(!schema_operational) { + new_parent_r = lyd_new(parent_r, schema->module, schema->name); + if(!new_parent_r) { + log_error("error creating container running -> %s\n", schema->name); + log_error("ly_error: %s\n", ly_errmsg(session_context)); + return NTS_ERR_FAILED; + } + } + + if(!instance->init) { + instance->init = true; + instance->operational = new_parent_o; + instance->running = new_parent_r; + } + + char mandatory = ' '; + if((schema->flags & LYS_MAND_TRUE) != 0) { + mandatory = 'M'; + } + if((schema->parent) && (schema->parent->nodetype == LYS_CASE)) { + if((schema->parent->flags & LYS_MAND_TRUE) != 0) { + mandatory = 'M'; + } + } + bool node_operational = ((schema->flags & LYS_CONFIG_W) == 0); + char *xpath = lyd_path(new_parent_o); + log_add_verbose(1, LOG_COLOR_BOLD_MAGENTA"[%15s] "LOG_COLOR_BOLD_YELLOW"[%c%c]"LOG_COLOR_RESET" %s\n", "CONTAINER", node_operational ? 'O' : 'R', mandatory, xpath); + free(xpath); + + int rc = instance_add_module(instance, schema->module); + if(rc != NTS_ERR_OK) { + log_error("instance_add_module failed\n"); + return rc; + } + + struct lys_node *child = 0; + LY_TREE_FOR(schema->child, child) { + int rc = generate_recursive(job, instance, child, new_parent_o, new_parent_r); + if(rc != NTS_ERR_OK) { + log_error("generate_recursive failed\n"); + return rc; + } + } + } break; + + //choice does not appear into the data path. get all the avalable choices, and choose a random one + case LYS_CHOICE: { + int choice_no = 0; + struct lys_node_case *choice = (struct lys_node_case *)schema->child; + while(choice) { + choice_no++; + choice = (struct lys_node_case *)choice->next; + } + + //select a random choice + choice_no = rand_uint16() % choice_no; + + int i = 0; + choice = (struct lys_node_case *)schema->child; + while(i < choice_no) { + i++; + choice = (struct lys_node_case *)choice->next; + } + + //after the choice was made, rerun the adding without other tree-searching (will run into a CASE) + schema = (struct lys_node *)choice; + goto generate_recursive_rerun_switch; + } break; + + //the actual "case" is this node's child, so we skip directly to that + case LYS_CASE: + //case contains mandatory + if(schema->child) { + schema = schema->child; + goto generate_recursive_rerun_switch; + } + else { + //blank case + return NTS_ERR_OK; + } + break; + + //populate a list + case LYS_LIST: { + //get min-max for current list + struct lys_node_list *list = (struct lys_node_list *)schema; + int min_added = list->min ? list->min : 1; + int max_added = list->max ? list->max : 65536; + + int populating_times = generate_get_instance_count(resolved_schema_path); + if(populating_times != 0) { + if(min_added < populating_times) { + min_added = populating_times; + } + if(min_added > max_added) { + min_added = max_added; + log_error("min-elements exceeds max-elements for path %s. truncated to %d\n", resolved_schema_path, max_added); + } + log_add_verbose(2, "populating %d times list '%s'\n", min_added, resolved_schema_path); + + //populate node with the intended number of values + while(min_added) { + //add list + + struct lyd_node *new_parent_o = parent_o; + struct lyd_node *new_parent_r = parent_r; + + new_parent_o = lyd_new(parent_o, schema->module, schema->name); + if(!new_parent_o) { + log_error("error creating list operational -> %s\n", schema->name); + log_error("ly_error: %s\n", ly_errmsg(session_context)); + return NTS_ERR_FAILED; + } + + if(!schema_operational) { + new_parent_r = lyd_new(parent_r, schema->module, schema->name); + if(!new_parent_r) { + log_error("error creating container running -> %s\n", schema->name); + log_error("ly_error: %s\n", ly_errmsg(session_context)); + return NTS_ERR_FAILED; + } + } + + if(!instance->init) { + instance->init = true; + instance->operational = new_parent_o; + instance->running = new_parent_r; + } + + char mandatory = ' '; + if((schema->flags & LYS_MAND_TRUE) != 0) { + mandatory = 'M'; + } + if((schema->parent) && (schema->parent->nodetype == LYS_CASE)) { + if((schema->parent->flags & LYS_MAND_TRUE) != 0) { + mandatory = 'M'; + } + } + bool node_operational = ((schema->flags & LYS_CONFIG_W) == 0); + char *xpath = lyd_path(new_parent_o); + log_add_verbose(1, LOG_COLOR_BOLD_MAGENTA"[%15s] "LOG_COLOR_BOLD_YELLOW"[%c%c]"LOG_COLOR_RESET" %s\n", "LIST", node_operational ? 'O' : 'R', mandatory, xpath); + free(xpath); + + int rc = instance_add_module(instance, schema->module); + if(rc != NTS_ERR_OK) { + log_error("instance_add_module failed\n"); + return rc; + } + + //populate all list elements below in the tree + struct lys_node *child = 0; + LY_TREE_FOR(schema->child, child) { + int rc = generate_recursive(job, instance, child, new_parent_o, new_parent_r); + if(rc != NTS_ERR_OK) { + log_error("generate_recursive failed\n"); + return rc; + } + } + + min_added--; + } + } + else { + log_add_verbose(2, "not populating list '%s'\n", resolved_schema_path); + } + } break; + + //populate the leaf + case LYS_LEAF: { + if(generate_add_leaf(job, instance, schema, parent_o, parent_r) != NTS_ERR_OK) { + return NTS_ERR_FAILED; + } + } break; + + //leaflist is treated the same as a LEAF, but with min/max characteristics of a LIST + case LYS_LEAFLIST: { + //get min-max for the current leaflist + struct lys_node_leaflist *list = (struct lys_node_leaflist *)schema; + int min_added = list->min ? list->min : 1; + int max_added = list->max ? list->max : 65536; + + int populating_times = generate_get_instance_count(resolved_schema_path); + if(populating_times != 0) { + if(min_added < populating_times) { + min_added = populating_times; + } + if(min_added > max_added) { + min_added = max_added; + log_error("min-elements exceeds max-elements for path %s truncated to %d\n", resolved_schema_path, max_added); + } + log_add_verbose(2, "populating %d times leaflist '%s'\n", min_added, resolved_schema_path); + + //add the leafs + while(min_added) { + if(generate_add_leaf(job, instance, schema, parent_o, parent_r) != NTS_ERR_OK) { + return NTS_ERR_FAILED; + } + min_added--; + } + } + else { + log_add_verbose(2, "not populating leaflist '%s'\n", resolved_schema_path); + } + } break; + + case LYS_ACTION: + case LYS_INPUT: + case LYS_OUTPUT: + case LYS_NOTIF: + //don't do anything, since we don't want to add this or go further down the tree when we meet them + break; + + //other node types (grouping, uses, augment, etc just traverse) + default: + log_add_verbose(1, "[%15s] %s\n", typeutils_yang_nodetype_to_str(schema->nodetype), resolved_schema_path); + + //traverse the tree down for any other node types, without adding anything to the path + struct lys_node *child = 0; + LY_TREE_FOR(schema->child, child) { + int rc = generate_recursive(job, instance, child, parent_o, parent_r); + if(rc != NTS_ERR_OK) { + return rc; + } + } + break; + } + + free(resolved_schema_path); + + return NTS_ERR_OK; +} + +static int generate_add_leaf(generate_job_t *job, generate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r) { + assert_session(); + assert(job); + assert(schema); + assert(parent_o); + + int rc = instance_add_module(instance, schema->module); + if(rc != NTS_ERR_OK) { + log_error("bad schema_instance_add module\n"); + return rc; + } + + struct lys_type *type = &((struct lys_node_leaf *)schema)->type; + + char *data_xpath = lyd_path(parent_o); + data_xpath = (char *)realloc(data_xpath, sizeof(char) * (strlen(data_xpath) + 1 + strlen(schema->name) + 1)); + if(!data_xpath) { + log_error("lyd_path failed\n"); + return NTS_ERR_FAILED; + } + strcat(data_xpath, "/"); + strcat(data_xpath, schema->name); + + //check whether the value is MANDATORY or not (for logging purposes) + char mandatory = ' '; + if((schema->flags & LYS_MAND_TRUE) != 0) { + mandatory = 'M'; + } + + if((schema->parent) && (schema->parent->nodetype == LYS_CASE)) { + if((schema->parent->flags & LYS_MAND_TRUE) != 0) { + mandatory = 'M'; + } + } + + bool node_operational = ((schema->flags & LYS_CONFIG_W) == 0); + log_add_verbose(1, LOG_COLOR_BOLD_MAGENTA"[%15s] "LOG_COLOR_BOLD_YELLOW"[%c%c]"LOG_COLOR_RESET" %s <-- ", typeutils_yang_type_to_str(type->base), node_operational ? 'O' : 'R', mandatory, data_xpath); + free(data_xpath); + + + char *resolved_schema_path = lys_path(schema, LYS_PATH_FIRST_PREFIX); + char *value = generate_get_restrict_schema(resolved_schema_path); + free(resolved_schema_path); + + generate_add_leaf_rerun_switch: + switch(type->base) { + case LY_TYPE_UNION: + if((type->info.uni.count == 0) && (type->der != 0)) { + type = &type->der->type; + } + + type = &type->info.uni.types[0]; + goto generate_add_leaf_rerun_switch; + break; + + case LY_TYPE_INST: { + struct lyd_node *parent = parent_o; + while(parent->parent) { + parent = parent->parent; + } + + if(value == 0) { + value = lyd_path(parent); + } + + goto generate_add_leaf_actual_add; + } break; + + case LY_TYPE_EMPTY: + if(rand_bool()) { //if present, add it + log_add(1, LOG_COLOR_CYAN"present"LOG_COLOR_RESET"\n"); + goto generate_add_leaf_actual_add; + } + else { + log_add(1, LOG_COLOR_CYAN"empty"LOG_COLOR_RESET"\n"); + return NTS_ERR_OK; + } + break; + + case LY_TYPE_LEAFREF: { + if(value == 0) { + int index = 0; + struct lyd_node *new_node = 0; + while((new_node == 0) && (index < LEAFREF_TOTAL_TEST_ENTRIES)) { + new_node = lyd_new_leaf(parent_o, schema->module, schema->name, leafref_test_val(index)); + index++; + } + + if(new_node == 0) { + log_error("error on lyd_new_leaf schema %s. didn't work with any temp val\n", schema->name); + return NTS_ERR_FAILED; + } + + //based on the new_node's path, try to find elements of relative path for the leafref + struct ly_set *set = lyd_find_path(new_node, type->info.lref.path); + lyd_free(new_node); + + if(set && set->number) { + //choose a random schema and get its value + static int set_number = 0; //checkAL aici trebuia oare random ? + set_number++; + if(set_number >= set->number) { + set_number = 0; + } + asprintf(&value, "%s", ((struct lyd_node_leaf_list *)set->set.d[set_number])->value_str); + if(!value) { + log_error("bad asprintf\n"); + return NTS_ERR_FAILED; + } + + int rc = instance_add_module(instance, set->set.d[set_number]->schema->module); + if(rc != NTS_ERR_OK) { + log_error("bad schema_instance_add module\n"); + return rc; + } + + ly_set_free(set); + + goto generate_add_leaf_actual_add; + } + else { + //adding to late-resolve list, as we don't have any nodes in the leafref path + int rc = generate_late_resolve_add_leaf(job, instance, schema, parent_o, parent_r); + if(rc != NTS_ERR_OK) { + return rc; + } + + if(!job->late_resolving) { + log_add(1, LOG_COLOR_BOLD_YELLOW"added to late-resolve list...\n"LOG_COLOR_RESET); + } + else { + log_add(1, LOG_COLOR_BOLD_YELLOW"REadded to late-resolve list...\n"LOG_COLOR_RESET); + } + + return NTS_ERR_OK; + } + } + } break; + + default: + if(value == 0) { + value = rand_get_populate_value(type); + } + goto generate_add_leaf_actual_add; + break; + } + + generate_add_leaf_actual_add: { + //add schema to operational + struct lyd_node *new_node = lyd_new_leaf(parent_o, schema->module, schema->name, value); + if(new_node == 0) { + log_error("error on lyd_new_leaf operational: %s\n", ly_errmsg(session_context)); + return NTS_ERR_FAILED; + } + + //print out the value + if(value) { + log_add(1, LOG_COLOR_CYAN"'%s'"LOG_COLOR_RESET"\n", value); + } + else { + log_add(1, "\n"); + } + + //if it fits the case, add it also to running + if(!node_operational) { + struct lyd_node *new_node = lyd_new_leaf(parent_r, schema->module, schema->name, value); + if(new_node == 0) { + log_error("error on lyd_new_leaf running: %s\n", ly_errmsg(session_context)); + return NTS_ERR_FAILED; + } + } + + free(value); + } + + return NTS_ERR_OK; +} + + + +static int generate_late_resolve(generate_job_t *job) { + assert(job); + + job->late_resolving = true; + + int prev_count = job->late_resolve_count + 1; + + while(prev_count > job->late_resolve_count) { + int late_resolve_count = job->late_resolve_count; + struct lys_node **late_resolve_schema = job->late_resolve_schema; + struct lyd_node **late_resolve_parent_o = job->late_resolve_parent_o; + struct lyd_node **late_resolve_parent_r = job->late_resolve_parent_r; + generate_instance_t **late_resolve_instance = job->late_resolve_instance; + + job->late_resolve_count = 0; + job->late_resolve_schema = 0; + job->late_resolve_parent_o = 0; + job->late_resolve_parent_r = 0; + job->late_resolve_instance = 0; + + prev_count = late_resolve_count; + + for(int i = 0; i < late_resolve_count; i++) { + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"late-populating "LOG_COLOR_RESET": "); + int rc = generate_add_leaf(job, late_resolve_instance[i], late_resolve_schema[i], late_resolve_parent_o[i], late_resolve_parent_r[i]); + if(rc != NTS_ERR_OK) { + log_error("generate_add_leaf failed on late-resolve\n"); + return rc; + } + } + + free(late_resolve_schema); + free(late_resolve_parent_o); + free(late_resolve_parent_r); + free(late_resolve_instance); + } + job->late_resolving = false; + + if(prev_count != 0) { + log_error("generate_late_resolve detected circular loop!\n"); + } + + return NTS_ERR_OK; +} + +static int generate_validate(generate_instance_t *instance, int count) { + assert(instance); + + int rc = 0; + int commit_ok = NTS_ERR_OK; + + for(int i = 0; i < count; i++) { + if(instance[i].operational) { + log_add_verbose(2, "available modules:"); + for(int j = 0; j < instance[i].mod_count; j++) { + log_add(2, " %s", instance[i].modules[j]->name); + } + log_add(2, "\n"); + log_add_verbose(1, "validating OPERATIONAL for [%d] : %s... ", i, instance[i].xpath); + + int solved_instance_errors = 1; + int solved_errors = 0; + bool success = false; + while(instance[i].operational && solved_instance_errors) { + solved_instance_errors = 0; + rc = lyd_validate_modules(&instance[i].operational, instance[i].modules, instance[i].mod_count, LYD_OPT_DATA, 0); + if(rc == 0) { + log_add(1, LOG_COLOR_BOLD_GREEN"success (%d)\n"LOG_COLOR_RESET, solved_errors); + success = true; + break; + } + else { + log_add(2, "\n"); + + struct ly_err_item *err = ly_err_first(session_context); + while(err) { + if((err->vecode == LYVE_NOWHEN) || (err->vecode == LYVE_NOMUST) || (err->vecode == LYVE_NOCONSTR) || (err->vecode == LYVE_NOLEAFREF) || (err->vecode == LYVE_NOMIN) || (err->vecode == LYVE_INVAL)) { + struct ly_set *set = lyd_find_path(instance[i].operational, err->path); + if(set && set->number) { + log_add_verbose(2, "operational error code %d on path %s with msg %s\n", err->vecode, err->path, err->msg); + log_add_verbose(2, LOG_COLOR_BOLD_RED" [WHEN-DELETE O]"LOG_COLOR_RESET" %s ... ", err->path); + + bool mandatory = false; + if((set->set.d[0]->schema->flags & LYS_MAND_TRUE) != 0) { + mandatory = true; + } + + if((set->set.d[0]->schema->parent) && (set->set.d[0]->schema->parent->nodetype == LYS_CASE)) { + if((set->set.d[0]->schema->parent->flags & LYS_MAND_TRUE) != 0) { + mandatory = true; + } + } + + if((set->set.d[0]->dflt != 0) || (lys_is_key((const struct lys_node_leaf *)set->set.d[0]->schema, 0)) || (mandatory) || (err->vecode == LYVE_NOMIN)) { + //delete whole parent + log_add(2, "deleted parent : %s\n", lyd_path(set->set.d[0]->parent)); + struct lyd_node *p = set->set.d[0]->parent; + lyd_free_withsiblings(set->set.d[0]); + lyd_free(p); + if(p == instance[i].operational) { + log_add_verbose(1, "instance became empty "LOG_COLOR_BOLD_GREEN"success\n"LOG_COLOR_RESET); + success = true; + instance[i].operational = 0; + break; + } + } + else { + //delete THIS node only + lyd_free(set->set.d[0]); + log_add(2, "deleted\n"); + if(set->set.d[0] == instance[i].operational) { + log_add_verbose(1, "instance became empty "LOG_COLOR_BOLD_GREEN"success\n"LOG_COLOR_RESET); + success = true; + instance[i].operational = 0; + break; + } + } + solved_instance_errors++; + + ly_set_free(set); + } + } + else if((err->vecode != 0) && (err->vecode != 29)) { + log_add_verbose(2, "operational error code %d on path %s with msg %s\n", err->vecode, err->path, err->msg); + } + + err = err->next; + } + ly_err_clean(session_context, 0); + } + + solved_errors += solved_instance_errors; + } + + if(!success) { + if(!solved_errors) { + log_add(1, LOG_COLOR_BOLD_YELLOW"failed"LOG_COLOR_RESET"\n%s\n", ly_errmsg(session_context)); + } + else { + log_add(1, LOG_COLOR_BOLD_YELLOW"partially solved (%d)"LOG_COLOR_RESET"\n", solved_errors); + } + } + } + + if(instance[i].running) { + log_add_verbose(1, "validating RUNNING... for [%d] : %s... ", i, instance[i].xpath); + + int solved_instance_errors = 1; + int solved_errors = 0; + bool success = false; + while(instance[i].running && solved_instance_errors) { + solved_instance_errors = 0; + rc = lyd_validate_modules(&instance[i].running, instance[i].modules, instance[i].mod_count, LYD_OPT_CONFIG, 0); + if(rc == 0) { + log_add(1, LOG_COLOR_BOLD_GREEN"success (%d)\n"LOG_COLOR_RESET, solved_errors); + success = true; + break; + } + else { + log_add(2, "\n"); + + struct ly_err_item *err = ly_err_first(session_context); + while(err) { + if((err->vecode == LYVE_NOWHEN) || (err->vecode == LYVE_NOMUST) || (err->vecode == LYVE_NOCONSTR) || (err->vecode == LYVE_NOLEAFREF) || (err->vecode == LYVE_NOMIN) || (err->vecode == LYVE_INVAL)) { + struct ly_set *set = lyd_find_path(instance[i].running, err->path); + if(set && set->number) { + log_add_verbose(2, "running error code %d on path %s with msg %s\n", err->vecode, err->path, err->msg); + log_add_verbose(2, LOG_COLOR_BOLD_RED" [WHEN-DELETE R]"LOG_COLOR_RESET" %s ... ", err->path); + + bool mandatory = false; + if((set->set.d[0]->schema->flags & LYS_MAND_TRUE) != 0) { + mandatory = true; + } + + if((set->set.d[0]->schema->parent) && (set->set.d[0]->schema->parent->nodetype == LYS_CASE)) { + if((set->set.d[0]->schema->parent->flags & LYS_MAND_TRUE) != 0) { + mandatory = true; + } + } + + if((set->set.d[0]->dflt != 0) || (lys_is_key((const struct lys_node_leaf *)set->set.d[0]->schema, 0)) || (mandatory) || (err->vecode == LYVE_NOMIN)) { + //delete whole parent + log_add(2, "deleted parent : %s\n", lyd_path(set->set.d[0]->parent)); + struct lyd_node *p = set->set.d[0]->parent; + lyd_free_withsiblings(set->set.d[0]); + lyd_free(p); + + if(p == instance[i].running) { + log_add_verbose(1, "instance became empty "LOG_COLOR_BOLD_GREEN"success\n"LOG_COLOR_RESET); + success = true; + instance[i].running = 0; + break; + } + } + else { + //delete THIS node only + lyd_free(set->set.d[0]); + log_add(2, "deleted\n"); + if(set->set.d[0] == instance[i].running) { + log_add_verbose(1, "instance became empty "LOG_COLOR_BOLD_GREEN"success\n"LOG_COLOR_RESET); + success = true; + instance[i].running = 0; + break; + } + } + solved_instance_errors++; + + ly_set_free(set); + } + } + else if((err->vecode != 0) && (err->vecode != 29)) { + log_add_verbose(2, "running error code %d on path %s with msg %s\n", err->vecode, err->path, err->msg); + } + + err = err->next; + } + ly_err_clean(session_context, 0); + } + + solved_errors += solved_instance_errors; + } + + if(!success) { + if(!solved_errors) { + log_add(1, LOG_COLOR_BOLD_YELLOW"failed"LOG_COLOR_RESET"\n%s\n", ly_errmsg(session_context)); + } + else { + log_add(1, LOG_COLOR_BOLD_YELLOW"partially solved (%d)"LOG_COLOR_RESET"\n", solved_errors); + } + } + } + } + + return commit_ok; +} + +static int generate_export_data(generate_job_t *job, const char *running_filename, const char *operational_filename) { + assert(job); + + if(job->operational) { + if(lyd_print_path(operational_filename, job->operational, LYD_JSON, LYP_FORMAT | LYP_WITHSIBLINGS) != 0) { + log_error("lyd_print_path failed for operational\n"); + return NTS_ERR_FAILED; + } + } + + if(job->running) { + if(lyd_print_path(running_filename, job->running, LYD_JSON, LYP_FORMAT | LYP_WITHSIBLINGS) != 0) { + log_error("lyd_print_path failed for running\n"); + return NTS_ERR_FAILED; + } + } + + return NTS_ERR_OK; +} + +static int instance_add_module(generate_instance_t *instance, const struct lys_module *module) { + assert(module); + assert(instance); + + for(int i = 0; i < instance->mod_count; i++) { + if(instance->modules[i] == module) { + return NTS_ERR_OK; + } + } + + instance->modules = (const struct lys_module **)realloc(instance->modules, sizeof(const struct lys_module *) * (instance->mod_count + 1)); + if(!instance->modules) { + log_error("bad realloc\n"); + return NTS_ERR_FAILED; + } + instance->modules[instance->mod_count] = module; + instance->mod_count++; + + return NTS_ERR_OK; +} + +static int generate_late_resolve_add_leaf(generate_job_t *job, generate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r) { + assert(job); + assert(instance); + + job->late_resolve_schema = (struct lys_node **)realloc(job->late_resolve_schema, (job->late_resolve_count + 1) * sizeof(struct lys_node *)); + if(!job->late_resolve_schema) { + log_error("bad realloc\n"); + return NTS_ERR_FAILED; + } + job->late_resolve_schema[job->late_resolve_count] = schema; + + job->late_resolve_parent_o = (struct lyd_node **)realloc(job->late_resolve_parent_o, (job->late_resolve_count + 1) * sizeof(struct lyd_node *)); + if(!job->late_resolve_parent_o) { + log_error("bad realloc\n"); + return NTS_ERR_FAILED; + } + job->late_resolve_parent_o[job->late_resolve_count] = parent_o; + + job->late_resolve_parent_r = (struct lyd_node **)realloc(job->late_resolve_parent_r, (job->late_resolve_count + 1) * sizeof(struct lyd_node *)); + if(!job->late_resolve_parent_r) { + log_error("bad realloc\n"); + return NTS_ERR_FAILED; + } + job->late_resolve_parent_r[job->late_resolve_count] = parent_r; + + job->late_resolve_instance = (generate_instance_t **)realloc(job->late_resolve_instance, (job->late_resolve_count + 1) * sizeof(generate_instance_t *)); + if(!job->late_resolve_instance) { + log_error("bad realloc\n"); + return NTS_ERR_FAILED; + } + job->late_resolve_instance[job->late_resolve_count] = instance; + + job->late_resolve_count++; + + return NTS_ERR_OK; +} + +static const char* leafref_test_val(int index) { + switch(index) { + case 0: + return "1"; + break; + + case 1: + return "1.1.1.1"; + break; + + case 2: + return "Fd:4D:63:A5:21:C5"; + break; + + case 3: + return ""; + break; + + case 4: + return "::1"; + break; + + case 5: + return "false"; + break; + + case 6: + return "TDD"; + break; + + case 7: + return "NR"; + break; + + case 8: + return "best-effort"; + break; + + case 9: + return "yes-fault:o-ran-sc-alarm-type"; + break; + + case 10: + return ""; + break; + + default: + log_error("index out of bounds\n"); + return 0; + break; + } +} + +static int generate_get_instance_count(const char *path) { + assert(path); + + for(int i = 0; i < framework_config.datastore_generate.custom_list_instances_count; i++) { + if(strcmp(path, framework_config.datastore_generate.custom_list_instances[i].path) == 0) { + return framework_config.datastore_generate.custom_list_instances[i].count; + } + } + return framework_config.datastore_generate.default_list_instances; +} + +static char *generate_get_restrict_schema(const char *path) { + assert(path); + char *ret = 0; + + for(int i = 0; i < framework_config.datastore_generate.restrict_schema_count; i++) { + if(strcmp(path, framework_config.datastore_generate.restrict_schema[i].path) == 0) { + ret = strdup(framework_config.datastore_generate.restrict_schema[i].values[framework_config.datastore_generate.restrict_schema[i].index]); + framework_config.datastore_generate.restrict_schema[i].index++; + if(framework_config.datastore_generate.restrict_schema[i].index >= framework_config.datastore_generate.restrict_schema[i].values_count) { + framework_config.datastore_generate.restrict_schema[i].index = 0; + } + break; + } + } + + return ret; +} diff --git a/ntsimulator/ntsim-ng/core/datastore/generate.h b/ntsimulator/ntsim-ng/core/datastore/generate.h new file mode 100644 index 0000000..f0b4208 --- /dev/null +++ b/ntsimulator/ntsim-ng/core/datastore/generate.h @@ -0,0 +1,28 @@ +/************************************************************************* +* +* Copyright 2020 highstreet technologies GmbH and others +* +* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +* +* 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. +***************************************************************************/ + +#pragma once + +#include +#include +#include + +struct lyd_node *datastore_load_external(const char *filename, bool operational); + +//generate all available root nodes (taking into consideration excluded, deprecated and unimplemented modules and containers) +int datastore_generate_data(const char *running_filename, const char *operational_filename); +int datastore_generate_external(void); diff --git a/ntsimulator/ntsim-ng/core/datastore/populate.c b/ntsimulator/ntsim-ng/core/datastore/populate.c index 19f6ee9..8435397 100644 --- a/ntsimulator/ntsim-ng/core/datastore/populate.c +++ b/ntsimulator/ntsim-ng/core/datastore/populate.c @@ -24,446 +24,130 @@ #include #include +#include "generate.h" #include "core/session.h" #include "core/framework.h" -#include "core/datastore/schema.h" +static int datastore_populate_from_store(const char *running_filename, const char *operational_filename); +static int datastore_populate_commit(void); -static int schema_populate_late_resolve(populate_job_t *job); -static int schema_populate_validate(populate_instance_t *instance, int count); -static int schema_populate_commit_to_datastore(populate_job_t *job); +int datastore_populate(int retries) { + int rc; -int schema_populate(void) { - assert_session(); - - log_message(1, LOG_COLOR_BOLD_YELLOW"schema_populate() begin\n"LOG_COLOR_RESET); - - char **xpaths = 0; - int instance_count = schema_get_xpaths(&xpaths); - if(instance_count < 0) { - log_error("schema_get_xpaths failed"); - return NTS_ERR_FAILED; - } - - populate_job_t job; - job.operational = 0; - job.running = 0; - job.late_resolve_count = 0; - job.late_resolve_instance = 0; - job.late_resolve_schema = 0; - job.late_resolve_parent_o = 0; - job.late_resolve_parent_r = 0; - job.late_resolving = false; - - populate_instance_t *instance = (populate_instance_t *)malloc(sizeof(populate_instance_t) * instance_count); - if(!instance) { - log_error("bad malloc"); - return NTS_ERR_FAILED; - } - - //populate everything - for(int i = 0; i < instance_count; i++) { - log_message(1, "populating "LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET" with data...\n", xpaths[i]); - - struct lys_node *schema_node = (struct lys_node *)ly_ctx_get_node(session_context, 0, xpaths[i], 0); - if(schema_node == 0) { - log_error("ly_ctx_get_node failed for %s", xpaths[i]); - return NTS_ERR_FAILED; - } - - if(schema_node == 0) { - log_message(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET); - log_error("ly_ctx_get_node failed for %s", xpaths[i]); - return NTS_ERR_FAILED; - } + while(retries) { + int failed = 0; - if(!schema_node->module->implemented) { - log_message(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET); - log_error("module is not implemented for %s", xpaths[i]); - return NTS_ERR_FAILED; - } - - if((schema_node->flags & LYS_STATUS_DEPRC) != 0) { - log_message(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET); - log_error("module is deprecated for %s", xpaths[i]); + rc = datastore_generate_external(); + if(rc != NTS_ERR_OK) { + log_error("datastore_generate_external() failed\n"); return NTS_ERR_FAILED; } - //populate current instance vals - instance[i].init = 0; - instance[i].xpath = strdup(xpaths[i]); - instance[i].modules = 0; - instance[i].mod_count = 0; - instance[i].operational = 0; - instance[i].running = 0; - - //do the actual population - int rc = schema_populate_recursive(&job, &instance[i], schema_node, 0, 0); + rc = datastore_populate_from_store(DATASTORE_RUNNING_PATH, DATASTORE_OPERATIONAL_PATH); if(rc != NTS_ERR_OK) { - log_error("schema_populate_recursive failed instance %d with xpath %s", i, instance[i].xpath); - return rc; + failed = 1; + log_error("datastore_populate_from_store() failed\n"); } - } - //link everything so we would be able to find everything in late-resolve - log_message(1, LOG_COLOR_BOLD_YELLOW"schema_populate() done populating, now linking... (%d root nodes)\n"LOG_COLOR_RESET, instance_count); - for(int i = 0; i < instance_count; i++) { - - if(instance[i].operational) { - if(job.operational) { - int rc = lyd_insert_sibling(&job.operational, instance[i].operational); - if(rc != 0) { - log_error("lyd_insert_sibling"); - return NTS_ERR_FAILED; - } - } - else { - job.operational = instance[i].operational; - } + if(failed) { + sr_discard_changes(session_running); + sr_discard_changes(session_operational); + log_error("datastore_populate() failed, discarding changes\n"); } - - if(instance[i].running) { - if(job.running) { - int rc = lyd_insert_sibling(&job.running, instance[i].running); - if(rc != 0) { - log_error("lyd_insert_sibling"); - return NTS_ERR_FAILED; - } - } - else { - job.running = instance[i].running; + else { + rc = datastore_populate_commit(); + if(rc != NTS_ERR_OK) { + log_error("datastore_populate_commit() failed\n"); + failed = 1; } } - } - //late-resolve - log_message(1, LOG_COLOR_BOLD_YELLOW"schema_populate() starting late-resolve process...\n"LOG_COLOR_RESET); - if(job.late_resolve_count) { - int rc = schema_populate_late_resolve(&job); - if(rc != NTS_ERR_OK) { - log_error("schema_populate_late_resolve failed"); - return rc; + if(!failed) { + break; } - } - - //validate data and remove invalid nodes - log_message(1, LOG_COLOR_BOLD_YELLOW"schema_populate() validating\n"LOG_COLOR_RESET); - int rc = schema_populate_validate(instance, instance_count); - if(rc != NTS_ERR_OK) { - log_error("schema_populate_commit_to_datastore failed"); - return rc; - } - - //commit to datastore - log_message(1, LOG_COLOR_BOLD_YELLOW"schema_populate() commiting to datastore\n"LOG_COLOR_RESET); - rc = schema_populate_commit_to_datastore(&job); - if(rc != NTS_ERR_OK) { - log_error("schema_populate_commit_to_datastore failed"); - return rc; + retries--; } - //cleanup - log_message(1, LOG_COLOR_BOLD_YELLOW"schema_populate() cleaning up... "LOG_COLOR_RESET); - for(int i = 0; i < instance_count; i++) { - log_message(1, "%d ", i); - - free(instance[i].modules); - free(instance[i].xpath); - - free(xpaths[i]); - } - free(xpaths); - free(job.late_resolve_instance); - free(job.late_resolve_schema); - free(job.late_resolve_parent_o); - free(job.late_resolve_parent_r); - - lyd_free_withsiblings(job.operational); - lyd_free_withsiblings(job.running); - - log_message(1, "\n"); - log_message(1, LOG_COLOR_BOLD_GREEN"schema_populate() finished\n"LOG_COLOR_RESET); - - return NTS_ERR_OK; -} - -static int schema_populate_late_resolve(populate_job_t *job) { - assert(job); - - job->late_resolving = true; - for(int i = 0; i < job->late_resolve_count; i++) { - log_message(1, LOG_COLOR_BOLD_YELLOW"late-populating "LOG_COLOR_RESET": "); - int rc = schema_populate_add_leaf(job, job->late_resolve_instance[i], job->late_resolve_schema[i], job->late_resolve_parent_o[i], job->late_resolve_parent_r[i]); - if(rc != NTS_ERR_OK) { - log_error("schema_populate_add_leaf failed on late-resolve"); - return rc; - } + if(retries == 0) { + log_error("datastore_populate() failed to populate\n"); + return NTS_ERR_FAILED; } - job->late_resolving = false; + log_add_verbose(1, LOG_COLOR_BOLD_GREEN"datastore_populate() success\n"LOG_COLOR_RESET); return NTS_ERR_OK; } -static int schema_populate_validate(populate_instance_t *instance, int count) { - assert_session(); - assert(instance); - - int rc = 0; - int commit_ok = NTS_ERR_OK; - - for(int i = 0; i < count; i++) { - if(instance[i].operational) { - log_message(2, "available modules:"); - for(int j = 0; j < instance[i].mod_count; j++) { - log_message(2, " %s", instance[i].modules[j]->name); - } - log_message(2, "\n"); - log_message(1, "validating OPERATIONAL for [%d] : %s... ", i, instance[i].xpath); - - int solved_instance_errors = 1; - int solved_errors = 0; - bool success = false; - while(instance[i].operational && solved_instance_errors) { - solved_instance_errors = 0; - rc = lyd_validate_modules(&instance[i].operational, instance[i].modules, instance[i].mod_count, LYD_OPT_DATA, 0); - if(rc == 0) { - log_message(1, LOG_COLOR_BOLD_GREEN"success (%d)\n"LOG_COLOR_RESET, solved_errors); - success = true; - break; - } - else { - log_message(2, "\n"); - - struct ly_err_item *err = ly_err_first(session_context); - while(err) { - if((err->vecode == LYVE_NOWHEN) || (err->vecode == LYVE_NOMUST) || (err->vecode == LYVE_NOCONSTR) || (err->vecode == LYVE_NOLEAFREF) || (err->vecode == LYVE_NOMIN) || (err->vecode == LYVE_INVAL)) { - struct ly_set *set = lyd_find_path(instance[i].operational, err->path); - if(set && set->number) { - log_message(2, "operational error code %d on path %s with msg %s\n", err->vecode, err->path, err->msg); - log_message(2, LOG_COLOR_BOLD_RED" [WHEN-DELETE O]"LOG_COLOR_RESET" %s ... ", err->path); - - bool mandatory = false; - if((set->set.d[0]->schema->flags & LYS_MAND_TRUE) != 0) { - mandatory = true; - } - if((set->set.d[0]->schema->parent) && (set->set.d[0]->schema->parent->nodetype == LYS_CASE)) { - if((set->set.d[0]->schema->parent->flags & LYS_MAND_TRUE) != 0) { - mandatory = true; - } - } - - if((set->set.d[0]->dflt != 0) || (lys_is_key((const struct lys_node_leaf *)set->set.d[0]->schema, 0)) || (mandatory) || (err->vecode == LYVE_NOMIN)) { - //delete whole parent - log_message(2, "deleted parent : %s\n", lyd_path(set->set.d[0]->parent)); - struct lyd_node *p = set->set.d[0]->parent; - lyd_free_withsiblings(set->set.d[0]); - lyd_free(p); - if(p == instance[i].operational) { - log_message(1, "instance became empty "LOG_COLOR_BOLD_GREEN"success\n"LOG_COLOR_RESET); - success = true; - instance[i].operational = 0; - break; - } - } - else { - //delete THIS node only - lyd_free(set->set.d[0]); - log_message(2, "deleted\n"); - if(set->set.d[0] == instance[i].operational) { - log_message(1, "instance became empty "LOG_COLOR_BOLD_GREEN"success\n"LOG_COLOR_RESET); - success = true; - instance[i].operational = 0; - break; - } - } - solved_instance_errors++; - - ly_set_free(set); - } - } - else if((err->vecode != 0) && (err->vecode != 29)) { - log_message(2, "operational error code %d on path %s with msg %s\n", err->vecode, err->path, err->msg); - } - - err = err->next; - } - ly_err_clean(session_context, 0); - } - - solved_errors += solved_instance_errors; - } - - if(!success) { - if(!solved_errors) { - log_message(1, LOG_COLOR_BOLD_YELLOW"failed"LOG_COLOR_RESET"\n%s\n", ly_errmsg(session_context)); - } - else { - log_message(1, LOG_COLOR_BOLD_YELLOW"partially solved (%d)"LOG_COLOR_RESET"\n", solved_errors); - } - } - } - - if(instance[i].running) { - log_message(1, "validating RUNNING... for [%d] : %s... ", i, instance[i].xpath); - - int solved_instance_errors = 1; - int solved_errors = 0; - bool success = false; - while(instance[i].running && solved_instance_errors) { - solved_instance_errors = 0; - rc = lyd_validate_modules(&instance[i].running, instance[i].modules, instance[i].mod_count, LYD_OPT_CONFIG, 0); - if(rc == 0) { - log_message(1, LOG_COLOR_BOLD_GREEN"success (%d)\n"LOG_COLOR_RESET, solved_errors); - success = true; - break; - } - else { - log_message(2, "\n"); - - struct ly_err_item *err = ly_err_first(session_context); - while(err) { - if((err->vecode == LYVE_NOWHEN) || (err->vecode == LYVE_NOMUST) || (err->vecode == LYVE_NOCONSTR) || (err->vecode == LYVE_NOLEAFREF) || (err->vecode == LYVE_NOMIN) || (err->vecode == LYVE_INVAL)) { - struct ly_set *set = lyd_find_path(instance[i].running, err->path); - if(set && set->number) { - log_message(2, "running error code %d on path %s with msg %s\n", err->vecode, err->path, err->msg); - log_message(2, LOG_COLOR_BOLD_RED" [WHEN-DELETE R]"LOG_COLOR_RESET" %s ... ", err->path); - - bool mandatory = false; - if((set->set.d[0]->schema->flags & LYS_MAND_TRUE) != 0) { - mandatory = true; - } - - if((set->set.d[0]->schema->parent) && (set->set.d[0]->schema->parent->nodetype == LYS_CASE)) { - if((set->set.d[0]->schema->parent->flags & LYS_MAND_TRUE) != 0) { - mandatory = true; - } - } - - if((set->set.d[0]->dflt != 0) || (lys_is_key((const struct lys_node_leaf *)set->set.d[0]->schema, 0)) || (mandatory) || (err->vecode == LYVE_NOMIN)) { - //delete whole parent - log_message(2, "deleted parent : %s\n", lyd_path(set->set.d[0]->parent)); - struct lyd_node *p = set->set.d[0]->parent; - lyd_free_withsiblings(set->set.d[0]); - lyd_free(p); - - if(p == instance[i].running) { - log_message(1, "instance became empty "LOG_COLOR_BOLD_GREEN"success\n"LOG_COLOR_RESET); - success = true; - instance[i].running = 0; - break; - } - } - else { - //delete THIS node only - lyd_free(set->set.d[0]); - log_message(2, "deleted\n"); - if(set->set.d[0] == instance[i].running) { - log_message(1, "instance became empty "LOG_COLOR_BOLD_GREEN"success\n"LOG_COLOR_RESET); - success = true; - instance[i].running = 0; - break; - } - } - solved_instance_errors++; - - ly_set_free(set); - } - } - else if((err->vecode != 0) && (err->vecode != 29)) { - log_message(2, "running error code %d on path %s with msg %s\n", err->vecode, err->path, err->msg); - } - - err = err->next; - } - ly_err_clean(session_context, 0); - } - - solved_errors += solved_instance_errors; - } - - if(!success) { - if(!solved_errors) { - log_message(1, LOG_COLOR_BOLD_YELLOW"failed"LOG_COLOR_RESET"\n%s\n", ly_errmsg(session_context)); - } - else { - log_message(1, LOG_COLOR_BOLD_YELLOW"partially solved (%d)"LOG_COLOR_RESET"\n", solved_errors); - } - } - } - } - - return commit_ok; -} - -static int schema_populate_commit_to_datastore(populate_job_t *job) { +static int datastore_populate_from_store(const char *running_filename, const char *operational_filename) { assert_session(); - assert(job); - + int rc = 0; - int commit_ok = 0; + struct lyd_node *data; - if(job->operational) { - rc = SR_ERR_OK; - log_message(1, "editing batch for OPERATIONAL... "); - rc = sr_edit_batch(session_operational, job->operational, "merge"); + data = datastore_load_external(running_filename, false); + if(data) { + log_add_verbose(1, "editing batch for RUNNING... "); + rc = sr_edit_batch(session_running, data, "replace"); + lyd_free_withsiblings(data); if (rc != SR_ERR_OK) { - log_message(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET); - commit_ok = NTS_ERR_FAILED; + log_add(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET); + return NTS_ERR_FAILED; } else { - log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET); + log_add(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET); + } + } + else { + if(running_filename) { + log_add_verbose(2, "datastore_populate_from_store(): %s could not be loaded, skipping\n", running_filename); } + } - rc = SR_ERR_OK; - log_message(1, "appling changes to OPERATIONAL... "); - rc = sr_apply_changes(session_operational, 0, 0); + data = datastore_load_external(operational_filename, true); + if(data) { + log_add_verbose(1, "editing batch for OPERATIONAL... "); + rc = sr_edit_batch(session_operational, data, "replace"); + lyd_free_withsiblings(data); if (rc != SR_ERR_OK) { - sr_discard_changes(session_operational); - commit_ok = NTS_ERR_FAILED; - log_message(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET); + log_add(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET); + return NTS_ERR_FAILED; } else { - log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET); + log_add(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET); + } + } + else { + if(running_filename) { + log_add_verbose(2, "datastore_populate_from_store(): %s could not be loaded, skipping\n", operational_filename); } } - if(job->running) { - // or you can do it like this, but will replace the WHOLE datastore - // rc = SR_ERR_OK; - // log_message(1, "editing batch for RUNNING..."); - // rc = sr_replace_config(session_running, 0, job->running, 0, 0); - // if (rc != SR_ERR_OK) { - // log_message(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET); - // commit_ok = NTS_ERR_FAILED; - // } - // else { - // log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET); - // } + return NTS_ERR_OK; +} - rc = SR_ERR_OK; - log_message(1, "editing batch for RUNNING..."); - rc = sr_edit_batch(session_running, job->running, "merge"); - if (rc != SR_ERR_OK) { - log_message(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET); - commit_ok = NTS_ERR_FAILED; - } - else { - log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET); - } +static int datastore_populate_commit(void) { + assert_session(); - rc = SR_ERR_OK; - log_message(1, "appling changes to RUNNING... "); - rc = sr_apply_changes(session_running, 0, 0); - if (rc != SR_ERR_OK) { - sr_discard_changes(session_running); - commit_ok = NTS_ERR_FAILED; - log_message(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET); - } - else { - log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET); - } + log_add_verbose(1, "appling changes to RUNNING... "); + int rc = sr_apply_changes(session_running, 0, 0); + if (rc != SR_ERR_OK) { + sr_discard_changes(session_running); + log_add(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET); + return NTS_ERR_FAILED; + } + else { + log_add(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET); + } + + log_add_verbose(1, "appling changes to OPERATIONAL... "); + rc = sr_apply_changes(session_operational, 0, 0); + if (rc != SR_ERR_OK) { + log_add(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET); + return NTS_ERR_FAILED; + } + else { + log_add(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET); } - return commit_ok; + return NTS_ERR_OK; } diff --git a/ntsimulator/ntsim-ng/core/datastore/populate.h b/ntsimulator/ntsim-ng/core/datastore/populate.h index 3df3693..78468e2 100644 --- a/ntsimulator/ntsim-ng/core/datastore/populate.h +++ b/ntsimulator/ntsim-ng/core/datastore/populate.h @@ -20,35 +20,8 @@ #include #include #include -#include -typedef struct { - int init; +#define DATASTORE_OPERATIONAL_PATH "log/datastore-operational.json" +#define DATASTORE_RUNNING_PATH "log/datastore-running.json" - char *xpath; - - const struct lys_module **modules; - int mod_count; - - struct lyd_node *operational; - struct lyd_node *running; -} populate_instance_t; - -typedef struct { - struct lyd_node *operational; - struct lyd_node *running; - bool late_resolving; - - int late_resolve_count; - struct lys_node **late_resolve_schema; - struct lyd_node **late_resolve_parent_o; - struct lyd_node **late_resolve_parent_r; - populate_instance_t **late_resolve_instance; -} populate_job_t; - -//populate.c -int schema_populate(void); //populate all available root nodes (taking into consideration excluded, deprecated and unimplemented) - -//populate_rec.c -int schema_populate_recursive(populate_job_t *job, populate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r); -int schema_populate_add_leaf(populate_job_t *job, populate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r); +int datastore_populate(int retries); diff --git a/ntsimulator/ntsim-ng/core/datastore/populate_rec.c b/ntsimulator/ntsim-ng/core/datastore/populate_rec.c deleted file mode 100644 index d185083..0000000 --- a/ntsimulator/ntsim-ng/core/datastore/populate_rec.c +++ /dev/null @@ -1,584 +0,0 @@ -/************************************************************************* -* -* Copyright 2020 highstreet technologies GmbH and others -* -* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 -* -* 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. -***************************************************************************/ - -#define _GNU_SOURCE - -#include "populate.h" -#include "utils/log_utils.h" -#include "utils/rand_utils.h" -#include "utils/type_utils.h" -#include -#include -#include - -#include "core/session.h" -#include "core/framework.h" - -#define SCHEMA_LEAFREF_TOTAL_ENTRIES 11 - -static int schema_instance_add_module(populate_instance_t *instance, const struct lys_module *module); -static int schema_populate_late_resolve_add_leaf(populate_job_t *job, populate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r); -static const char* schema_leafref_temp_val(int index); - -int schema_populate_recursive(populate_job_t *job, populate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r) { - assert_session(); - assert(job); - assert(schema); - assert(instance); - - char *resolved_schema_path = lys_path(schema, LYS_PATH_FIRST_PREFIX); - bool schema_operational = ((schema->flags & LYS_CONFIG_W) == 0); - - schema_populate_rerun_switch: - switch(schema->nodetype) { - //for container, just add it to the xpath, and iterate it's childeren to further traverse the tree - case LYS_CONTAINER: { - //add container - - struct lyd_node *new_parent_o = parent_o; - struct lyd_node *new_parent_r = parent_r; - - new_parent_o = lyd_new(parent_o, schema->module, schema->name); - if(!new_parent_o) { - log_error("error creating container operational -> %s", schema->name); - log_error("ly_error: %s\n", ly_errmsg(session_context)); - return NTS_ERR_FAILED; - } - - if(!schema_operational && !framework_arguments.operational_only) { - new_parent_r = lyd_new(parent_r, schema->module, schema->name); - if(!new_parent_r) { - log_error("error creating container running -> %s", schema->name); - log_error("ly_error: %s\n", ly_errmsg(session_context)); - return NTS_ERR_FAILED; - } - } - - if(!instance->init) { - instance->init = true; - instance->operational = new_parent_o; - instance->running = new_parent_r; - } - - char mandatory = ' '; - if((schema->flags & LYS_MAND_TRUE) != 0) { - mandatory = 'M'; - } - if((schema->parent) && (schema->parent->nodetype == LYS_CASE)) { - if((schema->parent->flags & LYS_MAND_TRUE) != 0) { - mandatory = 'M'; - } - } - bool node_operational = ((schema->flags & LYS_CONFIG_W) == 0); - char *xpath = lyd_path(new_parent_o); - log_message(1, LOG_COLOR_BOLD_MAGENTA"[%15s] "LOG_COLOR_BOLD_YELLOW"[%c%c]"LOG_COLOR_RESET" %s\n", "CONTAINER", node_operational ? 'O' : 'R', mandatory, xpath); - free(xpath); - - int rc = schema_instance_add_module(instance, schema->module); - if(rc != NTS_ERR_OK) { - log_error("schema_instance_add_module failed"); - return rc; - } - - struct lys_node *child = 0; - LY_TREE_FOR(schema->child, child) { - int rc = schema_populate_recursive(job, instance, child, new_parent_o, new_parent_r); - if(rc != NTS_ERR_OK) { - log_error("schema_populate_recursive failed"); - return rc; - } - } - } break; - - //choice does not appear into the data path. get all the avalable choices, and choose a random one - case LYS_CHOICE: { - int choice_no = 0; - struct lys_node_case *choice = (struct lys_node_case *)schema->child; - while(choice) { - choice_no++; - choice = (struct lys_node_case *)choice->next; - } - - //select a random choice - choice_no = rand_uint16() % choice_no; - - int i = 0; - choice = (struct lys_node_case *)schema->child; - while(i < choice_no) { - i++; - choice = (struct lys_node_case *)choice->next; - } - - //after the choice was made, rerun the adding without other tree-searching (will run into a CASE) - schema = (struct lys_node *)choice; - goto schema_populate_rerun_switch; - } break; - - //the actual "case" is this node's child, so we skip directly to that - case LYS_CASE: - //case contains mandatory - if(schema->child) { - schema = schema->child; - goto schema_populate_rerun_switch; - } - else { - //blank case - return NTS_ERR_OK; - } - break; - - //populate a list - case LYS_LIST: { - //get min-max for current list - struct lys_node_list *list = (struct lys_node_list *)schema; - int min_added = list->min ? list->min : 1; - int max_added = list->max ? list->max : 65536; - - int populating_times = framework_populate_get_instance_count(resolved_schema_path); - if(populating_times != 0) { - if(min_added < populating_times) { - min_added = populating_times; - } - if(min_added > max_added) { - min_added = max_added; - log_error("min-elements exceeds max-elements for path %s. truncated to %d", resolved_schema_path, max_added); - } - log_message(2, "populating %d times list '%s'\n", min_added, resolved_schema_path); - - //populate node with the intended number of values - while(min_added) { - //add list - - struct lyd_node *new_parent_o = parent_o; - struct lyd_node *new_parent_r = parent_r; - - new_parent_o = lyd_new(parent_o, schema->module, schema->name); - if(!new_parent_o) { - log_error("error creating list operational -> %s", schema->name); - log_error("ly_error: %s\n", ly_errmsg(session_context)); - return NTS_ERR_FAILED; - } - - if(!schema_operational && !framework_arguments.operational_only) { - new_parent_r = lyd_new(parent_r, schema->module, schema->name); - if(!new_parent_r) { - log_error("error creating container running -> %s", schema->name); - log_error("ly_error: %s\n", ly_errmsg(session_context)); - return NTS_ERR_FAILED; - } - } - - if(!instance->init) { - instance->init = true; - instance->operational = new_parent_o; - instance->running = new_parent_r; - } - - char mandatory = ' '; - if((schema->flags & LYS_MAND_TRUE) != 0) { - mandatory = 'M'; - } - if((schema->parent) && (schema->parent->nodetype == LYS_CASE)) { - if((schema->parent->flags & LYS_MAND_TRUE) != 0) { - mandatory = 'M'; - } - } - bool node_operational = ((schema->flags & LYS_CONFIG_W) == 0); - char *xpath = lyd_path(new_parent_o); - log_message(1, LOG_COLOR_BOLD_MAGENTA"[%15s] "LOG_COLOR_BOLD_YELLOW"[%c%c]"LOG_COLOR_RESET" %s\n", "LIST", node_operational ? 'O' : 'R', mandatory, xpath); - free(xpath); - - int rc = schema_instance_add_module(instance, schema->module); - if(rc != NTS_ERR_OK) { - log_error("schema_instance_add_module failed"); - return rc; - } - - //populate all list elements below in the tree - struct lys_node *child = 0; - LY_TREE_FOR(schema->child, child) { - int rc = schema_populate_recursive(job, instance, child, new_parent_o, new_parent_r); - if(rc != NTS_ERR_OK) { - log_error("schema_populate_recursive failed"); - return rc; - } - } - - min_added--; - } - } - else { - log_message(2, "not populating list '%s'\n", resolved_schema_path); - } - } break; - - //populate the leaf - case LYS_LEAF: { - if(schema_populate_add_leaf(job, instance, schema, parent_o, parent_r) != NTS_ERR_OK) { - return NTS_ERR_FAILED; - } - } break; - - //leaflist is treated the same as a LEAF, but with min/max characteristics of a LIST - case LYS_LEAFLIST: { - //get min-max for the current leaflist - struct lys_node_leaflist *list = (struct lys_node_leaflist *)schema; - int min_added = list->min ? list->min : 1; - int max_added = list->max ? list->max : 65536; - - int populating_times = framework_populate_get_instance_count(resolved_schema_path); - if(populating_times != 0) { - if(min_added < populating_times) { - min_added = populating_times; - } - if(min_added > max_added) { - min_added = max_added; - log_error("min-elements exceeds max-elements for path %s truncated to %d", resolved_schema_path, max_added); - } - log_message(2, "populating %d times leaflist '%s'\n", min_added, resolved_schema_path); - - //add the leafs - while(min_added) { - if(schema_populate_add_leaf(job, instance, schema, parent_o, parent_r) != NTS_ERR_OK) { - return NTS_ERR_FAILED; - } - min_added--; - } - } - else { - log_message(2, "not populating leaflist '%s'\n", resolved_schema_path); - } - } break; - - case LYS_ACTION: - case LYS_INPUT: - case LYS_OUTPUT: - case LYS_NOTIF: - //don't do anything, since we don't want to add this or go further down the tree when we meet them - break; - - //other node types (grouping, uses, augment, etc just traverse) - default: - log_message(1, "[%15s] %s\n", typeutils_yang_nodetype_to_str(schema->nodetype), resolved_schema_path); - - //traverse the tree down for any other node types, without adding anything to the path - struct lys_node *child = 0; - LY_TREE_FOR(schema->child, child) { - int rc = schema_populate_recursive(job, instance, child, parent_o, parent_r); - if(rc != NTS_ERR_OK) { - return rc; - } - } - break; - } - - free(resolved_schema_path); - - return NTS_ERR_OK; -} - -int schema_populate_add_leaf(populate_job_t *job, populate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r) { - assert_session(); - assert(job); - assert(schema); - assert(parent_o); - - int rc = schema_instance_add_module(instance, schema->module); - if(rc != NTS_ERR_OK) { - log_error("bad schema_instance_add module"); - return rc; - } - - struct lys_type *type = &((struct lys_node_leaf *)schema)->type; - - char *data_xpath = lyd_path(parent_o); - data_xpath = (char *)realloc(data_xpath, sizeof(char) * (strlen(data_xpath) + 1 + strlen(schema->name) + 1)); - if(!data_xpath) { - log_error("lyd_path failed"); - return NTS_ERR_FAILED; - } - strcat(data_xpath, "/"); - strcat(data_xpath, schema->name); - - //check whether the value is MANDATORY or not (for logging purposes) - char mandatory = ' '; - if((schema->flags & LYS_MAND_TRUE) != 0) { - mandatory = 'M'; - } - - if((schema->parent) && (schema->parent->nodetype == LYS_CASE)) { - if((schema->parent->flags & LYS_MAND_TRUE) != 0) { - mandatory = 'M'; - } - } - - bool node_operational = ((schema->flags & LYS_CONFIG_W) == 0); - log_message(1, LOG_COLOR_BOLD_MAGENTA"[%15s] "LOG_COLOR_BOLD_YELLOW"[%c%c]"LOG_COLOR_RESET" %s <-- ", typeutils_yang_type_to_str(type->base), node_operational ? 'O' : 'R', mandatory, data_xpath); - free(data_xpath); - - - char *resolved_schema_path = lys_path(schema, LYS_PATH_FIRST_PREFIX); - char *value = framework_populate_get_restrict_schema(resolved_schema_path); - free(resolved_schema_path); - - schema_populate_add_leaf_rerun_switch: - switch(type->base) { - case LY_TYPE_UNION: - if((type->info.uni.count == 0) && (type->der != 0)) { - type = &type->der->type; - } - - type = &type->info.uni.types[0]; - goto schema_populate_add_leaf_rerun_switch; - break; - - case LY_TYPE_INST: { - struct lyd_node *parent = parent_o; - while(parent->parent) { - parent = parent->parent; - } - - if(value == 0) { - value = lyd_path(parent); - } - - goto schema_populate_add_leaf_actual_add; - } break; - - case LY_TYPE_EMPTY: - if(rand_bool()) { //if present, add it - log_message(1, LOG_COLOR_CYAN"present"LOG_COLOR_RESET"\n"); - goto schema_populate_add_leaf_actual_add; - } - else { - log_message(1, LOG_COLOR_CYAN"empty"LOG_COLOR_RESET"\n"); - return NTS_ERR_OK; - } - break; - - case LY_TYPE_LEAFREF: { - if(value == 0) { - int index = 0; - struct lyd_node *new_node = 0; - while((new_node == 0) && (index < SCHEMA_LEAFREF_TOTAL_ENTRIES)) { - new_node = lyd_new_leaf(parent_o, schema->module, schema->name, schema_leafref_temp_val(index)); - index++; - } - - if(new_node == 0) { - log_error("error on lyd_new_leaf schema %s. didn't work with any temp val", schema->name); - return NTS_ERR_FAILED; - } - - //based on the new_node's path, try to find elements of relative path for the leafref - struct ly_set *set = lyd_find_path(new_node, type->info.lref.path); - lyd_free(new_node); - - if(set && set->number) { - //choose a random schema and get its value - static int set_number = 0; //checkAL aici trebuia oare random ? - set_number++; - if(set_number >= set->number) { - set_number = 0; - } - asprintf(&value, "%s", ((struct lyd_node_leaf_list *)set->set.d[set_number])->value_str); - if(!value) { - log_error("bad asprintf"); - return NTS_ERR_FAILED; - } - - int rc = schema_instance_add_module(instance, set->set.d[set_number]->schema->module); - if(rc != NTS_ERR_OK) { - log_error("bad schema_instance_add module"); - return rc; - } - - ly_set_free(set); - - goto schema_populate_add_leaf_actual_add; - } - else { - //adding to late-resolve list, as we don't have any nodes in the leafref path - int rc = schema_populate_late_resolve_add_leaf(job, instance, schema, parent_o, parent_r); - if(rc != NTS_ERR_OK) { - return rc; - } - - if(!job->late_resolving) { - log_message(1, LOG_COLOR_BOLD_YELLOW"added to late-resolve list...\n"LOG_COLOR_RESET); - } - else { - log_message(1, LOG_COLOR_BOLD_YELLOW"REadded to late-resolve list...\n"LOG_COLOR_RESET); - } - - return NTS_ERR_OK; - } - } - } break; - - default: - if(value == 0) { - value = rand_get_populate_value(type); - } - goto schema_populate_add_leaf_actual_add; - break; - } - - schema_populate_add_leaf_actual_add: { - //add schema to operational - struct lyd_node *new_node = lyd_new_leaf(parent_o, schema->module, schema->name, value); - if(new_node == 0) { - log_error("error on lyd_new_leaf operational: %s", ly_errmsg(session_context)); - return NTS_ERR_FAILED; - } - - //print out the value - if(value) { - log_message(1, LOG_COLOR_CYAN"'%s'"LOG_COLOR_RESET"\n", value); - } - else { - log_message(1, "\n"); - } - - //if it fits the case, add it also to running - if(!node_operational && !framework_arguments.operational_only) { - struct lyd_node *new_node = lyd_new_leaf(parent_r, schema->module, schema->name, value); - if(new_node == 0) { - log_error("error on lyd_new_leaf running: %s", ly_errmsg(session_context)); - return NTS_ERR_FAILED; - } - } - - free(value); - } - - return NTS_ERR_OK; -} - -static int schema_instance_add_module(populate_instance_t *instance, const struct lys_module *module) { - assert(module); - assert(instance); - - for(int i = 0; i < instance->mod_count; i++) { - if(instance->modules[i] == module) { - return NTS_ERR_OK; - } - } - - instance->modules = (const struct lys_module **)realloc(instance->modules, sizeof(const struct lys_module *) * (instance->mod_count + 1)); - if(!instance->modules) { - log_error("bad realloc"); - return NTS_ERR_FAILED; - } - instance->modules[instance->mod_count] = module; - instance->mod_count++; - - return NTS_ERR_OK; -} - -static int schema_populate_late_resolve_add_leaf(populate_job_t *job, populate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r) { - assert(job); - assert(instance); - - job->late_resolve_schema = (struct lys_node **)realloc(job->late_resolve_schema, (job->late_resolve_count + 1) * sizeof(struct lys_node *)); - if(!job->late_resolve_schema) { - log_error("bad realloc"); - return NTS_ERR_FAILED; - } - job->late_resolve_schema[job->late_resolve_count] = schema; - - job->late_resolve_parent_o = (struct lyd_node **)realloc(job->late_resolve_parent_o, (job->late_resolve_count + 1) * sizeof(struct lyd_node *)); - if(!job->late_resolve_parent_o) { - log_error("bad realloc"); - return NTS_ERR_FAILED; - } - job->late_resolve_parent_o[job->late_resolve_count] = parent_o; - - job->late_resolve_parent_r = (struct lyd_node **)realloc(job->late_resolve_parent_r, (job->late_resolve_count + 1) * sizeof(struct lyd_node *)); - if(!job->late_resolve_parent_r) { - log_error("bad realloc"); - return NTS_ERR_FAILED; - } - job->late_resolve_parent_r[job->late_resolve_count] = parent_r; - - job->late_resolve_instance = (populate_instance_t **)realloc(job->late_resolve_instance, (job->late_resolve_count + 1) * sizeof(populate_instance_t *)); - if(!job->late_resolve_instance) { - log_error("bad realloc"); - return NTS_ERR_FAILED; - } - job->late_resolve_instance[job->late_resolve_count] = instance; - - job->late_resolve_count++; - - return NTS_ERR_OK; -} - -static const char* schema_leafref_temp_val(int index) { - switch(index) { - case 0: - return "1"; - break; - - case 1: - return "1.1.1.1"; - break; - - case 2: - return "Fd:4D:63:A5:21:C5"; - break; - - case 3: - return ""; - break; - - case 4: - return "::1"; - break; - - case 5: - return "false"; - break; - - case 6: - return "TDD"; - break; - - case 7: - return "NR"; - break; - - case 8: - return "best-effort"; - break; - - case 9: - return "yes-fault:o-ran-sc-alarm-type"; - break; - - case 10: - return ""; - break; - - - - - default: - log_error("index out of bounds"); - return 0; - break; - } -} diff --git a/ntsimulator/ntsim-ng/core/datastore/schema.c b/ntsimulator/ntsim-ng/core/datastore/schema.c index 93ae199..d30cdb6 100644 --- a/ntsimulator/ntsim-ng/core/datastore/schema.c +++ b/ntsimulator/ntsim-ng/core/datastore/schema.c @@ -29,8 +29,9 @@ #include "core/framework.h" static int schema_print_recursive(struct lys_node *root); +static bool generate_is_excluded_module(const char *module); -int schema_get_xpaths(char ***root_xpath) { +int datastore_schema_get_xpaths(char ***root_xpath) { assert_session(); assert(root_xpath); @@ -41,17 +42,17 @@ int schema_get_xpaths(char ***root_xpath) { int total = 0; while((module = ly_ctx_get_module_iter(session_context, &idx)) != 0) { - if(!framework_is_populate_excluded_module(module->name) && (module->implemented)) { + if(!generate_is_excluded_module(module->name) && (module->implemented)) { LY_TREE_FOR(module->data, root) { if(((root->nodetype == LYS_CONTAINER) || (root->nodetype == LYS_LIST)) && ((root->flags & LYS_STATUS_DEPRC) == 0)) { list = (char **)realloc(list, sizeof(char *) * (total + 1)); if(!list) { - log_error("bad realloc"); + log_error("bad realloc\n"); return NTS_ERR_FAILED; } asprintf(&list[total], "/%s:%s", module->name, root->name); if(!list[total]) { - log_error("bad asprintf"); + log_error("bad asprintf\n"); return NTS_ERR_FAILED; } total++; @@ -62,12 +63,12 @@ int schema_get_xpaths(char ***root_xpath) { if(((chd->nodetype == LYS_CONTAINER) || (chd->nodetype == LYS_LIST)) && ((chd->flags & LYS_STATUS_DEPRC) == 0)) { list = (char **)realloc(list, sizeof(char *) * (total + 1)); if(!list) { - log_error("bad realloc"); + log_error("bad realloc\n"); return NTS_ERR_FAILED; } asprintf(&list[total], "/%s:%s", module->name, chd->name); if(!list[total]) { - log_error("bad asprintf"); + log_error("bad asprintf\n"); return NTS_ERR_FAILED; } total++; @@ -82,7 +83,7 @@ int schema_get_xpaths(char ***root_xpath) { return total; } -int schema_print_root_paths(void) { +int datastore_schema_print_root_paths(void) { assert_session(); struct lys_module *module; @@ -90,73 +91,73 @@ int schema_print_root_paths(void) { uint32_t idx = 0; while((module = (struct lys_module *)ly_ctx_get_module_iter(session_context, &idx)) != 0) { - log_message(2, "looking into module "LOG_COLOR_BOLD_MAGENTA"%s"LOG_COLOR_RESET"\n", module->name); + log_add_verbose(2, "looking into module "LOG_COLOR_BOLD_MAGENTA"%s"LOG_COLOR_RESET"\n", module->name); char flags[10]; strcpy(flags, "[ ]"); flags[1] = (module->implemented == 0) ? 'i' : ' '; - flags[3] = framework_is_populate_excluded_module(module->name) ? 'E' : ' '; + flags[3] = generate_is_excluded_module(module->name) ? 'E' : ' '; LY_TREE_FOR(module->data, root) { - log_message(2, " found "LOG_COLOR_CYAN"%s"LOG_COLOR_RESET" with name "LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET"\n", typeutils_yang_nodetype_to_str(root->nodetype), root->name); + log_add_verbose(2, " found "LOG_COLOR_CYAN"%s"LOG_COLOR_RESET" with name "LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET"\n", typeutils_yang_nodetype_to_str(root->nodetype), root->name); if((root->nodetype == LYS_CONTAINER) || (root->nodetype == LYS_LIST)) { flags[2] = ((root->flags & LYS_STATUS_DEPRC) != 0) ? 'D' : ' '; flags[4] = ((root->flags & LYS_CONFIG_W) == 0) ? 'O' : 'R'; flags[5] = (root->nodetype == LYS_CONTAINER) ? 'C' : 'L'; - log_message(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_CYAN" /%s:%s\n"LOG_COLOR_RESET, flags, module->name, root->name); + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_CYAN" /%s:%s\n"LOG_COLOR_RESET, flags, module->name, root->name); } else if(root->nodetype == LYS_USES) { struct lys_node *chd; LY_TREE_FOR(root->child, chd) { - log_message(2, " - found "LOG_COLOR_CYAN"%s"LOG_COLOR_RESET" with name "LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET"\n", typeutils_yang_nodetype_to_str(chd->nodetype), chd->name); + log_add_verbose(2, " - found "LOG_COLOR_CYAN"%s"LOG_COLOR_RESET" with name "LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET"\n", typeutils_yang_nodetype_to_str(chd->nodetype), chd->name); if((chd->nodetype == LYS_CONTAINER) || (chd->nodetype == LYS_LIST)) { flags[2] = ((chd->flags & LYS_STATUS_DEPRC) != 0) ? 'D' : ' '; flags[4] = ((chd->flags & LYS_CONFIG_W) == 0) ? 'O' : 'R'; flags[5] = (chd->nodetype == LYS_CONTAINER) ? 'C' : 'L'; - log_message(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_CYAN" /%s:%s\n"LOG_COLOR_RESET, flags, module->name, chd->name); + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_CYAN" /%s:%s\n"LOG_COLOR_RESET, flags, module->name, chd->name); } } } } } - log_message(1, "\n "LOG_COLOR_BOLD_YELLOW"i"LOG_COLOR_RESET" - not implemented | "LOG_COLOR_BOLD_YELLOW"D"LOG_COLOR_RESET" - deprecated | "LOG_COLOR_BOLD_YELLOW"E"LOG_COLOR_RESET" - excluded by config | "LOG_COLOR_BOLD_YELLOW"O"LOG_COLOR_RESET" - operational datastore | "LOG_COLOR_BOLD_YELLOW"R"LOG_COLOR_RESET" - running datastore | "LOG_COLOR_BOLD_YELLOW"C"LOG_COLOR_RESET" - container | "LOG_COLOR_BOLD_YELLOW"L"LOG_COLOR_RESET" - list\n\n"); + log_add_verbose(1, "\n "LOG_COLOR_BOLD_YELLOW"i"LOG_COLOR_RESET" - not implemented | "LOG_COLOR_BOLD_YELLOW"D"LOG_COLOR_RESET" - deprecated | "LOG_COLOR_BOLD_YELLOW"E"LOG_COLOR_RESET" - excluded by config | "LOG_COLOR_BOLD_YELLOW"O"LOG_COLOR_RESET" - operational datastore | "LOG_COLOR_BOLD_YELLOW"R"LOG_COLOR_RESET" - running datastore | "LOG_COLOR_BOLD_YELLOW"C"LOG_COLOR_RESET" - container | "LOG_COLOR_BOLD_YELLOW"L"LOG_COLOR_RESET" - list\n\n"); return NTS_ERR_OK; } -int schema_print_xpath(const char *xpath) { +int datastore_schema_print_xpath(const char *xpath) { assert_session(); assert(xpath); if(xpath == 0) { - log_error("xpath is null"); + log_error("xpath is null\n"); return NTS_ERR_FAILED; } - log_message(1, "printing out data structure for xpath: "LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET"\n", xpath); + log_add_verbose(1, "printing out data structure for xpath: "LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET"\n", xpath); struct lys_node *elem = (struct lys_node *)ly_ctx_get_node(session_context, 0, xpath, 0); if(elem == 0) { - log_error("ly_ctx_get_node failed for xpath: %s", xpath); + log_error("ly_ctx_get_node failed for xpath: %s\n", xpath); return NTS_ERR_FAILED; } struct lys_module *module = lys_node_module(elem); if(module == 0) { - log_error("lys_node_module failed for xpath: %s", xpath); + log_error("lys_node_module failed for xpath: %s\n", xpath); return NTS_ERR_FAILED; } - log_message(2, "module is %s @ revision %s\n", module->name, module->rev[0].date); + log_add_verbose(2, "module is %s @ revision %s\n", module->name, module->rev[0].date); int rc = schema_print_recursive(elem); if(rc != NTS_ERR_OK) { - log_error("schema_print_recursive failed for xpath: %s", xpath); + log_error("schema_print_recursive failed for xpath: %s\n", xpath); return NTS_ERR_FAILED; } - log_message(1, "\n "LOG_COLOR_BOLD_YELLOW"R"LOG_COLOR_RESET" - read only | "LOG_COLOR_BOLD_YELLOW"W"LOG_COLOR_RESET" - writeable | "LOG_COLOR_BOLD_YELLOW"*"LOG_COLOR_RESET" - key | "LOG_COLOR_BOLD_YELLOW"M"LOG_COLOR_RESET" - mandatory | "LOG_COLOR_BOLD_YELLOW"D"LOG_COLOR_RESET" - deprecated | "LOG_COLOR_BOLD_YELLOW"O"LOG_COLOR_RESET" - obsolete\n\n"); - log_message(2, "schema_print() finished\n"); + log_add_verbose(1, "\n "LOG_COLOR_BOLD_YELLOW"R"LOG_COLOR_RESET" - read only | "LOG_COLOR_BOLD_YELLOW"W"LOG_COLOR_RESET" - writeable | "LOG_COLOR_BOLD_YELLOW"*"LOG_COLOR_RESET" - key | "LOG_COLOR_BOLD_YELLOW"M"LOG_COLOR_RESET" - mandatory | "LOG_COLOR_BOLD_YELLOW"D"LOG_COLOR_RESET" - deprecated | "LOG_COLOR_BOLD_YELLOW"O"LOG_COLOR_RESET" - obsolete\n\n"); + log_add_verbose(2, "schema_print() finished\n"); return NTS_ERR_OK; @@ -177,18 +178,18 @@ static int schema_print_recursive(struct lys_node *root) { char *path = lys_data_path(root); if((root->nodetype != LYS_CHOICE) && (root->nodetype != LYS_CASE)) { - log_message(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET" %-100s ", my_status, path); + log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET" %-100s ", my_status, path); if(root->nodetype == LYS_LIST) { struct lys_node_list *list = (struct lys_node_list *)root; - log_message(1, LOG_COLOR_CYAN"%s "LOG_COLOR_MAGENTA"(m: %d M: %d)"LOG_COLOR_RESET, 4 + typeutils_yang_nodetype_to_str(root->nodetype), list->min, list->max); //+4 to skip "LYS_" + log_add(1, LOG_COLOR_CYAN"%s "LOG_COLOR_MAGENTA"(m: %d M: %d)"LOG_COLOR_RESET, 4 + typeutils_yang_nodetype_to_str(root->nodetype), list->min, list->max); //+4 to skip "LYS_" } else if(root->nodetype == LYS_LEAFLIST) { struct lys_node_leaflist *list = (struct lys_node_leaflist *)root; - log_message(1, LOG_COLOR_CYAN"%s "LOG_COLOR_MAGENTA"(m: %d M: %d)"LOG_COLOR_RESET, 4 + typeutils_yang_nodetype_to_str(root->nodetype), list->min, list->max); //+4 to skip "LYS_" + log_add(1, LOG_COLOR_CYAN"%s "LOG_COLOR_MAGENTA"(m: %d M: %d)"LOG_COLOR_RESET, 4 + typeutils_yang_nodetype_to_str(root->nodetype), list->min, list->max); //+4 to skip "LYS_" } else { - log_message(1, LOG_COLOR_CYAN"%-20s"LOG_COLOR_RESET, 4 + typeutils_yang_nodetype_to_str(root->nodetype)); //+4 to skip "LYS_" + log_add(1, LOG_COLOR_CYAN"%-20s"LOG_COLOR_RESET, 4 + typeutils_yang_nodetype_to_str(root->nodetype)); //+4 to skip "LYS_" } } free(path); @@ -198,37 +199,37 @@ static int schema_print_recursive(struct lys_node *root) { case LYS_LEAFLIST: { struct lys_type *type = &((struct lys_node_leaf *)root)->type; if(lys_is_key((const struct lys_node_leaf *)root, 0) != 0) { - log_message(1, LOG_COLOR_BOLD_YELLOW"[*]"LOG_COLOR_RESET); + log_add(1, LOG_COLOR_BOLD_YELLOW"[*]"LOG_COLOR_RESET); } else { - log_message(1, " "); + log_add(1, " "); } char *typestr = typeutils_type_to_str(type); - log_message(1, "[%s]", typestr); + log_add(1, "[%s]", typestr); free(typestr); if(root->parent) { if(root->parent->nodetype == LYS_CASE) { - log_message(1, " is a "LOG_COLOR_BLUE"CASE"LOG_COLOR_RESET" of "LOG_COLOR_CYAN"%s"LOG_COLOR_RESET, root->parent->parent->name); + log_add(1, " is a "LOG_COLOR_BLUE"CASE"LOG_COLOR_RESET" of "LOG_COLOR_CYAN"%s"LOG_COLOR_RESET, root->parent->parent->name); } } if(type->base == LY_TYPE_LEAFREF) { - log_message(1, " path: "LOG_COLOR_GREEN"%s"LOG_COLOR_RESET" ", type->info.lref.path); + log_add(1, " path: "LOG_COLOR_GREEN"%s"LOG_COLOR_RESET" ", type->info.lref.path); } else if(type->base == LY_TYPE_UNION) { if((type->info.uni.count == 0) && (type->der != 0)) { type = &type->der->type; } - log_message(1, " available union types (%d):"LOG_COLOR_GREEN, type->info.uni.count); + log_add(1, " available union types (%d):"LOG_COLOR_GREEN, type->info.uni.count); for(int i = 0; i < type->info.uni.count; i++) { char *typestr = typeutils_type_to_str(&type->info.uni.types[i]); - log_message(1, " %s", typestr); + log_add(1, " %s", typestr); free(typestr); } - log_message(1, LOG_COLOR_RESET); + log_add(1, LOG_COLOR_RESET); } } break; @@ -237,7 +238,7 @@ static int schema_print_recursive(struct lys_node *root) { } if((root->nodetype != LYS_CHOICE) && (root->nodetype != LYS_CASE)) { - log_message(1, "\n"); + log_add(1, "\n"); } struct lys_node *child = 0; @@ -250,3 +251,15 @@ static int schema_print_recursive(struct lys_node *root) { return NTS_ERR_OK; } + +static bool generate_is_excluded_module(const char *module) { + assert(module); + + for(int i = 0; i < framework_config.datastore_generate.excluded_modules_count; i++) { + if(strstr(module, framework_config.datastore_generate.excluded_modules[i]) != 0) { + return true; + } + } + + return false; +} diff --git a/ntsimulator/ntsim-ng/core/datastore/schema.h b/ntsimulator/ntsim-ng/core/datastore/schema.h index 490c3ba..a8637a1 100644 --- a/ntsimulator/ntsim-ng/core/datastore/schema.h +++ b/ntsimulator/ntsim-ng/core/datastore/schema.h @@ -20,7 +20,7 @@ #include #include -int schema_get_xpaths(char ***root_xpath); //returns number of xpaths, 0 if none, -1 if error +int datastore_schema_get_xpaths(char ***root_xpath); //returns number of xpaths, 0 if none, -1 if error -int schema_print_root_paths(void); -int schema_print_xpath(const char *xpath); +int datastore_schema_print_root_paths(void); +int datastore_schema_print_xpath(const char *xpath); diff --git a/ntsimulator/ntsim-ng/core/docker.c b/ntsimulator/ntsim-ng/core/docker.c index 7e8588d..25a9a83 100644 --- a/ntsimulator/ntsim-ng/core/docker.c +++ b/ntsimulator/ntsim-ng/core/docker.c @@ -20,12 +20,12 @@ #include "docker.h" #include "utils/log_utils.h" #include "utils/sys_utils.h" +#include "utils/nts_utils.h" #include "utils/http_client.h" #include "core/framework.h" #include "core/session.h" #include "core/context.h" #include -#include #include #include @@ -35,13 +35,6 @@ static cJSON *docker_network_info = 0; -struct installable_module { - char *name; - char *fullpath; - bool installed; - bool submodule; -}; - typedef struct { char *name; char *value; @@ -50,222 +43,26 @@ typedef struct { static environment_var_t *docker_environment_var; static int docker_environment_var_count = 0; -static int get_installable_modules(struct installable_module **modules); //list available modules for install -static void list_yangs(const char *path, struct installable_module **modules, int *total); - static char *docker_parse_json_message(const char *json_string); +static int docker_add_port(cJSON *portBindings, uint16_t docker_port, uint16_t host_port); -static int docker_container_create(const char *image, manager_network_function_instance_t *instance); -static int docker_container_start(manager_network_function_instance_t *instance); -static int docker_container_inspect(manager_network_function_instance_t *instance); - - -bool docker_container_init(void) { - int rc; - - sr_log_stderr(SR_LL_NONE); - log_message(1, "Entering container-init mode...\n"); - - // connect to sysrepo - rc = sr_connect(0, &session_connection); - if(SR_ERR_OK != rc) { - log_error("sr_connect failed"); - return false; - } - - /* get context */ - session_context = (struct ly_ctx *)sr_get_context(session_connection); - if(session_context == 0) { - log_error("sr_get_context failed"); - return false; - } - - /* install yang files */ - log_message(1, "Installing yang files...\n"); - struct installable_module *modules; - int total_modules = get_installable_modules(&modules); - log_message(1, "Found total modules: %d\n", total_modules); - - int old_failed_installations = 1; - int failed_installations = 0; - int install_round = 0; - while(failed_installations != old_failed_installations) { - old_failed_installations = failed_installations; - failed_installations = 0; - install_round++; - for(int i = 0; i < total_modules; i++) { - if(!modules[i].installed) { - modules[i].submodule = context_yang_is_module(modules[i].fullpath); - if(!modules[i].submodule) { - if(!framework_is_docker_excluded_module(modules[i].name)) { - log_message(1, "[round %d] trying to install module %s from %s... ", install_round, modules[i].name, modules[i].fullpath); - if(!context_module_install(modules[i].name, modules[i].fullpath)) { - failed_installations++; - log_message(1, LOG_COLOR_BOLD_YELLOW"failed"LOG_COLOR_RESET"\n"); - } - else { - log_message(1, LOG_COLOR_BOLD_GREEN"done"LOG_COLOR_RESET"\n"); - modules[i].installed = true; - } - } - else { - log_message(1, "[round %d] not installing module %s as it's excluded in config.\n", install_round, modules[i].name); - modules[i].installed = true; - } - } - else { - log_message(1, "[round %d] %s is a submodule... "LOG_COLOR_BOLD_YELLOW"skipping"LOG_COLOR_RESET"\n", install_round, modules[i].name); - modules[i].installed = true; - } - } - } - } - - if(failed_installations != 0) { - log_error("Failed to install all modules in %d rounds...", install_round); - return false; - } - else { - log_message(1, LOG_COLOR_BOLD_GREEN"successfully"LOG_COLOR_RESET" installed "LOG_COLOR_BOLD_GREEN"ALL"LOG_COLOR_RESET" modules in "LOG_COLOR_BOLD_YELLOW"%d"LOG_COLOR_RESET" rounds\n", (install_round - 1)); - } - - //set access for all installed modules - log_message(1, "Setting access configuration for installed modules... "); - for(int i = 0; i < total_modules; i++) { - if((!framework_is_docker_excluded_module(modules[i].name)) && (!modules[i].submodule)) { - if(!context_module_set_access(modules[i].name)) { - log_error("Failed to set access to module %s...", modules[i].name); - return false; - } - } - } - log_message(1, LOG_COLOR_BOLD_GREEN"done"LOG_COLOR_RESET"\n"); - - //cleanup module-install used memory - for(int i = 0; i < total_modules; i++) { - free(modules[i].name); - free(modules[i].fullpath); - } - free(modules); - - //get context - session_context = (struct ly_ctx *)sr_get_context(session_connection); - if(session_context == 0) { - log_error("sr_get_context failed"); - return false; - } - - //init context so we can see all the available modules, features, etc - rc = context_init(session_context); - if(rc != 0) { - log_error("context_init() failed"); - return false; - } - - /* enable features */ - log_message(1, "Enabling yang features...\n"); - char **available_features; - int total_available_features; - total_available_features = context_get_features(&available_features); - log_message(1, "Found total features: %d\n", total_available_features); - for(int i = 0; i < total_available_features; i++) { - log_message(1, "feature %s: ", available_features[i]); - - if(!context_get_feature_enabled(available_features[i])) { - if(!framework_is_docker_excluded_feature(available_features[i])) { - if(context_feature_enable(available_features[i])) { - log_message(1, "enabling... "LOG_COLOR_BOLD_GREEN"done"LOG_COLOR_RESET"\n"); - } - else { - log_error("enabling... failed\n"); - } - } - else { - log_message(1, "excluded in config, skipping\n"); - } - } - else { - log_message(1, "already "LOG_COLOR_BOLD_GREEN"enabled"LOG_COLOR_RESET", skipping.\n"); - } - } - for(int i = 0; i < total_available_features; i++) { - free(available_features[i]); - } - free(available_features); +static int docker_populate_images(docker_context_t *context, int count, const char *min_version); +static int docker_container_create(const char *image, docker_container_t *container); +static int docker_container_start(docker_container_t *container); +static int docker_container_inspect(docker_container_t *container); - sr_disconnect(session_connection); - context_free(); +int docker_init(const char **filter, int filter_count, const char *min_version, docker_context_t **context) { + assert(filter); + assert(filter_count); + assert(context); - log_message(1, LOG_COLOR_BOLD_GREEN"ntsim successfully initialized Docker container"LOG_COLOR_RESET"\n"); - return true; -} - -static int get_installable_modules(struct installable_module **modules) { - int total = 0; - *modules = 0; - list_yangs("/opt/dev/deploy/yang", modules, &total); - return total; -} - -static void list_yangs(const char *path, struct installable_module **modules, int *total) { - DIR *d; - struct dirent *dir; - d = opendir(path); - if(d) { - while((dir = readdir(d)) != NULL) { - if(dir->d_type == DT_DIR) { - if(strcmp(dir->d_name, ".") != 0 && strcmp(dir->d_name, "..") != 0) - { - char new_path[1024]; - snprintf(new_path, sizeof(new_path), "%s/%s", path, dir->d_name); - list_yangs(new_path, modules, total); - } - } else { - if(strstr(dir->d_name, ".yang") != 0) { - *modules = (struct installable_module *)realloc(*modules, sizeof(struct installable_module) * (*total + 1)); - if(!*modules) { - log_error("could not realloc"); - return; - } - - (*modules)[*total].name = (char*)malloc(sizeof(char) * (strlen(dir->d_name) + 1)); - if(!(*modules)[*total].name) { - log_error("could not alloc"); - return; - } - strcpy((*modules)[*total].name, dir->d_name); - (*modules)[*total].name[strlen(dir->d_name) - 5] = 0; //extract ".yang" - char *rev = strstr((*modules)[*total].name, "@"); - if(rev) { //extract revision, if exists - *rev = 0; - } - - (*modules)[*total].fullpath = (char*)malloc(sizeof(char) * (strlen(path) + 1 + strlen(dir->d_name) + 1)); - if(!(*modules)[*total].fullpath) { - log_error("could not alloc"); - return; - } - sprintf((*modules)[*total].fullpath, "%s/%s", path, dir->d_name); - - (*modules)[*total].installed = false; - (*modules)[*total].submodule = false; - - (*total)++; - } - } - } - closedir(d); - } -} - -int docker_device_init(void) { char *response = 0; char url[512]; - sprintf(url, "http://v%s/containers/%s/json", framework_environment.docker_engine_version, framework_environment.hostname); + sprintf(url, "http://v%s/containers/%s/json", framework_environment.settings.docker_engine_version, framework_environment.settings.hostname); int rc = http_socket_request(url, DOCKER_SOCK_FNAME, "GET", 0, 0, &response); if(rc != NTS_ERR_OK) { - log_error("http_socket_request failed"); + log_error("http_socket_request failed\n"); return NTS_ERR_FAILED; } @@ -273,20 +70,20 @@ int docker_device_init(void) { free(response); if(json_response == 0) { - log_error("could not parse JSON response for url=\"%s\"", url); + log_error("could not parse JSON response for url=\"%s\"\n", url); return NTS_ERR_FAILED; } cJSON *hostConfig = cJSON_GetObjectItemCaseSensitive(json_response, "HostConfig"); if(hostConfig == 0) { - log_error("could not get HostConfig object"); + log_error("could not get HostConfig object\n"); cJSON_Delete(json_response); return NTS_ERR_FAILED; } cJSON *networkMode = cJSON_GetObjectItemCaseSensitive(hostConfig, "NetworkMode"); if(networkMode == 0) { - log_error("could not get NetworkMode object"); + log_error("could not get NetworkMode object\n"); cJSON_Delete(json_response); return NTS_ERR_FAILED; } @@ -294,106 +91,173 @@ int docker_device_init(void) { docker_network_info = cJSON_Duplicate(networkMode, 1); cJSON_Delete(json_response); - log_message(2, "finished parsing docker inspect...\n"); - + log_add_verbose(2, "finished parsing docker inspect...\n"); - docker_environment_var_count = 5; + docker_environment_var_count = 9; docker_environment_var = (environment_var_t *)malloc(sizeof(environment_var_t) * docker_environment_var_count); if(docker_environment_var == 0) { - log_error("malloc failed"); + log_error("malloc failed\n"); cJSON_Delete(networkMode); return NTS_ERR_FAILED; } //set env variables for network functions docker_environment_var[0].name = ENV_VAR_SSH_CONNECTIONS; - asprintf(&docker_environment_var[0].value, "%d", framework_environment.ssh_connections); + asprintf(&docker_environment_var[0].value, "%d", framework_environment.settings.ssh_connections); docker_environment_var[1].name = ENV_VAR_TLS_CONNECTIONS; - asprintf(&docker_environment_var[1].value, "%d", framework_environment.tls_connections); + asprintf(&docker_environment_var[1].value, "%d", framework_environment.settings.tls_connections); docker_environment_var[2].name = ENV_VAR_IPV6ENABLED; - docker_environment_var[2].value = framework_environment.ip_v6_enabled ? "true" : "false"; + docker_environment_var[2].value = framework_environment.settings.ip_v6_enabled ? "true" : "false"; docker_environment_var[3].name = ENV_VAR_HOST_IP; - docker_environment_var[3].value = framework_environment.host_ip; - docker_environment_var[4].name = ENV_VAR_HOST_BASE_PORT; + docker_environment_var[3].value = framework_environment.host.ip; + + docker_environment_var[4].name = ENV_VAR_HOST_NETCONF_SSH_BASE_PORT; // docker_environment_var[4].value = will be updated by docker_create... + docker_environment_var[5].name = ENV_VAR_HOST_NETCONF_TLS_BASE_PORT; + // docker_environment_var[5].value = will be updated by docker_create... + docker_environment_var[6].name = ENV_VAR_HOST_TRANSFER_FTP_BASE_PORT; + // docker_environment_var[6].value = will be updated by docker_create... + docker_environment_var[7].name = ENV_VAR_HOST_TRANSFER_SFTP_BASE_PORT; + // docker_environment_var[7].value = will be updated by docker_create... + + docker_environment_var[8].name = ENV_VAR_VES_COMMON_HEADER_VERSION; + docker_environment_var[8].value = framework_environment.ves_endpoint.common_header_version; + + + + //docker context build + *context = (docker_context_t *)malloc(sizeof(docker_context_t) * filter_count); + if(*context == 0) { + log_error("bad malloc\n"); + free(docker_environment_var[0].value); + free(docker_environment_var[1].value); + free(docker_environment_var); + return NTS_ERR_FAILED; + } + + docker_context_t *ctx = *context; + for(int i = 0; i < filter_count; i++) { + ctx[i].image = strdup(filter[i]); + ctx[i].available_images = 0; + ctx[i].available_images_count = 0; + } + + docker_populate_images(ctx, filter_count, min_version); return NTS_ERR_OK; } -int docker_device_start(const manager_network_function_type *function_type, manager_network_function_instance_t *instance) { - assert(function_type); - assert(instance); +void docker_free(docker_context_t *context, int count) { + free(docker_environment_var[0].value); + free(docker_environment_var[1].value); + free(docker_environment_var); + + for(int i = 0; i < count; i++) { + free(context[i].image); + for(int j = 0; j < context[i].available_images_count; j++) { + free(context[i].available_images[j].repo); + free(context[i].available_images[j].tag); + } + free(context[i].available_images); + } +} + +int docker_start(const char *container_name, const char *tag, const char *image, const char *repo, uint16_t host_netconf_ssh_port, uint16_t host_netconf_tls_port, uint16_t host_ftp_port, uint16_t host_sftp_port, docker_container_t *container) { + assert(container_name); + assert(image); + assert(container); assert(docker_network_info); - char image[512]; - if(function_type->docker_version_tag && (function_type->docker_version_tag[0] != 0)) { - if(function_type->docker_repository && (function_type->docker_repository[0] != 0) && (strcmp(function_type->docker_repository, "local") != 0)) { - sprintf(image, "%s/%s:%s", function_type->docker_repository, function_type->docker_image_name, function_type->docker_version_tag); + char image_full[512]; + if(tag && (tag[0] != 0)) { + if(repo && (repo[0] != 0) && (strcmp(repo, "local") != 0)) { + sprintf(image_full, "%s/%s:%s", repo, image, tag); } else { - sprintf(image, "%s:%s", function_type->docker_image_name, function_type->docker_version_tag); + sprintf(image_full, "%s:%s", image, tag); } } else { - if(function_type->docker_repository && (function_type->docker_repository[0] != 0) && (strcmp(function_type->docker_repository, "local") != 0)) { - sprintf(image, "%s/%s:latest", function_type->docker_repository, function_type->docker_image_name); + if(repo && (repo[0] != 0) && (strcmp(repo, "local") != 0)) { + sprintf(image_full, "%s/%s:latest", repo, image); } else { - sprintf(image, "%s:latest", function_type->docker_image_name); + sprintf(image_full, "%s:latest", image); } } - int rc = docker_container_create(image, instance); + container->name = strdup(container_name); + container->id = 0; + container->docker_ip = 0; + container->docker_netconf_ssh_port = STANDARD_NETCONF_PORT; + container->docker_netconf_tls_port = container->docker_netconf_ssh_port + framework_environment.settings.ssh_connections; + container->docker_ftp_port= STANDARD_FTP_PORT; + container->docker_sftp_port= STANDARD_SFTP_PORT; + + container->host_ip = strdup(framework_environment.host.ip); + container->host_netconf_ssh_port = host_netconf_ssh_port; + container->host_netconf_tls_port = host_netconf_tls_port; + container->host_ftp_port = host_ftp_port; + container->host_sftp_port = host_sftp_port; + + int rc = docker_container_create(image_full, container); if(rc != NTS_ERR_OK) { - log_error("docker_container_create failed"); + log_error("docker_container_create failed\n"); return NTS_ERR_FAILED; } - rc = docker_container_start(instance); + rc = docker_container_start(container); if(rc != NTS_ERR_OK) { - log_error("docker_container_start failed"); - docker_device_stop(instance); + log_error("docker_container_start failed\n"); + docker_stop(container); return NTS_ERR_FAILED; } - rc = docker_container_inspect(instance); + rc = docker_container_inspect(container); if(rc != NTS_ERR_OK) { - log_error("docker_container_inspect failed"); - docker_device_stop(instance); + log_error("docker_container_inspect failed\n"); + docker_stop(container); return NTS_ERR_FAILED; } - log_message(2, "docker_device_start: docker_id: %s | name: %s | docker_ip: %s | host_port: %d\n", instance->docker_id, instance->name, instance->docker_ip, instance->host_port); + log_add_verbose(2, "docker_start: name: %s | id: %s | docker_ip: %s | netconf_ssh_port: (%d:%d) | netconf_tls_port: (%d:%d) | ftp_port: (%d:%d) | sftp_port: (%d:%d)\n", container->name, container->id, container->docker_ip, container->docker_netconf_ssh_port, container->host_netconf_ssh_port, container->docker_netconf_tls_port, container->host_netconf_tls_port, container->docker_ftp_port, container->host_ftp_port, container->docker_sftp_port, container->host_sftp_port); return NTS_ERR_OK; } -int docker_device_stop(manager_network_function_instance_t *instance) { - assert(instance); +int docker_stop(docker_container_t *container) { + assert(container); char url[512]; - sprintf(url, "http://v%s/containers/%s?force=true", framework_environment.docker_engine_version, instance->docker_id); + sprintf(url, "http://v%s/containers/%s?force=true", framework_environment.settings.docker_engine_version, container->id); + + free(container->name); + free(container->id); + free(container->docker_ip); + free(container->host_ip); int rc = http_socket_request(url, DOCKER_SOCK_FNAME, "DELETE", "", 0, 0); if(rc != NTS_ERR_OK) { - log_error("http_socket_request failed"); + log_error("http_socket_request failed\n"); return NTS_ERR_FAILED; } return NTS_ERR_OK; } -docker_usage_t docker_usage_get(const manager_network_function_type *function_type, int function_type_count) { - docker_usage_t ret; - ret.cpu = 0; - ret.mem = 0; +int docker_usage_get(const char **instances_id, int count, docker_usage_t *usage) { + assert(instances_id); + assert(usage); + + usage->cpu = 0; + usage->mem = 0; char buffer[1024]; char full_text[1024 * 1024]; FILE* pipe = popen("docker stats --no-stream --format \"table {{.ID}}|{{.CPUPerc}}|{{.MemUsage}}|\"", "r"); if (!pipe) { - log_error("popen() failed"); - return ret; + log_error("popen() failed\n"); + return NTS_ERR_FAILED; } int n = 1; @@ -465,19 +329,16 @@ docker_usage_t docker_usage_get(const manager_network_function_type *function_ty mem = strtof(buff, 0) * mul; - if(strcmp(container_name, framework_environment.hostname) == 0) { - ret.cpu += cpu; - ret.mem += mem; + if(strcmp(container_name, framework_environment.settings.hostname) == 0) { + usage->cpu += cpu; + usage->mem += mem; } else { - for(int i = 0; i < function_type_count; i++) { - for(int j = 0; j < function_type[i].started_instances; j++) { - - if(strcmp(container_name, function_type[i].instance[j].docker_id) == 0) { - ret.cpu += cpu; - ret.mem += mem; - break; - } + for(int i = 0; i < count; i++) { + if(strcmp(container_name, instances_id[i]) == 0) { + usage->cpu += cpu; + usage->mem += mem; + break; } } } @@ -486,10 +347,9 @@ docker_usage_t docker_usage_get(const manager_network_function_type *function_ty c = d; } + usage->cpu /= get_nprocs(); - ret.cpu /= get_nprocs(); - - return ret; + return NTS_ERR_OK; } static char *docker_parse_json_message(const char *json_string) { @@ -497,14 +357,13 @@ static char *docker_parse_json_message(const char *json_string) { cJSON *json_response = cJSON_Parse(json_string); if(json_response == 0) { - log_error("cJSON_Parse failed"); + log_error("cJSON_Parse failed\n"); return 0; } - cJSON *message; - message = cJSON_GetObjectItem(json_response, "message"); + cJSON *message = cJSON_GetObjectItem(json_response, "message"); if(message == 0) { - log_error("json parsing failed"); + log_error("json parsing failed\n"); cJSON_Delete(json_response); return 0; } @@ -514,30 +373,148 @@ static char *docker_parse_json_message(const char *json_string) { return ret; } -static int docker_container_create(const char *image, manager_network_function_instance_t *instance) { +static int docker_add_port(cJSON *portBindings, uint16_t docker_port, uint16_t host_port) { + assert(portBindings); + + cJSON *port = cJSON_CreateArray(); + if(port == 0) { + log_error("could not create JSON object: port\n"); + return NTS_ERR_FAILED; + } + + char dockerContainerPort[20]; + sprintf(dockerContainerPort, "%d/tcp", docker_port); + + if(cJSON_AddItemToObject(portBindings, dockerContainerPort, port) == 0) { + log_error("cJSON_AddItemToObject failed\n"); + return NTS_ERR_FAILED; + } + + cJSON *hostPort = cJSON_CreateObject(); + if(hostPort == 0) { + log_error("could not create JSON object: HostPort\n"); + return NTS_ERR_FAILED; + } + + char dockerHostPort[20]; + sprintf(dockerHostPort, "%d", host_port); + if(cJSON_AddStringToObject(hostPort, "HostPort", dockerHostPort) == 0) { + log_error("could not create JSON object: HostPortString\n"); + cJSON_Delete(hostPort); + return NTS_ERR_FAILED; + } + + if(cJSON_AddStringToObject(hostPort, "HostIp", "0.0.0.0") == 0) { //or, future, bind to container->host_ip + log_error("could not create JSON object: HostIpString\n"); + cJSON_Delete(hostPort); + return NTS_ERR_FAILED; + } + + if(cJSON_AddItemToArray(port, hostPort) == 0) { + log_error("cJSON_AddItemToArray failed\n"); + cJSON_Delete(hostPort); + return NTS_ERR_FAILED; + } + + return NTS_ERR_OK; +} + +static int docker_populate_images(docker_context_t *context, int count, const char *min_version) { + assert(context); + assert(count); + assert(min_version); + + char url[512]; + sprintf(url, "http://v%s/images/json", framework_environment.settings.docker_engine_version); + + char *response = 0; + int rc = http_socket_request(url, DOCKER_SOCK_FNAME, "GET", "", 0, &response); + if(rc != NTS_ERR_OK) { + log_error("http_socket_request failed\n"); + return NTS_ERR_FAILED; + } + + cJSON *json_response = cJSON_Parse(response); + free(response); + if(json_response == 0) { + log_error("cJSON_Parse failed\n"); + return NTS_ERR_FAILED; + } + + cJSON *element; + cJSON_ArrayForEach(element, json_response) { + cJSON *tag = cJSON_GetObjectItem(element, "RepoTags"); + if(tag) { + cJSON *ctag; + cJSON_ArrayForEach(ctag, tag) { + char *tag_name = ctag->valuestring; //contains repo/image:tag + for(int i = 0; i < count; i++) { + char *s = strstr(tag_name, context[i].image); + if(s != 0) { + char *tag = s + strlen(context[i].image); + if(*tag == ':') { + tag = strdup(s + strlen(context[i].image) + 1); + } + else if(*tag == 0) { + tag = strdup(""); + } + else { + continue; + } + + if(nts_vercmp(tag, min_version) >= 0) { + char *repo = 0; + if(s != tag_name) { + repo = strdup(tag_name); + *(strstr(repo, context[i].image) - 1) = 0; + } + else { + repo = strdup(""); + } + + context[i].available_images = (docker_available_images_t *)realloc(context[i].available_images, (sizeof(docker_available_images_t) * (context[i].available_images_count + 1))); + context[i].available_images[context[i].available_images_count].repo = repo; + context[i].available_images[context[i].available_images_count].tag = tag; + context[i].available_images_count++; + } + else { + free(tag); + } + } + } + } + } + } + + cJSON_Delete(json_response); + + return NTS_ERR_OK; +} + +static int docker_container_create(const char *image, docker_container_t *container) { assert(image); - assert(instance); + assert(container); cJSON *postDataJson = cJSON_CreateObject(); if(cJSON_AddStringToObject(postDataJson, "Image", image) == 0) { - log_error("could not create JSON object: Image"); + log_error("could not create JSON object: Image\n"); return NTS_ERR_FAILED; } - if(cJSON_AddStringToObject(postDataJson, "Hostname", instance->name) == 0) { - log_error("could not create JSON object: Hostname"); + if(cJSON_AddStringToObject(postDataJson, "Hostname", container->name) == 0) { + log_error("could not create JSON object: Hostname\n"); cJSON_Delete(postDataJson); return NTS_ERR_FAILED; } cJSON *hostConfig = cJSON_CreateObject(); if(hostConfig == 0) { - log_error("could not create JSON object: HostConfig"); + log_error("could not create JSON object: HostConfig\n"); cJSON_Delete(postDataJson); return NTS_ERR_FAILED; } if(cJSON_AddItemToObject(postDataJson, "HostConfig", hostConfig) == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(postDataJson); return NTS_ERR_FAILED; } @@ -549,70 +526,57 @@ static int docker_container_create(const char *image, manager_network_function_i return NTS_ERR_FAILED; } if(cJSON_AddItemToObject(hostConfig, "PortBindings", portBindings) == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(postDataJson); return NTS_ERR_FAILED; } - for(int i = 0; i < (framework_environment.ssh_connections + framework_environment.tls_connections + framework_environment.ftp_connections + framework_environment.sftp_connections); ++i) { - cJSON *port = cJSON_CreateArray(); - if(port == 0) { - log_error("could not create JSON object: port"); - cJSON_Delete(postDataJson); - return NTS_ERR_FAILED; - } - - char dockerContainerPort[20]; - if(i < framework_environment.ssh_connections + framework_environment.tls_connections) { - sprintf(dockerContainerPort, "%d/tcp", STANDARD_NETCONF_PORT + i); - } - else if(i < (framework_environment.ssh_connections + framework_environment.tls_connections + framework_environment.ftp_connections)) { - sprintf(dockerContainerPort, "%d/tcp", STANDARD_FTP_PORT); - } - else if(i < (framework_environment.ssh_connections + framework_environment.tls_connections + framework_environment.ftp_connections + framework_environment.sftp_connections)) { - sprintf(dockerContainerPort, "%d/tcp", STANDARD_SFTP_PORT); - } - if(cJSON_AddItemToObject(portBindings, dockerContainerPort, port) == 0) { - log_error("cJSON_AddItemToObject failed"); - cJSON_Delete(postDataJson); - return NTS_ERR_FAILED; - } - - cJSON *hostPort = cJSON_CreateObject(); - if(hostPort == 0) { - log_error("could not create JSON object: HostPort"); + for(int i = 0; i < framework_environment.settings.ssh_connections; i++) { + if(docker_add_port(portBindings, container->docker_netconf_ssh_port + i, container->host_netconf_ssh_port + i) != NTS_ERR_OK) { + log_error("docker_add_port() failed\n"); cJSON_Delete(postDataJson); return NTS_ERR_FAILED; } + } - char dockerHostPort[20]; - sprintf(dockerHostPort, "%d", instance->host_port + i); - if(cJSON_AddStringToObject(hostPort, "HostPort", dockerHostPort) == 0) { - log_error("could not create JSON object: HostPortString"); + for(int i = 0; i < framework_environment.settings.tls_connections; i++) { + if(docker_add_port(portBindings, container->docker_netconf_tls_port + i, container->host_netconf_tls_port + i) != NTS_ERR_OK) { + log_error("docker_add_port() failed\n"); cJSON_Delete(postDataJson); return NTS_ERR_FAILED; } + } - if(cJSON_AddStringToObject(hostPort, "HostIp", "0.0.0.0") == 0) { //instance->host_ip - log_error("could not create JSON object: HostIpString"); + for(int i = 0; i < framework_environment.settings.ftp_connections; i++) { + if(docker_add_port(portBindings, container->docker_ftp_port + i, container->host_ftp_port + i) != NTS_ERR_OK) { + log_error("docker_add_port() failed\n"); cJSON_Delete(postDataJson); return NTS_ERR_FAILED; } + } - if(cJSON_AddItemToArray(port, hostPort) == 0) { - log_error("cJSON_AddItemToArray failed"); + for(int i = 0; i < framework_environment.settings.sftp_connections; i++) { + if(docker_add_port(portBindings, container->docker_sftp_port + i, container->host_sftp_port + i) != NTS_ERR_OK) { + log_error("docker_add_port() failed\n"); cJSON_Delete(postDataJson); return NTS_ERR_FAILED; } } - //environment vars start - asprintf(&docker_environment_var[4].value, "%d", instance->host_port); + asprintf(&docker_environment_var[4].value, "%d", container->host_netconf_ssh_port); + asprintf(&docker_environment_var[5].value, "%d", container->host_netconf_tls_port); + asprintf(&docker_environment_var[6].value, "%d", container->host_ftp_port); + asprintf(&docker_environment_var[7].value, "%d", container->host_sftp_port); cJSON *env_variables_array = cJSON_CreateArray(); if(env_variables_array == 0) { - log_error("Could not create JSON object: Env array"); + log_error("Could not create JSON object: Env array\n"); + cJSON_Delete(postDataJson); + free(docker_environment_var[4].value); + free(docker_environment_var[5].value); + free(docker_environment_var[6].value); + free(docker_environment_var[7].value); return NTS_ERR_FAILED; } cJSON_AddItemToObject(postDataJson, "Env", env_variables_array); @@ -624,7 +588,13 @@ static int docker_container_create(const char *image, manager_network_function_i cJSON *env_var_obj = cJSON_CreateString(environment_var); if(env_var_obj == 0) { - log_error("could not create JSON object"); + log_error("could not create JSON object\n"); + cJSON_Delete(postDataJson); + free(docker_environment_var[4].value); + free(docker_environment_var[5].value); + free(docker_environment_var[6].value); + free(docker_environment_var[7].value); + free(environment_var); return NTS_ERR_FAILED; } cJSON_AddItemToArray(env_variables_array, env_var_obj); @@ -634,9 +604,11 @@ static int docker_container_create(const char *image, manager_network_function_i } free(docker_environment_var[4].value); + free(docker_environment_var[5].value); + free(docker_environment_var[6].value); + free(docker_environment_var[7].value); //environment vars finished - cJSON *netMode = cJSON_Duplicate(docker_network_info, 1); cJSON_AddItemToObject(hostConfig, "NetworkMode", netMode); @@ -645,20 +617,20 @@ static int docker_container_create(const char *image, manager_network_function_i cJSON_Delete(postDataJson); char url[512]; - sprintf(url, "http:/v%s/containers/create?name=%s", framework_environment.docker_engine_version, instance->name); + sprintf(url, "http:/v%s/containers/create?name=%s", framework_environment.settings.docker_engine_version, container->name); char *response = 0; int response_code = 0; int rc = http_socket_request(url, DOCKER_SOCK_FNAME, "POST", post_data_string, &response_code, &response); free(post_data_string); if(rc != NTS_ERR_OK) { - log_error("http_socket_request failed"); + log_error("http_socket_request failed\n"); return NTS_ERR_FAILED; } if(response_code != 201) { char *message = docker_parse_json_message(response); - log_error("docker_container_create failed (%d): %s", response_code, message); + log_error("docker_container_create failed (%d): %s\n", response_code, message); free(message); free(response); return NTS_ERR_FAILED; @@ -675,7 +647,7 @@ static int docker_container_create(const char *image, manager_network_function_i memset(container_id_short, '\0', sizeof(container_id_short)); strncpy(container_id_short, container_id->valuestring, 12); - instance->docker_id = strdup(container_id_short); + container->id = strdup(container_id_short); cJSON_Delete(json_response); return NTS_ERR_OK; @@ -687,17 +659,17 @@ static int docker_container_create(const char *image, manager_network_function_i } } -static int docker_container_start(manager_network_function_instance_t *instance) { - assert(instance); +static int docker_container_start(docker_container_t *container) { + assert(container); char url[512]; - sprintf(url, "http://v%s/containers/%s/start", framework_environment.docker_engine_version, instance->docker_id); + sprintf(url, "http://v%s/containers/%s/start", framework_environment.settings.docker_engine_version, container->id); char *response = 0; int response_code = 0; int rc = http_socket_request(url, DOCKER_SOCK_FNAME, "POST", "", &response_code, &response); if(rc != NTS_ERR_OK) { - log_error("http_socket_request failed"); + log_error("http_socket_request failed\n"); return NTS_ERR_FAILED; } else { @@ -708,7 +680,7 @@ static int docker_container_start(manager_network_function_instance_t *instance) } else if(response_code != 204) { char *message = docker_parse_json_message(response); - log_error("docker_container_start failed (%d): %s", response_code, message); + log_error("docker_container_start failed (%d): %s\n", response_code, message); free(message); free(response); return NTS_ERR_FAILED; @@ -719,50 +691,51 @@ static int docker_container_start(manager_network_function_instance_t *instance) return NTS_ERR_OK; } -static int docker_container_inspect(manager_network_function_instance_t *instance) { - assert(instance); +static int docker_container_inspect(docker_container_t *container) { + assert(container); char url[512]; - sprintf(url, "http://v%s/containers/%s/json", framework_environment.docker_engine_version, instance->docker_id); + sprintf(url, "http://v%s/containers/%s/json", framework_environment.settings.docker_engine_version, container->id); char *response = 0; int rc = http_socket_request(url, DOCKER_SOCK_FNAME, "GET", "", 0, &response); if(rc != NTS_ERR_OK) { - log_error("http_socket_request failed"); + log_error("http_socket_request failed\n"); + free(response); return NTS_ERR_FAILED; } cJSON *json_response = cJSON_Parse(response); free(response); if(json_response == 0) { - log_error("cJSON_Parse failed"); + log_error("cJSON_Parse failed\n"); return NTS_ERR_FAILED; } cJSON *main_node = cJSON_GetObjectItem(json_response, "NetworkSettings"); if(main_node == 0) { - log_error("json parsing failed"); + log_error("json parsing failed\n"); cJSON_Delete(json_response); return NTS_ERR_FAILED; } cJSON *node = cJSON_GetObjectItem(main_node, "Networks"); if(node == 0) { - log_error("json parsing failed"); + log_error("json parsing failed\n"); cJSON_Delete(json_response); return NTS_ERR_FAILED; } node = node->child; //get info from the first in array if(node == 0) { - log_error("json parsing failed"); + log_error("json parsing failed\n"); cJSON_Delete(json_response); return NTS_ERR_FAILED; } cJSON *element; - if(framework_environment.ip_v6_enabled) { + if(framework_environment.settings.ip_v6_enabled) { element = cJSON_GetObjectItem(node, "GlobalIPv6Address"); } else { @@ -770,12 +743,12 @@ static int docker_container_inspect(manager_network_function_instance_t *instanc } if(element == 0) { - log_error("json parsing failed"); + log_error("json parsing failed\n"); cJSON_Delete(json_response); return NTS_ERR_FAILED; } - instance->docker_ip = strdup(element->valuestring); + container->docker_ip = strdup(element->valuestring); cJSON_Delete(json_response); return NTS_ERR_OK; diff --git a/ntsimulator/ntsim-ng/core/docker.h b/ntsimulator/ntsim-ng/core/docker.h index 0185594..a44cab6 100644 --- a/ntsimulator/ntsim-ng/core/docker.h +++ b/ntsimulator/ntsim-ng/core/docker.h @@ -18,19 +18,46 @@ #pragma once #include -#include "core/app/manager.h" +#include + +typedef struct { + char *repo; + char *tag; +} docker_available_images_t; + +typedef struct { + char *image; + docker_available_images_t *available_images; + int available_images_count; +} docker_context_t; + +typedef struct { + char *name; + char *id; + + char *docker_ip; + uint16_t docker_netconf_ssh_port; + uint16_t docker_netconf_tls_port; + uint16_t docker_ftp_port; + uint16_t docker_sftp_port; + + char *host_ip; + uint16_t host_netconf_ssh_port; + uint16_t host_netconf_tls_port; + uint16_t host_ftp_port; + uint16_t host_sftp_port; +} docker_container_t; typedef struct { float cpu; float mem; } docker_usage_t; -//init current container. used *only* with --docker-init -bool docker_container_init(void); - //docker container functions for manager -int docker_device_init(void); -int docker_device_start(const manager_network_function_type *function_type, manager_network_function_instance_t *instance); -int docker_device_stop(manager_network_function_instance_t *instance); +int docker_init(const char **filter, int filter_count, const char *min_version, docker_context_t **context); +void docker_free(docker_context_t *context, int count); + +int docker_start(const char *container_name, const char *tag, const char *image, const char *repo, uint16_t host_netconf_ssh_port, uint16_t host_netconf_tls_port, uint16_t host_ftp_port, uint16_t host_sftp_port, docker_container_t *container); +int docker_stop(docker_container_t *container); -docker_usage_t docker_usage_get(const manager_network_function_type *function_type, int function_type_count); +int docker_usage_get(const char **instances_id, int count, docker_usage_t *usage); diff --git a/ntsimulator/ntsim-ng/core/faults/faults.c b/ntsimulator/ntsim-ng/core/faults/faults.c index 12ba223..c60e365 100644 --- a/ntsimulator/ntsim-ng/core/faults/faults.c +++ b/ntsimulator/ntsim-ng/core/faults/faults.c @@ -34,7 +34,7 @@ int faults_init(void) { rc = faults_ves_init(); if(rc != NTS_ERR_OK) { - log_error("faults_ves_init failed"); + log_error("faults_ves_init failed\n"); return NTS_ERR_FAILED; } @@ -87,14 +87,14 @@ fault_details_t *faults_generate_fault(void) { break; default: - log_error("invalid fault choosing method"); + log_error("invalid fault choosing method\n"); return 0; break; } int rc = faults_settings_process(faults, fault_iterator); if(rc != NTS_ERR_OK) { - log_error("faults_settings_process failed"); + log_error("faults_settings_process failed\n"); faults_settings_free(faults); return 0; } diff --git a/ntsimulator/ntsim-ng/core/faults/faults_counters.c b/ntsimulator/ntsim-ng/core/faults/faults_counters.c index 9817a18..500360a 100644 --- a/ntsimulator/ntsim-ng/core/faults/faults_counters.c +++ b/ntsimulator/ntsim-ng/core/faults/faults_counters.c @@ -59,7 +59,7 @@ int faults_counters_increase(const char *severity) { fault_counters.critical++; } else { - log_error("severity not found: %s", severity); + log_error("severity not found: %s\n", severity); ret = NTS_ERR_FAILED; } diff --git a/ntsimulator/ntsim-ng/core/faults/faults_logic.c b/ntsimulator/ntsim-ng/core/faults/faults_logic.c index 879fb5a..9479b43 100644 --- a/ntsimulator/ntsim-ng/core/faults/faults_logic.c +++ b/ntsimulator/ntsim-ng/core/faults/faults_logic.c @@ -34,16 +34,18 @@ void faults_fault_list_clear(void) { free(faults_fault_list); faults_fault_list = 0; faults_fault_list_iterator = 0; + log_add_verbose(2, "[faults] fault list cleared\n"); } int faults_fault_list_add(uint16_t delay) { faults_fault_list_len++; faults_fault_list = (uint16_t *)realloc(faults_fault_list, sizeof(uint16_t) * (faults_fault_list_len)); if(faults_fault_list == 0) { - log_error("realloc failed"); + log_error("realloc failed\n"); return NTS_ERR_FAILED; } faults_fault_list[faults_fault_list_len - 1] = delay; + log_add_verbose(2, "[faults] added %d\n", delay); return NTS_ERR_OK; } diff --git a/ntsimulator/ntsim-ng/core/faults/faults_processing.c b/ntsimulator/ntsim-ng/core/faults/faults_processing.c index 032f99c..2711f37 100644 --- a/ntsimulator/ntsim-ng/core/faults/faults_processing.c +++ b/ntsimulator/ntsim-ng/core/faults/faults_processing.c @@ -36,7 +36,7 @@ fault_settings_t *faults_settings_read(const char *json_plain) { fault_settings_t *ret = (fault_settings_t *)malloc(sizeof(fault_settings_t)); if(ret == 0) { - log_error("malloc failed"); + log_error("malloc failed\n"); goto faults_settings_read_failed_cleanup; } @@ -47,7 +47,7 @@ fault_settings_t *faults_settings_read(const char *json_plain) { cJSON *json = cJSON_Parse(json_plain); if(!json) { - log_error("json parsing error: %s", cJSON_GetErrorPtr()); + log_error("json parsing error: %s\n", cJSON_GetErrorPtr()); goto faults_settings_read_failed_cleanup; } @@ -61,7 +61,7 @@ fault_settings_t *faults_settings_read(const char *json_plain) { ret->yang_notif_template = strdup(node->valuestring); } else { - log_error("could not find yang-notif-template"); + log_error("could not find yang-notif-template\n"); goto faults_settings_read_failed_cleanup; } @@ -70,7 +70,7 @@ fault_settings_t *faults_settings_read(const char *json_plain) { ret->choosing_method = strdup(node->valuestring); } else { - log_error("could not find choosing-method"); + log_error("could not find choosing-method\n"); goto faults_settings_read_failed_cleanup; } @@ -83,7 +83,7 @@ fault_settings_t *faults_settings_read(const char *json_plain) { ret->fault = (fault_details_t *)realloc(ret->fault, sizeof(fault_details_t)*ret->fault_count); if(ret->fault == 0) { ret->fault_count--; - log_error("realloc failed"); + log_error("realloc failed\n"); goto faults_settings_read_failed_cleanup; } @@ -102,14 +102,14 @@ fault_settings_t *faults_settings_read(const char *json_plain) { ret->fault[ret->fault_count - 1].field_name = (char **)realloc(ret->fault[ret->fault_count - 1].field_name, sizeof(char*) * ret->fault[ret->fault_count - 1].field_count); if(ret->fault[ret->fault_count - 1].field_name == 0) { ret->fault[ret->fault_count - 1].field_count--; - log_error("realloc failed"); + log_error("realloc failed\n"); goto faults_settings_read_failed_cleanup; } ret->fault[ret->fault_count - 1].field_value = (char **)realloc(ret->fault[ret->fault_count - 1].field_value, sizeof(char*) * ret->fault[ret->fault_count - 1].field_count); if(ret->fault[ret->fault_count - 1].field_value == 0) { ret->fault[ret->fault_count - 1].field_count--; - log_error("realloc failed"); + log_error("realloc failed\n"); goto faults_settings_read_failed_cleanup; } @@ -119,16 +119,16 @@ fault_settings_t *faults_settings_read(const char *json_plain) { } } else { - log_error("could not find faults list"); + log_error("could not find faults list\n"); goto faults_settings_read_failed_cleanup; } - cJSON_free(json); + cJSON_Delete(json); return ret; faults_settings_read_failed_cleanup: faults_settings_free(ret); - cJSON_free(json); + cJSON_Delete(json); return 0; } @@ -195,32 +195,32 @@ int faults_settings_process(fault_settings_t *faults, int fault_no) { faults->fault[fault_no].yang_notif_processed = fault_process_vars(faults->yang_notif_template, &faults->fault[fault_no]); if(faults->fault[fault_no].condition == 0) { - log_error("could not find condition in fault"); + log_error("could not find condition in fault\n"); return NTS_ERR_FAILED; } if(faults->fault[fault_no].object == 0) { - log_error("could not find object in fault"); + log_error("could not find object in fault\n"); return NTS_ERR_FAILED; } if(faults->fault[fault_no].severity == 0) { - log_error("could not find severity in fault"); + log_error("could not find severity in fault\n"); return NTS_ERR_FAILED; } if(faults->fault[fault_no].date_time == 0) { - log_error("could not find date_time in fault"); + log_error("could not find date_time in fault\n"); return NTS_ERR_FAILED; } if(faults->fault[fault_no].specific_problem == 0) { - log_error("could not find specific_problem in fault"); + log_error("could not find specific_problem in fault\n"); return NTS_ERR_FAILED; } if(faults->fault[fault_no].yang_notif_processed == 0) { - log_error("could not find yang_notif_processed in fault"); + log_error("could not find yang_notif_processed in fault\n"); return NTS_ERR_FAILED; } @@ -233,7 +233,7 @@ static char *fault_process_vars(const char *template, const fault_details_t *det char *ret = strdup(template); if(ret == 0) { - log_error("strdup error"); + log_error("strdup error\n"); return 0; } @@ -272,7 +272,7 @@ static char *fault_process_vars(const char *template, const fault_details_t *det int var_size = pos_end - pos_start + 2; var = (char *)malloc(sizeof(char) * (var_size + 1)); if(var == 0) { - log_error("bad malloc"); + log_error("bad malloc\n"); goto fault_process_vars_failed; } @@ -286,14 +286,14 @@ static char *fault_process_vars(const char *template, const fault_details_t *det vars = (char **)realloc(vars, sizeof(char *) * vars_count); if(!vars) { vars_count = 0; - log_error("bad malloc"); + log_error("bad malloc\n"); goto fault_process_vars_failed; } vars[vars_count - 1] = strdup(var); if(!vars[vars_count - 1]) { vars_count--; - log_error("bad malloc"); + log_error("bad malloc\n"); goto fault_process_vars_failed; } free(var); @@ -309,7 +309,7 @@ static char *fault_process_vars(const char *template, const fault_details_t *det int func_size = pos_end - pos_start + 2; func = (char *)malloc(sizeof(char) * (func_size + 1)); if(func == 0) { - log_error("bad malloc"); + log_error("bad malloc\n"); goto fault_process_vars_failed; } @@ -323,14 +323,14 @@ static char *fault_process_vars(const char *template, const fault_details_t *det funcs = (char **)realloc(funcs, sizeof(char *) * funcs_count); if(!funcs) { funcs_count = 0; - log_error("bad malloc"); + log_error("bad malloc\n"); goto fault_process_vars_failed; } funcs[funcs_count - 1] = strdup(func); if(!funcs[funcs_count - 1]) { funcs_count--; - log_error("bad malloc"); + log_error("bad malloc\n"); goto fault_process_vars_failed; } free(func); @@ -349,7 +349,7 @@ static char *fault_process_vars(const char *template, const fault_details_t *det } if(var_value == 0) { - log_error("value %s not found", vars[i]); + log_error("value %s not found\n", vars[i]); goto fault_process_vars_failed; } @@ -369,7 +369,7 @@ static char *fault_process_vars(const char *template, const fault_details_t *det for(int i = 0; i < funcs_count; i++) { char *func_value = fault_process_function(funcs[i]); if(func_value == 0) { - log_error("function %s not found", vars[i]); + log_error("function %s not found\n", vars[i]); goto fault_process_vars_failed; } diff --git a/ntsimulator/ntsim-ng/core/faults/faults_ves.c b/ntsimulator/ntsim-ng/core/faults/faults_ves.c index e95deed..9340f87 100644 --- a/ntsimulator/ntsim-ng/core/faults/faults_ves.c +++ b/ntsimulator/ntsim-ng/core/faults/faults_ves.c @@ -36,13 +36,13 @@ static cJSON *ves_create_fault_fields(const char *alarm_condition, const char *a static int ves_message_send_internal(sr_session_ctx_t *session, const char *condition, const char *object, const char *severity, const char *date_time, const char *specific_problem, int port, uint32_t *seq_id); int faults_ves_init(void) { - fault_ves_sequence_number = (uint32_t *)malloc(sizeof(uint32_t) * (framework_environment.ssh_connections + framework_environment.tls_connections)); + fault_ves_sequence_number = (uint32_t *)malloc(sizeof(uint32_t) * (framework_environment.settings.ssh_connections + framework_environment.settings.tls_connections)); if(fault_ves_sequence_number == 0) { - log_error("malloc failed"); + log_error("malloc failed\n"); return NTS_ERR_FAILED; } - for(int i = 0; i < (framework_environment.ssh_connections + framework_environment.tls_connections); i++) { + for(int i = 0; i < (framework_environment.settings.ssh_connections + framework_environment.settings.tls_connections); i++) { fault_ves_sequence_number[i] = 0; } @@ -61,22 +61,36 @@ int faults_ves_message_send(sr_session_ctx_t *session, const char *condition, co assert(date_time); assert(specific_problem); + int sequence_index = 0; + int ssh_base_port = 0; + int tls_base_port = 0; nts_mount_point_addressing_method_t mp = nts_mount_point_addressing_method_get(session); if(mp == UNKNOWN_MAPPING) { - log_error("mount-point-addressing-method failed"); + log_error("mount-point-addressing-method failed\n"); return NTS_ERR_FAILED; } + else if(mp == DOCKER_MAPPING) { + ssh_base_port = STANDARD_NETCONF_PORT; + tls_base_port = ssh_base_port + framework_environment.settings.ssh_connections; + } + else { + ssh_base_port = framework_environment.host.ssh_base_port; + tls_base_port = framework_environment.host.tls_base_port; + } - int base_port = STANDARD_NETCONF_PORT; - if(mp == HOST_MAPPING) { - base_port = framework_environment.host_base_port; + for(int port = ssh_base_port; port < ssh_base_port + framework_environment.settings.ssh_connections; port++) { + uint32_t *seq_id = &fault_ves_sequence_number[sequence_index++]; + int rc = ves_message_send_internal(session, condition, object, severity, date_time, specific_problem, port, seq_id); + if(rc != NTS_ERR_OK) { + log_error("ves_message_send_internal failed\n"); + } } - for(int port = base_port; port < base_port + (framework_environment.ssh_connections + framework_environment.tls_connections); port++) { - uint32_t *seq_id = &fault_ves_sequence_number[port - base_port]; + for(int port = tls_base_port; port < tls_base_port + framework_environment.settings.tls_connections; port++) { + uint32_t *seq_id = &fault_ves_sequence_number[sequence_index++]; int rc = ves_message_send_internal(session, condition, object, severity, date_time, specific_problem, port, seq_id); if(rc != NTS_ERR_OK) { - log_error("ves_message_send_internal failed"); + log_error("ves_message_send_internal failed\n"); } } @@ -92,80 +106,80 @@ static cJSON *ves_create_fault_fields(const char *alarm_condition, const char *a cJSON *faultFields = cJSON_CreateObject(); if(faultFields == 0) { - log_error("could not create JSON object: faultFields"); + log_error("could not create JSON object: faultFields\n"); return 0; } if(cJSON_AddStringToObject(faultFields, "faultFieldsVersion", "4.0") == 0) { - log_error("could not create JSON object: faultFieldsVersion"); + log_error("could not create JSON object: faultFieldsVersion\n"); cJSON_Delete(faultFields); return 0; } if(cJSON_AddStringToObject(faultFields, "alarmCondition", alarm_condition) == 0) { - log_error("could not create JSON object: alarmCondition"); + log_error("could not create JSON object: alarmCondition\n"); cJSON_Delete(faultFields); return 0; } if(cJSON_AddStringToObject(faultFields, "alarmInterfaceA", alarm_object) == 0) { - log_error("could not create JSON object: alarmInterfaceA"); + log_error("could not create JSON object: alarmInterfaceA\n"); cJSON_Delete(faultFields); return 0; } if(cJSON_AddStringToObject(faultFields, "eventSourceType", "O_RAN_COMPONENT") == 0) { - log_error("could not create JSON object: eventSourceType"); + log_error("could not create JSON object: eventSourceType\n"); cJSON_Delete(faultFields); return 0; } if(cJSON_AddStringToObject(faultFields, "specificProblem", specific_problem) == 0) { - log_error("could not create JSON object: specificProblem"); + log_error("could not create JSON object: specificProblem\n"); cJSON_Delete(faultFields); return 0; } if(cJSON_AddStringToObject(faultFields, "eventSeverity", severity) == 0) { - log_error("could not create JSON object: eventSeverity"); + log_error("could not create JSON object: eventSeverity\n"); cJSON_Delete(faultFields); return 0; } if(cJSON_AddStringToObject(faultFields, "vfStatus", "Active") == 0) { - log_error("could not create JSON object: vfStatus"); + log_error("could not create JSON object: vfStatus\n"); cJSON_Delete(faultFields); return 0; } cJSON *alarmAdditionalInformation = cJSON_CreateObject(); if(alarmAdditionalInformation == 0) { - log_error("could not create JSON object: alarmAdditionalInformation"); + log_error("could not create JSON object: alarmAdditionalInformation\n"); cJSON_Delete(faultFields); return 0; } cJSON_AddItemToObject(faultFields, "alarmAdditionalInformation", alarmAdditionalInformation); if(cJSON_AddStringToObject(alarmAdditionalInformation, "eventTime", date_time) == 0) { - log_error("could not create JSON object: eventTime"); + log_error("could not create JSON object: eventTime\n"); cJSON_Delete(faultFields); return 0; } if(cJSON_AddStringToObject(alarmAdditionalInformation, "equipType", "O-RAN-sim") == 0) { - log_error("could not create JSON object: equipType"); + log_error("could not create JSON object: equipType\n"); cJSON_Delete(faultFields); return 0; } if(cJSON_AddStringToObject(alarmAdditionalInformation, "vendor", "Melacon") == 0) { - log_error("could not create JSON object: vendor"); + log_error("could not create JSON object: vendor\n"); cJSON_Delete(faultFields); return 0; } if(cJSON_AddStringToObject(alarmAdditionalInformation, "model", "Simulated Device") == 0) { - log_error("could not create JSON object: model"); + log_error("could not create JSON object: model\n"); cJSON_Delete(faultFields); return 0; } @@ -180,28 +194,34 @@ static int ves_message_send_internal(sr_session_ctx_t *session, const char *cond assert(date_time); assert(specific_problem); - char *hostname_string = framework_environment.hostname; + char *hostname_string = framework_environment.settings.hostname; cJSON *post_data_json = cJSON_CreateObject(); if(post_data_json == 0) { - log_error("cJSON_CreateObject failed"); + log_error("cJSON_CreateObject failed\n"); return NTS_ERR_FAILED; } cJSON *event = cJSON_CreateObject(); if(event == 0) { - log_error("cJSON_CreateObject failed"); + log_error("cJSON_CreateObject failed\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } cJSON_AddItemToObject(post_data_json, "event", event); char *source_name = 0; - asprintf(&source_name, "%s-%d", hostname_string, port); + if (framework_environment.settings.ssh_connections + framework_environment.settings.tls_connections == 1) { + // we don't want to append the port to the source name if we only expose one port + asprintf(&source_name, "%s", hostname_string); + } + else { + asprintf(&source_name, "%s_%d", hostname_string, port); + } cJSON *common_event_header = ves_create_common_event_header("fault", "O_RAN_COMPONENT_Alarms", source_name, "Low", (*seq_id)++); free(source_name); if(common_event_header == 0) { - log_error("ves_create_common_event_header failed"); + log_error("ves_create_common_event_header failed\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } @@ -209,7 +229,7 @@ static int ves_message_send_internal(sr_session_ctx_t *session, const char *cond cJSON *fault_fields = ves_create_fault_fields(condition, object, severity, date_time, specific_problem); if(fault_fields == 0) { - log_error("ves_create_fault_fields failed"); + log_error("ves_create_fault_fields failed\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } @@ -218,7 +238,7 @@ static int ves_message_send_internal(sr_session_ctx_t *session, const char *cond char *post_data = cJSON_PrintUnformatted(post_data_json); ves_details_t *ves_details = ves_endpoint_details_get(session); if(!ves_details) { - log_error("ves_endpoint_details_get failed"); + log_error("ves_endpoint_details_get failed\n"); return NTS_ERR_FAILED; } @@ -228,7 +248,7 @@ static int ves_message_send_internal(sr_session_ctx_t *session, const char *cond free(post_data); if(rc != NTS_ERR_OK) { - log_error("http_request failed"); + log_error("http_request failed\n"); return NTS_ERR_FAILED; } diff --git a/ntsimulator/ntsim-ng/core/framework.c b/ntsimulator/ntsim-ng/core/framework.c index c241468..c916d96 100644 --- a/ntsimulator/ntsim-ng/core/framework.c +++ b/ntsimulator/ntsim-ng/core/framework.c @@ -33,119 +33,111 @@ #include "utils/rand_utils.h" framework_arguments_t framework_arguments; -framework_config_t framework_config; framework_environment_t framework_environment; +framework_config_t framework_config; -const char *argp_program_version = "ntsim-ng v1.0.6"; +const char *argp_program_version = 0; //is set later const char *argp_program_bug_address = " / "; static char doc[] = "ntsim - new generation"; static struct argp_option options[] = { - // docker init functionality, independent from rest of the app - { "docker-init", 'i', 0, 0, "Runs initialization tasks for the Docker container that's being built. Do not run manually." }, - - // daemon modes (choose only one) + { "container-init", 'i', 0, 0, "Runs initialization tasks for the Docker container that's being built. Do not run manually." }, + { "supervisor", 's', 0, 0, "Run as supervisor; manager/network-function is chosen via config.json"}, { "manager", 'm', 0, 0, "Run the daemon as manager." }, { "network-function", 'f', 0, 0, "Run the daemon as network function." }, - - // global settings, can be combined - { "operational-only", 'o', 0, 0, "When this is set, the RUNNING datastore is actually the OPERATIONAL one." }, + { "generate", 'g', 0, 0, "Generate population data without commiting." }, + { "test-mode", 't', 0, 0, "Test mode." }, + + // tools + { "ls", '1', 0, 0, "Print all available root paths." }, + { "schema", '2', "XPATH", 0, "Print schema for XPATH." }, + { "fixed-rand", 'r', "SEED", 0, "Initialize RAND seed to a fixed value (for debugging purposes)." }, { "verbose", 'v', "LEVEL", 0, "Verbosity level for printing to stdout (logs will still save everything). LEVEL is: 0=errors only, 1=requested info(default), 2=info" }, { "workspace", 'w', "PATH", 0, "Initialize workspace to a different one than the current working directory." }, - - // test modes (choose only one) - { "test-mode", 't', 0, 0, "Test mode to be deleted after." }, - { "exhaustive-test", '0', 0, 0, "Do an automated test on the whole delpoy." }, - - // functions, can be combined - { "ls", '1', 0, 0, "Print all available root paths." }, - { "schema", '2', "XPATH", 0, "Print schema for XPATH." }, - { "populate", '3', 0, 0, "Populate everything." }, - { "enable-features", '4', 0, 0, "Enables features. Usually works combined with populate." }, - - // function settings, can be combined with functions as well - { "nc-server-init", 'n', 0, 0, "Sets netconf server configuration." }, - { "loop", 'l', 0, 0, "After doing the job, don't exit until CTRL+C is pressed." }, { 0 } }; volatile sig_atomic_t framework_sigint; -static void framework_signal_handler(int signo); +static int framework_env_init(void); +static int framework_config_init(void); + +static void framework_signal_handler(int signo); static error_t parse_opt(int key, char *arg, struct argp_state *state); -void framework_init(int argc, char **argv) { +int framework_init(int argc, char **argv) { + //environment vars + framework_environment.nts.version = getenv(ENV_VAR_NTS_BUILD_VERSION) ? strdup(getenv(ENV_VAR_NTS_BUILD_VERSION)) : strdup("N/A"); + framework_environment.nts.build_time = getenv(ENV_VAR_NTS_BUILD_TIME) ? strdup(getenv(ENV_VAR_NTS_BUILD_TIME)) : strdup("N/A"); + + //set argp_version + char *version = 0; + asprintf(&version, "ntsim-ng v%s build %s", framework_environment.nts.version, framework_environment.nts.build_time); + argp_program_version = version; + //initialize app arguments - framework_arguments.container_init = false; - framework_arguments.nc_server_init = false; + framework_arguments.nts_mode = NTS_MODE_DEFAULT; + + framework_arguments.argc = argc; + framework_arguments.argv = argv; - framework_arguments.manager = false; - framework_arguments.network_function = false; - framework_arguments.no_rand = false; framework_arguments.fixed_seed = 0; - framework_arguments.operational_only = false; framework_arguments.verbosity_level = 1; - framework_arguments.loop = false; - framework_arguments.test_mode = false; - - framework_arguments.exhaustive_test = false; + framework_arguments.print_root_paths = false; framework_arguments.print_structure_xpath = 0; - framework_arguments.populate_all = false; - framework_arguments.enable_features = false; + //parse provided command line arguments + struct argp argp = { options, parse_opt, 0, doc, 0, 0, 0 }; + argp_parse(&argp, argc, argv, 0, 0, &framework_arguments); + + //manage signals framework_sigint = 0; signal(SIGINT, framework_signal_handler); signal(SIGTERM, framework_signal_handler); - signal(SIGKILL, framework_signal_handler); signal(SIGQUIT, framework_signal_handler); - //parse provided command line arguments - struct argp argp = { options, parse_opt, 0, doc, 0, 0, 0 }; - argp_parse(&argp, argc, argv, 0, 0, &framework_arguments); - //disable buffering for stdout setbuf(stdout, NULL); - int status = 0; - - //test whether log and config folders are ok - if(!dir_exists("config")) { - status |= 1; - mkdir("config", 0777); - } + //init logging subsystem + char *log_file = 0; + char *stderr_file = 0; if(!dir_exists("log")) { - status |= 2; mkdir("log", 0777); } - //init logging subsystem - log_init("log/log.txt"); - log_message(2, "app was called: "); - for(int i = 0; i < argc; i++) { - log_message(2, "%s ", argv[i]); - } - log_message(2, "\n"); + switch(framework_arguments.nts_mode) { + case NTS_MODE_CONTAINER_INIT: + log_file = "log/log-install.txt"; + stderr_file = "log/stderr-install.txt"; + break; - char cwd[PATH_MAX]; - getcwd(cwd, sizeof(cwd)); - log_message(2, "current working dir is: %s\n", cwd); + case NTS_MODE_SUPERVISOR: + log_file = "log/log-supervisor.txt"; + stderr_file = "log/stderr-supervisor.txt"; + break; - if(status & 1) { - log_message(2, "config folder wasn't found, and was created.\n"); - } + case NTS_MODE_GENERATE_DATA: + log_file = "log/log-generate.txt"; + stderr_file = "log/stderr-generate.txt"; + break; - if(status & 2) { - log_message(2, "log folder wasn't found, and was created.\n"); + default: + log_file = "log/log.txt"; + stderr_file = "log/stderr.txt"; + break; } - if(!file_exists("config/config.json")) { - log_message(2, "config.json file missing. created.\n"); - file_touch("config/config.json", "{}"); - } + log_init(log_file); + log_redirect_stderr(stderr_file); + + char cwd[PATH_MAX]; + getcwd(cwd, sizeof(cwd)); + log_add_verbose(2, "[framework] current working dir is: %s\n", cwd); //init rand generator if needed if(framework_arguments.no_rand == false) { @@ -155,397 +147,618 @@ void framework_init(int argc, char **argv) { rand_init_fixed(framework_arguments.fixed_seed); } + log_add_verbose(2, "[framework] app was called: "); + for(int i = 0; i < argc; i++) { + log_add(2, "%s ", argv[i]); + } + log_add(2, "\n"); + + if(framework_env_init() != NTS_ERR_OK) { + log_error("[framework] framework_env_init() failed\n"); + return NTS_ERR_FAILED; + } + + if(framework_config_init() != NTS_ERR_OK) { + log_error("[framework] framework_config_init() failed\n"); + return NTS_ERR_FAILED; + } + + log_add_verbose(2, "[framework] init complete\n"); + return NTS_ERR_OK; +} + +static int framework_env_init(void) { + log_add_verbose(2, "[framework-env] started\n"); + + /* + The following env vars are taken care of by framework_init() + framework_environment.nts.version + framework_environment.nts.build_time + */ + + framework_environment.nts.manual = getenv(ENV_VAR_NTS_MANUAL) ? true : false; + framework_environment.nts.function_type = getenv(ENV_VAR_NTS_FUNCTION_TYPE) ? strdup(getenv(ENV_VAR_NTS_FUNCTION_TYPE)) : strdup(""); + framework_environment.nts.nf_standalone_start_features = getenv(ENV_VAR_NTS_NF_STANDALONE_START_FEATURES) ? strdup(getenv(ENV_VAR_NTS_NF_STANDALONE_START_FEATURES)) : strdup(""); + + framework_environment.settings.docker_engine_version = getenv(ENV_VAR_DOCKER_ENGINE_VERSION) ? strdup(getenv(ENV_VAR_DOCKER_ENGINE_VERSION)) : strdup("1.40"); + framework_environment.settings.hostname = getenv(ENV_VAR_HOSTNAME) ? strdup(getenv(ENV_VAR_HOSTNAME)) : strdup("localhost"); + + bool ip_ok = get_local_ips("eth0", &framework_environment.settings.ip_v4, &framework_environment.settings.ip_v6); + if(!ip_ok) { + log_error("[framework-env] could not get local IP addresses\n"); + } + + char *ipv6_env_var = getenv(ENV_VAR_IPV6ENABLED); + if(ipv6_env_var == 0) { + log_error("[framework-env] could not get the IPv6 Enabled env variable\n"); + } + framework_environment.settings.ip_v6_enabled = (strcmp(ipv6_env_var, "true") == 0) ? true : false; + framework_environment.settings.ssh_connections = get_int_from_string_with_default(getenv(ENV_VAR_SSH_CONNECTIONS), 1); + framework_environment.settings.tls_connections = get_int_from_string_with_default(getenv(ENV_VAR_TLS_CONNECTIONS), 0); + framework_environment.settings.ftp_connections = 1; + framework_environment.settings.sftp_connections = 1; + + //build version and build time are set in the begining of the function + framework_environment.host.ip = getenv(ENV_VAR_HOST_IP) ? strdup(getenv(ENV_VAR_HOST_IP)) : strdup("127.0.0.1"); + framework_environment.host.base_port = get_int_from_string_with_default(getenv(ENV_VAR_HOST_BASE_PORT), 1000); + framework_environment.host.ssh_base_port = get_int_from_string_with_default(getenv(ENV_VAR_HOST_NETCONF_SSH_BASE_PORT), 0); + framework_environment.host.tls_base_port = get_int_from_string_with_default(getenv(ENV_VAR_HOST_NETCONF_TLS_BASE_PORT), 0); + framework_environment.host.ftp_base_port = get_int_from_string_with_default(getenv(ENV_VAR_HOST_TRANSFER_FTP_BASE_PORT), 0); + framework_environment.host.sftp_base_port = get_int_from_string_with_default(getenv(ENV_VAR_HOST_TRANSFER_SFTP_BASE_PORT), 0); + + framework_environment.sdn_controller.protocol = getenv(ENV_VAR_SDN_CONTROLLER_IP) ? strdup(getenv(ENV_VAR_SDN_CONTROLLER_PROTOCOL)) : strdup("https"); + framework_environment.sdn_controller.ip = getenv(ENV_VAR_SDN_CONTROLLER_IP) ? strdup(getenv(ENV_VAR_SDN_CONTROLLER_IP)) : strdup("127.0.0.1"); + framework_environment.sdn_controller.port = get_int_from_string_with_default(getenv(ENV_VAR_SDN_CONTROLLER_PORT), 8181); + framework_environment.sdn_controller.callhome_port = get_int_from_string_with_default(getenv(ENV_VAR_SDN_CONTROLLER_CALLHOME_PORT), 6666); + framework_environment.sdn_controller.username = getenv(ENV_VAR_SDN_CONTROLLER_USERNAME) ? strdup(getenv(ENV_VAR_SDN_CONTROLLER_USERNAME)) : strdup("admin"); + framework_environment.sdn_controller.password = getenv(ENV_VAR_SDN_CONTROLLER_PASSWORD) ? strdup(getenv(ENV_VAR_SDN_CONTROLLER_PASSWORD)) : strdup("admin"); + + framework_environment.ves_endpoint.common_header_version = getenv(ENV_VAR_VES_COMMON_HEADER_VERSION) ? strdup(getenv(ENV_VAR_VES_COMMON_HEADER_VERSION)) : strdup("7.2"); + framework_environment.ves_endpoint.protocol = getenv(ENV_VAR_VES_ENDPOINT_PROTOCOL) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_PROTOCOL)) : strdup("https"); + framework_environment.ves_endpoint.ip = getenv(ENV_VAR_VES_ENDPOINT_IP) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_IP)) : strdup("127.0.0.1"); + framework_environment.ves_endpoint.port = get_int_from_string_with_default(getenv(ENV_VAR_VES_ENDPOINT_PORT), 1234); + framework_environment.ves_endpoint.auth_method = getenv(ENV_VAR_VES_ENDPOINT_AUTH_METHOD) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_AUTH_METHOD)) : strdup("no-auth"); + framework_environment.ves_endpoint.username = getenv(ENV_VAR_VES_ENDPOINT_USERNAME) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_USERNAME)) : strdup("admin"); + framework_environment.ves_endpoint.password = getenv(ENV_VAR_VES_ENDPOINT_PASSWORD) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_PASSWORD)) : strdup("admin"); + framework_environment.ves_endpoint.certificate = getenv(ENV_VAR_VES_ENDPOINT_CERTIFICATE) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_CERTIFICATE)) : strdup(""); + + log_add_verbose(2, "[framework-env] nts.manual = %d\n", framework_environment.nts.manual); + log_add_verbose(2, "[framework-env] nts.version = %s\n", framework_environment.nts.version); + log_add_verbose(2, "[framework-env] nts.build_time = %s\n", framework_environment.nts.build_time); + log_add_verbose(2, "[framework-env] nts.function_type = %s\n", framework_environment.nts.function_type); + log_add_verbose(2, "[framework-env] nts.nf_standalone_start_features = %s\n", framework_environment.nts.nf_standalone_start_features); + + log_add_verbose(2, "[framework-env] settings.docker_engine_version = %s\n", framework_environment.settings.docker_engine_version); + log_add_verbose(2, "[framework-env] settings.hostname = %s\n", framework_environment.settings.hostname); + log_add_verbose(2, "[framework-env] settings.ip_v4 = %s\n", framework_environment.settings.ip_v4); + log_add_verbose(2, "[framework-env] settings.ip_v6 = %s\n", framework_environment.settings.ip_v6); + log_add_verbose(2, "[framework-env] settings.ip_v6_enabled = %s\n", framework_environment.settings.ip_v6_enabled ? "true" : "false"); + log_add_verbose(2, "[framework-env] settings.ssh_connections = %d\n", framework_environment.settings.ssh_connections); + log_add_verbose(2, "[framework-env] settings.tls_connections = %d\n", framework_environment.settings.tls_connections); + log_add_verbose(2, "[framework-env] settings.ftp_connections = %d\n", framework_environment.settings.ftp_connections); + log_add_verbose(2, "[framework-env] settings.sftp_connections = %d\n", framework_environment.settings.sftp_connections); + + //check ports + if(framework_environment.host.base_port < 1000) { + log_add_verbose(2, "[framework-env] host.base_port < 1000 -> disabling\n"); + framework_environment.host.base_port = 0; + } + + if(framework_environment.host.ssh_base_port < 1000) { + log_add_verbose(2, "[framework-env] host.ssh_base_port < 1000 -> using base_port\n"); + framework_environment.host.ssh_base_port = framework_environment.host.base_port; + } + + if(framework_environment.host.tls_base_port < 1000) { + log_add_verbose(2, "[framework-env] host.tls_base_port < 1000 -> using base_port\n"); + framework_environment.host.tls_base_port = framework_environment.host.base_port; + } + + if(framework_environment.host.ftp_base_port < 1000) { + log_add_verbose(2, "[framework-env] host.ftp_base_port < 1000 -> using base_port\n"); + framework_environment.host.ftp_base_port = framework_environment.host.base_port; + } + + if(framework_environment.host.sftp_base_port < 1000) { + log_add_verbose(2, "[framework-env] host.sftp_base_port < 1000 -> using base_port\n"); + framework_environment.host.sftp_base_port = framework_environment.host.base_port; + } + + if(framework_environment.host.base_port == 0) { + if(framework_environment.host.ssh_base_port == 0) { + log_error("[framework-env] host.ssh_base_port unknown\n"); + return NTS_ERR_FAILED; + } + + if(framework_environment.host.tls_base_port == 0) { + log_error("[framework-env] host.tls_base_port unknown\n"); + return NTS_ERR_FAILED; + } + + if(framework_environment.host.ftp_base_port == 0) { + log_error("[framework-env] host.ftp_base_port unknown\n"); + return NTS_ERR_FAILED; + } + + if(framework_environment.host.sftp_base_port == 0) { + log_error("[framework-env] host.sftp_base_port unknown\n"); + return NTS_ERR_FAILED; + } + } + + log_add_verbose(2, "[framework-env] host.ip = %s\n", framework_environment.host.ip); + log_add_verbose(2, "[framework-env] host.base_port = %d\n", framework_environment.host.base_port); + log_add_verbose(2, "[framework-env] host.ssh_base_port = %d\n", framework_environment.host.ssh_base_port); + log_add_verbose(2, "[framework-env] host.tls_base_port = %d\n", framework_environment.host.tls_base_port); + log_add_verbose(2, "[framework-env] host.ftp_base_port = %d\n", framework_environment.host.ftp_base_port); + log_add_verbose(2, "[framework-env] host.sftp_base_port = %d\n", framework_environment.host.sftp_base_port); + + log_add_verbose(2, "[framework-env] sdn_controller.protocol = %s\n", framework_environment.sdn_controller.protocol); + log_add_verbose(2, "[framework-env] sdn_controller.ip = %s\n", framework_environment.sdn_controller.ip); + log_add_verbose(2, "[framework-env] sdn_controller.port = %d\n", framework_environment.sdn_controller.port); + log_add_verbose(2, "[framework-env] sdn_controller.callhome_port = %d\n", framework_environment.sdn_controller.callhome_port); + log_add_verbose(2, "[framework-env] sdn_controller.username = %s\n", framework_environment.sdn_controller.username); + log_add_verbose(2, "[framework-env] sdn_controller.password = %s\n", framework_environment.sdn_controller.password); + + log_add_verbose(2, "[framework-env] ves_endpoint.common_header_version = %s\n", framework_environment.ves_endpoint.common_header_version); + log_add_verbose(2, "[framework-env] ves_endpoint.protocol = %s\n", framework_environment.ves_endpoint.protocol); + log_add_verbose(2, "[framework-env] ves_endpoint.ip = %s\n", framework_environment.ves_endpoint.ip); + log_add_verbose(2, "[framework-env] ves_endpoint.port = %d\n", framework_environment.ves_endpoint.port); + log_add_verbose(2, "[framework-env] ves_endpoint.auth_method = %s\n", framework_environment.ves_endpoint.auth_method); + log_add_verbose(2, "[framework-env] ves_endpoint.username = %s\n", framework_environment.ves_endpoint.username); + log_add_verbose(2, "[framework-env] ves_endpoint.password = %s\n", framework_environment.ves_endpoint.password); + log_add_verbose(2, "[framework-env] ves_endpoint.certificate = %s\n", framework_environment.ves_endpoint.certificate); + + log_add_verbose(2, "[framework-env] finished\n"); + return NTS_ERR_OK; +} + +static int framework_config_init(void) { + log_add_verbose(2, "[framework-config] started\n"); + //init app config - framework_config.docker_excluded_modules = 0; - framework_config.docker_excluded_modules_count = 0; - framework_config.docker_excluded_features = 0; - framework_config.docker_excluded_features_count = 0; - framework_config.debug_max_string_size = 0; - framework_config.populate_excluded_modules = 0; - framework_config.populate_excluded_modules_count = 0; - framework_config.default_list_instances = 1; - framework_config.custom_list_instances_count = 0; - framework_config.custom_list_instances = 0; - framework_config.restrict_schema_count = 0; - framework_config.restrict_schema = 0; - - log_message(2, "starting parsing config.json\n"); + framework_config.docker.excluded_modules = 0; + framework_config.docker.excluded_modules_count = 0; + framework_config.docker.excluded_features = 0; + framework_config.docker.excluded_features_count = 0; + + framework_config.supervisor.rules_count = 0; + framework_config.supervisor.rules = 0; + + framework_config.datastore_generate.debug_max_string_size = 0; + framework_config.datastore_generate.excluded_modules = 0; + framework_config.datastore_generate.excluded_modules_count = 0; + framework_config.datastore_generate.default_list_instances = 1; + framework_config.datastore_generate.custom_list_instances_count = 0; + framework_config.datastore_generate.custom_list_instances = 0; + framework_config.datastore_generate.restrict_schema_count = 0; + framework_config.datastore_generate.restrict_schema = 0; + + framework_config.datastore_populate.random_generation_enabled = 1; + framework_config.datastore_populate.preg_operational_count = 0; + framework_config.datastore_populate.preg_operational = 0; + framework_config.datastore_populate.preg_running_count = 0; + framework_config.datastore_populate.preg_running = 0; + + //config init + if(!dir_exists("config")) { + log_add_verbose(2, "[framework-config] config/ folder wasn't found; created.\n"); + mkdir("config", 0777); + } + + if(!file_exists("config/config.json")) { + log_add_verbose(2, "[framework-config] config.json file missing; created.\n"); + file_touch("config/config.json", "{}"); + } + + log_add_verbose(2, "[framework-config] parsing config.json\n"); char *config_contents = file_read_content("config/config.json"); cJSON *json = cJSON_Parse(config_contents); free(config_contents); if(!json) { - log_error("config.json :%s", cJSON_GetErrorPtr()); + log_error("[framework-config] config.json error: %s\n", cJSON_GetErrorPtr()); } else { cJSON *main_node; cJSON *node; - main_node = cJSON_GetObjectItem(json, "docker-rules"); - if(main_node) { - node = cJSON_GetObjectItem(main_node, "excluded-modules"); - if(node) { - if(cJSON_IsArray(node)) { - cJSON *element; - cJSON_ArrayForEach(element, node) { - if(cJSON_IsString(element)) { - log_message(2, "adding docker-rules/exclude-modules: %s\n", element->valuestring); - framework_config.docker_excluded_modules = (char **)realloc(framework_config.docker_excluded_modules, sizeof(char*) * (framework_config.docker_excluded_modules_count + 1)); - if(!framework_config.docker_excluded_modules) { - log_error("bad realloc"); - } - framework_config.docker_excluded_modules[framework_config.docker_excluded_modules_count] = (char *)malloc(sizeof(char) * (strlen(element->valuestring) + 1)); - if(!framework_config.docker_excluded_modules[framework_config.docker_excluded_modules_count]) { - log_error("bad malloc"); + if(framework_arguments.nts_mode == NTS_MODE_CONTAINER_INIT) { + main_node = cJSON_GetObjectItem(json, "container-rules"); + if(main_node) { + node = cJSON_GetObjectItem(main_node, "excluded-modules"); + if(node) { + if(cJSON_IsArray(node)) { + cJSON *element; + cJSON_ArrayForEach(element, node) { + if(cJSON_IsString(element)) { + log_add_verbose(2, "[framework-config] adding container-rules/exclude-modules: %s\n", element->valuestring); + framework_config.docker.excluded_modules = (char **)realloc(framework_config.docker.excluded_modules, sizeof(char*) * (framework_config.docker.excluded_modules_count + 1)); + if(!framework_config.docker.excluded_modules) { + log_error("[framework-config] bad realloc\n"); + } + framework_config.docker.excluded_modules[framework_config.docker.excluded_modules_count] = (char *)malloc(sizeof(char) * (strlen(element->valuestring) + 1)); + if(!framework_config.docker.excluded_modules[framework_config.docker.excluded_modules_count]) { + log_error("[framework-config] bad malloc\n"); + } + strcpy(framework_config.docker.excluded_modules[framework_config.docker.excluded_modules_count], element->valuestring); + framework_config.docker.excluded_modules_count++; } - strcpy(framework_config.docker_excluded_modules[framework_config.docker_excluded_modules_count], element->valuestring); - framework_config.docker_excluded_modules_count++; } } } - } - node = cJSON_GetObjectItem(main_node, "excluded-features"); - if(node) { - if(cJSON_IsArray(node)) { - cJSON *element; - cJSON_ArrayForEach(element, node) { - if(cJSON_IsString(element)) { - log_message(2, "adding docker-rules/excluded-features: %s\n", element->valuestring); - framework_config.docker_excluded_features = (char **)realloc(framework_config.docker_excluded_features, sizeof(char*) * (framework_config.docker_excluded_features_count + 1)); - if(!framework_config.docker_excluded_features) { - log_error("bad realloc"); - } - framework_config.docker_excluded_features[framework_config.docker_excluded_features_count] = (char *)malloc(sizeof(char) * (strlen(element->valuestring) + 1)); - if(!framework_config.docker_excluded_features[framework_config.docker_excluded_features_count]) { - log_error("bad malloc"); + node = cJSON_GetObjectItem(main_node, "excluded-features"); + if(node) { + if(cJSON_IsArray(node)) { + cJSON *element; + cJSON_ArrayForEach(element, node) { + if(cJSON_IsString(element)) { + log_add_verbose(2, "[framework-config] adding container-rules/excluded-features: %s\n", element->valuestring); + framework_config.docker.excluded_features = (char **)realloc(framework_config.docker.excluded_features, sizeof(char*) * (framework_config.docker.excluded_features_count + 1)); + if(!framework_config.docker.excluded_features) { + log_error("[framework-config] bad realloc\n"); + } + framework_config.docker.excluded_features[framework_config.docker.excluded_features_count] = (char *)malloc(sizeof(char) * (strlen(element->valuestring) + 1)); + if(!framework_config.docker.excluded_features[framework_config.docker.excluded_features_count]) { + log_error("[framework-config] bad malloc\n"); + } + strcpy(framework_config.docker.excluded_features[framework_config.docker.excluded_features_count], element->valuestring); + framework_config.docker.excluded_features_count++; } - strcpy(framework_config.docker_excluded_features[framework_config.docker_excluded_features_count], element->valuestring); - framework_config.docker_excluded_features_count++; } } } } } + else if(framework_arguments.nts_mode == NTS_MODE_SUPERVISOR) { + main_node = cJSON_GetObjectItem(json, "supervisor-rules"); + if(main_node) { + cJSON *app; + cJSON_ArrayForEach(app, main_node) { + if(cJSON_IsObject(app)) { + cJSON *object = cJSON_GetObjectItem(app, "path"); + if(object) { + framework_config.supervisor.rules = (supervisor_rules_t *)realloc(framework_config.supervisor.rules, sizeof(supervisor_rules_t) * (framework_config.supervisor.rules_count + 1)); + if(!framework_config.supervisor.rules) { + log_error("[framework-config] bad realloc\n"); + } + + char *path = strdup(object->valuestring); + bool autorestart = false; + bool nomanual = false; + char *stdout_path = 0; + char *stderr_path = 0; + + int args_count = 0; + char **args = 0; + cJSON *args_json = cJSON_GetObjectItem(app, "args"); + if(args_json) { + args_count = cJSON_GetArraySize(args_json); + if(args_count) { + args = malloc(sizeof(char *) * args_count); + int i = 0; + cJSON *arg; + cJSON_ArrayForEach(arg, args_json) { + args[i] = strdup(arg->valuestring); + i++; + } + } + } - main_node = cJSON_GetObjectItem(json, "debug-max-string-size"); - if(main_node) { - framework_config.debug_max_string_size = main_node->valueint; - log_message(2, "setting debug-max-string-sizes: %d\n", framework_config.debug_max_string_size); - } + object = cJSON_GetObjectItem(app, "autorestart"); + if(object) { + autorestart = object->valueint; + } + + object = cJSON_GetObjectItem(app, "nomanual"); + if(object) { + nomanual = object->valueint; + } - main_node = cJSON_GetObjectItem(json, "populate-rules"); - if(main_node) { - node = cJSON_GetObjectItem(main_node, "excluded-modules"); - if(node) { - if(cJSON_IsArray(node)) { - cJSON *element; - cJSON_ArrayForEach(element, node) { - if(cJSON_IsString(element)) { - log_message(2, "adding populate-rules/excluded-modules: %s\n", element->valuestring); - framework_config.populate_excluded_modules = (char **)realloc(framework_config.populate_excluded_modules, sizeof(char*) * (framework_config.populate_excluded_modules_count + 1)); - if(!framework_config.populate_excluded_modules) { - log_error("bad realloc"); + object = cJSON_GetObjectItem(app, "stdout"); + if(object) { + stdout_path = strdup(object->valuestring); } - framework_config.populate_excluded_modules[framework_config.populate_excluded_modules_count] = (char *)malloc(sizeof(char) * (strlen(element->valuestring) + 1)); - if(!framework_config.populate_excluded_modules[framework_config.populate_excluded_modules_count]) { - log_error("bad malloc"); + + object = cJSON_GetObjectItem(app, "stderr"); + if(object) { + stderr_path = strdup(object->valuestring); } - strcpy(framework_config.populate_excluded_modules[framework_config.populate_excluded_modules_count], element->valuestring); - framework_config.populate_excluded_modules_count++; + + framework_config.supervisor.rules[framework_config.supervisor.rules_count].name = strdup(app->string); + framework_config.supervisor.rules[framework_config.supervisor.rules_count].path = path; + framework_config.supervisor.rules[framework_config.supervisor.rules_count].args = args; + framework_config.supervisor.rules[framework_config.supervisor.rules_count].args_count = args_count; + framework_config.supervisor.rules[framework_config.supervisor.rules_count].autorestart = autorestart; + framework_config.supervisor.rules[framework_config.supervisor.rules_count].nomanual = nomanual; + framework_config.supervisor.rules[framework_config.supervisor.rules_count].stdout_path = stdout_path; + framework_config.supervisor.rules[framework_config.supervisor.rules_count].stderr_path = stderr_path; + + log_add_verbose(2, "[framework-config] adding supervisor command: %s with autorestart: %d\n", path, autorestart); + framework_config.supervisor.rules_count++; } } } } + } + else { + main_node = cJSON_GetObjectItem(json, "datastore-random-generation-rules"); + if(main_node) { + node = cJSON_GetObjectItem(main_node, "excluded-modules"); + if(node) { + if(cJSON_IsArray(node)) { + cJSON *element; + cJSON_ArrayForEach(element, node) { + if(cJSON_IsString(element)) { + log_add_verbose(2, "[framework-config] adding datastore-random-generation-rules/excluded-modules: %s\n", element->valuestring); + framework_config.datastore_generate.excluded_modules = (char **)realloc(framework_config.datastore_generate.excluded_modules, sizeof(char*) * (framework_config.datastore_generate.excluded_modules_count + 1)); + if(!framework_config.datastore_generate.excluded_modules) { + log_error("[framework-config] bad realloc\n"); + } + framework_config.datastore_generate.excluded_modules[framework_config.datastore_generate.excluded_modules_count] = (char *)malloc(sizeof(char) * (strlen(element->valuestring) + 1)); + if(!framework_config.datastore_generate.excluded_modules[framework_config.datastore_generate.excluded_modules_count]) { + log_error("[framework-config] bad malloc\n"); + } + strcpy(framework_config.datastore_generate.excluded_modules[framework_config.datastore_generate.excluded_modules_count], element->valuestring); + framework_config.datastore_generate.excluded_modules_count++; + } + } + } + } - node = cJSON_GetObjectItem(main_node, "default-list-instances"); - if(node) { - if(cJSON_IsNumber(node)) { - framework_config.default_list_instances = node->valueint; - log_message(2, "found populate-rules/default-list-instances to be: %d\n", framework_config.default_list_instances); + node = cJSON_GetObjectItem(main_node, "debug-max-string-size"); + if(node) { + framework_config.datastore_generate.debug_max_string_size = node->valueint; + log_add_verbose(2, "[framework-config] setting datastore-random-generation-rules/debug-max-string-size: %d\n", framework_config.datastore_generate.debug_max_string_size); + } + + node = cJSON_GetObjectItem(main_node, "default-list-instances"); + if(node) { + if(cJSON_IsNumber(node)) { + framework_config.datastore_generate.default_list_instances = node->valueint; + log_add_verbose(2, "[framework-config] setting datastore-random-generation-rules/default-list-instances: %d\n", framework_config.datastore_generate.default_list_instances); + } } - } - node = cJSON_GetObjectItem(main_node, "custom-list-instances"); - if(node) { - if(cJSON_IsArray(node)) { - cJSON *element; - cJSON_ArrayForEach(element, node) { - if(cJSON_IsObject(element)) { - cJSON *object; - cJSON_ArrayForEach(object, element) { - char *path = object->string; - int count = object->valueint; - log_message(2, "adding populate-rules/custom-list-instances %s - %d\n", path, count); - framework_config.custom_list_instances = (custom_list_instances_t *)realloc(framework_config.custom_list_instances, sizeof(custom_list_instances_t) * (framework_config.custom_list_instances_count + 1)); - if(!framework_config.custom_list_instances) { - log_error("bad realloc"); + node = cJSON_GetObjectItem(main_node, "custom-list-instances"); + if(node) { + if(cJSON_IsArray(node)) { + cJSON *element; + cJSON_ArrayForEach(element, node) { + if(cJSON_IsObject(element)) { + cJSON *object; + cJSON_ArrayForEach(object, element) { + char *path = object->string; + int count = object->valueint; + log_add_verbose(2, "[framework-config] adding datastore-random-generation-rules/custom-list-instances %s - %d\n", path, count); + framework_config.datastore_generate.custom_list_instances = (custom_list_instances_t *)realloc(framework_config.datastore_generate.custom_list_instances, sizeof(custom_list_instances_t) * (framework_config.datastore_generate.custom_list_instances_count + 1)); + if(!framework_config.datastore_generate.custom_list_instances) { + log_error("[framework-config] bad realloc\n"); + } + + framework_config.datastore_generate.custom_list_instances[framework_config.datastore_generate.custom_list_instances_count].path = (char *)malloc(sizeof(char) * (strlen(path) + 1)); + if(!framework_config.datastore_generate.custom_list_instances[framework_config.datastore_generate.custom_list_instances_count].path) { + log_error("[framework-config] bad malloc\n"); + } + strcpy(framework_config.datastore_generate.custom_list_instances[framework_config.datastore_generate.custom_list_instances_count].path, path); + framework_config.datastore_generate.custom_list_instances[framework_config.datastore_generate.custom_list_instances_count].count = count; + framework_config.datastore_generate.custom_list_instances_count++; } - - framework_config.custom_list_instances[framework_config.custom_list_instances_count].path = (char *)malloc(sizeof(char) * (strlen(path) + 1)); - if(!framework_config.custom_list_instances[framework_config.custom_list_instances_count].path) { - log_error("bad malloc"); + } + } + } + } + + node = cJSON_GetObjectItem(main_node, "restrict-schema"); + if(node) { + if(cJSON_IsArray(node)) { + cJSON *element; + cJSON_ArrayForEach(element, node) { + if(cJSON_IsObject(element)) { + cJSON *object; + cJSON_ArrayForEach(object, element) { + char *path = object->string; + + log_add_verbose(2, "[framework-config] adding datastore-random-generation-rules/restrict-schema: %s with values:", path); + framework_config.datastore_generate.restrict_schema = (restrict_schema_t *)realloc(framework_config.datastore_generate.restrict_schema, sizeof(restrict_schema_t) * (framework_config.datastore_generate.restrict_schema_count + 1)); + if(!framework_config.datastore_generate.restrict_schema) { + log_error("[framework-config] bad realloc\n"); + } + + framework_config.datastore_generate.restrict_schema[framework_config.datastore_generate.restrict_schema_count].path = (char *)malloc(sizeof(char) * (strlen(path) + 1)); + if(!framework_config.datastore_generate.restrict_schema[framework_config.datastore_generate.restrict_schema_count].path) { + log_error("[framework-config] bad malloc\n"); + } + strcpy(framework_config.datastore_generate.restrict_schema[framework_config.datastore_generate.restrict_schema_count].path, path); + + + framework_config.datastore_generate.restrict_schema[framework_config.datastore_generate.restrict_schema_count].values_count = 0; + framework_config.datastore_generate.restrict_schema[framework_config.datastore_generate.restrict_schema_count].values = 0; + framework_config.datastore_generate.restrict_schema[framework_config.datastore_generate.restrict_schema_count].index = 0; + cJSON *value; + cJSON_ArrayForEach(value, object) { + if(cJSON_IsString(value)) { + framework_config.datastore_generate.restrict_schema[framework_config.datastore_generate.restrict_schema_count].values = (char **)realloc(framework_config.datastore_generate.restrict_schema[framework_config.datastore_generate.restrict_schema_count].values, sizeof(char*) * (framework_config.datastore_generate.restrict_schema[framework_config.datastore_generate.restrict_schema_count].values_count + 1)); + if(!framework_config.datastore_generate.restrict_schema[framework_config.datastore_generate.restrict_schema_count].values) { + log_error("[framework-config] bad realloc\n"); + } + framework_config.datastore_generate.restrict_schema[framework_config.datastore_generate.restrict_schema_count].values[framework_config.datastore_generate.restrict_schema[framework_config.datastore_generate.restrict_schema_count].values_count] = (char *)malloc(sizeof(char) * (strlen(value->valuestring) + 1)); + if(!framework_config.datastore_generate.restrict_schema[framework_config.datastore_generate.restrict_schema_count].values[framework_config.datastore_generate.restrict_schema[framework_config.datastore_generate.restrict_schema_count].values_count]) { + log_error("[framework-config] bad malloc\n"); + } + strcpy(framework_config.datastore_generate.restrict_schema[framework_config.datastore_generate.restrict_schema_count].values[framework_config.datastore_generate.restrict_schema[framework_config.datastore_generate.restrict_schema_count].values_count], value->valuestring); + framework_config.datastore_generate.restrict_schema[framework_config.datastore_generate.restrict_schema_count].values_count++; + + log_add(2, " %s", value->valuestring); + } + } + log_add(2, "\n"); + + framework_config.datastore_generate.restrict_schema_count++; } - strcpy(framework_config.custom_list_instances[framework_config.custom_list_instances_count].path, path); - framework_config.custom_list_instances[framework_config.custom_list_instances_count].count = count; - framework_config.custom_list_instances_count++; } } } } } - node = cJSON_GetObjectItem(main_node, "restrict-schema"); - if(node) { - if(cJSON_IsArray(node)) { - cJSON *element; - cJSON_ArrayForEach(element, node) { - if(cJSON_IsObject(element)) { - cJSON *object; - cJSON_ArrayForEach(object, element) { - char *path = object->string; - - log_message(2, "adding populate-rules/restrict-schema: %s with values:", path); - framework_config.restrict_schema = (restrict_schema_t *)realloc(framework_config.restrict_schema, sizeof(restrict_schema_t) * (framework_config.restrict_schema_count + 1)); - if(!framework_config.restrict_schema) { - log_error("bad realloc"); + main_node = cJSON_GetObjectItem(json, "datastore-populate-rules"); + if(main_node) { + node = cJSON_GetObjectItem(main_node, "random-generation-enabled"); + if(node) { + framework_config.datastore_populate.random_generation_enabled = node->valueint; + log_add_verbose(2, "[framework-config] setting datastore-populate-rules/random-generation-enabled: %d\n", framework_config.datastore_populate.random_generation_enabled); + } + else { + log_add_verbose(2, "[framework-config] setting datastore-populate-rules/random-generation-enabled: %d [default value]\n", framework_config.datastore_populate.random_generation_enabled); + } + + node = cJSON_GetObjectItem(main_node, "pre-generated-operational-data"); + if(node) { + if(cJSON_IsArray(node)) { + cJSON *element; + cJSON_ArrayForEach(element, node) { + if(cJSON_IsString(element)) { + log_add_verbose(2, "[framework-config] adding datastore-populate-rules/pre-generated-operational-data: %s\n", element->valuestring); + framework_config.datastore_populate.preg_operational = (char **)realloc(framework_config.datastore_populate.preg_operational, sizeof(char*) * (framework_config.datastore_populate.preg_operational_count + 1)); + if(!framework_config.datastore_populate.preg_operational) { + log_error("[framework-config] bad realloc\n"); } - - framework_config.restrict_schema[framework_config.restrict_schema_count].path = (char *)malloc(sizeof(char) * (strlen(path) + 1)); - if(!framework_config.restrict_schema[framework_config.restrict_schema_count].path) { - log_error("bad malloc"); + framework_config.datastore_populate.preg_operational[framework_config.datastore_populate.preg_operational_count] = (char *)malloc(sizeof(char) * (strlen(element->valuestring) + 1)); + if(!framework_config.datastore_populate.preg_operational[framework_config.datastore_populate.preg_operational_count]) { + log_error("[framework-config] bad malloc\n"); } - strcpy(framework_config.restrict_schema[framework_config.restrict_schema_count].path, path); - - - framework_config.restrict_schema[framework_config.restrict_schema_count].values_count = 0; - framework_config.restrict_schema[framework_config.restrict_schema_count].values = 0; - framework_config.restrict_schema[framework_config.restrict_schema_count].index = 0; - cJSON *value; - cJSON_ArrayForEach(value, object) { - if(cJSON_IsString(value)) { - framework_config.restrict_schema[framework_config.restrict_schema_count].values = (char **)realloc(framework_config.restrict_schema[framework_config.restrict_schema_count].values, sizeof(char*) * (framework_config.restrict_schema[framework_config.restrict_schema_count].values_count + 1)); - if(!framework_config.restrict_schema[framework_config.restrict_schema_count].values) { - log_error("bad realloc"); - } - framework_config.restrict_schema[framework_config.restrict_schema_count].values[framework_config.restrict_schema[framework_config.restrict_schema_count].values_count] = (char *)malloc(sizeof(char) * (strlen(value->valuestring) + 1)); - if(!framework_config.restrict_schema[framework_config.restrict_schema_count].values[framework_config.restrict_schema[framework_config.restrict_schema_count].values_count]) { - log_error("bad malloc"); - } - strcpy(framework_config.restrict_schema[framework_config.restrict_schema_count].values[framework_config.restrict_schema[framework_config.restrict_schema_count].values_count], value->valuestring); - framework_config.restrict_schema[framework_config.restrict_schema_count].values_count++; + strcpy(framework_config.datastore_populate.preg_operational[framework_config.datastore_populate.preg_operational_count], element->valuestring); + framework_config.datastore_populate.preg_operational_count++; + } + } + } + } - log_message(2, " %s", value->valuestring); - } + node = cJSON_GetObjectItem(main_node, "pre-generated-running-data"); + if(node) { + if(cJSON_IsArray(node)) { + cJSON *element; + cJSON_ArrayForEach(element, node) { + if(cJSON_IsString(element)) { + log_add_verbose(2, "[framework-config] adding datastore-populate-rules/pre-generated-running-data: %s\n", element->valuestring); + framework_config.datastore_populate.preg_running = (char **)realloc(framework_config.datastore_populate.preg_running, sizeof(char*) * (framework_config.datastore_populate.preg_running_count + 1)); + if(!framework_config.datastore_populate.preg_running) { + log_error("[framework-config] bad realloc\n"); } - log_message(2, "\n"); - - framework_config.restrict_schema_count++; + framework_config.datastore_populate.preg_running[framework_config.datastore_populate.preg_running_count] = (char *)malloc(sizeof(char) * (strlen(element->valuestring) + 1)); + if(!framework_config.datastore_populate.preg_running[framework_config.datastore_populate.preg_running_count]) { + log_error("[framework-config] bad malloc\n"); + } + strcpy(framework_config.datastore_populate.preg_running[framework_config.datastore_populate.preg_running_count], element->valuestring); + framework_config.datastore_populate.preg_running_count++; } } } } + } } - cJSON_free(json); + cJSON_Delete(json); } - log_message(2, "finished parsing config.json\n"); - - //environment vars - bool ip_ok = get_local_ips("eth0", &framework_environment.ip_v4, &framework_environment.ip_v6); - if(!ip_ok) { - log_error("could not get local IP addresses"); - } + log_add_verbose(2, "[framework-config] finished parsing config.json\n"); - char *ipv6_env_var = getenv(ENV_VAR_IPV6ENABLED); - if(ipv6_env_var == 0) { - log_error("could not get the IPv6 Enabled env variable"); - } - framework_environment.ip_v6_enabled = (strcmp(ipv6_env_var, "true") == 0) ? true : false; - - - framework_environment.docker_engine_version = getenv(ENV_VAR_DOCKER_ENGINE_VERSION) ? strdup(getenv(ENV_VAR_DOCKER_ENGINE_VERSION)) : strdup("1.40"); - framework_environment.hostname = getenv(ENV_VAR_HOSTNAME) ? strdup(getenv(ENV_VAR_HOSTNAME)) : strdup("localhost"); - framework_environment.host_ip = getenv(ENV_VAR_HOST_IP) ? strdup(getenv(ENV_VAR_HOST_IP)) : strdup("127.0.0.1"); - framework_environment.host_base_port = get_int_from_string_with_default(getenv(ENV_VAR_HOST_BASE_PORT), 1000); - framework_environment.ssh_connections = get_int_from_string_with_default(getenv(ENV_VAR_SSH_CONNECTIONS), 1); - framework_environment.tls_connections = get_int_from_string_with_default(getenv(ENV_VAR_TLS_CONNECTIONS), 0); - framework_environment.ftp_connections = 1; - framework_environment.sftp_connections = 1; - - framework_environment.sdn_controller_ip = getenv(ENV_VAR_SDN_CONTROLLER_IP) ? strdup(getenv(ENV_VAR_SDN_CONTROLLER_IP)) : strdup("127.0.0.1"); - framework_environment.sdn_controller_port = get_int_from_string_with_default(getenv(ENV_VAR_SDN_CONTROLLER_PORT), 8181); - framework_environment.sdn_controller_callhome_port = get_int_from_string_with_default(getenv(ENV_VAR_SDN_CONTROLLER_CALLHOME_PORT), 6666); - framework_environment.sdn_controller_username = getenv(ENV_VAR_SDN_CONTROLLER_USERNAME) ? strdup(getenv(ENV_VAR_SDN_CONTROLLER_USERNAME)) : strdup("admin"); - framework_environment.sdn_controller_password = getenv(ENV_VAR_SDN_CONTROLLER_PASSWORD) ? strdup(getenv(ENV_VAR_SDN_CONTROLLER_PASSWORD)) : strdup("admin"); - - framework_environment.ves_endpoint_protocol = getenv(ENV_VAR_VES_ENDPOINT_PROTOCOL) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_PROTOCOL)) : strdup("https"); - framework_environment.ves_endpoint_ip = getenv(ENV_VAR_VES_ENDPOINT_IP) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_IP)) : strdup("127.0.0.1"); - framework_environment.ves_endpoint_port = get_int_from_string_with_default(getenv(ENV_VAR_VES_ENDPOINT_PORT), 1234); - framework_environment.ves_endpoint_auth_method = getenv(ENV_VAR_VES_ENDPOINT_AUTH_METHOD) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_AUTH_METHOD)) : strdup("no-auth"); - framework_environment.ves_endpoint_username = getenv(ENV_VAR_VES_ENDPOINT_USERNAME) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_USERNAME)) : strdup("admin"); - framework_environment.ves_endpoint_password = getenv(ENV_VAR_VES_ENDPOINT_PASSWORD) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_PASSWORD)) : strdup("admin"); - framework_environment.ves_endpoint_certificate = getenv(ENV_VAR_VES_ENDPOINT_CERTIFICATE) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_CERTIFICATE)) : strdup(""); - - log_message(2, "[env] ip_v6_enabled = %s\n", framework_environment.ip_v6_enabled ? "true" : "false"); - log_message(2, "[env] ip_v4 = %s\n", framework_environment.ip_v4); - log_message(2, "[env] ip_v6 = %s\n", framework_environment.ip_v6); - log_message(2, "[env] docker_engine_version = %s\n", framework_environment.docker_engine_version); - log_message(2, "[env] hostname = %s\n", framework_environment.hostname); - log_message(2, "[env] host_ip = %s\n", framework_environment.host_ip); - log_message(2, "[env] host_base_port = %d\n", framework_environment.host_base_port); - log_message(2, "[env] ssh_connections = %d\n", framework_environment.ssh_connections); - log_message(2, "[env] tls_connections = %d\n", framework_environment.tls_connections); - log_message(2, "[env] ftp_connections = %d\n", framework_environment.ftp_connections); - log_message(2, "[env] sftp_connections = %d\n", framework_environment.sftp_connections); - - log_message(2, "[env] sdn_controller_ip = %s\n", framework_environment.sdn_controller_ip); - log_message(2, "[env] sdn_controller_port = %d\n", framework_environment.sdn_controller_port); - log_message(2, "[env] sdn_controller_callhome_port = %d\n", framework_environment.sdn_controller_callhome_port); - log_message(2, "[env] sdn_controller_username = %s\n", framework_environment.sdn_controller_username); - log_message(2, "[env] sdn_controller_password = %s\n", framework_environment.sdn_controller_password); - - log_message(2, "[env] ves_endpoint_protocol = %s\n", framework_environment.ves_endpoint_protocol); - log_message(2, "[env] ves_endpoint_ip = %s\n", framework_environment.ves_endpoint_ip); - log_message(2, "[env] ves_endpoint_port = %d\n", framework_environment.ves_endpoint_port); - log_message(2, "[env] ves_endpoint_auth_method = %s\n", framework_environment.ves_endpoint_auth_method); - log_message(2, "[env] ves_endpoint_username = %s\n", framework_environment.ves_endpoint_username); - log_message(2, "[env] ves_endpoint_password = %s\n", framework_environment.ves_endpoint_password); - log_message(2, "[env] ves_endpoint_certificate = %s\n", framework_environment.ves_endpoint_certificate); - - log_message(2, "finished environment vars\n"); + return NTS_ERR_OK; } void framework_free(void) { - log_message(2, "framework_free()... "); - - free(framework_environment.ip_v4); - free(framework_environment.ip_v6); - free(framework_environment.docker_engine_version); - free(framework_environment.hostname); - free(framework_environment.host_ip); - free(framework_environment.sdn_controller_ip); - free(framework_environment.sdn_controller_username); - free(framework_environment.sdn_controller_password); - free(framework_environment.ves_endpoint_protocol); - free(framework_environment.ves_endpoint_ip); - free(framework_environment.ves_endpoint_auth_method); - free(framework_environment.ves_endpoint_username); - free(framework_environment.ves_endpoint_password); - free(framework_environment.ves_endpoint_certificate); - - if(framework_arguments.print_structure_xpath) { - free(framework_arguments.print_structure_xpath); - framework_arguments.print_structure_xpath = 0; - } - - if(framework_config.docker_excluded_modules_count) { - for(int i = 0; i < framework_config.docker_excluded_modules_count; i++) { - free(framework_config.docker_excluded_modules[i]); - } - free(framework_config.docker_excluded_modules); - } + log_add_verbose(2, "[framework-config] framework_free()... "); + + signal(SIGINT, 0); + signal(SIGTERM, 0); + signal(SIGQUIT, 0); + + free((char *)argp_program_version); + argp_program_version = 0; + + free(framework_environment.nts.version); + free(framework_environment.nts.build_time); + free(framework_environment.nts.function_type); + free(framework_environment.nts.nf_standalone_start_features); + free(framework_environment.settings.ip_v4); + free(framework_environment.settings.ip_v6); + free(framework_environment.settings.docker_engine_version); + free(framework_environment.settings.hostname); + free(framework_environment.host.ip); + free(framework_environment.sdn_controller.protocol); + free(framework_environment.sdn_controller.ip); + free(framework_environment.sdn_controller.username); + free(framework_environment.sdn_controller.password); + free(framework_environment.ves_endpoint.common_header_version); + free(framework_environment.ves_endpoint.protocol); + free(framework_environment.ves_endpoint.ip); + free(framework_environment.ves_endpoint.auth_method); + free(framework_environment.ves_endpoint.username); + free(framework_environment.ves_endpoint.password); + free(framework_environment.ves_endpoint.certificate); + + free(framework_arguments.print_structure_xpath); + framework_arguments.print_structure_xpath = 0; - if(framework_config.docker_excluded_features_count) { - for(int i = 0; i < framework_config.docker_excluded_features_count; i++) { - free(framework_config.docker_excluded_features[i]); + for(int i = 0; i < framework_config.supervisor.rules_count; i++) { + free(framework_config.supervisor.rules[i].name); + free(framework_config.supervisor.rules[i].path); + for(int j = 0; j < framework_config.supervisor.rules[i].args_count; j++) { + free(framework_config.supervisor.rules[i].args[j]); } - free(framework_config.docker_excluded_features); + free(framework_config.supervisor.rules[i].args); + free(framework_config.supervisor.rules[i].stdout_path); + free(framework_config.supervisor.rules[i].stderr_path); } - if(framework_config.populate_excluded_modules_count) { - for(int i = 0; i < framework_config.populate_excluded_modules_count; i++) { - free(framework_config.populate_excluded_modules[i]); - } - free(framework_config.populate_excluded_modules); - } + free(framework_config.supervisor.rules); - for(int i = 0; i < framework_config.custom_list_instances_count; i++) { - free(framework_config.custom_list_instances[i].path); - + for(int i = 0; i < framework_config.docker.excluded_modules_count; i++) { + free(framework_config.docker.excluded_modules[i]); } - free(framework_config.custom_list_instances); + free(framework_config.docker.excluded_modules); - for(int i = 0; i < framework_config.restrict_schema_count; i++) { - free(framework_config.restrict_schema[i].path); - for(int j = 0; j < framework_config.restrict_schema[i].values_count; j++) { - free(framework_config.restrict_schema[i].values[j]); - } - free(framework_config.restrict_schema[i].values); + for(int i = 0; i < framework_config.docker.excluded_features_count; i++) { + free(framework_config.docker.excluded_features[i]); } - free(framework_config.restrict_schema); - - log_message(2, "done\n"); - log_close(); - if(framework_arguments.container_init) { - rename("log/log.txt", "log/install_log.txt"); + free(framework_config.docker.excluded_features); + + for(int i = 0; i < framework_config.datastore_generate.excluded_modules_count; i++) { + free(framework_config.datastore_generate.excluded_modules[i]); } -} + free(framework_config.datastore_generate.excluded_modules); -bool framework_is_docker_excluded_module(const char *module) { - assert(module); - for(int i = 0; i < framework_config.docker_excluded_modules_count; i++) { - if(strstr(module, framework_config.docker_excluded_modules[i]) != 0) { - return true; - } + for(int i = 0; i < framework_config.datastore_generate.custom_list_instances_count; i++) { + free(framework_config.datastore_generate.custom_list_instances[i].path); + } - - return false; -} + free(framework_config.datastore_generate.custom_list_instances); -bool framework_is_docker_excluded_feature(const char *feature) { - assert(feature); - - for(int i = 0; i < framework_config.docker_excluded_features_count; i++) { - if(strstr(feature, framework_config.docker_excluded_features[i]) != 0) { - return true; + for(int i = 0; i < framework_config.datastore_generate.restrict_schema_count; i++) { + free(framework_config.datastore_generate.restrict_schema[i].path); + for(int j = 0; j < framework_config.datastore_generate.restrict_schema[i].values_count; j++) { + free(framework_config.datastore_generate.restrict_schema[i].values[j]); } + free(framework_config.datastore_generate.restrict_schema[i].values); } - - return false; -} + free(framework_config.datastore_generate.restrict_schema); -bool framework_is_populate_excluded_module(const char *module) { - assert(module); - - for(int i = 0; i < framework_config.populate_excluded_modules_count; i++) { - if(strstr(module, framework_config.populate_excluded_modules[i]) != 0) { - return true; - } + for(int i = 0; i < framework_config.datastore_populate.preg_operational_count; i++) { + free(framework_config.datastore_populate.preg_operational[i]); } - - return false; -} + free(framework_config.datastore_populate.preg_operational); -int framework_populate_get_instance_count(const char *path) { - assert(path); - - for(int i = 0; i < framework_config.custom_list_instances_count; i++) { - if(strcmp(path, framework_config.custom_list_instances[i].path) == 0) { - return framework_config.custom_list_instances[i].count; - } + for(int i = 0; i < framework_config.datastore_populate.preg_running_count; i++) { + free(framework_config.datastore_populate.preg_running[i]); } - return framework_config.default_list_instances; -} + free(framework_config.datastore_populate.preg_running); -char *framework_populate_get_restrict_schema(const char *path) { - assert(path); - char *ret = 0; - for(int i = 0; i < framework_config.restrict_schema_count; i++) { - if(strcmp(path, framework_config.restrict_schema[i].path) == 0) { - ret = strdup(framework_config.restrict_schema[i].values[framework_config.restrict_schema[i].index]); - framework_config.restrict_schema[i].index++; - if(framework_config.restrict_schema[i].index >= framework_config.restrict_schema[i].values_count) { - framework_config.restrict_schema[i].index = 0; - } - break; - } - } - - return ret; + log_add(2, "done\n"); + log_close(); } static void framework_signal_handler(int signo) { @@ -556,24 +769,27 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { framework_arguments_t *iter_arguments = state->input; switch (key) { case 'i': - iter_arguments->container_init = true; + iter_arguments->nts_mode = NTS_MODE_CONTAINER_INIT; break; - case 'n': - iter_arguments->nc_server_init = true; + case 's': + iter_arguments->nts_mode = NTS_MODE_SUPERVISOR; break; case 'm': - iter_arguments->manager = true; + iter_arguments->nts_mode = NTS_MODE_MANAGER; break; case 'f': - iter_arguments->network_function = true; + iter_arguments->nts_mode = NTS_MODE_NETWORK_FUNCTION; break; + case 'g': + iter_arguments->nts_mode = NTS_MODE_GENERATE_DATA; + break; - case 'l': - iter_arguments->loop = true; + case 't': + iter_arguments->nts_mode = NTS_MODE_TEST; break; case 'r': @@ -587,14 +803,6 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { } break; - case 'o': - iter_arguments->operational_only = true; - break; - - case 't': - iter_arguments->test_mode = true; - break; - case 'v': iter_arguments->verbosity_level = arg[0] - '0'; break; @@ -603,10 +811,6 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { chdir(arg); break; - case '0': - iter_arguments->exhaustive_test = true; - break; - case '1': iter_arguments->print_root_paths = true; break; @@ -614,7 +818,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { case '2': iter_arguments->print_structure_xpath = (char *)malloc(sizeof(char) * (strlen(arg) + 1)); if(!iter_arguments->print_structure_xpath) { - log_error("very bad malloc failure here"); + log_error("[framework-arg] bad malloc\n"); return 1; } strcpy(iter_arguments->print_structure_xpath, arg); @@ -623,14 +827,6 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { } break; - case '3': - iter_arguments->populate_all = true; - break; - - case '4': - iter_arguments->enable_features = true; - break; - case ARGP_KEY_ARG: if (state->arg_num >= 2) { argp_usage(state); diff --git a/ntsimulator/ntsim-ng/core/framework.h b/ntsimulator/ntsim-ng/core/framework.h index be44555..2f169f0 100644 --- a/ntsimulator/ntsim-ng/core/framework.h +++ b/ntsimulator/ntsim-ng/core/framework.h @@ -23,27 +23,128 @@ #include #include -#define ENV_VAR_HOSTNAME "HOSTNAME" -#define ENV_VAR_DOCKER_ENGINE_VERSION "DOCKER_ENGINE_VERSION" -#define ENV_VAR_IPV6ENABLED "IPv6_ENABLED" -#define ENV_VAR_HOST_IP "NETCONF_NTS_HOST_IP" -#define ENV_VAR_HOST_BASE_PORT "NETCONF_NTS_HOST_BASE_PORT" -#define ENV_VAR_SSH_CONNECTIONS "SSH_CONNECTIONS" -#define ENV_VAR_TLS_CONNECTIONS "TLS_CONNECTIONS" - -#define ENV_VAR_SDN_CONTROLLER_IP "SDN_CONTROLLER_IP" -#define ENV_VAR_SDN_CONTROLLER_PORT "SDN_CONTROLLER_PORT" -#define ENV_VAR_SDN_CONTROLLER_CALLHOME_PORT "SDN_CONTROLLER_CALLHOME_PORT" -#define ENV_VAR_SDN_CONTROLLER_USERNAME "SDN_CONTROLLER_USERNAME" -#define ENV_VAR_SDN_CONTROLLER_PASSWORD "SDN_CONTROLLER_PASSWORD" - -#define ENV_VAR_VES_ENDPOINT_PROTOCOL "VES_ENDPOINT_PROTOCOL" -#define ENV_VAR_VES_ENDPOINT_IP "VES_ENDPOINT_IP" -#define ENV_VAR_VES_ENDPOINT_PORT "VES_ENDPOINT_PORT" -#define ENV_VAR_VES_ENDPOINT_AUTH_METHOD "VES_ENDPOINT_AUTH_METHOD" -#define ENV_VAR_VES_ENDPOINT_USERNAME "VES_ENDPOINT_USERNAME" -#define ENV_VAR_VES_ENDPOINT_PASSWORD "VES_ENDPOINT_PASSWORD" -#define ENV_VAR_VES_ENDPOINT_CERTIFICATE "VES_ENDPOINT_CERTIFICATE" +#define ENV_VAR_NTS_MANUAL "NTS_MANUAL" +#define ENV_VAR_NTS_BUILD_VERSION "NTS_BUILD_VERSION" +#define ENV_VAR_NTS_BUILD_TIME "NTS_BUILD_DATE" +#define ENV_VAR_NTS_FUNCTION_TYPE "NTS_FUNCTION_TYPE" +#define ENV_VAR_NTS_NF_STANDALONE_START_FEATURES "NTS_NF_STANDALONE_START_FEATURES" + +#define ENV_VAR_DOCKER_ENGINE_VERSION "DOCKER_ENGINE_VERSION" +#define ENV_VAR_HOSTNAME "HOSTNAME" +#define ENV_VAR_IPV6ENABLED "IPv6_ENABLED" +#define ENV_VAR_SSH_CONNECTIONS "SSH_CONNECTIONS" +#define ENV_VAR_TLS_CONNECTIONS "TLS_CONNECTIONS" + +#define ENV_VAR_HOST_IP "NTS_HOST_IP" +#define ENV_VAR_HOST_BASE_PORT "NTS_HOST_BASE_PORT" +#define ENV_VAR_HOST_NETCONF_SSH_BASE_PORT "NTS_HOST_NETCONF_SSH_BASE_PORT" +#define ENV_VAR_HOST_NETCONF_TLS_BASE_PORT "NTS_HOST_NETCONF_TLS_BASE_PORT" +#define ENV_VAR_HOST_TRANSFER_FTP_BASE_PORT "NTS_HOST_TRANSFER_FTP_BASE_PORT" +#define ENV_VAR_HOST_TRANSFER_SFTP_BASE_PORT "NTS_HOST_TRANSFER_SFTP_BASE_PORT" + +#define ENV_VAR_SDN_CONTROLLER_PROTOCOL "SDN_CONTROLLER_PROTOCOL" +#define ENV_VAR_SDN_CONTROLLER_IP "SDN_CONTROLLER_IP" +#define ENV_VAR_SDN_CONTROLLER_PORT "SDN_CONTROLLER_PORT" +#define ENV_VAR_SDN_CONTROLLER_CALLHOME_PORT "SDN_CONTROLLER_CALLHOME_PORT" +#define ENV_VAR_SDN_CONTROLLER_USERNAME "SDN_CONTROLLER_USERNAME" +#define ENV_VAR_SDN_CONTROLLER_PASSWORD "SDN_CONTROLLER_PASSWORD" + +#define ENV_VAR_VES_COMMON_HEADER_VERSION "VES_COMMON_HEADER_VERSION" +#define ENV_VAR_VES_ENDPOINT_PROTOCOL "VES_ENDPOINT_PROTOCOL" +#define ENV_VAR_VES_ENDPOINT_IP "VES_ENDPOINT_IP" +#define ENV_VAR_VES_ENDPOINT_PORT "VES_ENDPOINT_PORT" +#define ENV_VAR_VES_ENDPOINT_AUTH_METHOD "VES_ENDPOINT_AUTH_METHOD" +#define ENV_VAR_VES_ENDPOINT_USERNAME "VES_ENDPOINT_USERNAME" +#define ENV_VAR_VES_ENDPOINT_PASSWORD "VES_ENDPOINT_PASSWORD" +#define ENV_VAR_VES_ENDPOINT_CERTIFICATE "VES_ENDPOINT_CERTIFICATE" + +typedef enum { + NTS_MODE_DEFAULT = 0, + NTS_MODE_CONTAINER_INIT, + NTS_MODE_SUPERVISOR, + NTS_MODE_MANAGER, + NTS_MODE_NETWORK_FUNCTION, + NTS_MODE_GENERATE_DATA, + NTS_MODE_TEST, +} nts_mode_t; + +typedef struct { + nts_mode_t nts_mode; + + int argc; + char **argv; //no-copy + + bool no_rand; + unsigned int fixed_seed; + int verbosity_level; + + bool print_root_paths; + char *print_structure_xpath; +} framework_arguments_t; + +typedef struct { + struct { + bool manual; + char *version; + char *build_time; + char *function_type; + char *nf_standalone_start_features; + } nts; + + struct { + char *docker_engine_version; + + char *hostname; + char *ip_v4; + char *ip_v6; + bool ip_v6_enabled; + uint16_t ssh_connections; + uint16_t tls_connections; + uint16_t ftp_connections; + uint16_t sftp_connections; + } settings; + + struct { + char *ip; + uint16_t base_port; + uint16_t ssh_base_port; + uint16_t tls_base_port; + uint16_t ftp_base_port; + uint16_t sftp_base_port; + } host; + + struct { + char *protocol; + char *ip; + uint16_t port; + uint16_t callhome_port; + char *username; + char *password; + } sdn_controller; + + struct { + char *common_header_version; + + char *protocol; + char *ip; + uint16_t port; + char *auth_method; + char *username; + char *password; + char *certificate; + } ves_endpoint; +} framework_environment_t; + +typedef struct { + char *name; + char *path; + char **args; + int args_count; + bool nomanual; + bool autorestart; + char *stdout_path; + char *stderr_path; +} supervisor_rules_t; typedef struct { char *path; @@ -58,92 +159,50 @@ typedef struct { } restrict_schema_t; typedef struct { - bool container_init; - bool nc_server_init; + struct { + int excluded_modules_count; + char **excluded_modules; - bool no_rand; - unsigned int fixed_seed; - bool operational_only; - int verbosity_level; - bool loop; - bool test_mode; + int excluded_features_count; + char **excluded_features; + } docker; - bool manager; - bool network_function; + struct { + int rules_count; + supervisor_rules_t *rules; + } supervisor; - bool exhaustive_test; - bool print_root_paths; - char *print_structure_xpath; - bool populate_all; - bool enable_features; -} framework_arguments_t; + struct { + int debug_max_string_size; -typedef struct { - int docker_excluded_modules_count; - char **docker_excluded_modules; + int excluded_modules_count; + char **excluded_modules; - int docker_excluded_features_count; - char **docker_excluded_features; + int default_list_instances; - int debug_max_string_size; + int custom_list_instances_count; + custom_list_instances_t *custom_list_instances; - int populate_excluded_modules_count; - char **populate_excluded_modules; + int restrict_schema_count; + restrict_schema_t *restrict_schema; + } datastore_generate; - int default_list_instances; + struct { + bool random_generation_enabled; - int custom_list_instances_count; - custom_list_instances_t *custom_list_instances; + int preg_operational_count; + char **preg_operational; - int restrict_schema_count; - restrict_schema_t *restrict_schema; + int preg_running_count; + char **preg_running; + } datastore_populate; } framework_config_t; -typedef struct { - char *docker_engine_version; - - char *ip_v4; - char *ip_v6; - bool ip_v6_enabled; - - char *hostname; - char *host_ip; - uint16_t host_base_port; - uint16_t ssh_connections; - uint16_t tls_connections; - uint16_t ftp_connections; - uint16_t sftp_connections; - - char *sdn_controller_ip; - uint16_t sdn_controller_port; - uint16_t sdn_controller_callhome_port; - char *sdn_controller_username; - char *sdn_controller_password; - - char *ves_endpoint_protocol; - char *ves_endpoint_ip; - uint16_t ves_endpoint_port; - char *ves_endpoint_auth_method; - char *ves_endpoint_username; - char *ves_endpoint_password; - char *ves_endpoint_certificate; -} framework_environment_t; - extern framework_arguments_t framework_arguments; -extern framework_config_t framework_config; extern framework_environment_t framework_environment; +extern framework_config_t framework_config; volatile sig_atomic_t framework_sigint; -void framework_init(int argc, char **argv); +int framework_init(int argc, char **argv); void framework_free(void); - -//docker-related functions -bool framework_is_docker_excluded_module(const char *module); -bool framework_is_docker_excluded_feature(const char *feature); - -//populate-related functions -bool framework_is_populate_excluded_module(const char *module); - -int framework_populate_get_instance_count(const char *path); -char *framework_populate_get_restrict_schema(const char *path); //returns null if there is no restricted entry, value otherwise. value must be freed diff --git a/ntsimulator/ntsim-ng/core/nc_config.c b/ntsimulator/ntsim-ng/core/nc_config.c index 43402eb..4357790 100644 --- a/ntsimulator/ntsim-ng/core/nc_config.c +++ b/ntsimulator/ntsim-ng/core/nc_config.c @@ -21,6 +21,9 @@ #include "utils/log_utils.h" #include "utils/sys_utils.h" #include "utils/http_client.h" + +#include +#include #include #include @@ -33,14 +36,13 @@ #define SERVER_PRIVATE_KEY_PATH "/home/netconf/.ssh/melacon.server.key" #define SERVER_PUBLIC_KEY_PATH "/home/netconf/.ssh/melacon.server.key.pub.pem" #define SERVER_CERT_PATH "/home/netconf/.ssh/melacon.server.crt" -#define CLIENT_CERT_PATH "/home/netconf/.ssh/client.crt" #define CA_CERT_PATH "/home/netconf/.ssh/ca.pem" static int nc_config_netconf_port = STANDARD_NETCONF_PORT; static int load_ssh_keys(sr_session_ctx_t *session); static int load_trusted_certificates(sr_session_ctx_t *session); -static int remove_nacm(sr_session_ctx_t *session); +static int configure_nacm(sr_session_ctx_t *session); static int create_ssh_listen_endpoints(struct lyd_node *netconf_node, int ssh_connections); static int create_tls_listen_endpoints(struct lyd_node *netconf_node, int tls_connections); static int configure_endpoints_connections(sr_session_ctx_t *session); @@ -50,54 +52,57 @@ int netconf_configure(void) { nc_config_netconf_port = STANDARD_NETCONF_PORT; - sr_session_ctx_t *current_session; - rc = sr_session_start(session_connection, SR_DS_RUNNING, ¤t_session); - if(rc != 0) { - log_error("could not start session on running datastore"); + //check if was already ran + sr_val_t *val = 0; + rc = sr_get_item(session_running, "/ietf-keystore:keystore", 0, &val); + if(rc != SR_ERR_OK) { + log_error("sr_get_item failed\n"); return NTS_ERR_FAILED; } + + bool already_done = (val->dflt == false); + sr_free_val(val); + val = 0; + if(already_done) { + log_add_verbose(2, "netconf_configure() already ran, skipping...\n"); + return NTS_ERR_OK; + } // generate and load private keys - log_message(1, "ietf-keystore startup datastore configuration..."); //checkAS e ok aici ? - rc = load_ssh_keys(current_session); + log_add_verbose(1, "ietf-keystore startup datastore configuration..."); + rc = load_ssh_keys(session_running); if(rc != 0) { - log_error("could not load SSH keys"); + log_error("could not load SSH keys\n"); return NTS_ERR_FAILED; } - log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET); + log_add(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET); // load trusted certificates - log_message(1, "ietf-truststore startup datastore configuration..."); - rc = load_trusted_certificates(current_session); + log_add_verbose(1, "ietf-truststore startup datastore configuration..."); + rc = load_trusted_certificates(session_running); if(rc != 0) { - log_error("could not load trusted certificates"); + log_error("could not load trusted certificates\n"); return NTS_ERR_FAILED; } - log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET); + log_add(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET); - // remove NACM - log_message(1, "Removing NACM..."); - rc = remove_nacm(current_session); + // configuring NACM + log_add_verbose(1, "configuring NACM..."); + rc = configure_nacm(session_running); if(rc != 0) { - log_error("could not remove NACM"); + log_error("could not configure NACM\n"); return NTS_ERR_FAILED; } - log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET); + log_add(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET); // configure SSH connections - log_message(1, "Configuring connection endpoints..."); - rc = configure_endpoints_connections(current_session); + log_add_verbose(1, "Configuring connection endpoints..."); + rc = configure_endpoints_connections(session_running); if(rc != 0) { - log_error("could not configure endpoint connections forNETCONF Server"); - return NTS_ERR_FAILED; - } - log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET); - - rc = sr_session_stop(current_session); - if(rc != 0) { - log_error("could not configure stop current sysrepo session"); + log_error("could not configure endpoint connections forNETCONF Server\n"); return NTS_ERR_FAILED; } + log_add(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET); return NTS_ERR_OK; } @@ -111,42 +116,42 @@ static int load_ssh_keys(sr_session_ctx_t *session) { rc = system(GEN_KEY_SCRIPT); if(rc != 0) { - log_error("could not generate the SSH keys"); + log_error("could not generate the SSH keys\n"); return NTS_ERR_FAILED; } struct lys_module *module; module = (struct lys_module *)ly_ctx_get_module(session_context, "ietf-keystore", 0, 0); if(module == 0) { - log_error("could not get module %s from context", "ietf-keystore"); + log_error("could not get module %s from context\n", "ietf-keystore"); return NTS_ERR_FAILED; } struct lyd_node *keystore_node = 0; keystore_node = lyd_new(NULL, module, "keystore"); if(keystore_node == 0) { - log_error("could not create a new lyd_node"); + log_error("could not create a new lyd_node\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-keystore:keystore/asymmetric-keys/asymmetric-key[name='%s']/algorithm", KS_KEY_NAME); rcl = lyd_new_path(keystore_node, 0, xpath, "rsa2048", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } char *private_key = read_key(SERVER_PRIVATE_KEY_PATH); if(private_key == 0) { - log_error("could not read the private key from path=%s", SERVER_PRIVATE_KEY_PATH); + log_error("could not read the private key from path=%s\n", SERVER_PRIVATE_KEY_PATH); return NTS_ERR_FAILED; } - log_message(2, "Private Key that was built: \n%s\n", private_key); + log_add_verbose(2, "Private Key that was built: \n%s\n", private_key); sprintf(xpath, "/ietf-keystore:keystore/asymmetric-keys/asymmetric-key[name='%s']/private-key", KS_KEY_NAME); rcl = lyd_new_path(keystore_node, 0, xpath, private_key, 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } @@ -154,15 +159,15 @@ static int load_ssh_keys(sr_session_ctx_t *session) { char *public_key = read_key(SERVER_PUBLIC_KEY_PATH); if(public_key == 0) { - log_error("could not read the public key from path=%s", SERVER_PUBLIC_KEY_PATH); + log_error("could not read the public key from path=%s\n", SERVER_PUBLIC_KEY_PATH); return NTS_ERR_FAILED; } - log_message(2, "Public Key that was built: \n%s\n", public_key); + log_add_verbose(2, "Public Key that was built: \n%s\n", public_key); sprintf(xpath, "/ietf-keystore:keystore/asymmetric-keys/asymmetric-key[name='%s']/public-key", KS_KEY_NAME); rcl = lyd_new_path(keystore_node, 0, xpath, public_key, 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } @@ -170,15 +175,15 @@ static int load_ssh_keys(sr_session_ctx_t *session) { char *certificate = read_key(SERVER_CERT_PATH); if(certificate == 0) { - log_error("could not read the certificate from path=%s", SERVER_CERT_PATH); + log_error("could not read the certificate from path=%s\n", SERVER_CERT_PATH); return NTS_ERR_FAILED; } - log_message(2, "Certificate that was built: \n%s\n", certificate); + log_add_verbose(2, "Certificate that was built: \n%s\n", certificate); sprintf(xpath, "/ietf-keystore:keystore/asymmetric-keys/asymmetric-key[name='%s']/certificates/certificate[name='%s']/cert", KS_KEY_NAME, KS_CERT_NAME); rcl = lyd_new_path(keystore_node, 0, xpath, certificate, 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } @@ -186,20 +191,20 @@ static int load_ssh_keys(sr_session_ctx_t *session) { rc = sr_edit_batch(session, keystore_node, "replace"); if(rc != SR_ERR_OK) { - log_error("could not edit batch on datastore"); + log_error("could not edit batch on datastore\n"); return NTS_ERR_FAILED; } rc = sr_validate(session, "ietf-keystore", 0); if(rc != SR_ERR_OK) { struct ly_err_item *err = ly_err_first(session_context); - log_error("sr_validate issues on STARTUP: %s", err->msg); + log_error("sr_validate issues on STARTUP: %s\n", err->msg); return false; } rc = sr_apply_changes(session, 0, 0); if(rc != SR_ERR_OK) { - log_error("could not apply changes on datastore"); + log_error("could not apply changes on datastore\n"); return NTS_ERR_FAILED; } @@ -216,13 +221,13 @@ static int load_trusted_certificates(sr_session_ctx_t *session) { struct lys_module *module; module = (struct lys_module *)ly_ctx_get_module(session_context, "ietf-truststore", 0, 0); if(module == 0) { - log_error("could not get module %s from context", "ietf-truststore"); + log_error("could not get module %s from context\n", "ietf-truststore"); return NTS_ERR_FAILED; } trusted_certificate_node = lyd_new(NULL, module, "truststore"); if(trusted_certificate_node == 0) { - log_error("could not create a new lyd_node"); + log_error("could not create a new lyd_node\n"); return NTS_ERR_FAILED; } @@ -232,7 +237,7 @@ static int load_trusted_certificates(sr_session_ctx_t *session) { char *client_cert = read_key(CLIENT_CERT_PATH); rcl = lyd_new_path(trusted_certificate_node, 0, xpath, client_cert, 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } free(client_cert); @@ -241,34 +246,34 @@ static int load_trusted_certificates(sr_session_ctx_t *session) { char *ca_cert = read_key(CA_CERT_PATH); rcl = lyd_new_path(trusted_certificate_node, 0, xpath, ca_cert, 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } free(ca_cert); rc = sr_edit_batch(session, trusted_certificate_node, "replace"); if(rc != SR_ERR_OK) { - log_error("could not edit batch on datastore"); + log_error("could not edit batch on datastore\n"); return NTS_ERR_FAILED; } rc = sr_validate(session, "ietf-truststore", 0); if(rc != SR_ERR_OK) { struct ly_err_item *err = ly_err_first(session_context); - log_error("sr_validate issues on STARTUP: %s", err->msg); + log_error("sr_validate issues on STARTUP: %s\n", err->msg); return NTS_ERR_FAILED; } rc = sr_apply_changes(session, 0, 0); if(rc != SR_ERR_OK) { - log_error("could not apply changes on datastore"); + log_error("could not apply changes on datastore\n"); return NTS_ERR_FAILED; } return NTS_ERR_OK; } -static int remove_nacm(sr_session_ctx_t *session) { +static int configure_nacm(sr_session_ctx_t *session) { assert(session); int rc = NTS_ERR_OK; @@ -278,40 +283,90 @@ static int remove_nacm(sr_session_ctx_t *session) { struct lys_module *module = 0; module = (struct lys_module *) ly_ctx_get_module(session_context, "ietf-netconf-acm", 0, 0); if(module == 0) { - log_error("could not get module %s from context", "ietf-netconf-acm"); + log_error("could not get module %s from context\n", "ietf-netconf-acm"); return NTS_ERR_FAILED; } struct lyd_node *nacm_node = 0; nacm_node = lyd_new(NULL, module, "nacm"); if(nacm_node == 0) { - log_error("could not create a new lyd_node"); + log_error("could not create a new lyd_node\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-acm:nacm/enable-nacm"); - rcl = lyd_new_path(nacm_node, 0, xpath, "false", 0, LYD_PATH_OPT_NOPARENTRET); + rcl = lyd_new_path(nacm_node, 0, xpath, "true", 0, LYD_PATH_OPT_NOPARENTRET); + if(rcl == 0) { + log_error("could not create yang path\n"); + return NTS_ERR_FAILED; + } + + sprintf(xpath, "/ietf-netconf-acm:nacm/groups/group[name='sudo']/user-name"); + // we hardcoded here the username to be used + rcl = lyd_new_path(nacm_node, 0, xpath, "netconf", 0, LYD_PATH_OPT_NOPARENTRET); + if(rcl == 0) { + log_error("could not create yang path\n"); + return NTS_ERR_FAILED; + } + + sprintf(xpath, "/ietf-netconf-acm:nacm/rule-list[name='sudo-rules']/group"); + rcl = lyd_new_path(nacm_node, 0, xpath, "sudo", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not create yang path\n"); + return NTS_ERR_FAILED; + } + + sprintf(xpath, "/ietf-netconf-acm:nacm/rule-list[name='sudo-rules']/rule[name='allow-all-sudo']/module-name"); + rcl = lyd_new_path(nacm_node, 0, xpath, "*", 0, LYD_PATH_OPT_NOPARENTRET); + if(rcl == 0) { + log_error("could not create yang path\n"); + return NTS_ERR_FAILED; + } + + sprintf(xpath, "/ietf-netconf-acm:nacm/rule-list[name='sudo-rules']/rule[name='allow-all-sudo']/path"); + rcl = lyd_new_path(nacm_node, 0, xpath, "/", 0, LYD_PATH_OPT_NOPARENTRET); + if(rcl == 0) { + log_error("could not create yang path\n"); + return NTS_ERR_FAILED; + } + + sprintf(xpath, "/ietf-netconf-acm:nacm/rule-list[name='sudo-rules']/rule[name='allow-all-sudo']/access-operations"); + rcl = lyd_new_path(nacm_node, 0, xpath, "*", 0, LYD_PATH_OPT_NOPARENTRET); + if(rcl == 0) { + log_error("could not create yang path\n"); + return NTS_ERR_FAILED; + } + + sprintf(xpath, "/ietf-netconf-acm:nacm/rule-list[name='sudo-rules']/rule[name='allow-all-sudo']/action"); + rcl = lyd_new_path(nacm_node, 0, xpath, "permit", 0, LYD_PATH_OPT_NOPARENTRET); + if(rcl == 0) { + log_error("could not create yang path\n"); + return NTS_ERR_FAILED; + } + + sprintf(xpath, "/ietf-netconf-acm:nacm/rule-list[name='sudo-rules']/rule[name='allow-all-sudo']/comment"); + rcl = lyd_new_path(nacm_node, 0, xpath, "Corresponds all the rules under the sudo group as defined in O-RAN.WG4.MP.0-v05.00", 0, LYD_PATH_OPT_NOPARENTRET); + if(rcl == 0) { + log_error("could not create yang path\n"); return NTS_ERR_FAILED; } rc = sr_edit_batch(session, nacm_node, "replace"); if(rc != SR_ERR_OK) { - log_error("could not edit batch on datastore"); + log_error("could not edit batch on datastore\n"); return NTS_ERR_FAILED; } rc = sr_validate(session, "ietf-netconf-acm", 0); if(rc != SR_ERR_OK) { struct ly_err_item *err = ly_err_first(session_context); - log_error("sr_validate issues on STARTUP: %s", err->msg); + log_error("sr_validate issues on STARTUP: %s\n", err->msg); return NTS_ERR_FAILED; } rc = sr_apply_changes(session, 0, 0); if(rc != SR_ERR_OK) { - log_error("could not apply changes on datastore"); + log_error("could not apply changes on datastore\n"); return NTS_ERR_FAILED; } @@ -326,7 +381,7 @@ static int create_ssh_listen_endpoints(struct lyd_node *netconf_node, int ssh_co struct lyd_node *rcl = 0; - if(framework_environment.ip_v6_enabled) { + if(framework_environment.settings.ip_v6_enabled) { sprintf(local_ip, "::"); } else { @@ -335,7 +390,7 @@ static int create_ssh_listen_endpoints(struct lyd_node *netconf_node, int ssh_co char *public_ssh_key = read_key(SERVER_PUBLIC_SSH_KEY_PATH); if(public_ssh_key == 0) { - log_error("could not read the public ssh key from file %s", SERVER_PUBLIC_SSH_KEY_PATH); + log_error("could not read the public ssh key from file %s\n", SERVER_PUBLIC_SSH_KEY_PATH); return NTS_ERR_FAILED; } @@ -344,14 +399,14 @@ static int create_ssh_listen_endpoints(struct lyd_node *netconf_node, int ssh_co ssh_key_string = strtok(public_ssh_key, " "); ssh_key_string = strtok(NULL, " "); - for(int i=0; i < ssh_connections; ++i) { + for(int i = 0; i < ssh_connections; ++i) { char endpoint_name[100]; sprintf(endpoint_name, "mng-ssh-%d", i); sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/local-address", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, local_ip, 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } @@ -360,70 +415,70 @@ static int create_ssh_listen_endpoints(struct lyd_node *netconf_node, int ssh_co sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/local-port", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, local_port, 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/keepalives/idle-time", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, "1", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/keepalives/max-probes", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, "10", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/keepalives/probe-interval", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, "5", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/server-identity/host-key[name='default-key']/public-key/keystore-reference", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, KS_KEY_NAME, 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/supported-authentication-methods/publickey", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, "", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/supported-authentication-methods/passsword", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, "", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/supported-authentication-methods/other", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, "interactive", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/users/user[name='netconf']/authorized-key[name='%s']/algorithm", endpoint_name, KS_KEY_NAME); rcl = lyd_new_path(netconf_node, 0, xpath, "ssh-rsa", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/users/user[name='netconf']/authorized-key[name='%s']/key-data", endpoint_name, KS_KEY_NAME); rcl = lyd_new_path(netconf_node, 0, xpath, ssh_key_string, 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } } @@ -440,107 +495,117 @@ static int create_tls_listen_endpoints(struct lyd_node *netconf_node, int tls_co char xpath[500]; char local_ip[30]; - if(framework_environment.ip_v6_enabled) { + if(framework_environment.settings.ip_v6_enabled) { sprintf(local_ip, "::"); } else { sprintf(local_ip, "0.0.0.0"); } - for(int i=0; i < tls_connections; ++i) { + for(int i = 0; i < tls_connections + 1; ++i) { char endpoint_name[100]; - sprintf(endpoint_name, "mng-tls-%d", i); + char local_port[10]; + + + + if(i == tls_connections) { + //manager connection port + sprintf(endpoint_name, "manger-tls-internal"); + sprintf(local_port, "%d", CLIENT_CONFIG_TLS_PORT); + } + else { + sprintf(endpoint_name, "mng-tls-%d", i); + sprintf(local_port, "%d", nc_config_netconf_port++); + } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/local-address", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, local_ip, 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } - char local_port[10]; - sprintf(local_port, "%d", nc_config_netconf_port++); sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/local-port", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, local_port, 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/keepalives/idle-time", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, "1", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/keepalives/max-probes", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, "10", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/keepalives/probe-interval", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, "5", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/server-identity/keystore-reference/asymmetric-key", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, KS_KEY_NAME, 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/server-identity/keystore-reference/certificate", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, KS_CERT_NAME, 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/required", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, "", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/ca-certs", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, "cacerts", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/client-certs", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, "clientcerts", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/cert-maps/cert-to-name[id='1']/fingerprint", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, "02:E9:38:1F:F6:8B:62:DE:0A:0B:C5:03:81:A8:03:49:A0:00:7F:8B:F3", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/cert-maps/cert-to-name[id='1']/map-type", endpoint_name); rcl = lyd_new_path(netconf_node, session_context, xpath, "ietf-x509-cert-to-name:specified", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/cert-maps/cert-to-name[id='1']/name", endpoint_name); rcl = lyd_new_path(netconf_node, 0, xpath, "netconf-tls", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } } @@ -556,7 +621,7 @@ static int configure_endpoints_connections(sr_session_ctx_t *session) { struct lys_module *module = 0; module = (struct lys_module *)ly_ctx_get_module(session_context, "ietf-netconf-server", 0, 0); if(module == 0) { - log_error("could not get module %s from context", "ietf-netconf-server"); + log_error("could not get module %s from context\n", "ietf-netconf-server"); return NTS_ERR_FAILED; } @@ -564,55 +629,55 @@ static int configure_endpoints_connections(sr_session_ctx_t *session) { struct lyd_node *netconf_node = 0; netconf_node = lyd_new_path(NULL, session_context, "/ietf-netconf-server:netconf-server", 0, 0, 0); if(netconf_node == 0) { - log_error("could not create a new lyd_node"); + log_error("could not create a new lyd_node\n"); return NTS_ERR_FAILED; } // create the SSH endpoints in ietf-netconf-server int ssh_connections = 0; - if(framework_arguments.manager) { + if(framework_arguments.nts_mode == NTS_MODE_MANAGER) { ssh_connections = 1; } else { - ssh_connections = framework_environment.ssh_connections; + ssh_connections = framework_environment.settings.ssh_connections; } if(ssh_connections == 0) { - log_error("ssh_connections must be at least 1"); + log_error("ssh_connections must be at least 1\n"); return NTS_ERR_FAILED; } rc = create_ssh_listen_endpoints(netconf_node, ssh_connections); if(rc != NTS_ERR_OK) { - log_error("could not create %d SSH Listen endpoints on the NETCONF Server", ssh_connections); + log_error("could not create %d SSH Listen endpoints on the NETCONF Server\n", ssh_connections); return NTS_ERR_FAILED; } // create the TLS endpoints in ietf-netconf-server - if(framework_arguments.manager == false) { - rc = create_tls_listen_endpoints(netconf_node, framework_environment.tls_connections); + if(framework_arguments.nts_mode != NTS_MODE_MANAGER) { + rc = create_tls_listen_endpoints(netconf_node, framework_environment.settings.tls_connections); if(rc != NTS_ERR_OK) { - log_error("could not create %d TLS Listen endpoints on the NETCONF Server", framework_environment.tls_connections); + log_error("could not create %d TLS Listen endpoints on the NETCONF Server\n", framework_environment.settings.tls_connections); return NTS_ERR_FAILED; } } rc = sr_edit_batch(session, netconf_node, "replace"); if(rc != SR_ERR_OK) { - log_error("could not edit batch on datastore"); + log_error("could not edit batch on datastore\n"); return NTS_ERR_FAILED; } rc = sr_validate(session, "ietf-netconf-server", 0); if(rc != SR_ERR_OK) { struct ly_err_item *err = ly_err_first(session_context); - log_error("sr_validate issues on STARTUP: %s", err->msg); + log_error("sr_validate issues on STARTUP: %s\n", err->msg); return NTS_ERR_FAILED; } rc = sr_apply_changes(session, 0, 0); if(rc != SR_ERR_OK) { - log_error("could not apply changes on datastore"); + log_error("could not apply changes on datastore\n"); return NTS_ERR_FAILED; } diff --git a/ntsimulator/ntsim-ng/core/nc_config.h b/ntsimulator/ntsim-ng/core/nc_config.h index 1dc1f28..b62273d 100644 --- a/ntsimulator/ntsim-ng/core/nc_config.h +++ b/ntsimulator/ntsim-ng/core/nc_config.h @@ -17,7 +17,9 @@ #pragma once -#include -#include +#define CLIENT_CONFIG_TLS_PORT 800 +#define CLIENT_CA_FILE "/home/netconf/.ssh/ca.pem" +#define CLIENT_CERT_PATH "/home/netconf/.ssh/client.crt" +#define CLIENT_KEY_PATH "/home/netconf/.ssh/client.key" int netconf_configure(void); diff --git a/ntsimulator/ntsim-ng/core/session.c b/ntsimulator/ntsim-ng/core/session.c index 716bc56..3f64622 100644 --- a/ntsimulator/ntsim-ng/core/session.c +++ b/ntsimulator/ntsim-ng/core/session.c @@ -35,33 +35,27 @@ int session_init(void) { /* connect to sysrepo */ rc = sr_connect(0, &session_connection); if(SR_ERR_OK != rc) { - log_error("sr_connect failed"); + log_error("sr_connect failed\n"); goto session_init_cleanup; } /* start session */ rc = sr_session_start(session_connection, SR_DS_OPERATIONAL, &session_operational); if (rc != SR_ERR_OK) { - log_error("sr_session_start operational failed"); + log_error("sr_session_start operational failed\n"); goto session_init_cleanup; } - if(framework_arguments.operational_only == false) { - rc = sr_session_start(session_connection, SR_DS_RUNNING, &session_running); - if (rc != SR_ERR_OK) { - log_error("sr_session_start running failed"); - goto session_init_cleanup; - } - } - else { - session_running = session_operational; + rc = sr_session_start(session_connection, SR_DS_RUNNING, &session_running); + if (rc != SR_ERR_OK) { + log_error("sr_session_start running failed\n"); + goto session_init_cleanup; } - /* get context */ session_context = (struct ly_ctx *)sr_get_context(session_connection); if(session_context == 0) { - log_error("sr_get_context failed"); + log_error("sr_get_context failed\n"); goto session_init_cleanup; } @@ -72,20 +66,19 @@ session_init_cleanup: } void session_free(void) { - log_message(2, "session_free()... "); + log_add_verbose(2, "session_free()... "); if(session_subscription) { sr_unsubscribe(session_subscription); } sr_session_stop(session_operational); - if(framework_arguments.operational_only == false) { - sr_session_stop(session_running); - } + sr_session_stop(session_running); + sr_disconnect(session_connection); session_connection = 0; session_running = 0; session_operational = 0; session_context = 0; - log_message(2, "done\n"); + log_add(2, "done\n"); } diff --git a/ntsimulator/ntsim-ng/core/test.c b/ntsimulator/ntsim-ng/core/test.c index 8902984..52ed5ff 100644 --- a/ntsimulator/ntsim-ng/core/test.c +++ b/ntsimulator/ntsim-ng/core/test.c @@ -37,29 +37,29 @@ int exhaustive_test_run(void) { //first get all xpaths char **xpaths = 0; - int xpaths_count = schema_get_xpaths(&xpaths); + int xpaths_count = datastore_schema_get_xpaths(&xpaths); if(xpaths_count < 0) { - log_error("schema_get_xpaths failed"); + log_error("datastore_schema_get_xpaths failed\n"); return NTS_ERR_FAILED; } else { - log_message(0, "schema_get_xpaths executed with "LOG_COLOR_BOLD_GREEN"success"LOG_COLOR_RESET" (%d)\n", xpaths_count); + log_add_verbose(0, "datastore_schema_get_xpaths executed with "LOG_COLOR_BOLD_GREEN"success"LOG_COLOR_RESET" (%d)\n", xpaths_count); } //switching verbosity level to 0 so we don't see logs int old_verbosity_level = framework_arguments.verbosity_level; framework_arguments.verbosity_level = 0; - //testing schema_print_xpath() + //testing datastore_schema_print_xpath() for(int i = 0 ; i < xpaths_count; i++) { - int rc = schema_print_xpath(xpaths[i]); + int rc = datastore_schema_print_xpath(xpaths[i]); if(rc != NTS_ERR_OK) { - log_error("error in schema_print_xpath"); + log_error("error in datastore_schema_print_xpath\n"); return rc; } } - log_message(0, "schema_print_xpath executed with "LOG_COLOR_BOLD_GREEN"success"LOG_COLOR_RESET" for all paths\n"); + log_add_verbose(0, "datastore_schema_print_xpath executed with "LOG_COLOR_BOLD_GREEN"success"LOG_COLOR_RESET" for all paths\n"); //freeing paths for(int i = 0; i < xpaths_count; i++) { @@ -68,15 +68,14 @@ int exhaustive_test_run(void) { free(xpaths); //testing schema_populate - int rc = schema_populate(); + int rc = datastore_populate(1); if(rc != NTS_ERR_OK) { - log_error("error in schema_populate"); + log_error("error in datastore_populate\n"); return rc; } - log_message(0, "schema_populate executed with "LOG_COLOR_BOLD_GREEN"success"LOG_COLOR_RESET"\n"); - - log_message(0, LOG_COLOR_BOLD_GREEN"ALL TESTS WENT GOOD!"LOG_COLOR_RESET"\n\n\n"); + log_add_verbose(0, "datastore_populate executed with "LOG_COLOR_BOLD_GREEN"success"LOG_COLOR_RESET"\n"); + log_add_verbose(0, LOG_COLOR_BOLD_GREEN"ALL TESTS WENT GOOD!"LOG_COLOR_RESET"\n\n\n"); //switching back verbosity level framework_arguments.verbosity_level = old_verbosity_level; diff --git a/ntsimulator/ntsim-ng/features/manual_notification/manual_notification.c b/ntsimulator/ntsim-ng/features/manual_notification/manual_notification.c index e76fa61..e768c73 100644 --- a/ntsimulator/ntsim-ng/features/manual_notification/manual_notification.c +++ b/ntsimulator/ntsim-ng/features/manual_notification/manual_notification.c @@ -35,19 +35,44 @@ #define MANUAL_NOTIFICATION_RPC_SCHEMA_XPATH "/nts-network-function:invoke-notification" static int manual_notification_pm_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data); +static sr_subscription_ctx_t *manual_notification_subscription = 0; + +int manual_notification_feature_get_status(void) { + return (manual_notification_subscription != 0); +} int manual_notification_feature_start(sr_session_ctx_t *current_session) { assert_session(); + assert(current_session); - int rc = sr_rpc_subscribe(current_session, MANUAL_NOTIFICATION_RPC_SCHEMA_XPATH, manual_notification_pm_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &session_subscription); - if(rc != SR_ERR_OK) { - log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc)); - return NTS_ERR_FAILED; + if(manual_notification_subscription == 0) { + int rc = sr_rpc_subscribe(current_session, MANUAL_NOTIFICATION_RPC_SCHEMA_XPATH, manual_notification_pm_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &manual_notification_subscription); + if(rc != SR_ERR_OK) { + log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc)); + return NTS_ERR_FAILED; + } + } + + return NTS_ERR_OK; +} + +int manual_notification_feature_stop(void) { + assert_session(); + + if(manual_notification_subscription) { + int rc = sr_unsubscribe(manual_notification_subscription); + if(rc != SR_ERR_OK) { + log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc)); + return NTS_ERR_FAILED; + } + + manual_notification_subscription = 0; } return NTS_ERR_OK; } + static int manual_notification_pm_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) { int rc; diff --git a/ntsimulator/ntsim-ng/features/manual_notification/manual_notification.h b/ntsimulator/ntsim-ng/features/manual_notification/manual_notification.h index 6b2fd83..cbea12b 100644 --- a/ntsimulator/ntsim-ng/features/manual_notification/manual_notification.h +++ b/ntsimulator/ntsim-ng/features/manual_notification/manual_notification.h @@ -19,4 +19,7 @@ #include +int manual_notification_feature_get_status(void); int manual_notification_feature_start(sr_session_ctx_t *current_session); +int manual_notification_feature_stop(void); + diff --git a/ntsimulator/ntsim-ng/features/netconf_call_home/netconf_call_home.c b/ntsimulator/ntsim-ng/features/netconf_call_home/netconf_call_home.c index b3bacb0..8952cb7 100644 --- a/ntsimulator/ntsim-ng/features/netconf_call_home/netconf_call_home.c +++ b/ntsimulator/ntsim-ng/features/netconf_call_home/netconf_call_home.c @@ -30,13 +30,19 @@ #include "core/framework.h" #define NETCONF_CALLHOME_ENABLED_SCHEMA_PATH "/nts-network-function:simulation/network-function/netconf/call-home" -#define NETCONF_CALLHOME_CURL_SEND_PAYLOAD_FORMAT "{\"odl-netconf-callhome-server:device\":[{\"odl-netconf-callhome-server:unique-id\":\"%s\",\"odl-netconf-callhome-server:ssh-host-key\":\"%s\",\"odl-netconf-callhome-server:credentials\":{\"odl-netconf-callhome-server:username\":\"netconf\",\"odl-netconf-callhome-server:passwords\":[\"netconf\"]}}]}" +#define NETCONF_CALLHOME_CURL_SEND_PAYLOAD_FORMAT "{\"odl-netconf-callhome-server:device\":[{\"odl-netconf-callhome-server:unique-id\":\"%s\",\"odl-netconf-callhome-server:ssh-host-key\":\"%s\",\"odl-netconf-callhome-server:credentials\":{\"odl-netconf-callhome-server:username\":\"netconf\",\"odl-netconf-callhome-server:passwords\":[\"netconf!\"]}}]}" #define SDN_CONTROLLER_DETAILS_SCHEMA_PATH "/nts-network-function:simulation/sdn-controller" static int create_ssh_callhome_endpoint(sr_session_ctx_t *current_session, struct lyd_node *netconf_node); static int create_tls_callhome_endpoint(sr_session_ctx_t *current_session, struct lyd_node *netconf_node); static int send_odl_callhome_configuration(sr_session_ctx_t *current_session); +static int netconf_call_home_status = 0; + +int netconf_call_home_feature_get_status(void) { + return netconf_call_home_status; +} + int netconf_call_home_feature_start(sr_session_ctx_t *current_session) { assert(current_session); assert_session(); @@ -49,51 +55,55 @@ int netconf_call_home_feature_start(sr_session_ctx_t *current_session) { callhome_enabled = value->data.bool_val; sr_free_val(value); } + else { + // if value is not set yet, feature enable means we want to start call-home + callhome_enabled = true; + } if(callhome_enabled == false) { - log_message(2, "NETCONF CallHome is not enabled, not configuring NETCONF Server.\n"); + log_add_verbose(2, "NETCONF CallHome is not enabled, not configuring NETCONF Server.\n"); return NTS_ERR_OK; } struct lyd_node *netconf_node = 0; netconf_node = lyd_new_path(NULL, session_context, "/ietf-netconf-server:netconf-server", 0, 0, 0); if(netconf_node == 0) { - log_error("could not create a new lyd_node"); + log_error("could not create a new lyd_node\n"); return NTS_ERR_FAILED; } rc = create_ssh_callhome_endpoint(current_session, netconf_node); if(rc != NTS_ERR_OK) { - log_error("could not create SSH CallHome endpoint on the NETCONF Server"); + log_error("could not create SSH CallHome endpoint on the NETCONF Server\n"); return NTS_ERR_FAILED; } rc = create_tls_callhome_endpoint(current_session, netconf_node); if(rc != NTS_ERR_OK) { - log_error("could not create TLS CallHome endpoint on the NETCONF Server"); + log_error("could not create TLS CallHome endpoint on the NETCONF Server\n"); return NTS_ERR_FAILED; } rc = sr_edit_batch(current_session, netconf_node, "merge"); if(rc != SR_ERR_OK) { - log_error("could not edit batch on datastore"); + log_error("could not edit batch on datastore\n"); return NTS_ERR_FAILED; } rc = sr_validate(current_session, "ietf-netconf-server", 0); if(rc != SR_ERR_OK) { - struct ly_err_item *err = ly_err_first(session_context); - log_error("sr_validate issues on STARTUP: %s", err->msg); + log_error("sr_validate issues on STARTUP\n"); return NTS_ERR_FAILED; } rc = sr_apply_changes(current_session, 0, 0); if(rc != SR_ERR_OK) { - log_error("could not apply changes on datastore"); + log_error("could not apply changes on datastore\n"); return NTS_ERR_FAILED; } lyd_free_withsiblings(netconf_node); + netconf_call_home_status = 1; return NTS_ERR_OK; } @@ -103,23 +113,9 @@ static int create_ssh_callhome_endpoint(sr_session_ctx_t *current_session, struc assert(current_session); assert(netconf_node); - sr_val_t *value = 0; - - bool callhome_enabled = false; - int rc = sr_get_item(current_session, NETCONF_CALLHOME_ENABLED_SCHEMA_PATH, 0, &value); - if(rc == SR_ERR_OK) { - callhome_enabled = value->data.bool_val; - sr_free_val(value); - } - - if(callhome_enabled == false) { - log_message(2, "NETCONF CallHome is not enabled, not configuring NETCONF Server.\n"); - return NTS_ERR_OK; - } - controller_details_t *controller = controller_details_get(current_session); if(controller == 0) { - log_error("controller_details_get failed"); + log_error("controller_details_get failed\n"); return NTS_ERR_FAILED; } @@ -128,7 +124,7 @@ static int create_ssh_callhome_endpoint(sr_session_ctx_t *current_session, struc controller_details_free(controller); if(controller_ip == 0) { - log_error("strdup failed"); + log_error("strdup failed\n"); return NTS_ERR_FAILED; } @@ -136,7 +132,7 @@ static int create_ssh_callhome_endpoint(sr_session_ctx_t *current_session, struc sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/tcp-client-parameters/keepalives/idle-time"); struct lyd_node *rcl = lyd_new_path(netconf_node, 0, xpath, "1", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); free(controller_ip); return NTS_ERR_FAILED; } @@ -144,7 +140,7 @@ static int create_ssh_callhome_endpoint(sr_session_ctx_t *current_session, struc sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/tcp-client-parameters/keepalives/max-probes"); rcl = lyd_new_path(netconf_node, 0, xpath, "10", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); free(controller_ip); return NTS_ERR_FAILED; } @@ -152,7 +148,7 @@ static int create_ssh_callhome_endpoint(sr_session_ctx_t *current_session, struc sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/tcp-client-parameters/keepalives/probe-interval"); rcl = lyd_new_path(netconf_node, 0, xpath, "5", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); free(controller_ip); return NTS_ERR_FAILED; } @@ -160,7 +156,7 @@ static int create_ssh_callhome_endpoint(sr_session_ctx_t *current_session, struc sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/tcp-client-parameters/remote-address"); rcl = lyd_new_path(netconf_node, 0, xpath, controller_ip, 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); free(controller_ip); return NTS_ERR_FAILED; } @@ -171,55 +167,55 @@ static int create_ssh_callhome_endpoint(sr_session_ctx_t *current_session, struc sprintf(port, "%d", controller_callhome_port); rcl = lyd_new_path(netconf_node, 0, xpath, port, 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/ssh-server-parameters/server-identity/host-key[name='default-key']/public-key/keystore-reference"); rcl = lyd_new_path(netconf_node, 0, xpath, KS_KEY_NAME, 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/ssh-server-parameters/client-authentication/supported-authentication-methods/publickey"); rcl = lyd_new_path(netconf_node, 0, xpath, "", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/ssh-server-parameters/client-authentication/supported-authentication-methods/passsword"); rcl = lyd_new_path(netconf_node, 0, xpath, "", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/ssh-server-parameters/client-authentication/supported-authentication-methods/other"); rcl = lyd_new_path(netconf_node, 0, xpath, "interactive", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/ssh-server-parameters/client-authentication/users"); rcl = lyd_new_path(netconf_node, 0, xpath, "", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/connection-type/persistent"); rcl = lyd_new_path(netconf_node, 0, xpath, "", 0, LYD_PATH_OPT_NOPARENTRET); if(rcl == 0) { - log_error("could not created yang path"); + log_error("could not created yang path\n"); return NTS_ERR_FAILED; } - rc = send_odl_callhome_configuration(current_session); + int rc = send_odl_callhome_configuration(current_session); if(rc != NTS_ERR_OK) { - log_message(2, "could not send ODL Call Home configuration.\n"); + log_add_verbose(2, "could not send ODL Call Home configuration.\n"); } return NTS_ERR_OK; @@ -240,40 +236,41 @@ static int send_odl_callhome_configuration(sr_session_ctx_t *current_session) { char *public_ssh_key = read_key(SERVER_PUBLIC_SSH_KEY_PATH); if(public_ssh_key == 0) { - log_error("could not read the public ssh key from file %s", SERVER_PUBLIC_SSH_KEY_PATH); + log_error("could not read the public ssh key from file %s\n", SERVER_PUBLIC_SSH_KEY_PATH); return NTS_ERR_FAILED; } char *ssh_key_string; ssh_key_string = strtok(public_ssh_key, " "); ssh_key_string = strtok(NULL, " "); + ssh_key_string[strlen(ssh_key_string) - 1] = 0; // trim the newline character // checkAS we have hardcoded here the username and password of the NETCONF Server char *odl_callhome_payload = 0; - asprintf(&odl_callhome_payload, NETCONF_CALLHOME_CURL_SEND_PAYLOAD_FORMAT, framework_environment.hostname, ssh_key_string); + asprintf(&odl_callhome_payload, NETCONF_CALLHOME_CURL_SEND_PAYLOAD_FORMAT, framework_environment.settings.hostname, ssh_key_string); free(public_ssh_key); if(odl_callhome_payload == 0) { - log_error("bad asprintf"); + log_error("bad asprintf\n"); return NTS_ERR_FAILED; } controller_details_t *controller = controller_details_get(current_session); if(controller == 0) { - log_error("controller_details_get failed"); + log_error("controller_details_get failed\n"); return NTS_ERR_FAILED; } char *url = 0; - asprintf(&url, "%s/rests/data/odl-netconf-callhome-server:netconf-callhome-server/allowed-devices/device=%s", controller->base_url, framework_environment.hostname); + asprintf(&url, "%s/rests/data/odl-netconf-callhome-server:netconf-callhome-server/allowed-devices/device=%s", controller->base_url, framework_environment.settings.hostname); if(url == 0) { - log_error("bad asprintf"); + log_error("bad asprintf\n"); controller_details_free(controller); return NTS_ERR_FAILED; } int rc = http_request(url, controller->username, controller->password, "PUT", odl_callhome_payload, 0, 0); if(rc != NTS_ERR_OK) { - log_error("http_request failed"); + log_error("http_request failed\n"); } free(url); diff --git a/ntsimulator/ntsim-ng/features/netconf_call_home/netconf_call_home.h b/ntsimulator/ntsim-ng/features/netconf_call_home/netconf_call_home.h index 48a9661..2220dc8 100644 --- a/ntsimulator/ntsim-ng/features/netconf_call_home/netconf_call_home.h +++ b/ntsimulator/ntsim-ng/features/netconf_call_home/netconf_call_home.h @@ -19,4 +19,5 @@ #include +int netconf_call_home_feature_get_status(void); int netconf_call_home_feature_start(sr_session_ctx_t *current_session); diff --git a/ntsimulator/ntsim-ng/features/ves_file_ready/ves_file_ready.c b/ntsimulator/ntsim-ng/features/ves_file_ready/ves_file_ready.c index 7cd56d5..af79d0e 100644 --- a/ntsimulator/ntsim-ng/features/ves_file_ready/ves_file_ready.c +++ b/ntsimulator/ntsim-ng/features/ves_file_ready/ves_file_ready.c @@ -37,18 +37,44 @@ static int ves_file_ready_invoke_pm_cb(sr_session_ctx_t *session, const char *pa static int ves_file_ready_send_message(sr_session_ctx_t *session, const char *file_location); static cJSON* ves_create_file_ready_fields(const char* file_location); static void ves_file_ready_vsftp_daemon_init(void); +static void ves_file_ready_vsftp_daemon_deinit(void); + +static sr_subscription_ctx_t *ves_file_ready_subscription = 0; + +int ves_file_ready_feature_get_status(void) { + return (ves_file_ready_subscription != 0); +} int ves_file_ready_feature_start(sr_session_ctx_t *current_session) { assert(current_session); assert_session(); - int rc = sr_rpc_subscribe(current_session, FILE_READY_RPC_SCHEMA_XPATH, ves_file_ready_invoke_pm_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &session_subscription); - if(rc != SR_ERR_OK) { - log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc)); - return NTS_ERR_FAILED; + if(ves_file_ready_subscription == 0) { + int rc = sr_rpc_subscribe(current_session, FILE_READY_RPC_SCHEMA_XPATH, ves_file_ready_invoke_pm_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &ves_file_ready_subscription); + if(rc != SR_ERR_OK) { + log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc)); + return NTS_ERR_FAILED; + } + + ves_file_ready_vsftp_daemon_init(); } - ves_file_ready_vsftp_daemon_init(); + return NTS_ERR_OK; +} + +int ves_file_ready_feature_stop(void) { + assert_session(); + + if(ves_file_ready_subscription) { + int rc = sr_unsubscribe(ves_file_ready_subscription); + if(rc != SR_ERR_OK) { + log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc)); + return NTS_ERR_FAILED; + } + + ves_file_ready_vsftp_daemon_deinit(); + ves_file_ready_subscription = 0; + } return NTS_ERR_OK; } @@ -57,6 +83,10 @@ static void ves_file_ready_vsftp_daemon_init(void) { system("/usr/sbin/vsftpd &"); } +static void ves_file_ready_vsftp_daemon_deinit(void) { + system("killall -9 vsftpd"); +} + static int ves_file_ready_invoke_pm_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) { int rc; @@ -91,46 +121,46 @@ static int ves_file_ready_send_message(sr_session_ctx_t *session, const char *fi cJSON *post_data_json = cJSON_CreateObject(); if(post_data_json == 0) { - log_error("could not create cJSON object"); + log_error("could not create cJSON object\n"); return NTS_ERR_FAILED; } cJSON *event = cJSON_CreateObject(); if(event == 0) { - log_error("could not create cJSON object"); + log_error("could not create cJSON object\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } if(cJSON_AddItemToObject(post_data_json, "event", event) == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } - char *hostname_string = framework_environment.hostname; + char *hostname_string = framework_environment.settings.hostname; cJSON *common_event_header = ves_create_common_event_header("notification", "Notification-gnb_Nokia-FileReady", hostname_string, "Normal", sequence_number++); if(common_event_header == 0) { - log_error("could not create cJSON object"); + log_error("could not create cJSON object\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } if(cJSON_AddItemToObject(event, "commonEventHeader", common_event_header) == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } cJSON *file_ready_fields = ves_create_file_ready_fields(file_location); if(file_ready_fields == 0) { - log_error("could not create cJSON object"); + log_error("could not create cJSON object\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } if(cJSON_AddItemToObject(event, "notificationFields", file_ready_fields) == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } @@ -138,14 +168,14 @@ static int ves_file_ready_send_message(sr_session_ctx_t *session, const char *fi char *post_data = cJSON_PrintUnformatted(post_data_json); cJSON_Delete(post_data_json); if(post_data == 0) { - log_error("cJSON_PrintUnformatted failed"); + log_error("cJSON_PrintUnformatted failed\n"); return NTS_ERR_FAILED; } ves_details_t *ves_details = ves_endpoint_details_get(session); if(!ves_details) { - log_error("ves_endpoint_details_get failed"); + log_error("ves_endpoint_details_get failed\n"); free(post_data); return NTS_ERR_FAILED; } @@ -155,7 +185,7 @@ static int ves_file_ready_send_message(sr_session_ctx_t *session, const char *fi free(post_data); if(rc != NTS_ERR_OK) { - log_error("http_request failed"); + log_error("http_request failed\n"); return NTS_ERR_FAILED; } @@ -167,44 +197,44 @@ static cJSON* ves_create_file_ready_fields(const char* file_location) { cJSON *file_ready_fields = cJSON_CreateObject(); if(file_ready_fields == 0) { - log_error("could not create JSON object"); + log_error("could not create JSON object\n"); return 0; } if(cJSON_AddStringToObject(file_ready_fields, "changeIdentifier", "PM_MEAS_FILES") == 0) { - log_error("cJSON_AddStringToObject failed"); + log_error("cJSON_AddStringToObject failed\n"); cJSON_Delete(file_ready_fields); return 0; } if(cJSON_AddStringToObject(file_ready_fields, "changeType", "FileReady") == 0) { - log_error("cJSON_AddStringToObject failed"); + log_error("cJSON_AddStringToObject failed\n"); cJSON_Delete(file_ready_fields); return 0; } if(cJSON_AddStringToObject(file_ready_fields, "notificationFieldsVersion", "2.0") == 0) { - log_error("cJSON_AddStringToObject failed"); + log_error("cJSON_AddStringToObject failed\n"); cJSON_Delete(file_ready_fields); return 0; } cJSON *array_of_named_hash_map = cJSON_CreateArray(); if(array_of_named_hash_map == 0) { - log_error("could not create JSON object"); + log_error("could not create JSON object\n"); cJSON_Delete(file_ready_fields); return 0; } if(cJSON_AddItemToObject(file_ready_fields, "arrayOfNamedHashMap", array_of_named_hash_map) == 0) { - log_error("cJSON_AddStringToObject failed"); + log_error("cJSON_AddStringToObject failed\n"); cJSON_Delete(file_ready_fields); return 0; } cJSON *additional_fields_entry = cJSON_CreateObject(); if(additional_fields_entry == 0) { - log_error("could not create JSON object"); + log_error("could not create JSON object\n"); cJSON_Delete(file_ready_fields); return 0; } @@ -213,14 +243,14 @@ static cJSON* ves_create_file_ready_fields(const char* file_location) { if(filename == 0) { if(cJSON_AddStringToObject(additional_fields_entry, "name", "dummy_file.tar.gz") == 0) { - log_error("cJSON_AddStringToObject failed"); + log_error("cJSON_AddStringToObject failed\n"); cJSON_Delete(file_ready_fields); return 0; } } else { if(cJSON_AddStringToObject(additional_fields_entry, "name", filename + 1) == 0) { - log_error("cJSON_AddStringToObject failed"); + log_error("cJSON_AddStringToObject failed\n"); cJSON_Delete(file_ready_fields); return 0; } @@ -228,43 +258,43 @@ static cJSON* ves_create_file_ready_fields(const char* file_location) { cJSON *hash_map = cJSON_CreateObject(); if(hash_map == 0) { - log_error("could not create JSON object"); + log_error("could not create JSON object\n"); cJSON_Delete(file_ready_fields); return 0; } if(cJSON_AddItemToObject(additional_fields_entry, "hashMap", hash_map) == 0) { - log_error("cJSON_AddStringToObject failed"); + log_error("cJSON_AddStringToObject failed\n"); cJSON_Delete(file_ready_fields); return 0; } if(cJSON_AddStringToObject(hash_map, "location", file_location) == 0) { - log_error("cJSON_AddStringToObject failed"); + log_error("cJSON_AddStringToObject failed\n"); cJSON_Delete(file_ready_fields); return 0; } if(cJSON_AddStringToObject(hash_map, "compression", "gzip") == 0) { - log_error("cJSON_AddStringToObject failed"); + log_error("cJSON_AddStringToObject failed\n"); cJSON_Delete(file_ready_fields); return 0; } if(cJSON_AddStringToObject(hash_map, "fileFormatType", "org.3GPP.32.435#measCollec") == 0) { - log_error("cJSON_AddStringToObject failed"); + log_error("cJSON_AddStringToObject failed\n"); cJSON_Delete(file_ready_fields); return 0; } if(cJSON_AddStringToObject(hash_map, "fileFormatVersion", "V5") == 0) { - log_error("cJSON_AddStringToObject failed"); + log_error("cJSON_AddStringToObject failed\n"); cJSON_Delete(file_ready_fields); return 0; } if(cJSON_AddItemToArray(array_of_named_hash_map, additional_fields_entry) == 0) { - log_error("cJSON_AddStringToObject failed"); + log_error("cJSON_AddStringToObject failed\n"); cJSON_Delete(file_ready_fields); return 0; } diff --git a/ntsimulator/ntsim-ng/features/ves_file_ready/ves_file_ready.h b/ntsimulator/ntsim-ng/features/ves_file_ready/ves_file_ready.h index 67f951a..8047127 100644 --- a/ntsimulator/ntsim-ng/features/ves_file_ready/ves_file_ready.h +++ b/ntsimulator/ntsim-ng/features/ves_file_ready/ves_file_ready.h @@ -19,4 +19,6 @@ #include +int ves_file_ready_feature_get_status(void); int ves_file_ready_feature_start(sr_session_ctx_t *current_session); +int ves_file_ready_feature_stop(void); diff --git a/ntsimulator/ntsim-ng/features/ves_heartbeat/ves_heartbeat.c b/ntsimulator/ntsim-ng/features/ves_heartbeat/ves_heartbeat.c index 4bfc075..74f7f62 100644 --- a/ntsimulator/ntsim-ng/features/ves_heartbeat/ves_heartbeat.c +++ b/ntsimulator/ntsim-ng/features/ves_heartbeat/ves_heartbeat.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "core/session.h" #include "core/framework.h" @@ -50,41 +51,74 @@ static void *ves_heartbeat_thread_routine(void *arg); static cJSON* ves_create_heartbeat_fields(int heartbeat_period); static int heartbeat_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *private_data); +static volatile sig_atomic_t ves_heartbeat_stopsig; +static sr_subscription_ctx_t *ves_heartbeat_subscription = 0; + +int ves_heartbeat_feature_get_status(void) { + return (ves_heartbeat_subscription != 0); +} + int ves_heartbeat_feature_start(sr_session_ctx_t *current_session) { assert_session(); + assert(current_session); - sr_val_t *value = 0; - if(pthread_mutex_init(&ves_heartbeat_lock, NULL) != 0) { - log_error("mutex init has failed"); - return NTS_ERR_FAILED; - } + if(ves_heartbeat_subscription == 0) { + sr_val_t *value = 0; + if(pthread_mutex_init(&ves_heartbeat_lock, NULL) != 0) { + log_error("mutex init has failed\n"); + return NTS_ERR_FAILED; + } - ves_heartbeat_period = 0; - ves_sequence_number = 0; + ves_heartbeat_stopsig = 0; + ves_heartbeat_period = 0; + ves_sequence_number = 0; - int rc = sr_get_item(current_session, HEARTBEAT_SCHEMA_XPATH, 0, &value); - if(rc == SR_ERR_OK) { - ves_heartbeat_period_set(value->data.uint16_val); - sr_free_val(value); - } - else if(rc != SR_ERR_NOT_FOUND) { - log_error("sr_get_item failed"); - } + int rc = sr_get_item(current_session, HEARTBEAT_SCHEMA_XPATH, 0, &value); + if(rc == SR_ERR_OK) { + ves_heartbeat_period_set(value->data.uint16_val); + sr_free_val(value); + } + else if(rc != SR_ERR_NOT_FOUND) { + log_error("sr_get_item failed\n"); + } - rc = sr_module_change_subscribe(current_session, "nts-network-function", HEARTBEAT_SCHEMA_XPATH, heartbeat_change_cb, NULL, 0, SR_SUBSCR_CTX_REUSE, &session_subscription); - if(rc != SR_ERR_OK) { - log_error("could not subscribe to heartbeat"); - return NTS_ERR_FAILED; + rc = sr_module_change_subscribe(current_session, "nts-network-function", HEARTBEAT_SCHEMA_XPATH, heartbeat_change_cb, NULL, 0, SR_SUBSCR_CTX_REUSE, &ves_heartbeat_subscription); + if(rc != SR_ERR_OK) { + log_error("could not subscribe to heartbeat\n"); + return NTS_ERR_FAILED; + } + + if(pthread_create(&ves_heartbeat_thread, 0, ves_heartbeat_thread_routine, 0)) { + log_error("could not create thread for heartbeat\n"); + return NTS_ERR_FAILED; + } } - if(pthread_create(&ves_heartbeat_thread, 0, ves_heartbeat_thread_routine, 0)) { - log_error("could not create thread for heartbeat"); - return NTS_ERR_FAILED; + return NTS_ERR_OK; +} + +int ves_heartbeat_feature_stop(void) { + assert_session(); + + if(ves_heartbeat_subscription) { + int rc = sr_unsubscribe(ves_heartbeat_subscription); + if(rc != SR_ERR_OK) { + log_error("could not subscribe to heartbeat\n"); + return NTS_ERR_FAILED; + } + + void *status; + ves_heartbeat_stopsig = 1; + pthread_join(ves_heartbeat_thread, &status); + pthread_mutex_destroy(&ves_heartbeat_lock); + + ves_heartbeat_subscription = 0; } return NTS_ERR_OK; } + static int ves_heartbeat_period_get(void) { pthread_mutex_lock(&ves_heartbeat_lock); int ret = ves_heartbeat_period; @@ -99,48 +133,48 @@ static void ves_heartbeat_period_set(int new_period) { } static int ves_heartbeat_send_ves_message(void) { - char *hostname_string = framework_environment.hostname; + char *hostname_string = framework_environment.settings.hostname; cJSON *post_data_json = cJSON_CreateObject(); if(post_data_json == 0) { - log_error("cJSON_CreateObject failed"); + log_error("cJSON_CreateObject failed\n"); return NTS_ERR_FAILED; } cJSON *event = cJSON_CreateObject(); if(event == 0) { - log_error("cJSON_CreateObject failed"); + log_error("cJSON_CreateObject failed\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } if(cJSON_AddItemToObject(post_data_json, "event", event) == 0) { - log_error("cJOSN_AddItemToObject failed"); + log_error("cJOSN_AddItemToObject failed\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } cJSON *common_event_header = ves_create_common_event_header("heartbeat", "Controller", hostname_string, "Low", ves_sequence_number++); if(common_event_header == 0) { - log_error("ves_create_common_event_header failed"); + log_error("ves_create_common_event_header failed\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } if(cJSON_AddItemToObject(event, "commonEventHeader", common_event_header) == 0) { - log_error("cJOSN_AddItemToObject failed"); + log_error("cJOSN_AddItemToObject failed\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } cJSON *heartbeat_fields = ves_create_heartbeat_fields(ves_heartbeat_period_get()); if(heartbeat_fields == 0) { - log_error("ves_create_heartbeat_fields failed"); + log_error("ves_create_heartbeat_fields failed\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } if(cJSON_AddItemToObject(event, "heartbeatFields", heartbeat_fields) == 0) { - log_error("cJOSN_AddItemToObject failed"); + log_error("cJOSN_AddItemToObject failed\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } @@ -148,13 +182,13 @@ static int ves_heartbeat_send_ves_message(void) { char *post_data = cJSON_PrintUnformatted(post_data_json); cJSON_Delete(post_data_json); if(post_data == 0) { - log_error("cJSON_PrintUnformatted failed"); + log_error("cJSON_PrintUnformatted failed\n"); return NTS_ERR_FAILED; } ves_details_t *ves_details = ves_endpoint_details_get(0); if(!ves_details) { - log_error("ves_endpoint_details_get failed"); + log_error("ves_endpoint_details_get failed\n"); free(post_data); return NTS_ERR_FAILED; } @@ -164,7 +198,7 @@ static int ves_heartbeat_send_ves_message(void) { free(post_data); if(rc != NTS_ERR_OK) { - log_error("http_request failed"); + log_error("http_request failed\n"); return NTS_ERR_FAILED; } @@ -175,7 +209,7 @@ static void *ves_heartbeat_thread_routine(void *arg) { int current_heartbeat_period = 0; unsigned int timer_counter = 0; - while(!framework_sigint) { + while((!framework_sigint) && (!ves_heartbeat_stopsig)) { current_heartbeat_period = ves_heartbeat_period_get(); timer_counter++; @@ -184,7 +218,7 @@ static void *ves_heartbeat_thread_routine(void *arg) { int rc = ves_heartbeat_send_ves_message(); if(rc != NTS_ERR_FAILED) { - log_error("could not send VES heartbeat"); + log_error("could not send VES heartbeat\n"); } } @@ -197,45 +231,45 @@ static void *ves_heartbeat_thread_routine(void *arg) { static cJSON* ves_create_heartbeat_fields(int heartbeat_period) { cJSON *heartbeat_fields = cJSON_CreateObject(); if(heartbeat_fields == 0) { - log_error("could not create JSON object"); + log_error("could not create JSON object\n"); return 0; } if(cJSON_AddStringToObject(heartbeat_fields, "heartbeatFieldsVersion", "3.0") == 0) { - log_error("cJSON_Add*ToObject failed"); + log_error("cJSON_Add*ToObject failed\n"); cJSON_Delete(heartbeat_fields); return 0; } if(cJSON_AddNumberToObject(heartbeat_fields, "heartbeatInterval", (double)(heartbeat_period)) == 0) { - log_error("cJSON_Add*ToObject failed"); + log_error("cJSON_Add*ToObject failed\n"); cJSON_Delete(heartbeat_fields); return 0; } cJSON *additional_fields = cJSON_CreateObject(); if(additional_fields == 0) { - log_error("could not create JSON object"); - log_error("cJSON_Add*ToObject failed"); + log_error("could not create JSON object\n"); + log_error("cJSON_Add*ToObject failed\n"); cJSON_Delete(heartbeat_fields); return 0; } if(cJSON_AddItemToObject(heartbeat_fields, "additionalFields", additional_fields) == 0) { - log_error("cJSON_Add*ToObject failed"); + log_error("cJSON_Add*ToObject failed\n"); cJSON_Delete(heartbeat_fields); return 0; } char *current_date_and_time = get_current_date_and_time(); if(current_date_and_time == 0) { - log_error("get_current_date_and_time failed"); + log_error("get_current_date_and_time failed\n"); cJSON_Delete(heartbeat_fields); return 0; } if(cJSON_AddStringToObject(additional_fields, "eventTime", current_date_and_time) == 0) { - log_error("cJSON_Add*ToObject failed"); + log_error("cJSON_Add*ToObject failed\n"); cJSON_Delete(heartbeat_fields); free(current_date_and_time); return 0; @@ -255,7 +289,7 @@ static int heartbeat_change_cb(sr_session_ctx_t *session, const char *module_nam if(event == SR_EV_DONE) { rc = sr_get_changes_iter(session, HEARTBEAT_SCHEMA_XPATH, &it); if(rc != SR_ERR_OK) { - log_error("sr_get_changes_iter failed"); + log_error("sr_get_changes_iter failed\n"); return SR_ERR_VALIDATION_FAILED; } diff --git a/ntsimulator/ntsim-ng/features/ves_heartbeat/ves_heartbeat.h b/ntsimulator/ntsim-ng/features/ves_heartbeat/ves_heartbeat.h index 0cea6c7..b182821 100644 --- a/ntsimulator/ntsim-ng/features/ves_heartbeat/ves_heartbeat.h +++ b/ntsimulator/ntsim-ng/features/ves_heartbeat/ves_heartbeat.h @@ -19,4 +19,6 @@ #include +int ves_heartbeat_feature_get_status(void); int ves_heartbeat_feature_start(sr_session_ctx_t *current_session); +int ves_heartbeat_feature_stop(void); diff --git a/ntsimulator/ntsim-ng/features/ves_pnf_registration/ves_pnf_registration.c b/ntsimulator/ntsim-ng/features/ves_pnf_registration/ves_pnf_registration.c index 62ccd47..69e459e 100644 --- a/ntsimulator/ntsim-ng/features/ves_pnf_registration/ves_pnf_registration.c +++ b/ntsimulator/ntsim-ng/features/ves_pnf_registration/ves_pnf_registration.c @@ -33,8 +33,14 @@ static int ves_pnf_sequence_number = 0; -static int ves_pnf_registration_send(sr_session_ctx_t *current_session, const char *nf_ip_address, int nf_port, bool is_tls); -static cJSON* ves_create_pnf_registration_fields(const char *nf_ip_address, int nf_port, bool is_tls); +static int ves_pnf_registration_send(sr_session_ctx_t *current_session, const char *nf_ip_v4_address, const char *nf_ip_v6_address, int nf_port, bool is_tls); +static cJSON* ves_create_pnf_registration_fields(const char *nf_ip_v4_address, const char *nf_ip_v6_address, int nf_port, bool is_tls); + +static int ves_pnf_registration_status = 0; + +int ves_pnf_registration_feature_get_status(void) { + return ves_pnf_registration_status; +} int ves_pnf_registration_feature_start(sr_session_ctx_t *current_session) { assert(current_session); @@ -50,105 +56,128 @@ int ves_pnf_registration_feature_start(sr_session_ctx_t *current_session) { sr_free_val(value); } else if(rc != SR_ERR_NOT_FOUND) { - log_error("sr_get_item failed"); + log_error("sr_get_item failed\n"); return NTS_ERR_FAILED; } + else { + // if value is not set yet, feature enable means we want to start pnf-registration + pnf_registration_enabled = true; + } if(pnf_registration_enabled == false) { - log_message(2, "PNF registration is disabled\n"); + log_add_verbose(2, "PNF registration is disabled\n"); return NTS_ERR_OK; } - bool host_addressing_enabled = (nts_mount_point_addressing_method_get(current_session) == HOST_MAPPING); - - char nf_ip_address[128]; - int nf_port; + char nf_ip_v4_address[128]; + char nf_ip_v6_address[128]; + int nf_ssh_port; + int nf_tls_port; - if(host_addressing_enabled) { - strcpy(nf_ip_address, framework_environment.host_ip); - nf_port = framework_environment.host_base_port; + nts_mount_point_addressing_method_t mp = nts_mount_point_addressing_method_get(current_session); + if(mp == UNKNOWN_MAPPING) { + log_error("mount-point-addressing-method failed\n"); + return NTS_ERR_FAILED; + } + else if(mp == DOCKER_MAPPING) { + if (framework_environment.settings.ip_v4 != 0) { + strcpy(nf_ip_v4_address, framework_environment.settings.ip_v4); + } + if (framework_environment.settings.ip_v6) { + strcpy(nf_ip_v6_address, framework_environment.settings.ip_v6); + } + nf_ssh_port = STANDARD_NETCONF_PORT; + nf_tls_port = nf_ssh_port + framework_environment.settings.ssh_connections; } else { - if(framework_environment.ip_v6_enabled) { - strcpy(nf_ip_address, framework_environment.ip_v6); + if (framework_environment.settings.ip_v6_enabled) { + strcpy(nf_ip_v6_address, framework_environment.host.ip); } else { - strcpy(nf_ip_address, framework_environment.ip_v4); - } - - nf_port = STANDARD_NETCONF_PORT; + strcpy(nf_ip_v4_address, framework_environment.host.ip); + } + nf_ssh_port = framework_environment.host.ssh_base_port; + nf_tls_port = framework_environment.host.tls_base_port; } - int port = 0; - for(int i = 0; i < framework_environment.ssh_connections; ++port, ++i) { - rc = ves_pnf_registration_send(current_session, nf_ip_address, nf_port + port, false); + for(int i = 0; i < framework_environment.settings.ssh_connections; i++) { + rc = ves_pnf_registration_send(current_session, nf_ip_v4_address, nf_ip_v6_address, nf_ssh_port + i, false); if(rc != NTS_ERR_OK) { - log_error("could not send pnfRegistration message for IP=%s and port=%d and protocol SSH", nf_ip_address, nf_port + port); + log_error("could not send pnfRegistration message for IPv4=%s and IPv6=%s and port=%d and protocol SSH\n", nf_ip_v4_address, nf_ip_v6_address, nf_ssh_port + i); continue; } } - for(int i = 0; i < framework_environment.tls_connections; ++port, ++i) { - rc = ves_pnf_registration_send(current_session, nf_ip_address, nf_port + port, true); + for(int i = 0; i < framework_environment.settings.tls_connections; i++) { + rc = ves_pnf_registration_send(current_session, nf_ip_v4_address, nf_ip_v6_address, nf_tls_port + i, true); if(rc != NTS_ERR_OK) { - log_error("could not send pnfRegistration message for IP=%s and port=%d and protocol TLS", nf_ip_address, nf_port + port); + log_error("could not send pnfRegistration message for IPv4=%s and IPv6=%s and port=%d and protocol TLS\n", nf_ip_v4_address, nf_ip_v6_address, nf_tls_port + i); continue; } } + log_add_verbose(2, "PNF registration enabled\n"); + ves_pnf_registration_status = 1; + return NTS_ERR_OK; } -static int ves_pnf_registration_send(sr_session_ctx_t *current_session, const char *nf_ip_address, int nf_port, bool is_tls) { +static int ves_pnf_registration_send(sr_session_ctx_t *current_session, const char *nf_ip_v4_address, const char *nf_ip_v6_address, int nf_port, bool is_tls) { assert(current_session); - assert(nf_ip_address); cJSON *post_data_json = cJSON_CreateObject(); if(post_data_json == 0) { - log_error("could not create cJSON object"); + log_error("could not create cJSON object\n"); return NTS_ERR_FAILED; } cJSON *event = cJSON_CreateObject(); if(event == 0) { - log_error("could not create cJSON object"); + log_error("could not create cJSON object\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } if(cJSON_AddItemToObject(post_data_json, "event", event) == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } - char *hostname_string = framework_environment.hostname; + char *hostname_string = framework_environment.settings.hostname; char source_name[100]; - sprintf(source_name, "%s_%d", hostname_string, nf_port); + + if (framework_environment.settings.ssh_connections + framework_environment.settings.tls_connections == 1) { + // we don't want to append the port to the mountpoint name if we only expose one port + sprintf(source_name, "%s", hostname_string); + } + else { + sprintf(source_name, "%s_%d", hostname_string, nf_port); + } cJSON *common_event_header = ves_create_common_event_header("pnfRegistration", "EventType5G", source_name, "Normal", ves_pnf_sequence_number++); if(common_event_header == 0) { - log_error("could not create cJSON object"); + log_error("could not create cJSON object\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } if(cJSON_AddItemToObject(event, "commonEventHeader", common_event_header) == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } - cJSON *pnf_registration_fields = ves_create_pnf_registration_fields(nf_ip_address, nf_port, is_tls); + cJSON *pnf_registration_fields = ves_create_pnf_registration_fields(nf_ip_v4_address, nf_ip_v6_address, nf_port, is_tls); if(pnf_registration_fields == 0) { - log_error("could not create cJSON object"); + log_error("could not create cJSON object\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } if(cJSON_AddItemToObject(event, "pnfRegistrationFields", pnf_registration_fields) == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(post_data_json); return NTS_ERR_FAILED; } @@ -156,14 +185,14 @@ static int ves_pnf_registration_send(sr_session_ctx_t *current_session, const ch char *post_data = cJSON_PrintUnformatted(post_data_json); cJSON_Delete(post_data_json); if(post_data == 0) { - log_error("cJSON_PrintUnformatted failed"); + log_error("cJSON_PrintUnformatted failed\n"); return NTS_ERR_FAILED; } ves_details_t *ves_details = ves_endpoint_details_get(current_session); if(!ves_details) { - log_error("ves_endpoint_details_get failed"); + log_error("ves_endpoint_details_get failed\n"); free(post_data); return NTS_ERR_FAILED; } @@ -173,45 +202,44 @@ static int ves_pnf_registration_send(sr_session_ctx_t *current_session, const ch free(post_data); if(rc != NTS_ERR_OK) { - log_error("http_request failed"); + log_error("http_request failed\n"); return NTS_ERR_FAILED; } return NTS_ERR_OK; } -static cJSON* ves_create_pnf_registration_fields(const char *nf_ip_address, int nf_port, bool is_tls) { - assert(nf_ip_address); +static cJSON* ves_create_pnf_registration_fields(const char *nf_ip_v4_address, const char *nf_ip_v6_address, int nf_port, bool is_tls) { //checkAL aici n-ar trebui niste valori "adevarate" ? cJSON *pnf_registration_fields = cJSON_CreateObject(); if(pnf_registration_fields == 0) { - log_error("could not create JSON object"); + log_error("could not create JSON object\n"); return 0; } if(cJSON_AddStringToObject(pnf_registration_fields, "pnfRegistrationFieldsVersion", "2.0") == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } if(cJSON_AddStringToObject(pnf_registration_fields, "lastServiceDate", "2019-08-16") == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } char *mac_addr = rand_mac_address(); if(mac_addr == 0) { - log_error("rand_mac_address failed") + log_error("rand_mac_address failed\n") cJSON_Delete(pnf_registration_fields); return 0; } if(cJSON_AddStringToObject(pnf_registration_fields, "macAddress", mac_addr) == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); free(mac_addr); return 0; @@ -219,65 +247,69 @@ static cJSON* ves_create_pnf_registration_fields(const char *nf_ip_address, int free(mac_addr); if(cJSON_AddStringToObject(pnf_registration_fields, "manufactureDate", "2019-08-16") == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } if(cJSON_AddStringToObject(pnf_registration_fields, "modelNumber", "Simulated Device Melacon") == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } - if(cJSON_AddStringToObject(pnf_registration_fields, "oamV4IpAddress", nf_ip_address) == 0) { - log_error("cJSON_AddItemToObject failed"); - cJSON_Delete(pnf_registration_fields); - return 0; + if (nf_ip_v4_address != 0 && strlen(nf_ip_v4_address) > 0) { + if(cJSON_AddStringToObject(pnf_registration_fields, "oamV4IpAddress", nf_ip_v4_address) == 0) { + log_error("cJSON_AddItemToObject failed\n"); + cJSON_Delete(pnf_registration_fields); + return 0; + } } - if(cJSON_AddStringToObject(pnf_registration_fields, "oamV6IpAddress", "0:0:0:0:0:ffff:a0a:011") == 0) { - log_error("cJSON_AddItemToObject failed"); - cJSON_Delete(pnf_registration_fields); - return 0; + if (nf_ip_v6_address != 0 && strlen(nf_ip_v6_address) > 0) { + if(cJSON_AddStringToObject(pnf_registration_fields, "oamV6IpAddress", nf_ip_v6_address) == 0) { + log_error("cJSON_AddItemToObject failed\n"); + cJSON_Delete(pnf_registration_fields); + return 0; + } } char serial_number[512]; - sprintf(serial_number, "%s-%s-%d-Simulated Device Melacon", framework_environment.hostname, nf_ip_address, nf_port); + sprintf(serial_number, "%s-%s-%d-Simulated Device Melacon", framework_environment.settings.hostname, nf_ip_v4_address, nf_port); if(cJSON_AddStringToObject(pnf_registration_fields, "serialNumber", serial_number) == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } if(cJSON_AddStringToObject(pnf_registration_fields, "softwareVersion", "2.3.5") == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } if(cJSON_AddStringToObject(pnf_registration_fields, "unitFamily", "Simulated Device") == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } if(cJSON_AddStringToObject(pnf_registration_fields, "unitType", "O-RAN-sim") == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } if(cJSON_AddStringToObject(pnf_registration_fields, "vendorName", "Melacon") == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } cJSON *additional_fields = cJSON_CreateObject(); if(additional_fields == 0) { - log_error("could not create JSON object"); + log_error("could not create JSON object\n"); cJSON_Delete(pnf_registration_fields); return 0; } @@ -287,7 +319,7 @@ static cJSON* ves_create_pnf_registration_fields(const char *nf_ip_address, int sprintf(port_string, "%d", nf_port); if(cJSON_AddStringToObject(additional_fields, "oamPort", port_string) == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } @@ -295,19 +327,19 @@ static cJSON* ves_create_pnf_registration_fields(const char *nf_ip_address, int if(is_tls) { //TLS specific configuration if(cJSON_AddStringToObject(additional_fields, "protocol", "TLS") == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } if(cJSON_AddStringToObject(additional_fields, "username", "netconf") == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } if(cJSON_AddStringToObject(additional_fields, "keyId", KS_KEY_NAME) == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } @@ -315,62 +347,63 @@ static cJSON* ves_create_pnf_registration_fields(const char *nf_ip_address, int else { //SSH specific configuration if(cJSON_AddStringToObject(additional_fields, "protocol", "SSH") == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } if(cJSON_AddStringToObject(additional_fields, "username", "netconf") == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } - if(cJSON_AddStringToObject(additional_fields, "password", "netconf") == 0) { - log_error("cJSON_AddItemToObject failed"); + // hardcoded password here + if(cJSON_AddStringToObject(additional_fields, "password", "netconf!") == 0) { + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } } if(cJSON_AddStringToObject(additional_fields, "reconnectOnChangedSchema", "false") == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } if(cJSON_AddStringToObject(additional_fields, "sleep-factor", "1.5") == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } if(cJSON_AddStringToObject(additional_fields, "tcpOnly", "false") == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } if(cJSON_AddStringToObject(additional_fields, "connectionTimeout", "20000") == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } if(cJSON_AddStringToObject(additional_fields, "maxConnectionAttempts", "100") == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } if(cJSON_AddStringToObject(additional_fields, "betweenAttemptsTimeout", "2000") == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } if(cJSON_AddStringToObject(additional_fields, "keepaliveDelay", "120") == 0) { - log_error("cJSON_AddItemToObject failed"); + log_error("cJSON_AddItemToObject failed\n"); cJSON_Delete(pnf_registration_fields); return 0; } diff --git a/ntsimulator/ntsim-ng/features/ves_pnf_registration/ves_pnf_registration.h b/ntsimulator/ntsim-ng/features/ves_pnf_registration/ves_pnf_registration.h index 0512ed0..50ad52e 100644 --- a/ntsimulator/ntsim-ng/features/ves_pnf_registration/ves_pnf_registration.h +++ b/ntsimulator/ntsim-ng/features/ves_pnf_registration/ves_pnf_registration.h @@ -19,4 +19,5 @@ #include +int ves_pnf_registration_feature_get_status(void); int ves_pnf_registration_feature_start(sr_session_ctx_t *current_session); diff --git a/ntsimulator/ntsim-ng/features/web_cut_through/web_cut_through.c b/ntsimulator/ntsim-ng/features/web_cut_through/web_cut_through.c index 8139b17..0ae406a 100644 --- a/ntsimulator/ntsim-ng/features/web_cut_through/web_cut_through.c +++ b/ntsimulator/ntsim-ng/features/web_cut_through/web_cut_through.c @@ -31,47 +31,119 @@ #define SYSTEM_NAME_SCHEMA_XPATH "/ietf-system:system/onap-system:name" #define SYSTEM_WEB_UI_SCHEMA_XPATH "/ietf-system:system/onap-system:web-ui" +#define IETF_SYSTEM_CONTACT_SCHEMA_XPATH "/ietf-system:system/contact" +#define IETF_SYSTEM_HOSTNAME_SCHEMA_XPATH "/ietf-system:system/hostname" +#define IETF_SYSTEM_LOCATION_SCHEMA_XPATH "/ietf-system:system/location" +#define IETF_SYSTEM_TIMEZONE_NAME_SCHEMA_XPATH "/ietf-system:system/clock/timezone-name" +#define IETF_SYSTEM_NTP_ENABLED_SCHEMA_XPATH "/ietf-system:system/ntp/enabled" +static int web_cut_through_status = 0; + +int web_cut_through_feature_get_status(void) { + return web_cut_through_status; +} int web_cut_through_feature_start(sr_session_ctx_t *current_session) { assert(current_session); assert_session(); - int rc = 0; + if(web_cut_through_status == 0) { + //update ietf-system details + int rc = sr_set_item_str(current_session, SYSTEM_NAME_SCHEMA_XPATH, framework_environment.settings.hostname, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } - //update ietf-system details - rc = sr_set_item_str(current_session, SYSTEM_NAME_SCHEMA_XPATH, framework_environment.hostname, 0, 0); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; - } + controller_details_t *controller_details = controller_details_get(current_session); + if(controller_details == 0) { + log_error("controller_details_get failed\n"); + return NTS_ERR_FAILED; + } - controller_details_t *controller_details = controller_details_get(current_session); - if(controller_details == 0) { - log_error("controller_details_get failed"); - return NTS_ERR_FAILED; - } + char *web_ui = 0; + asprintf(&web_ui, "%s/odlux/index.html#/configuration/%s", controller_details->base_url, framework_environment.settings.hostname); + controller_details_free(controller_details); - char *web_ui = 0; - asprintf(&web_ui, "%s/odlux/index.html#/about", controller_details->base_url); - controller_details_free(controller_details); + if(web_ui == 0) { + log_error("asprintf failed\n"); + return NTS_ERR_FAILED; + } - if(web_ui == 0) { - log_error("asprintf failed"); - return NTS_ERR_FAILED; - } + rc = sr_set_item_str(current_session, SYSTEM_WEB_UI_SCHEMA_XPATH, web_ui, 0, 0); + free(web_ui); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + rc = sr_set_item_str(current_session, IETF_SYSTEM_CONTACT_SCHEMA_XPATH, "O-RAN-SC SIM project", 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + rc = sr_set_item_str(current_session, IETF_SYSTEM_HOSTNAME_SCHEMA_XPATH, framework_environment.settings.hostname, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + rc = sr_set_item_str(current_session, IETF_SYSTEM_LOCATION_SCHEMA_XPATH, "Open Wireless Lab", 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + rc = sr_set_item_str(current_session, IETF_SYSTEM_TIMEZONE_NAME_SCHEMA_XPATH, "UTC", 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + rc = sr_set_item_str(current_session, IETF_SYSTEM_NTP_ENABLED_SCHEMA_XPATH, "false", 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } - rc = sr_set_item_str(current_session, SYSTEM_WEB_UI_SCHEMA_XPATH, web_ui, 0, 0); - free(web_ui); - if(rc != SR_ERR_OK) { - log_error("sr_set_item_str failed"); - return NTS_ERR_FAILED; + rc = sr_apply_changes(current_session, 0, 0); + if(rc != SR_ERR_OK) { + log_error("could not apply changes on datastore\n"); + return NTS_ERR_FAILED; + } + + web_cut_through_status = 1; } - rc = sr_apply_changes(current_session, 0, 0); - if(rc != SR_ERR_OK) { - log_error("could not apply changes on datastore"); - return NTS_ERR_FAILED; + return NTS_ERR_OK; +} + +int web_cut_through_feature_stop(sr_session_ctx_t *current_session) { + assert(current_session); + assert_session(); + + if(web_cut_through_status) { + //update ietf-system details + int rc = sr_delete_item(current_session, SYSTEM_NAME_SCHEMA_XPATH, 0); + if(rc != SR_ERR_OK) { + log_error("sr_delete_item failed\n"); + return NTS_ERR_FAILED; + } + + rc = sr_delete_item(current_session, SYSTEM_WEB_UI_SCHEMA_XPATH, 0); + if(rc != SR_ERR_OK) { + log_error("sr_delete_item failed\n"); + return NTS_ERR_FAILED; + } + + rc = sr_apply_changes(current_session, 0, 0); + if(rc != SR_ERR_OK) { + log_error("could not apply changes on datastore\n"); + return NTS_ERR_FAILED; + } + + web_cut_through_status = 0; } return NTS_ERR_OK; diff --git a/ntsimulator/ntsim-ng/features/web_cut_through/web_cut_through.h b/ntsimulator/ntsim-ng/features/web_cut_through/web_cut_through.h index b3fb221..4a41740 100644 --- a/ntsimulator/ntsim-ng/features/web_cut_through/web_cut_through.h +++ b/ntsimulator/ntsim-ng/features/web_cut_through/web_cut_through.h @@ -19,4 +19,6 @@ #include +int web_cut_through_feature_get_status(void); int web_cut_through_feature_start(sr_session_ctx_t *current_session); +int web_cut_through_feature_stop(sr_session_ctx_t *current_session); diff --git a/ntsimulator/ntsim-ng/main.c b/ntsimulator/ntsim-ng/main.c index 61fc129..316fe0a 100644 --- a/ntsimulator/ntsim-ng/main.c +++ b/ntsimulator/ntsim-ng/main.c @@ -26,189 +26,162 @@ #include "utils/nc_client.h" #include "core/framework.h" -#include "core/docker.h" +#include "core/container.h" #include "core/session.h" #include "core/context.h" #include "core/test.h" #include "core/nc_config.h" +#include "core/app/supervisor.h" #include "core/app/manager.h" #include "core/app/network_function.h" #include "core/datastore/schema.h" +#include "core/datastore/generate.h" #include "core/datastore/populate.h" -#include "core/faults/faults.h" - -#include "features/ves_pnf_registration/ves_pnf_registration.h" -#include "features/ves_heartbeat/ves_heartbeat.h" -#include "features/ves_file_ready/ves_file_ready.h" -#include "features/manual_notification/manual_notification.h" -#include "features/netconf_call_home/netconf_call_home.h" -#include "features/web_cut_through/web_cut_through.h" int main(int argc, char **argv) { int return_code = EXIT_SUCCESS; - framework_init(argc, argv); + if(framework_init(argc, argv) != NTS_ERR_OK) { + log_error(LOG_COLOR_BOLD_RED"framework_init() error\n"); + framework_free(); + return EXIT_FAILURE; + } - if(framework_arguments.container_init) { - if(!docker_container_init()) { - log_error("docker_container_init() failed"); - return_code = EXIT_FAILURE; - } + //common init + switch(framework_arguments.nts_mode) { + case NTS_MODE_MANAGER: + case NTS_MODE_NETWORK_FUNCTION: + case NTS_MODE_GENERATE_DATA: + case NTS_MODE_TEST: + case NTS_MODE_DEFAULT: + sr_log_stderr(SR_LL_INF); //checkAL WRN + + if(session_init() != NTS_ERR_OK) { + log_error("session_init() failed\n"); + return_code = EXIT_FAILURE; + goto main_clean_session; + } - framework_free(); - return return_code; + if(context_init(session_context) != 0) { + log_error("context_init() failed\n"); + return_code = EXIT_FAILURE; + goto main_clean_context; + } + + nc_client_init(); + break; + + default: + break; } - else { //not in container-init mode - sr_log_stderr(SR_LL_NONE); - - int rc; - rc = session_init(); - if(rc != 0) { - log_error("session_init() failed"); - return_code = EXIT_FAILURE; - goto non_container_init_cleanup; - } - - rc = context_init(session_context); - if(rc != 0) { - log_error("context_init() failed"); - return_code = EXIT_FAILURE; - goto non_container_init_cleanup; - } - - nc_client_init(); - - if(framework_arguments.nc_server_init) { + + //netconf server configure + switch(framework_arguments.nts_mode) { + case NTS_MODE_MANAGER: + case NTS_MODE_NETWORK_FUNCTION: //configure local netconf server - rc = netconf_configure(); - if(rc != 0) { - log_error("netconf_configure() failed"); + if(netconf_configure() != NTS_ERR_OK) { + log_error("netconf_configure() failed\n") + return_code = EXIT_FAILURE; + goto main_clean; + } + break; + + default: + break; + } + + switch(framework_arguments.nts_mode) { + case NTS_MODE_CONTAINER_INIT: + if(!container_self_init()) { + log_error("container_self_init() failed\n"); return_code = EXIT_FAILURE; - goto non_container_init_cleanup; } - } - if(framework_arguments.manager) { - //run in manager mode + goto main_clean_framework; + break; + + case NTS_MODE_SUPERVISOR: + //run in supervisor mode + if(supervisor_run() != NTS_ERR_OK) { + log_error("supervisor_run() failed\n"); + return_code = EXIT_FAILURE; + } + + goto main_clean_framework; + break; + + case NTS_MODE_MANAGER: if(manager_run() != NTS_ERR_OK) { + log_error("manager_run() failed\n"); return_code = EXIT_FAILURE; - goto non_container_init_cleanup; } - } - else if(framework_arguments.network_function) { - //run in network function mode + + goto main_clean; + break; + + case NTS_MODE_NETWORK_FUNCTION: if(network_function_run() != NTS_ERR_OK) { + log_error("network_function_run() failed\n"); return_code = EXIT_FAILURE; - goto non_container_init_cleanup; } - } - else { - if(framework_arguments.test_mode) { - if(test_mode_run() != NTS_ERR_OK) { - return_code = EXIT_FAILURE; - goto non_container_init_cleanup; - } + + goto main_clean; + break; + + case NTS_MODE_GENERATE_DATA: + if(datastore_generate_data(DATASTORE_RUNNING_PATH, DATASTORE_OPERATIONAL_PATH) != NTS_ERR_OK) { + log_error("datastore_generate_data() failed\n"); + return_code = EXIT_FAILURE; } - else if(framework_arguments.exhaustive_test) { - //exhaustive test - if(exhaustive_test_run() != NTS_ERR_OK) { - return_code = EXIT_FAILURE; - goto non_container_init_cleanup; - } + + goto main_clean; + break; + + case NTS_MODE_TEST: + if(exhaustive_test_run() != NTS_ERR_OK) { + log_error("exhaustive_test_run() failed\n"); + return_code = EXIT_FAILURE; } + + goto main_clean; + break; + case NTS_MODE_DEFAULT: if(framework_arguments.print_root_paths) { - //print all root paths with their attributes - if(schema_print_root_paths() != NTS_ERR_OK) { + if(datastore_schema_print_root_paths() != NTS_ERR_OK) { + log_error("datastore_schema_print_root_paths() failed\n"); return_code = EXIT_FAILURE; - goto non_container_init_cleanup; + goto main_clean; } } if(framework_arguments.print_structure_xpath != 0) { //print the associated structure - if(schema_print_xpath(framework_arguments.print_structure_xpath) != NTS_ERR_OK) { - return_code = EXIT_FAILURE; - goto non_container_init_cleanup; - } - } - - if(framework_arguments.populate_all) { - // populate all - if(schema_populate() != NTS_ERR_OK) { - return_code = EXIT_FAILURE; - goto non_container_init_cleanup; - } - } - - if(framework_arguments.enable_features) { - // check if PNF registration is enabled and send PNF registration message if so - rc = ves_pnf_registration_feature_start(session_running); - if(rc != 0) { - log_error("ves_pnf_registration_feature_start() failed"); - return_code = EXIT_FAILURE; - goto non_container_init_cleanup; - } - - // start feature for handling the heartbeat VES message - rc = ves_heartbeat_feature_start(session_running); - if(rc != 0) { - log_error("ves_heartbeat_feature_start() failed"); - return_code = EXIT_FAILURE; - goto non_container_init_cleanup; - } - - // start feature for handling the fileReady VES message - rc = ves_file_ready_feature_start(session_running); - if(rc != 0) { - log_error("ves_file_ready_feature_start() failed"); - return_code = EXIT_FAILURE; - goto non_container_init_cleanup; - } - - // start feature for manual notification - rc = manual_notification_feature_start(session_running); - if(rc != 0) { - log_error("manual_notification_feature_start() failed"); + if(datastore_schema_print_xpath(framework_arguments.print_structure_xpath) != NTS_ERR_OK) { + log_error("datastore_schema_print_xpath() failed\n"); return_code = EXIT_FAILURE; - goto non_container_init_cleanup; - } - - // start feature for NETCONF Call Home - rc = netconf_call_home_feature_start(session_running); - if(rc != 0) { - log_error("netconf_call_home_feature_start() failed"); - return_code = EXIT_FAILURE; - goto non_container_init_cleanup; - } - - // start feature for web cut through - rc = web_cut_through_feature_start(session_running); - if(rc != 0) { - log_error("web_cut_through_feature_start() failed"); - return_code = EXIT_FAILURE; - goto non_container_init_cleanup; + goto main_clean; } } - if(framework_arguments.loop) { - while(!framework_sigint) { - sleep(1); - } - } - } - - non_container_init_cleanup: - log_message(1, LOG_COLOR_BOLD_RED"\nstopping now...\n"LOG_COLOR_RESET); - - nc_client_destroy(); - context_free(); - session_free(); - framework_free(); + goto main_clean; + break; - return return_code; + default: + assert(0); + break; } - return EXIT_FAILURE; +main_clean: + log_add_verbose(1, LOG_COLOR_BOLD_RED"\nstopping now...\n"LOG_COLOR_RESET); + nc_client_destroy(); +main_clean_context: + context_free(); +main_clean_session: + session_free(); +main_clean_framework: + framework_free(); + return return_code; } diff --git a/ntsimulator/ntsim-ng/utils/http_client.c b/ntsimulator/ntsim-ng/utils/http_client.c index 245223f..d0d9827 100644 --- a/ntsimulator/ntsim-ng/utils/http_client.c +++ b/ntsimulator/ntsim-ng/utils/http_client.c @@ -45,7 +45,7 @@ int http_request(const char *url, const char *username, const char* password, co CURL *curl = curl_easy_init(); if(curl == 0) { - log_error("could not initialize cURL"); + log_error("could not initialize cURL\n"); return NTS_ERR_FAILED; } @@ -53,14 +53,14 @@ int http_request(const char *url, const char *username, const char* password, co struct curl_slist *header = 0; header = curl_slist_append(header, "Content-Type: application/json"); if(!header) { - log_error("curl_slist_append failed"); + log_error("curl_slist_append failed\n"); curl_easy_cleanup(curl); return NTS_ERR_FAILED; } header = curl_slist_append(header, "Accept: application/json"); if(!header) { - log_error("curl_slist_append failed"); + log_error("curl_slist_append failed\n"); curl_easy_cleanup(curl); return NTS_ERR_FAILED; } @@ -85,7 +85,7 @@ int http_request(const char *url, const char *username, const char* password, co char *credentials = 0; asprintf(&credentials, "%s:%s", username, password); if(credentials == 0) { - log_error("asprintf failed"); + log_error("asprintf failed\n"); curl_slist_free_all(header); curl_easy_cleanup(curl); return NTS_ERR_FAILED; @@ -100,15 +100,18 @@ int http_request(const char *url, const char *username, const char* password, co curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response_data); } - log_message(2, "%s-ing cURL to url=\"%s\" with body=\"%s\"\n", method, url, send_data_good); + log_add_verbose(2, "%s-ing cURL to url=\"%s\" with body=\"%s\"... ", method, url, send_data_good); CURLcode res = curl_easy_perform(curl); curl_slist_free_all(header); if(res != CURLE_OK) { - log_message(2, "--> could not send cURL to url=%s, with error: %s\n", url, curl_easy_strerror(res)); + log_add(2, "failed with error: %s\n", curl_easy_strerror(res)); curl_easy_cleanup(curl); return NTS_ERR_FAILED; } + else { + log_add(2, "success\n"); + } if(response_code) { long http_rc; @@ -136,7 +139,7 @@ int http_socket_request(const char *url, const char *sock_fname, const char *met CURL *curl = curl_easy_init(); if(curl == 0) { - log_error("could not initialize cURL"); + log_error("could not initialize cURL\n"); return NTS_ERR_FAILED; } @@ -144,21 +147,21 @@ int http_socket_request(const char *url, const char *sock_fname, const char *met struct curl_slist *header = 0; header = curl_slist_append(header, "Content-Type: application/json"); if(!header) { - log_error("curl_slist_append failed"); + log_error("curl_slist_append failed\n"); curl_easy_cleanup(curl); return NTS_ERR_FAILED; } header = curl_slist_append(header, "Accept: application/json"); if(!header) { - log_error("curl_slist_append failed"); + log_error("curl_slist_append failed\n"); curl_easy_cleanup(curl); return NTS_ERR_FAILED; } curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header); - curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 1L); //seconds timeout for a connection - curl_easy_setopt(curl, CURLOPT_TIMEOUT, 2L); //seconds timeout for an operation + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15L); //seconds timeout for a connection + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 15L); //seconds timeout for an operation curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1L); curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L); @@ -173,15 +176,18 @@ int http_socket_request(const char *url, const char *sock_fname, const char *met curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response_data); } - log_message(2, "%s-ing cURL to url=\"%s\" with body=\"%s\"\n", method, url, send_data_good); + log_add_verbose(2, "%s-ing cURL to url=\"%s\" with body=\"%s\"\n", method, url, send_data_good); CURLcode res = curl_easy_perform(curl); curl_slist_free_all(header); if(res != CURLE_OK) { - log_message(2, "--> could not send cURL to url=%s, with error: %s\n", url, curl_easy_strerror(res)); + log_add(2, "failed with error %s\n", curl_easy_strerror(res)); curl_easy_cleanup(curl); return NTS_ERR_FAILED; } + else { + log_add(2, "success\n"); + } if(response_code) { long http_rc; @@ -203,7 +209,7 @@ static size_t curl_write_cb(void *data, size_t size, size_t nmemb, void *userp) char *ptr = realloc(mem->response, mem->size + realsize + 1); if(ptr == NULL) { - log_error("realloc failed"); + log_error("realloc failed\n"); return 0; /* out of memory! */ } diff --git a/ntsimulator/ntsim-ng/utils/log_utils.c b/ntsimulator/ntsim-ng/utils/log_utils.c index 7624036..b0e26af 100644 --- a/ntsimulator/ntsim-ng/utils/log_utils.c +++ b/ntsimulator/ntsim-ng/utils/log_utils.c @@ -25,10 +25,16 @@ #include #include +#include +#include +#include +#include +#include + + #include static int instances = 0; -static int errors = 0; static FILE* logfile = 0; static char *extract_format(const char *format); @@ -40,83 +46,104 @@ void log_init(const char *logfilename) { logfile = fopen(logfilename, "w"); assert(logfile); - - time_t t = time(NULL); - struct tm tm = *localtime(&t); - fprintf(logfile, "started at: %d-%02d-%02d %02d:%02d:%02d\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); - fprintf(stdout, LOG_COLOR_BOLD_RED"started at: %d-%02d-%02d %02d:%02d:%02d\n"LOG_COLOR_RESET, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); } -void log__message(char const * const filename, uint32_t location, const int verbose_level, const char *format, ...) { +void log__message(char const * const fname, uint32_t location, int verbose_level, const char *format, ...) { + va_list arg; - char *format2 = 0; - asprintf(&format2, "[%s:%u] %s", filename, location, format); - if(format2 == 0) { - fprintf(stderr, LOG_COLOR_BOLD_RED"bad malloc in log system\n"LOG_COLOR_RESET); - format2 = (char *)format; + char *verbose_file = 0; + int free_verbose_file = 0; + + char *verbose_screen = 0; + int free_verbose_screen = 0; + + if(verbose_level < 0) { + //when verbose negative, treat as add (no filename, line, time, etc) + verbose_level = -verbose_level; + verbose_file = (char *)format; + verbose_screen = (char *)format; } + else { + //extract just the filename, no path + const char *filename = fname + strlen(fname) - 1; + while((filename != fname) && (*filename != '/')) { + filename--; + } + if(*filename == '/') { + filename++; + } - va_start(arg, format); - char *new_format = extract_format(format2); - vfprintf(logfile, new_format, arg); + time_t t = time(NULL); + struct tm tm = *localtime(&t); + + asprintf(&verbose_file, "[%d-%02d-%02d|%02d:%02d:%02d|%s:%u] %s", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, filename, location, format); + if(verbose_file == 0) { + verbose_file = (char *)format; + } + else { + free_verbose_file = 1; + } - if(new_format != format2) { - free(new_format); + if(verbose_level != 0) { + asprintf(&verbose_screen, "[%d-%02d-%02d|%02d:%02d:%02d] %s", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, format); + } + else { + verbose_screen = strdup(verbose_file); + } + + if(verbose_screen == 0) { + verbose_screen = (char *)format; + } + else { + free_verbose_screen = 1; + } } + + //log to file in an uncolored format (simple format) + va_start(arg, format); + char *simple_format = extract_format(verbose_file); + vfprintf(logfile, simple_format, arg); - if(format2 != format) { - free(format2); + if(simple_format != verbose_file) { + free(simple_format); } - fflush(logfile); va_end(arg); + fflush(logfile); + + if(free_verbose_file) { + free(verbose_file); + } if(verbose_level <= framework_arguments.verbosity_level) { + + if(verbose_level == 0) { + fprintf(stderr, LOG_COLOR_BOLD_RED); + va_start(arg, format); + vfprintf(stderr, verbose_screen, arg); + va_end(arg); + fprintf(stderr, LOG_COLOR_RESET); + + fprintf(stdout, LOG_COLOR_BOLD_RED); + } + va_start(arg, format); - vfprintf(stdout, format, arg); + vfprintf(stdout, verbose_screen, arg); va_end(arg); - } -} - -void log__error(char const * const function, uint32_t location, const char *format, ...) { - va_list arg; - bool has_newline = false; - if(format[strlen(format) - 1] == '\n') { - has_newline = true; - } - errors++; - char *new_format = extract_format(format); - fprintf(logfile, "[error in %s():%d] ", function, location); - va_start(arg, format); - vfprintf(logfile, new_format, arg); - if(new_format != format) { - free(new_format); - } - if(!has_newline) { - fprintf(logfile, "\n"); + if(verbose_level == 0) { + fprintf(stdout, LOG_COLOR_RESET); + } } - fflush(logfile); - va_end(arg); - fprintf(stderr, "["LOG_COLOR_RED"error in "LOG_COLOR_BOLD_RED"%s()"LOG_COLOR_RED":"LOG_COLOR_BOLD_CYAN"%d"LOG_COLOR_RESET"] ", function, location); - va_start(arg, format); - vfprintf(stderr, format, arg); - if(!has_newline) { - fprintf(stderr, "\n"); + if(free_verbose_screen) { + free(verbose_screen); } - va_end(arg); } void log_close(void) { - time_t t = time(NULL); - struct tm tm = *localtime(&t); - fprintf(logfile, "finished at: %d-%02d-%02d %02d:%02d:%02d\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); fclose(logfile); - - if(errors) { - fprintf(stderr, "-------- !!!!!! ERRORS WERE PRESENT, CHECK ERROR FILE !!!!!! ------------\n\n\n\n"); - } + instances--; } static char *extract_format(const char *format) { @@ -160,3 +187,10 @@ static char *extract_format(const char *format) { return ret; } + +void log_redirect_stderr(const char *stderrfilename) { + remove(stderrfilename); + int stderr_fd = open(stderrfilename, O_WRONLY | O_CREAT | O_TRUNC, 0666); + dup2(stderr_fd, STDERR_FILENO); + close(stderr_fd); +} diff --git a/ntsimulator/ntsim-ng/utils/log_utils.h b/ntsimulator/ntsim-ng/utils/log_utils.h index 59fd277..2b18099 100644 --- a/ntsimulator/ntsim-ng/utils/log_utils.h +++ b/ntsimulator/ntsim-ng/utils/log_utils.h @@ -38,14 +38,14 @@ #define NTS_ERR_FAILED (-1) void log_init(const char *logfilename); -void log_message(const int verbose_level, const char *format, ...); +void log_redirect_stderr(const char *stderrfilename); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wvariadic-macros" -#define log_message(verbose_level, format, args...) log__message(__FILE__, (uint32_t)__LINE__, verbose_level, format, ## args); -#define log_error(format, args...) log__error(__func__, (uint32_t)__LINE__, format, ## args); +#define log_add_verbose(verbose_level, format, args...) log__message(__FILE__, (uint32_t)__LINE__, verbose_level, format, ## args); +#define log_add(verbose_level, format, args...) log__message(__FILE__, (uint32_t)__LINE__, -verbose_level, format, ## args); +#define log_error(format, args...) log__message(__FILE__, (uint32_t)__LINE__, 0, format, ## args); #pragma GCC diagnostic pop void log_close(void); -//use log_error instead -void log__error(char const * const function, uint32_t location, const char *format, ...); -void log__message(char const * const filename, uint32_t location, const int verbose_level, const char *format, ...); +//masked functions (use macros defined above) +void log__message(char const * const fname, uint32_t location, int verbose_level, const char *format, ...); diff --git a/ntsimulator/ntsim-ng/utils/nc_client.c b/ntsimulator/ntsim-ng/utils/nc_client.c index f3cb997..03d11c3 100644 --- a/ntsimulator/ntsim-ng/utils/nc_client.c +++ b/ntsimulator/ntsim-ng/utils/nc_client.c @@ -25,6 +25,7 @@ #include #include "core/session.h" +#include "core/nc_config.h" #include #include @@ -52,8 +53,6 @@ nc_client_t *nc_client_ssh_connect(const char *host, uint16_t port, const char * client->edit_batch_root = 0; - nc_client_init(); - nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, 3); nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, -1); nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, -1); @@ -61,7 +60,9 @@ nc_client_t *nc_client_ssh_connect(const char *host, uint16_t port, const char * nc_client_ssh_set_username(username); client->password = strdup(password); if(client->password == 0) { + log_error("strdup failed\n"); free(client); + return 0; } nc_client_ssh_set_auth_password_clb(nc_client_pass_cb, client); @@ -69,7 +70,7 @@ nc_client_t *nc_client_ssh_connect(const char *host, uint16_t port, const char * client->session = nc_connect_ssh(host, port, 0); if(client->session == 0) { - log_error("nc_connect_ssh failed"); + log_error("nc_connect_ssh failed\n"); free(client->password); free(client); return 0; @@ -78,6 +79,39 @@ nc_client_t *nc_client_ssh_connect(const char *host, uint16_t port, const char * return client; } +nc_client_t *nc_client_tls_connect(const char *host, uint16_t port) { + assert(host); + assert(port > 20); + + nc_client_t *client = (nc_client_t *)malloc(sizeof(nc_client_t)); + if(client == 0) { + return 0; + } + + client->edit_batch_root = 0; + client->password = 0; + int rc = nc_client_tls_set_cert_key_paths(CLIENT_CERT_PATH, CLIENT_KEY_PATH); + if(rc != 0) { + log_error("nc_client_tls_set_cert_key_paths failed\n"); + return 0; + } + + rc = nc_client_tls_set_trusted_ca_paths(CLIENT_CA_FILE, 0); + if(rc != 0) { + log_error("nc_client_tls_set_trusted_ca_paths failed\n"); + return 0; + } + + client->session = nc_connect_tls(host, port, 0); + if(client->session == 0) { + log_error("nc_connect_tls failed\n"); + free(client); + return 0; + } + + return client; +} + int nc_client_disconnect(nc_client_t *client) { assert(client); @@ -100,13 +134,13 @@ struct lyd_node *nc_client_send_rpc(nc_client_t *client, struct lyd_node *data, char *xmldata = 0; if(lyd_print_mem(&xmldata, data, LYD_XML, 0) != 0) { - log_error("lyd_print_mem failed"); + log_error("lyd_print_mem failed\n"); return 0; } rpc = nc_rpc_act_generic_xml(xmldata, NC_PARAMTYPE_CONST); if(rpc == 0) { - log_error("could not create rpc"); + log_error("could not create rpc\n"); free(xmldata); return 0; } @@ -114,7 +148,7 @@ struct lyd_node *nc_client_send_rpc(nc_client_t *client, struct lyd_node *data, msg_id = 0; send_ret = nc_send_rpc(client->session, rpc, timeout, &msg_id); if(send_ret != NC_MSG_RPC) { - log_error("could not send rpc"); + log_error("could not send rpc\n"); free(xmldata); nc_rpc_free(rpc); return 0; @@ -127,14 +161,14 @@ struct lyd_node *nc_client_send_rpc(nc_client_t *client, struct lyd_node *data, goto repeat_nc_recv_reply; } - log_error("could not get rpc reply"); + log_error("could not get rpc reply\n"); free(xmldata); nc_rpc_free(rpc); return 0; } if(reply->type != NC_RPL_DATA) { - log_error("reply has no data"); + log_error("reply has no data\n"); free(xmldata); nc_rpc_free(rpc); nc_reply_free(reply); @@ -146,7 +180,7 @@ struct lyd_node *nc_client_send_rpc(nc_client_t *client, struct lyd_node *data, LY_TREE_FOR(((struct nc_reply_data *)reply)->data->child, chd) { char *temp_xml = 0; if(lyd_print_mem(&temp_xml, chd, LYD_XML, 0) != 0) { - log_error("lyd_print_mem failed"); + log_error("lyd_print_mem failed\n"); free(ret_data_xml); free(xmldata); nc_rpc_free(rpc); @@ -180,14 +214,14 @@ struct lyd_node *nc_client_get_batch(nc_client_t *client, const char *xpath, int rpc = nc_rpc_get(xpath, NC_WD_UNKNOWN, NC_PARAMTYPE_CONST); if(rpc == 0) { - log_error("could not create rpc"); + log_error("could not create rpc\n"); return 0; } msg_id = 0; send_ret = nc_send_rpc(client->session, rpc, timeout, &msg_id); if(send_ret != NC_MSG_RPC) { - log_error("could not send rpc"); + log_error("could not send rpc\n"); nc_rpc_free(rpc); return 0; } @@ -200,13 +234,13 @@ struct lyd_node *nc_client_get_batch(nc_client_t *client, const char *xpath, int goto repeat_nc_recv_reply; } - log_error("could not get rpc reply"); + log_error("could not get rpc reply\n"); nc_rpc_free(rpc); return 0; } if(reply->type != NC_RPL_DATA) { - log_error("reply has no data"); + log_error("reply has no data\n"); nc_rpc_free(rpc); nc_reply_free(reply); return 0; @@ -214,7 +248,7 @@ struct lyd_node *nc_client_get_batch(nc_client_t *client, const char *xpath, int char *ret_data_xml = 0; if(lyd_print_mem(&ret_data_xml, ((struct nc_reply_data *)reply)->data, LYD_XML, 0) != 0) { - log_error("lyd_print_mem failed"); + log_error("lyd_print_mem failed\n"); nc_reply_free(reply); nc_rpc_free(rpc); return 0; @@ -241,13 +275,13 @@ int nc_client_edit_batch(nc_client_t *client, struct lyd_node *data, int timeout char *content = 0; int rc = lyd_print_mem(&content, data, LYD_XML, 0); if(rc != 0) { - log_error("lyd_print_mem failed"); + log_error("lyd_print_mem failed\n"); return NTS_ERR_FAILED; } rpc = nc_rpc_edit(NC_DATASTORE_RUNNING, NC_RPC_EDIT_DFLTOP_MERGE, NC_RPC_EDIT_TESTOPT_SET, NC_RPC_EDIT_ERROPT_STOP, content, NC_PARAMTYPE_CONST); if(rpc == 0) { - log_error("could not create rpc"); + log_error("could not create rpc\n"); free(content); return NTS_ERR_FAILED; } @@ -255,7 +289,7 @@ int nc_client_edit_batch(nc_client_t *client, struct lyd_node *data, int timeout msg_id = 0; send_ret = nc_send_rpc(client->session, rpc, timeout, &msg_id); if(send_ret != NC_MSG_RPC) { - log_error("could not send rpc"); + log_error("could not send rpc\n"); free(content); nc_rpc_free(rpc); return NTS_ERR_FAILED; @@ -263,7 +297,7 @@ int nc_client_edit_batch(nc_client_t *client, struct lyd_node *data, int timeout reply_ret = nc_recv_reply(client->session, rpc, msg_id, timeout, LYD_OPT_DESTRUCT | LYD_OPT_NOSIBLINGS, &reply); if((reply_ret != NC_MSG_REPLY) || (reply->type != NC_RPL_OK)) { - log_error("could not get rpc reply"); + log_error("could not get rpc reply\n"); free(content); nc_rpc_free(rpc); @@ -285,14 +319,14 @@ int nc_client_set_item_str(nc_client_t *client, const char *xpath, const char *v if(client->edit_batch_root) { struct lyd_node *n = lyd_new_path(client->edit_batch_root, 0, xpath, (void*)value, LYD_ANYDATA_CONSTSTRING, 0); if(n == 0) { - log_error("lyd_new_path error"); + log_error("lyd_new_path error\n"); return NTS_ERR_FAILED; } } else { client->edit_batch_root = lyd_new_path(0, session_context, xpath, (void*)value, LYD_ANYDATA_CONSTSTRING, 0); if(client->edit_batch_root == 0) { - log_error("lyd_new_path error"); + log_error("lyd_new_path error\n"); return NTS_ERR_FAILED; } } @@ -339,7 +373,8 @@ int lyd_utils_dup(sr_session_ctx_t *session, const char *xpath_s, const char *xp const char *value = ((struct lyd_node_leaf_list*)snode)->value_str; char *new_xpath = str_replace(xpath_c, xpath_s, xpath_d); - ly_log_options(0); + // ly_log_options(0); + ly_verb(LY_LLERR); //checkAL lyd_new_path(*tree, 0, new_xpath, (void*)value, LYD_ANYDATA_CONSTSTRING, 0); free(xpath_c); free(new_xpath); diff --git a/ntsimulator/ntsim-ng/utils/nc_client.h b/ntsimulator/ntsim-ng/utils/nc_client.h index c5f66b3..77bd2ef 100644 --- a/ntsimulator/ntsim-ng/utils/nc_client.h +++ b/ntsimulator/ntsim-ng/utils/nc_client.h @@ -18,6 +18,7 @@ #pragma once #define NC_ENABLED_SSH +#define NC_ENABLED_TLS #include #include #include @@ -34,6 +35,7 @@ typedef struct { } nc_client_t; nc_client_t *nc_client_ssh_connect(const char *host, uint16_t port, const char *username, const char *password); +nc_client_t *nc_client_tls_connect(const char *host, uint16_t port); int nc_client_disconnect(nc_client_t *client); struct lyd_node *nc_client_send_rpc(nc_client_t *client, struct lyd_node *data, int timeout); diff --git a/ntsimulator/ntsim-ng/utils/nts_utils.c b/ntsimulator/ntsim-ng/utils/nts_utils.c index b3c7d5d..60fa015 100644 --- a/ntsimulator/ntsim-ng/utils/nts_utils.c +++ b/ntsimulator/ntsim-ng/utils/nts_utils.c @@ -26,7 +26,17 @@ #include #include -#define MOUNT_POINT_ADDRESSING_METHOD_SCHEMA_XPATH "/nts-network-function:simulation/network-function/mount-point-addressing-method" +#define NTS_MANAGER_SDN_CONTROLLER_CONFIG_XPATH "/nts-manager:simulation/sdn-controller" +#define NTS_NF_SDN_CONTROLLER_CONFIG_XPATH "/nts-network-function:simulation/sdn-controller" +#define NTS_MANAGER_VES_ENDPOINT_CONFIG_XPATH "/nts-manager:simulation/ves-endpoint" +#define NTS_NF_VES_ENDPOINT_CONFIG_XPATH "/nts-network-function:simulation/ves-endpoint" + +#define NTS_NETWORK_FUNCTION_FTYPE_SCHEMA_XPATH "/nts-network-function:simulation/network-function/function-type" +#define NTS_NETWORK_FUNCTION_MPAM_SCHEMA_XPATH "/nts-network-function:simulation/network-function/mount-point-addressing-method" +#define NTS_NETWORK_FUNCTION_FAULT_GENERATION_SCHEMA_XPATH "/nts-network-function:simulation/network-function/fault-generation" +#define NTS_NETWORK_FUNCTION_NETCONF_SCHEMA_XPATH "/nts-network-function:simulation/network-function/netconf" +#define NTS_NETWORK_FUNCTION_VES_SCHEMA_XPATH "/nts-network-function:simulation/network-function/ves" + cJSON* ves_create_common_event_header(const char *domain, const char *event_type, const char *source_name, const char *priority, int seq_id) { assert(domain); @@ -39,26 +49,26 @@ cJSON* ves_create_common_event_header(const char *domain, const char *event_type asprintf(&eventId, "%s-%d", event_type, seq_id); if(eventId == 0) { - log_error("asprintf failed"); + log_error("asprintf failed\n"); return 0; } cJSON *common_event_header = cJSON_CreateObject(); if(common_event_header == 0) { - log_error("could not create JSON object"); + log_error("could not create JSON object\n"); free(eventId); return 0; } if(cJSON_AddStringToObject(common_event_header, "domain", domain) == 0) { - log_error("cJSON AddStringToObject error"); + log_error("cJSON AddStringToObject error\n"); free(eventId); cJSON_Delete(common_event_header); return 0; } if(cJSON_AddStringToObject(common_event_header, "eventId", eventId) == 0) { - log_error("cJSON AddStringToObject error"); + log_error("cJSON AddStringToObject error\n"); free(eventId); cJSON_Delete(common_event_header); return 0; @@ -67,85 +77,85 @@ cJSON* ves_create_common_event_header(const char *domain, const char *event_type free(eventId); if(cJSON_AddStringToObject(common_event_header, "eventName", event_type) == 0) { - log_error("cJSON AddStringToObject error"); + log_error("cJSON AddStringToObject error\n"); cJSON_Delete(common_event_header); return 0; } if(cJSON_AddNumberToObject(common_event_header, "sequence", (double)(seq_id)) == 0) { - log_error("cJSON AddNumberToObject error"); + log_error("cJSON AddNumberToObject error\n"); cJSON_Delete(common_event_header); return 0; } if(cJSON_AddStringToObject(common_event_header, "priority", priority) == 0) { - log_error("cJSON AddStringToObject error"); + log_error("cJSON AddStringToObject error\n"); cJSON_Delete(common_event_header); return 0; } if(cJSON_AddStringToObject(common_event_header, "reportingEntityId", "") == 0) { - log_error("cJSON AddStringToObject error"); + log_error("cJSON AddStringToObject error\n"); cJSON_Delete(common_event_header); return 0; } if(cJSON_AddStringToObject(common_event_header, "reportingEntityName", source_name) == 0) { - log_error("cJSON AddStringToObject error"); + log_error("cJSON AddStringToObject error\n"); cJSON_Delete(common_event_header); return 0; } if(cJSON_AddStringToObject(common_event_header, "sourceId", "") == 0) { - log_error("cJSON AddStringToObject error"); + log_error("cJSON AddStringToObject error\n"); cJSON_Delete(common_event_header); return 0; } if(cJSON_AddStringToObject(common_event_header, "sourceName", source_name) == 0) { - log_error("cJSON AddStringToObject error"); + log_error("cJSON AddStringToObject error\n"); cJSON_Delete(common_event_header); return 0; } if(cJSON_AddNumberToObject(common_event_header, "startEpochMicrosec", (double)(useconds)) == 0) { - log_error("cJSON AddNumberToObject error"); + log_error("cJSON AddNumberToObject error\n"); cJSON_Delete(common_event_header); return 0; } if(cJSON_AddNumberToObject(common_event_header, "lastEpochMicrosec", (double)(useconds)) == 0) { - log_error("cJSON AddNumberToObject error"); + log_error("cJSON AddNumberToObject error\n"); cJSON_Delete(common_event_header); return 0; } if(cJSON_AddStringToObject(common_event_header, "nfNamingCode", "sdn controller") == 0) { - log_error("cJSON AddStringToObject error"); + log_error("cJSON AddStringToObject error\n"); cJSON_Delete(common_event_header); return 0; } if(cJSON_AddStringToObject(common_event_header, "nfVendorName", "sdn") == 0) { - log_error("cJSON AddStringToObject error"); + log_error("cJSON AddStringToObject error\n"); cJSON_Delete(common_event_header); return 0; } if(cJSON_AddStringToObject(common_event_header, "timeZoneOffset", "+00:00") == 0) { - log_error("cJSON AddStringToObject error"); + log_error("cJSON AddStringToObject error\n"); cJSON_Delete(common_event_header); return 0; } if(cJSON_AddStringToObject(common_event_header, "version", "4.1") == 0) { - log_error("cJSON AddStringToObject error"); + log_error("cJSON AddStringToObject error\n"); cJSON_Delete(common_event_header); return 0; } - if(cJSON_AddStringToObject(common_event_header, "vesEventListenerVersion", "7.2") == 0) { - log_error("cJSON AddStringToObject error"); + if(cJSON_AddStringToObject(common_event_header, "vesEventListenerVersion", framework_environment.ves_endpoint.common_header_version) == 0) { + log_error("cJSON AddStringToObject error\n"); cJSON_Delete(common_event_header); return 0; } @@ -163,14 +173,14 @@ nts_mount_point_addressing_method_t nts_mount_point_addressing_method_get(sr_ses if(current_session == 0) { rc = sr_session_start(session_connection, SR_DS_RUNNING, ¤t_session); if(rc != SR_ERR_OK) { - log_error("could not start sysrepo session"); + log_error("could not start sysrepo session\n"); return ret; } session_started = true; } sr_val_t *value = 0; - rc = sr_get_item(session_running, MOUNT_POINT_ADDRESSING_METHOD_SCHEMA_XPATH, 0, &value); + rc = sr_get_item(session_running, NTS_NETWORK_FUNCTION_MPAM_SCHEMA_XPATH, 0, &value); if(rc == SR_ERR_OK) { if(strcmp(value->data.enum_val, "host-mapping") == 0) { ret = HOST_MAPPING; @@ -184,7 +194,7 @@ nts_mount_point_addressing_method_t nts_mount_point_addressing_method_get(sr_ses if(session_started) { rc = sr_session_stop(current_session); if(rc != SR_ERR_OK) { - log_error("could not stop sysrepo session"); + log_error("could not stop sysrepo session\n"); return ret; } } @@ -201,7 +211,7 @@ ves_details_t *ves_endpoint_details_get(sr_session_ctx_t *current_session) { if(current_session == 0) { rc = sr_session_start(session_connection, SR_DS_RUNNING, ¤t_session); if(rc != SR_ERR_OK) { - log_error("could not start sysrepo session"); + log_error("could not start sysrepo session\n"); return 0; } session_started = true; @@ -210,7 +220,7 @@ ves_details_t *ves_endpoint_details_get(sr_session_ctx_t *current_session) { struct lyd_node *data = 0; char *xpath_to_get; - if(framework_arguments.manager) { + if(framework_arguments.nts_mode == NTS_MODE_MANAGER) { xpath_to_get = "/nts-manager:simulation/ves-endpoint"; } else { @@ -229,7 +239,7 @@ ves_details_t *ves_endpoint_details_get(sr_session_ctx_t *current_session) { if(session_started) { rc = sr_session_stop(current_session); if(rc != SR_ERR_OK) { - log_error("could not stop sysrepo session"); + log_error("could not stop sysrepo session\n"); lyd_free(data); return 0; } @@ -243,7 +253,7 @@ ves_details_t *ves_endpoint_details_get(sr_session_ctx_t *current_session) { ves_details_t *ret = (ves_details_t *)malloc(sizeof(ves_details_t)); if(!ret) { - log_error("malloc failed"); + log_error("malloc failed\n"); lyd_free(data); return 0; } @@ -280,7 +290,14 @@ ves_details_t *ves_endpoint_details_get(sr_session_ctx_t *current_session) { } lyd_free(data); - asprintf(&ret->url, "%s://%s:%d/eventListener/v7", ret->protocol, ret->ip, ret->port); + if (strstr(ret->ip, ":")) { + // IPv6 address + asprintf(&ret->url, "%s://[%s]:%d/eventListener/v7", ret->protocol, ret->ip, ret->port); + } + else { + asprintf(&ret->url, "%s://%s:%d/eventListener/v7", ret->protocol, ret->ip, ret->port); + } + if((ret->protocol == 0) || (ret->ip == 0) || (ret->auth_method == 0) || (ret->username == 0) || (ret->password == 0) || (ret->url == 0)) { free(ret->protocol); free(ret->ip); @@ -317,7 +334,7 @@ controller_details_t *controller_details_get(sr_session_ctx_t *current_session) if(current_session == 0) { rc = sr_session_start(session_connection, SR_DS_RUNNING, ¤t_session); if(rc != SR_ERR_OK) { - log_error("could not start sysrepo session"); + log_error("could not start sysrepo session\n"); return 0; } session_started = true; @@ -326,7 +343,7 @@ controller_details_t *controller_details_get(sr_session_ctx_t *current_session) struct lyd_node *data = 0; char *xpath_to_get; - if(framework_arguments.manager) { + if(framework_arguments.nts_mode == NTS_MODE_MANAGER) { xpath_to_get = "/nts-manager:simulation/sdn-controller"; } else { @@ -345,7 +362,7 @@ controller_details_t *controller_details_get(sr_session_ctx_t *current_session) if(session_started) { rc = sr_session_stop(current_session); if(rc != SR_ERR_OK) { - log_error("could not stop sysrepo session"); + log_error("could not stop sysrepo session\n"); lyd_free(data); return 0; } @@ -359,7 +376,7 @@ controller_details_t *controller_details_get(sr_session_ctx_t *current_session) controller_details_t *ret = (controller_details_t *)malloc(sizeof(controller_details_t)); if(!ret) { - log_error("malloc failed"); + log_error("malloc failed\n"); lyd_free(data); return 0; } @@ -372,14 +389,16 @@ controller_details_t *controller_details_get(sr_session_ctx_t *current_session) ret->username = 0; ret->password = 0; - ret->protocol = strdup("http"); ret->auth_method = strdup("basic"); struct lyd_node *chd = 0; LY_TREE_FOR(data->child, chd) { const char *val = ((const struct lyd_node_leaf_list *)chd)->value_str; - if(strcmp(chd->schema->name, "controller-ip") == 0) { + if(strcmp(chd->schema->name, "controller-protocol") == 0) { + ret->protocol = strdup(val); + } + else if(strcmp(chd->schema->name, "controller-ip") == 0) { ret->ip = strdup(val); } else if(strcmp(chd->schema->name, "controller-port") == 0) { @@ -397,7 +416,14 @@ controller_details_t *controller_details_get(sr_session_ctx_t *current_session) } lyd_free(data); - asprintf(&ret->base_url, "%s://%s:%d", ret->protocol, ret->ip, ret->port); + if (strstr(ret->ip, ":")) { + // IPv6 address + asprintf(&ret->base_url, "%s://[%s]:%d", ret->protocol, ret->ip, ret->port); + } + else { + asprintf(&ret->base_url, "%s://%s:%d", ret->protocol, ret->ip, ret->port); + } + if((ret->protocol == 0) || (ret->ip == 0) || (ret->auth_method == 0) || (ret->username == 0) || (ret->password == 0) || (ret->base_url == 0)) { free(ret->protocol); free(ret->ip); @@ -423,3 +449,305 @@ void controller_details_free(controller_details_t *instance) { free(instance->password); free(instance); } + +int nts_vercmp(const char *ver1, const char *ver2) { + assert(ver1); + assert(ver2); + + int i = 0; + int v1 = 0, v2 = 0, v3 = 0; + while(ver1[i] && (ver1[i] != '.')) { + v1 *= 10; + v1 += ver1[i] - '0'; + i++; + } + + if(ver1[i]) { + i++; + while(ver1[i] && (ver1[i] != '.')) { + v2 *= 10; + v2 += ver1[i] - '0'; + i++; + } + + if(ver1[i]) { + i++; + while(ver1[i] && (ver1[i] != '.')) { + v3 *= 10; + v3 += ver1[i] - '0'; + i++; + } + } + } + + + int V1 = 0, V2 = 0, V3 = 0; + i = 0; + while(ver2[i] && (ver2[i] != '.')) { + V1 *= 10; + V1 += ver2[i] - '0'; + i++; + } + + if(ver2[i]) { + i++; + while(ver2[i] && (ver2[i] != '.')) { + V2 *= 10; + V2 += ver2[i] - '0'; + i++; + } + + if(ver2[i]) { + i++; + while(ver2[i] && (ver2[i] != '.')) { + V3 *= 10; + V3 += ver2[i] - '0'; + i++; + } + } + } + + if(v1 < V1) { + return -1; + } + else if(v1 > V1) { + return 1; + } + + if(v2 < V2) { + return -1; + } + else if(v2 > V2) { + return 1; + } + + if(v3 < V3) { + return -1; + } + else if(v3 > V3) { + return 1; + } + + return 0; +} + +int nts_utils_populate_info(sr_session_ctx_t *current_session, const char *function_type) { + assert(current_session); + assert(function_type); + + bool manager = (strcmp(function_type, "NTS_FUNCTION_TYPE_MANAGER") == 0); + + int rc; + char int_to_str[30]; + //setup sdn-controller defaults + if(strlen(framework_environment.sdn_controller.protocol)) { + if(manager) { + rc = sr_set_item_str(current_session, NTS_MANAGER_SDN_CONTROLLER_CONFIG_XPATH"/controller-protocol", (const char*)framework_environment.sdn_controller.protocol, 0, 0); + } + else { + rc = sr_set_item_str(current_session, NTS_NF_SDN_CONTROLLER_CONFIG_XPATH"/controller-protocol", (const char*)framework_environment.sdn_controller.protocol, 0, 0); + } + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + } + + if(strlen(framework_environment.sdn_controller.ip)) { + if(manager) { + rc = sr_set_item_str(current_session, NTS_MANAGER_SDN_CONTROLLER_CONFIG_XPATH"/controller-ip", (const char*)framework_environment.sdn_controller.ip, 0, 0); + } + else { + rc = sr_set_item_str(current_session, NTS_NF_SDN_CONTROLLER_CONFIG_XPATH"/controller-ip", (const char*)framework_environment.sdn_controller.ip, 0, 0); + } + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + } + + sprintf(int_to_str, "%d", framework_environment.sdn_controller.port); + if(manager) { + rc = sr_set_item_str(current_session, NTS_MANAGER_SDN_CONTROLLER_CONFIG_XPATH"/controller-port", (const char*)int_to_str, 0, 0); + } + else { + rc = sr_set_item_str(current_session, NTS_NF_SDN_CONTROLLER_CONFIG_XPATH"/controller-port", (const char*)int_to_str, 0, 0); + } + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + sprintf(int_to_str, "%d", framework_environment.sdn_controller.callhome_port); + if(manager) { + rc = sr_set_item_str(current_session, NTS_MANAGER_SDN_CONTROLLER_CONFIG_XPATH"/controller-netconf-call-home-port", (const char*)int_to_str, 0, 0); + } + else { + rc = sr_set_item_str(current_session, NTS_NF_SDN_CONTROLLER_CONFIG_XPATH"/controller-netconf-call-home-port", (const char*)int_to_str, 0, 0); + } + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + if(strlen(framework_environment.sdn_controller.username)) { + if(manager) { + rc = sr_set_item_str(current_session, NTS_MANAGER_SDN_CONTROLLER_CONFIG_XPATH"/controller-username", (const char*)framework_environment.sdn_controller.username, 0, 0); + } + else { + rc = sr_set_item_str(current_session, NTS_NF_SDN_CONTROLLER_CONFIG_XPATH"/controller-username", (const char*)framework_environment.sdn_controller.username, 0, 0); + } + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + } + + if(strlen(framework_environment.sdn_controller.password)) { + if(manager) { + rc = sr_set_item_str(current_session, NTS_MANAGER_SDN_CONTROLLER_CONFIG_XPATH"/controller-password", (const char*)framework_environment.sdn_controller.password, 0, 0); + } + else { + rc = sr_set_item_str(current_session, NTS_NF_SDN_CONTROLLER_CONFIG_XPATH"/controller-password", (const char*)framework_environment.sdn_controller.password, 0, 0); + } + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + } + + //setup ves-endpoint details + if(strlen(framework_environment.ves_endpoint.protocol)) { + if(manager) { + rc = sr_set_item_str(current_session, NTS_MANAGER_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-protocol", (const char*)framework_environment.ves_endpoint.protocol, 0, 0); + } + else { + rc = sr_set_item_str(current_session, NTS_NF_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-protocol", (const char*)framework_environment.ves_endpoint.protocol, 0, 0); + } + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + } + + if(strlen(framework_environment.ves_endpoint.ip)) { + if(manager) { + rc = sr_set_item_str(current_session, NTS_MANAGER_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-ip", (const char*)framework_environment.ves_endpoint.ip, 0, 0); + } + else { + rc = sr_set_item_str(current_session, NTS_NF_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-ip", (const char*)framework_environment.ves_endpoint.ip, 0, 0); + } + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + } + + sprintf(int_to_str, "%d", framework_environment.ves_endpoint.port); + if(manager) { + rc = sr_set_item_str(current_session, NTS_MANAGER_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-port", (const char*)int_to_str, 0, 0); + } + else { + rc = sr_set_item_str(current_session, NTS_NF_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-port", (const char*)int_to_str, 0, 0); + } + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + if(strlen(framework_environment.ves_endpoint.auth_method)) { + if(manager) { + rc = sr_set_item_str(current_session, NTS_MANAGER_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-auth-method", (const char*)framework_environment.ves_endpoint.auth_method, 0, 0); + } + else { + rc = sr_set_item_str(current_session, NTS_NF_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-auth-method", (const char*)framework_environment.ves_endpoint.auth_method, 0, 0); + } + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + } + + if(strlen(framework_environment.ves_endpoint.username)) { + if(manager) { + rc = sr_set_item_str(current_session, NTS_MANAGER_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-username", (const char*)framework_environment.ves_endpoint.username, 0, 0); + } + else { + rc = sr_set_item_str(current_session, NTS_NF_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-username", (const char*)framework_environment.ves_endpoint.username, 0, 0); + } + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + } + + if(strlen(framework_environment.ves_endpoint.password)) { + if(manager) { + rc = sr_set_item_str(current_session, NTS_MANAGER_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-password", (const char*)framework_environment.ves_endpoint.password, 0, 0); + } + else { + rc = sr_set_item_str(current_session, NTS_NF_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-password", (const char*)framework_environment.ves_endpoint.password, 0, 0); + } + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + } + + if(strlen(framework_environment.ves_endpoint.certificate)) { + if(manager) { + rc = sr_set_item_str(current_session, NTS_MANAGER_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-certificate", (const char*)framework_environment.ves_endpoint.certificate, 0, 0); + } + else { + rc = sr_set_item_str(current_session, NTS_NF_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-certificate", (const char*)framework_environment.ves_endpoint.certificate, 0, 0); + } + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + } + + if(manager == false) { + //presence containers + rc = sr_set_item_str(current_session, NTS_NETWORK_FUNCTION_FAULT_GENERATION_SCHEMA_XPATH, 0, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + rc = sr_set_item_str(current_session, NTS_NETWORK_FUNCTION_NETCONF_SCHEMA_XPATH, 0, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + rc = sr_set_item_str(current_session, NTS_NETWORK_FUNCTION_VES_SCHEMA_XPATH, 0, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + } + + //also set the network-function module for easy identifying the function type + rc = sr_set_item_str(current_session, NTS_NETWORK_FUNCTION_FTYPE_SCHEMA_XPATH, function_type, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + //mount-point-addressing-method + rc = sr_set_item_str(current_session, NTS_NETWORK_FUNCTION_MPAM_SCHEMA_XPATH, "docker-mapping", 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_set_item_str failed\n"); + return NTS_ERR_FAILED; + } + + //apply all changes + rc = sr_apply_changes(current_session, 0, 0); + if(rc != SR_ERR_OK) { + log_error("sr_apply_changes failed: %s\n", sr_strerror(rc)); + return NTS_ERR_FAILED; + } + + return NTS_ERR_OK; +} diff --git a/ntsimulator/ntsim-ng/utils/nts_utils.h b/ntsimulator/ntsim-ng/utils/nts_utils.h index 29f3944..01a43d7 100644 --- a/ntsimulator/ntsim-ng/utils/nts_utils.h +++ b/ntsimulator/ntsim-ng/utils/nts_utils.h @@ -38,7 +38,7 @@ typedef struct { char *url; } ves_details_t; -typedef struct { +typedef struct { char *ip; uint16_t port; uint16_t nc_callhome_port; @@ -59,3 +59,7 @@ void ves_details_free(ves_details_t *instance); controller_details_t *controller_details_get(sr_session_ctx_t *current_session); void controller_details_free(controller_details_t *instance); + +int nts_utils_populate_info(sr_session_ctx_t *current_session, const char *function_type); + +int nts_vercmp(const char *ver1, const char *ver2); diff --git a/ntsimulator/ntsim-ng/utils/rand_utils.c b/ntsimulator/ntsim-ng/utils/rand_utils.c index 6b1fd6f..06d746c 100644 --- a/ntsimulator/ntsim-ng/utils/rand_utils.c +++ b/ntsimulator/ntsim-ng/utils/rand_utils.c @@ -69,7 +69,7 @@ void rand_init(void) { FILE* urandom = fopen("/dev/urandom", "r"); if(urandom == 0) { - log_error("failed to open /dev/urandom"); + log_error("failed to open /dev/urandom\n"); } else { fread(&seed, sizeof(int), 1, urandom); @@ -79,9 +79,9 @@ void rand_init(void) { srand(seed); srandom(seed); - log_message(2, "rand_init() was called and seed was initialized to %u\n", seed); + log_add_verbose(2, "rand_init() was called and seed was initialized to %u\n", seed); if(RAND_MAX < 65536) { - log_error("RAND_MAX is too low: %d", RAND_MAX); + log_error("RAND_MAX is too low: %d\n", RAND_MAX); } } @@ -89,10 +89,10 @@ void rand_init_fixed(unsigned int seed) { srand(seed); srandom(seed); - log_message(2, "rand_init_fixed() was called and seed was initialized to %u\n", seed); + log_add_verbose(2, "rand_init_fixed() was called and seed was initialized to %u\n", seed); if(RAND_MAX < 65536) { - log_error("RAND_MAX is too low: %d", RAND_MAX); + log_error("RAND_MAX is too low: %d\n", RAND_MAX); } } @@ -106,7 +106,7 @@ char *rand_get_populate_value(const struct lys_type *type) { asprintf(&full_type, "%s:%s", type->der->module->name, type->der->name); if(full_type == 0) { - log_error("bad malloc"); + log_error("bad malloc\n"); return 0; } @@ -166,7 +166,7 @@ char *rand_get_populate_value(const struct lys_type *type) { } struct lys_ident *ident = rand_identity(type->info.ident.ref[0]); if(ident == 0) { - log_error("rand_identity failed"); + log_error("rand_identity failed\n"); return 0; } @@ -213,7 +213,7 @@ char *rand_get_populate_value(const struct lys_type *type) { if(expression) { char *ret = rand_regex(expression); if(ret == 0) { - log_error("rand_regex failed"); + log_error("rand_regex failed\n"); free(expression); return 0; } @@ -221,7 +221,7 @@ char *rand_get_populate_value(const struct lys_type *type) { while(strlen(ret) < min_length) { char *add = rand_regex(expression); if(add == 0) { - log_error("rand_regex failed"); + log_error("rand_regex failed\n"); free(expression); free(ret); return 0; @@ -236,7 +236,7 @@ char *rand_get_populate_value(const struct lys_type *type) { free(expression); if(ret == 0) { - log_error("rand_regex failed"); + log_error("rand_regex failed\n"); return 0; } @@ -344,7 +344,7 @@ char *rand_get_populate_value(const struct lys_type *type) { case LY_TYPE_BITS: ret = (char*)malloc(1); if(ret == 0) { - log_error("malloc failed"); + log_error("malloc failed\n"); return 0; } ret[0] = 0; @@ -355,7 +355,7 @@ char *rand_get_populate_value(const struct lys_type *type) { bool first = (ret == 0); ret = (char*)realloc(ret, sizeof(char) * (strlen(ret) + 1 + strlen(val) + 1)); if(ret == 0) { - log_error("malloc failed"); + log_error("malloc failed\n"); return 0; } @@ -391,7 +391,7 @@ char *rand_get_populate_value(const struct lys_type *type) { uint8_t *data = (uint8_t *)malloc(sizeof(uint8_t) * length); if(!data) { - log_error("bad malloc"); + log_error("bad malloc\n"); return 0; } @@ -408,7 +408,7 @@ char *rand_get_populate_value(const struct lys_type *type) { case LY_TYPE_UNION: case LY_TYPE_INST: asprintf(&ret, "{late_resolve_%s}", type->der->name); - log_error("needed: %s", ret); + log_error("needed: %s\n", ret); assert(0); return ret; break; @@ -416,7 +416,7 @@ char *rand_get_populate_value(const struct lys_type *type) { case LY_TYPE_UNKNOWN: default: asprintf(&ret, "{unimplemented_%s}", type->der->name); - log_error("can't generate random for: %s", type->der->name); + log_error("can't generate random for: %s\n", type->der->name); assert(0); return ret; break; @@ -474,7 +474,7 @@ char *rand_regex(const char *regexp) { char *regexp64 = b64_encode((const unsigned char*)regexp, strlen(regexp)); if(regexp64 == 0) { - log_error("b64_encode failed"); + log_error("b64_encode failed\n"); return 0; } @@ -488,7 +488,7 @@ char *rand_regex(const char *regexp) { free(regexp64); if(cmd == 0) { - log_error("asprintf failed"); + log_error("asprintf failed\n"); return 0; } @@ -496,7 +496,7 @@ char *rand_regex(const char *regexp) { while(last_char == ' ') { FILE* pipe = popen(cmd, "r"); if (!pipe) { - log_error("popen() failed"); + log_error("popen() failed\n"); free(cmd); return 0; } @@ -534,8 +534,8 @@ static char *rand_string(int min_length, int max_length) { length = min_length; } else { - if((framework_config.debug_max_string_size) && (framework_config.debug_max_string_size < max_length)) { - max_length = framework_config.debug_max_string_size; + if((framework_config.datastore_generate.debug_max_string_size) && (framework_config.datastore_generate.debug_max_string_size < max_length)) { + max_length = framework_config.datastore_generate.debug_max_string_size; } length = min_length + rand_uint16() % (max_length - min_length); @@ -543,7 +543,7 @@ static char *rand_string(int min_length, int max_length) { char *ret = (char *)malloc(length + 1); if(!ret) { - log_error("bad malloc"); + log_error("bad malloc\n"); return 0; } @@ -664,7 +664,7 @@ static rand_range_t rand_range(const char *range, const LY_DATA_TYPE type) { //remove spaces char *rrange = (char*)malloc(sizeof(char) * (strlen(range) + 1)); if (!rrange) { - log_error("bad malloc"); + log_error("bad malloc\n"); return ret; } @@ -886,7 +886,7 @@ static char *rand_date_and_time(void) { char *ret = (char *)malloc(21); if(!ret) { - log_error("bad malloc"); + log_error("bad malloc\n"); return 0; } strftime(ret, 21, "%Y-%m-%dT%H:%M:%SZ", <); diff --git a/ntsimulator/ntsim-ng/utils/sys_utils.c b/ntsimulator/ntsim-ng/utils/sys_utils.c index 1007b62..3449d63 100644 --- a/ntsimulator/ntsim-ng/utils/sys_utils.c +++ b/ntsimulator/ntsim-ng/utils/sys_utils.c @@ -68,7 +68,7 @@ void file_touch(const char *fname, const char *content) { FILE *f = fopen(fname, "w"); if(f == 0) { - log_error("fopen failed"); + log_error("fopen failed\n"); return; } @@ -260,8 +260,8 @@ bool check_port_open(const char *host, uint16_t port) { } freeaddrinfo(res); - if(returnStatus == 0) { - close(simpleSocket); + close(simpleSocket); + if(returnStatus == 0) { return true; } @@ -423,7 +423,7 @@ char *read_key(const char *filename) { fp = fopen(filename, "r"); if(fp == 0) { - log_error("could not open file %s", filename); + log_error("could not open file %s\n", filename); return 0; } @@ -439,7 +439,7 @@ char *read_key(const char *filename) { if(key_string) { key_string = (char *)realloc(key_string, strlen(key_string) + read + 1); if(key_string == 0) { - log_error("bad allocation"); + log_error("bad allocation\n"); free(line); return 0; } @@ -449,7 +449,7 @@ char *read_key(const char *filename) { else { key_string = strdup(line); if(key_string == 0) { - log_error("bad allocation"); + log_error("bad allocation\n"); free(line); return 0; } diff --git a/ntsimulator/ntsim-ng/utils/type_utils.c b/ntsimulator/ntsim-ng/utils/type_utils.c index 1221181..034bcf0 100644 --- a/ntsimulator/ntsim-ng/utils/type_utils.c +++ b/ntsimulator/ntsim-ng/utils/type_utils.c @@ -205,7 +205,7 @@ char* typeutils_type_to_str(const struct lys_type *type) { if(type->info.enums.count) { ret = (char*)realloc(ret, sizeof(char) * 1024 * 1024); if(!ret) { - log_error("bad malloc"); + log_error("bad malloc\n"); return 0; } diff --git a/ntsimulator/ubuntu_build.sh b/ntsimulator/ubuntu_build.sh deleted file mode 100755 index d32ef57..0000000 --- a/ntsimulator/ubuntu_build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker-compose -f nts-ng-docker-image-build-ubuntu.yaml build --build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') -- 2.16.6