Add supoprt for D release use-case. 67/5867/1
authorAlex Stancu <alexandru.stancu@highstreet-technologies.com>
Fri, 9 Apr 2021 12:13:00 +0000 (15:13 +0300)
committerAlex Stancu <alexandru.stancu@highstreet-technologies.com>
Fri, 9 Apr 2021 12:13:05 +0000 (15:13 +0300)
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 <alexandru.stancu@highstreet-technologies.com>
157 files changed:
ntsimulator/.env
ntsimulator/deploy/base/build_ntsim-ng.sh
ntsimulator/deploy/base/client.key [new file with mode: 0644]
ntsimulator/deploy/base/common.h.in [new file with mode: 0644]
ntsimulator/deploy/base/ubuntu.Dockerfile
ntsimulator/deploy/base/yang/nts-common.yang
ntsimulator/deploy/base/yang/nts-network-function.yang
ntsimulator/deploy/nts-manager/Dockerfile [new file with mode: 0644]
ntsimulator/deploy/nts-manager/config.json
ntsimulator/deploy/nts-manager/container-tag.yaml
ntsimulator/deploy/nts-manager/local.Dockerfile [new file with mode: 0644]
ntsimulator/deploy/nts-manager/supervisord.conf [deleted file]
ntsimulator/deploy/nts-manager/yang/nts-manager.yang
ntsimulator/deploy/o-ran-du/Dockerfile [new file with mode: 0644]
ntsimulator/deploy/o-ran-du/config.json [new file with mode: 0644]
ntsimulator/deploy/o-ran-du/container-tag.yaml [new file with mode: 0644]
ntsimulator/deploy/o-ran-du/data/README.md [new file with mode: 0644]
ntsimulator/deploy/o-ran-du/data/o-ran-sc-du-hello-world-operational.xml [new file with mode: 0644]
ntsimulator/deploy/o-ran-du/data/o-ran-sc-du-hello-world-running.xml [new file with mode: 0644]
ntsimulator/deploy/o-ran-du/local.Dockerfile [moved from ntsimulator/deploy/x-ran/ubuntu.Dockerfile with 80% similarity]
ntsimulator/deploy/o-ran-du/yang/ietf-system.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-du/yang/o-ran-sc-du-hello-world.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-du/yang/onap-system.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/Dockerfile [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/config.json [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/container-tag.yaml [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/data/README.md [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/data/ietf-hardware-operational.json [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/data/ietf-hardware-running.json [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/local.Dockerfile [moved from ntsimulator/deploy/o-ran/ubuntu.Dockerfile with 80% similarity]
ntsimulator/deploy/o-ran-ru-fh/yang/iana-hardware@2018-03-13.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/iana-if-type@2017-01-19.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/ietf-alarms@2019-09-11.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/ietf-crypto-types@2019-10-18.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/ietf-dhcpv6-types@2018-01-30.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/ietf-hardware@2018-03-13.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/ietf-inet-types@2013-07-15.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/ietf-interfaces@2018-02-20.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/ietf-ip@2018-02-22.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/ietf-netconf-acm@2018-02-14.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/ietf-network-instance@2019-01-21.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/ietf-restconf@2017-01-26.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/ietf-subscribed-notifications@2019-09-09.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/ietf-system.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/ietf-yang-schema-mount@2019-01-14.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/ietf-yang-types@2013-07-15.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ald-port@2019-07-03.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ald@2019-07-03.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-antenna-calibration@2020-12-10.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-beamforming@2020-04-17.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-compression-factors@2020-08-10.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-delay-management@2020-08-10.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-dhcp@2020-12-10.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ecpri-delay@2019-02-04.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ethernet-forwarding@2020-04-17.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-externalio@2019-07-03.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-fan@2019-07-03.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-file-management@2019-07-03.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-fm@2019-02-04.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-hardware@2020-12-10.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-interfaces@2020-12-10.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-laa-operations@2019-07-03.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-laa@2019-07-03.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-lbm@2019-02-04.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-module-cap@2020-12-10.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-mplane-int@2019-07-03.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-operations@2020-12-10.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-performance-management@2020-12-10.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-processing-element@2020-04-17.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-shared-cell@2020-12-10.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-software-management@2019-07-03.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-supervision@2020-12-10.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-sync@2020-08-10.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-trace@2019-07-03.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-transceiver@2019-07-03.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-troubleshooting@2019-02-04.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-udp-echo@2019-02-04.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-uplane-conf@2020-12-10.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-usermgmt@2020-12-10.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-ves-subscribed-notifications@2020-12-10.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-wg4-features@2020-12-10.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-ru-fh/yang/onap-system.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran/Dockerfile [new file with mode: 0644]
ntsimulator/deploy/o-ran/config.json
ntsimulator/deploy/o-ran/container-tag.yaml
ntsimulator/deploy/o-ran/data/README.md [new file with mode: 0644]
ntsimulator/deploy/o-ran/local.Dockerfile [moved from ntsimulator/deploy/nts-manager/ubuntu.Dockerfile with 71% similarity]
ntsimulator/deploy/o-ran/supervisord.conf [deleted file]
ntsimulator/deploy/x-ran/Dockerfile [new file with mode: 0644]
ntsimulator/deploy/x-ran/config.json
ntsimulator/deploy/x-ran/container-tag.yaml
ntsimulator/deploy/x-ran/data/README.md [new file with mode: 0644]
ntsimulator/deploy/x-ran/local.Dockerfile [new file with mode: 0644]
ntsimulator/deploy/x-ran/supervisord.conf [deleted file]
ntsimulator/docker-compose.yaml
ntsimulator/nts-ng-docker-image-build-ubuntu.yaml
ntsimulator/nts-start.sh [new file with mode: 0755]
ntsimulator/nts-stop.sh [new file with mode: 0755]
ntsimulator/nts_build.sh [new file with mode: 0755]
ntsimulator/ntsim-ng/core/app/app_common.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/app/app_common.h [new file with mode: 0644]
ntsimulator/ntsim-ng/core/app/manager.c
ntsimulator/ntsim-ng/core/app/manager.h
ntsimulator/ntsim-ng/core/app/manager_actions.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/app/manager_context.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/app/manager_operations.c
ntsimulator/ntsim-ng/core/app/manager_sysrepo.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/app/network_function.c
ntsimulator/ntsim-ng/core/app/supervisor.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/app/supervisor.h [new file with mode: 0644]
ntsimulator/ntsim-ng/core/container.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/container.h [new file with mode: 0644]
ntsimulator/ntsim-ng/core/context.c
ntsimulator/ntsim-ng/core/datastore/generate.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/datastore/generate.h [new file with mode: 0644]
ntsimulator/ntsim-ng/core/datastore/populate.c
ntsimulator/ntsim-ng/core/datastore/populate.h
ntsimulator/ntsim-ng/core/datastore/populate_rec.c [deleted file]
ntsimulator/ntsim-ng/core/datastore/schema.c
ntsimulator/ntsim-ng/core/datastore/schema.h
ntsimulator/ntsim-ng/core/docker.c
ntsimulator/ntsim-ng/core/docker.h
ntsimulator/ntsim-ng/core/faults/faults.c
ntsimulator/ntsim-ng/core/faults/faults_counters.c
ntsimulator/ntsim-ng/core/faults/faults_logic.c
ntsimulator/ntsim-ng/core/faults/faults_processing.c
ntsimulator/ntsim-ng/core/faults/faults_ves.c
ntsimulator/ntsim-ng/core/framework.c
ntsimulator/ntsim-ng/core/framework.h
ntsimulator/ntsim-ng/core/nc_config.c
ntsimulator/ntsim-ng/core/nc_config.h
ntsimulator/ntsim-ng/core/session.c
ntsimulator/ntsim-ng/core/test.c
ntsimulator/ntsim-ng/features/manual_notification/manual_notification.c
ntsimulator/ntsim-ng/features/manual_notification/manual_notification.h
ntsimulator/ntsim-ng/features/netconf_call_home/netconf_call_home.c
ntsimulator/ntsim-ng/features/netconf_call_home/netconf_call_home.h
ntsimulator/ntsim-ng/features/ves_file_ready/ves_file_ready.c
ntsimulator/ntsim-ng/features/ves_file_ready/ves_file_ready.h
ntsimulator/ntsim-ng/features/ves_heartbeat/ves_heartbeat.c
ntsimulator/ntsim-ng/features/ves_heartbeat/ves_heartbeat.h
ntsimulator/ntsim-ng/features/ves_pnf_registration/ves_pnf_registration.c
ntsimulator/ntsim-ng/features/ves_pnf_registration/ves_pnf_registration.h
ntsimulator/ntsim-ng/features/web_cut_through/web_cut_through.c
ntsimulator/ntsim-ng/features/web_cut_through/web_cut_through.h
ntsimulator/ntsim-ng/main.c
ntsimulator/ntsim-ng/utils/http_client.c
ntsimulator/ntsim-ng/utils/log_utils.c
ntsimulator/ntsim-ng/utils/log_utils.h
ntsimulator/ntsim-ng/utils/nc_client.c
ntsimulator/ntsim-ng/utils/nc_client.h
ntsimulator/ntsim-ng/utils/nts_utils.c
ntsimulator/ntsim-ng/utils/nts_utils.h
ntsimulator/ntsim-ng/utils/rand_utils.c
ntsimulator/ntsim-ng/utils/sys_utils.c
ntsimulator/ntsim-ng/utils/type_utils.c
ntsimulator/ubuntu_build.sh [deleted file]

index 42632ac..4104951 100644 (file)
@@ -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
index 49cac32..b64f071 100755 (executable)
 # ***************************************************************************/
 
 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 (file)
index 0000000..7ccdab1
--- /dev/null
@@ -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 (file)
index 0000000..fa0cee6
--- /dev/null
@@ -0,0 +1,1645 @@
+/**
+ * @file common.h
+ * @author Michal Vasko <mvasko@cesnet.cz>
+ * @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 <errno.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <string.h>
+#include <time.h>
+
+#include <libyang/libyang.h>
+
+#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 <stdatomic.h>
+
+# 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
index 21439db..69d69ce 100644 (file)
 
 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}
index ea7e60b..86d7b3e 100644 (file)
@@ -11,34 +11,43 @@ module nts-common {
     "O-RAN-SC";
   contact
     " Web: <https://wiki.o-ran-sc.org/display/SIM/SIM>
-        Editors:  
+        Editors:
         Alex Stancu <mailto:alexandru.stancu@highstreet-technologies.com>
         Adrian Lita <mailto:adrian.lita@highstreet-technologies.com>
         Martin Skorupski <mailto:martin.skorupski@highstreet-technologies.com>";
   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
+}
index 65fee7b..626038d 100644 (file)
@@ -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: <https://wiki.o-ran-sc.org/display/SIM/SIM>
-        Editors:  
+        Editors:
         Alex Stancu <mailto:alexandru.stancu@highstreet-technologies.com>
         Adrian Lita <mailto:adrian.lita@highstreet-technologies.com>
         Martin Skorupski <mailto:martin.skorupski@highstreet-technologies.com>";
   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 (file)
index 0000000..11790fb
--- /dev/null
@@ -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"]
index aafc0d3..f71c4f9 100644 (file)
@@ -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
index e0c7ce8..ee93a5d 100644 (file)
@@ -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 (file)
index 0000000..d07a799
--- /dev/null
@@ -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 (file)
index 9e0ca99..0000000
+++ /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
index 311a730..5f7bc14 100644 (file)
@@ -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: <https://wiki.o-ran-sc.org/display/SIM/SIM>
-        Editors:  
+        Editors:
         Alex Stancu <mailto:alexandru.stancu@highstreet-technologies.com>
         Adrian Lita <mailto:adrian.lita@highstreet-technologies.com>
         Martin Skorupski <mailto:martin.skorupski@highstreet-technologies.com>";
   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 (file)
index 0000000..bdb4cd8
--- /dev/null
@@ -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 (file)
index 0000000..3696617
--- /dev/null
@@ -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" : "<alarm-notif xmlns=\"urn:o-ran:fm:1.0\"><fault-id>$$uint16_counter$$</fault-id><fault-source>%%object%%</fault-source><affected-objects><name>%%affected-object%%</name></affected-objects><fault-severity>%%fault-severity%%</fault-severity><is-cleared>%%cleared%%</is-cleared><fault-text>%%text%%</fault-text><event-time>%%date-time%%</event-time></alarm-notif>",
+        "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 (file)
index 0000000..ee93a5d
--- /dev/null
@@ -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 (file)
index 0000000..7b501f4
--- /dev/null
@@ -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 (file)
index 0000000..e832268
--- /dev/null
@@ -0,0 +1,14 @@
+<network-function xmlns="urn:o-ran-sc:yang:o-ran-sc-du-hello-world">
+    <du-to-ru-connection>
+      <name>O-RU-1</name>
+      <status>connected</status>
+    </du-to-ru-connection>
+    <du-to-ru-connection>
+      <name>O-RU-2</name>
+      <status>disconnected</status>
+    </du-to-ru-connection>
+    <du-to-ru-connection>
+      <name>O-RU-3</name>
+      <status>unable-to-connect</status>
+    </du-to-ru-connection>
+  </network-function>
\ 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 (file)
index 0000000..756ba3b
--- /dev/null
@@ -0,0 +1,11 @@
+<network-function xmlns="urn:o-ran-sc:yang:o-ran-sc-du-hello-world">
+    <du-to-ru-connection>
+      <name>O-RU-1</name>
+    </du-to-ru-connection>
+    <du-to-ru-connection>
+      <name>O-RU-2</name>
+    </du-to-ru-connection>
+    <du-to-ru-connection>
+      <name>O-RU-3</name>
+    </du-to-ru-connection>
+  </network-function>
\ No newline at end of file
similarity index 80%
rename from ntsimulator/deploy/x-ran/ubuntu.Dockerfile
rename to ntsimulator/deploy/o-ran-du/local.Dockerfile
index f5cdd80..ae00eb7 100644 (file)
 #### 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 (file)
index 0000000..141ddba
--- /dev/null
@@ -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:   <http://tools.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+
+     WG Chair: Thomas Nadeau
+               <mailto:tnadeau@lucidvision.com>
+
+     WG Chair: Juergen Schoenwaelder
+               <mailto:j.schoenwaelder@jacobs-university.de>
+
+     Editor:   Andy Bierman
+               <mailto:andy@yumaworks.com>
+
+     Editor:   Martin Bjorklund
+               <mailto:mbj@tail-f.com>";
+
+  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 (file)
index 0000000..77115f5
--- /dev/null
@@ -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 (file)
index 0000000..3e19429
--- /dev/null
@@ -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: <https://www.onap.org>
+     Editors:
+        Alex Stancu <mailto:alexandru.stancu@highstreet-technologies.com>
+        Adrian Lita <mailto:adrian.lita@highstreet-technologies.com>
+        Martin Skorupski <mailto:martin.skorupski@highstreet-technologies.com>";
+  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 (file)
index 0000000..7a2b56a
--- /dev/null
@@ -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 (file)
index 0000000..818320d
--- /dev/null
@@ -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" : "<alarm-notif xmlns=\"urn:o-ran:fm:1.0\"><fault-id>$$uint16_counter$$</fault-id><fault-source>%%object%%</fault-source><affected-objects><name>%%affected-object%%</name></affected-objects><fault-severity>%%fault-severity%%</fault-severity><is-cleared>%%cleared%%</is-cleared><fault-text>%%text%%</fault-text><event-time>%%date-time%%</event-time></alarm-notif>",
+        "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 (file)
index 0000000..ee93a5d
--- /dev/null
@@ -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 (file)
index 0000000..7b501f4
--- /dev/null
@@ -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 (file)
index 0000000..18c83c9
--- /dev/null
@@ -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 (file)
index 0000000..ab757fa
--- /dev/null
@@ -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
+      }
+    ]
+  }
+}
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 (file)
 #### 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 (file)
index 0000000..52bcaf3
--- /dev/null
@@ -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 (file)
index 0000000..24d04e6
--- /dev/null
@@ -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
+     <mailto:iana&iana.org>";
+  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.
+     <http://www.iana.org/assignments/smi-numbers>";
+
+  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 (file)
index 0000000..a1c195f
--- /dev/null
@@ -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:   <https://trac.ietf.org/trac/ccamp>
+     WG List:  <mailto:ccamp@ietf.org>
+
+     Editor:   Stefan Vallin
+               <mailto:stefan@wallan.se>
+
+     Editor:   Martin Bjorklund
+               <mailto:mbj@tail-f.com>";
+  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 (file)
index 0000000..c620734
--- /dev/null
@@ -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:   <http://datatracker.ietf.org/wg/netconf/>
+     WG List:  <mailto:netconf@ietf.org>
+     Author:   Kent Watsen <mailto:kent+ietf@watsen.net>
+     Author:   Wang Haiguang <wang.haiguang.shieldlab@huawei.com>";
+
+  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 <operational> (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 (file)
index 0000000..c0d7193
--- /dev/null
@@ -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 (file)
index 0000000..f444e26
--- /dev/null
@@ -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:   <https://datatracker.ietf.org/wg/netmod/>
+   WG List:  <mailto:netmod@ietf.org>
+   Editor:   Andy Bierman
+             <mailto:andy@yumaworks.com>
+   Editor:   Martin Bjorklund
+             <mailto:mbj@tail-f.com>
+   Editor:   Jie Dong
+             <mailto:jie.dong@huawei.com>
+   Editor:   Dan Romascanu
+             <mailto:dromasca@gmail.com>";
+
+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 (file)
index 0000000..4b0db8e
--- /dev/null
@@ -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:   <http://tools.ietf.org/wg/netmod/>
+  WG List:  <mailto:netmod@ietf.org>
+  WG Chair: David Kessens
+            <mailto:david.kessens@nsn.com>
+  WG Chair: Juergen Schoenwaelder
+            <mailto:j.schoenwaelder@jacobs-university.de>
+  Editor:   Juergen Schoenwaelder
+            <mailto:j.schoenwaelder@jacobs-university.de>";
+
+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 <http://www.iana.org/>.
+    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 (file)
index 0000000..8dae9d3
--- /dev/null
@@ -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:   <https://datatracker.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+     Editor:   Martin Bjorklund
+               <mailto:mbj@tail-f.com>";
+
+  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 (file)
index 0000000..449081b
--- /dev/null
@@ -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:   <https://datatracker.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+     Editor:   Martin Bjorklund
+               <mailto:mbj@tail-f.com>";
+  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 (file)
index 0000000..ec9687a
--- /dev/null
@@ -0,0 +1,440 @@
+module ietf-netconf-acm {
+
+  namespace "urn:ietf:params:xml:ns:yang:ietf-netconf-acm";
+
+  prefix nacm;
+
+  import ietf-yang-types {
+    prefix yang;
+  }
+
+  organization
+    "IETF NETCONF (Network Configuration) Working Group";
+
+  contact
+    "WG Web:   <https://datatracker.ietf.org/wg/netconf/>
+     WG List:  <mailto:netconf@ietf.org>
+     Author:   Andy Bierman
+               <mailto:andy@yumaworks.com>
+     Author:   Martin Bjorklund
+               <mailto:mbj@tail-f.com>";
+
+  description
+    "Network Configuration Access Control Model.
+     Copyright (c) 2012 - 2018 IETF Trust and the persons
+     identified as authors of the code.  All rights reserved.
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD
+     License set forth in Section 4.c of the IETF Trust's
+     Legal Provisions Relating to IETF Documents
+     (https://trustee.ietf.org/license-info).
+     This version of this YANG module is part of RFC 8341; see
+     the RFC itself for full legal notices.";
+
+  revision "2018-02-14" {
+    description
+      "Added support for YANG 1.1 actions and notifications tied to
+       data nodes.  Clarified how NACM extensions can be used by
+       other data models.";
+    reference
+      "RFC 8341: Network Configuration Access Control Model";
+  }
+
+  revision "2012-02-22" {
+    description
+      "Initial version.";
+    reference
+      "RFC 6536: Network Configuration Protocol (NETCONF)
+                 Access Control Model";
+  }
+
+  /*
+   * Extension statements
+   */
+
+  extension default-deny-write {
+    description
+      "Used to indicate that the data model node
+       represents a sensitive security system parameter.
+       If present, the NETCONF server will only allow the designated
+       'recovery session' to have write access to the node.  An
+       explicit access control rule is required for all other users.
+       If the NACM module is used, then it must be enabled (i.e.,
+       /nacm/enable-nacm object equals 'true'), or this extension
+       is ignored.
+       The 'default-deny-write' extension MAY appear within a data
+       definition statement.  It is ignored otherwise.";
+  }
+
+  extension default-deny-all {
+    description
+      "Used to indicate that the data model node
+       controls a very sensitive security system parameter.
+       If present, the NETCONF server will only allow the designated
+       'recovery session' to have read, write, or execute access to
+       the node.  An explicit access control rule is required for all
+       other users.
+       If the NACM module is used, then it must be enabled (i.e.,
+       /nacm/enable-nacm object equals 'true'), or this extension
+       is ignored.
+       The 'default-deny-all' extension MAY appear within a data
+       definition statement, 'rpc' statement, or 'notification'
+       statement.  It is ignored otherwise.";
+  }
+
+  /*
+   * Derived types
+   */
+
+  typedef user-name-type {
+    type string {
+      length "1..max";
+    }
+    description
+      "General-purpose username string.";
+  }
+
+  typedef matchall-string-type {
+    type string {
+      pattern '\*';
+    }
+    description
+      "The string containing a single asterisk '*' is used
+       to conceptually represent all possible values
+       for the particular leaf using this data type.";
+  }
+
+  typedef access-operations-type {
+    type bits {
+      bit create {
+        description
+          "Any protocol operation that creates a
+           new data node.";
+      }
+      bit read {
+        description
+          "Any protocol operation or notification that
+           returns the value of a data node.";
+      }
+      bit update {
+        description
+          "Any protocol operation that alters an existing
+           data node.";
+      }
+      bit delete {
+        description
+          "Any protocol operation that removes a data node.";
+      }
+      bit exec {
+        description
+          "Execution access to the specified protocol operation.";
+      }
+    }
+    description
+      "Access operation.";
+  }
+
+  typedef group-name-type {
+    type string {
+      length "1..max";
+      pattern '[^\*].*';
+    }
+    description
+      "Name of administrative group to which
+       users can be assigned.";
+  }
+
+  typedef action-type {
+    type enumeration {
+      enum permit {
+        description
+          "Requested action is permitted.";
+      }
+      enum deny {
+        description
+          "Requested action is denied.";
+      }
+    }
+    description
+      "Action taken by the server when a particular
+       rule matches.";
+  }
+
+  typedef node-instance-identifier {
+    type yang:xpath1.0;
+    description
+      "Path expression used to represent a special
+       data node, action, or notification instance-identifier
+       string.
+       A node-instance-identifier value is an
+       unrestricted YANG instance-identifier expression.
+       All the same rules as an instance-identifier apply,
+       except that predicates for keys are optional.  If a key
+       predicate is missing, then the node-instance-identifier
+       represents all possible server instances for that key.
+       This XML Path Language (XPath) expression is evaluated in the
+       following context:
+          o  The set of namespace declarations are those in scope on
+             the leaf element where this type is used.
+          o  The set of variable bindings contains one variable,
+             'USER', which contains the name of the user of the
+             current session.
+          o  The function library is the core function library, but
+             note that due to the syntax restrictions of an
+             instance-identifier, no functions are allowed.
+          o  The context node is the root node in the data tree.
+       The accessible tree includes actions and notifications tied
+       to data nodes.";
+  }
+
+  /*
+   * Data definition statements
+   */
+
+  container nacm {
+    nacm:default-deny-all;
+
+    description
+      "Parameters for NETCONF access control model.";
+
+    leaf enable-nacm {
+      type boolean;
+      default "true";
+      description
+        "Enables or disables all NETCONF access control
+         enforcement.  If 'true', then enforcement
+         is enabled.  If 'false', then enforcement
+         is disabled.";
+    }
+
+    leaf read-default {
+      type action-type;
+      default "permit";
+      description
+        "Controls whether read access is granted if
+         no appropriate rule is found for a
+         particular read request.";
+    }
+
+    leaf write-default {
+      type action-type;
+      default "deny";
+      description
+        "Controls whether create, update, or delete access
+         is granted if no appropriate rule is found for a
+         particular write request.";
+    }
+
+    leaf exec-default {
+      type action-type;
+      default "permit";
+      description
+        "Controls whether exec access is granted if no appropriate
+         rule is found for a particular protocol operation request.";
+    }
+
+    leaf enable-external-groups {
+      type boolean;
+      default "true";
+      description
+        "Controls whether the server uses the groups reported by the
+         NETCONF transport layer when it assigns the user to a set of
+         NACM groups.  If this leaf has the value 'false', any group
+         names reported by the transport layer are ignored by the
+         server.";
+    }
+
+    leaf denied-operations {
+      type yang:zero-based-counter32;
+      config false;
+      mandatory true;
+      description
+        "Number of times since the server last restarted that a
+         protocol operation request was denied.";
+    }
+
+    leaf denied-data-writes {
+      type yang:zero-based-counter32;
+      config false;
+      mandatory true;
+      description
+        "Number of times since the server last restarted that a
+         protocol operation request to alter
+         a configuration datastore was denied.";
+    }
+
+    leaf denied-notifications {
+      type yang:zero-based-counter32;
+      config false;
+      mandatory true;
+      description
+        "Number of times since the server last restarted that
+         a notification was dropped for a subscription because
+         access to the event type was denied.";
+    }
+
+    container groups {
+      description
+        "NETCONF access control groups.";
+
+      list group {
+        key name;
+
+        description
+          "One NACM group entry.  This list will only contain
+           configured entries, not any entries learned from
+           any transport protocols.";
+
+        leaf name {
+          type group-name-type;
+          description
+            "Group name associated with this entry.";
+        }
+
+        leaf-list user-name {
+          type user-name-type;
+          description
+            "Each entry identifies the username of
+             a member of the group associated with
+             this entry.";
+        }
+      }
+    }
+
+    list rule-list {
+      key name;
+      ordered-by user;
+      description
+        "An ordered collection of access control rules.";
+
+      leaf name {
+        type string {
+          length "1..max";
+        }
+        description
+          "Arbitrary name assigned to the rule-list.";
+      }
+      leaf-list group {
+        type union {
+          type matchall-string-type;
+          type group-name-type;
+        }
+        description
+          "List of administrative groups that will be
+           assigned the associated access rights
+           defined by the 'rule' list.
+           The string '*' indicates that all groups apply to the
+           entry.";
+      }
+
+      list rule {
+        key name;
+        ordered-by user;
+        description
+          "One access control rule.
+           Rules are processed in user-defined order until a match is
+           found.  A rule matches if 'module-name', 'rule-type', and
+           'access-operations' match the request.  If a rule
+           matches, the 'action' leaf determines whether or not
+           access is granted.";
+
+        leaf name {
+          type string {
+            length "1..max";
+          }
+          description
+            "Arbitrary name assigned to the rule.";
+        }
+
+        leaf module-name {
+          type union {
+            type matchall-string-type;
+            type string;
+          }
+          default "*";
+          description
+            "Name of the module associated with this rule.
+             This leaf matches if it has the value '*' or if the
+             object being accessed is defined in the module with the
+             specified module name.";
+        }
+        choice rule-type {
+          description
+            "This choice matches if all leafs present in the rule
+             match the request.  If no leafs are present, the
+             choice matches all requests.";
+          case protocol-operation {
+            leaf rpc-name {
+              type union {
+                type matchall-string-type;
+                type string;
+              }
+              description
+                "This leaf matches if it has the value '*' or if
+                 its value equals the requested protocol operation
+                 name.";
+            }
+          }
+          case notification {
+            leaf notification-name {
+              type union {
+                type matchall-string-type;
+                type string;
+              }
+              description
+                "This leaf matches if it has the value '*' or if its
+                 value equals the requested notification name.";
+            }
+          }
+
+          case data-node {
+            leaf path {
+              type node-instance-identifier;
+              mandatory true;
+              description
+                "Data node instance-identifier associated with the
+                 data node, action, or notification controlled by
+                 this rule.
+                 Configuration data or state data
+                 instance-identifiers start with a top-level
+                 data node.  A complete instance-identifier is
+                 required for this type of path value.
+                 The special value '/' refers to all possible
+                 datastore contents.";
+            }
+          }
+        }
+
+        leaf access-operations {
+          type union {
+            type matchall-string-type;
+            type access-operations-type;
+          }
+          default "*";
+          description
+            "Access operations associated with this rule.
+             This leaf matches if it has the value '*' or if the
+             bit corresponding to the requested operation is set.";
+        }
+
+        leaf action {
+          type action-type;
+          mandatory true;
+          description
+            "The access control action associated with the
+             rule.  If a rule has been determined to match a
+             particular request, then this object is used
+             to determine whether to permit or deny the
+             request.";
+        }
+
+        leaf comment {
+          type string;
+          description
+            "A textual description of the access rule.";
+        }
+      }
+    }
+  }
+}
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 (file)
index 0000000..fe92ca1
--- /dev/null
@@ -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:   <https://datatracker.ietf.org/wg/rtgwg>
+     WG List:  <mailto:rtgwg@ietf.org>
+
+     Author:   Lou Berger
+               <mailto:lberger@labn.net>
+     Author:   Christian Hopps
+               <mailto:chopps@chopps.org>
+     Author:   Acee Lindem
+               <mailto:acee@cisco.com>
+     Author:   Dean Bogdanovic
+               <mailto:ivandean@gmail.com>";
+  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 (file)
index 0000000..44dac71
--- /dev/null
@@ -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:   <https://datatracker.ietf.org/wg/netconf/>
+     WG List:  <mailto:netconf@ietf.org>
+
+     Author:   Andy Bierman
+               <mailto:andy@yumaworks.com>
+
+     Author:   Martin Bjorklund
+               <mailto:mbj@tail-f.com>
+
+     Author:   Kent Watsen
+               <mailto:kwatsen@juniper.net>";
+
+  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:
+
+             <system-restart
+                xmlns='urn:ietf:params:xml:ns:yang:ietf-system'/>
+
+           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 (file)
index 0000000..14df349
--- /dev/null
@@ -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:  <https:/datatracker.ietf.org/wg/netconf/>
+     WG List: <mailto:netconf@ietf.org>
+
+     Author:  Alexander Clemm
+              <mailto:ludwig@clemm.org>
+
+     Author:  Eric Voit
+              <mailto:evoit@cisco.com>
+
+     Author:  Alberto Gonzalez Prieto
+              <mailto:alberto.gonzalez@microsoft.com>
+
+     Author:  Einar Nilsen-Nygaard
+              <mailto:einarnn@cisco.com>
+
+     Author:  Ambika Prasad Tripathy
+              <mailto:ambtripa@cisco.com>";
+  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 (file)
index 0000000..141ddba
--- /dev/null
@@ -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:   <http://tools.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+
+     WG Chair: Thomas Nadeau
+               <mailto:tnadeau@lucidvision.com>
+
+     WG Chair: Juergen Schoenwaelder
+               <mailto:j.schoenwaelder@jacobs-university.de>
+
+     Editor:   Andy Bierman
+               <mailto:andy@yumaworks.com>
+
+     Editor:   Martin Bjorklund
+               <mailto:mbj@tail-f.com>";
+
+  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 (file)
index 0000000..1f4f242
--- /dev/null
@@ -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:   <https://datatracker.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+
+     Editor:   Martin Bjorklund
+               <mailto:mbj@tail-f.com>
+
+     Editor:   Ladislav Lhotka
+               <mailto:lhotka@nic.cz>";
+
+  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 (file)
index 0000000..45b8c55
--- /dev/null
@@ -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:   <http://tools.ietf.org/wg/netmod/>
+  WG List:  <mailto:netmod@ietf.org>
+  WG Chair: David Kessens
+            <mailto:david.kessens@nsn.com>
+  WG Chair: Juergen Schoenwaelder
+            <mailto:j.schoenwaelder@jacobs-university.de>
+  Editor:   Juergen Schoenwaelder
+            <mailto:j.schoenwaelder@jacobs-university.de>";
+
+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 (file)
index 0000000..2cafb9e
--- /dev/null
@@ -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 (file)
index 0000000..d09cc30
--- /dev/null
@@ -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 (file)
index 0000000..bb99b77
--- /dev/null
@@ -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 (file)
index 0000000..7707dac
--- /dev/null
@@ -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 (file)
index 0000000..5816b5e
--- /dev/null
@@ -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 (file)
index 0000000..6e64c49
--- /dev/null
@@ -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 (file)
index 0000000..00b556b
--- /dev/null
@@ -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 (file)
index 0000000..88f1678
--- /dev/null
@@ -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 (file)
index 0000000..8c67b63
--- /dev/null
@@ -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 (file)
index 0000000..8779f71
--- /dev/null
@@ -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 (file)
index 0000000..79fb588
--- /dev/null
@@ -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 (file)
index 0000000..ee07645
--- /dev/null
@@ -0,0 +1,213 @@
+module o-ran-file-management {
+  yang-version 1.1;
+  namespace "urn:o-ran:file-management:1.0";
+  prefix "o-ran-file-mgmt";
+
+  import ietf-crypto-types {
+    prefix "ct";
+  }
+
+
+  organization "O-RAN Alliance";
+
+  contact
+    "www.o-ran.org";
+
+  description
+    "This module defines the configuration and operations for handling upload.
+
+    Copyright 2019 the O-RAN Alliance.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
+    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+    POSSIBILITY OF SUCH DAMAGE.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the above disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the above disclaimer in the documentation
+    and/or other materials provided with the distribution.
+    * Neither the Members of the O-RAN Alliance nor the names of its
+    contributors may be used to endorse or promote products derived from
+    this software without specific prior written permission.";
+
+  revision "2019-07-03" {
+    description
+      "version 1.1.0
+
+      1) backward compatible changes to correct sFTP Server Authentication .
+      2) minor fixes according to lack of descriptions
+      3) backward compatible changes to introduce groupings";
+
+    reference "ORAN-WG4.M.0-v01.00";
+  }
+
+  revision "2019-02-04" {
+    description
+      "version 1.0.0
+
+      1) imported model from xRAN
+      2) changed namespace and reference from xran to o-ran";
+
+    reference "ORAN-WG4.M.0-v01.00";
+  }
+
+  grouping file-path-grouping {
+    description "Complete logical path of the file to upload/download
+    (no wildcard is allowed) ex : /o-RAN/log/syslog.1";
+
+    leaf local-logical-file-path {
+      type string;
+      mandatory true;
+      description "Local logical file path";
+    }
+
+    leaf remote-file-path {
+      type string;
+      mandatory true;
+      description "URI specifying the remote-file-path on O-DU/NMS.
+      Format:sftp://<username>@<host>[:port]/path";
+    }
+  }
+
+  grouping output-status-grouping {
+    description "Status grouping";
+
+    leaf status {
+      type enumeration {
+        enum SUCCESS {
+            description "";}
+        enum FAILURE {
+            description "";}
+      }
+      description "Operation status";
+      }
+
+    leaf reject-reason {
+      when "../status = 'FAILURE'";
+      type string;
+      description "";
+    }
+  }
+
+  grouping credential-information {
+    description "Type of authentication to use for SFTP upload or download.";
+    choice credentials {
+      case password {
+        container password {
+          presence true;
+          leaf password {
+            type string;
+            mandatory true;
+            description
+              "password needed for O-RU authentication.";
+          }
+          description
+            "password for O-RU authentication method in use";
+        }
+        container server {
+          list keys {
+            key algorithm;
+            ordered-by user;
+            uses ct:public-key-grouping;
+            description
+              "List of allowed algorithms with its keys";
+          }
+          description
+            "Key for sFTP server authentication";
+        }
+      }
+      case certificate {
+        container certificate {
+          presence true;
+          description
+            "certificate authentication method in use";
+        }
+      }
+     description "";
+    }
+  }
+
+  grouping retrieve-input {
+    description "Grouping for information retrieval RPC input";
+    leaf logical-path {
+      type string;
+      mandatory true;
+      description "O-RAN unit of which the files are to be listed.
+      ex :  O-RAN/log, o-RAN/PM, O-RAN/transceiver";
+    }
+    leaf file-name-filter {
+      type string;
+      description "Filter which are to be applied on the result list of file names (* is allowed as wild-card).";
+    }
+  }
+
+  grouping retrieve-output {
+    description "Grouping for information retrieval RPC output";
+    uses output-status-grouping;
+    leaf-list file-list {
+      when "../status = 'SUCCESS'";
+      type string;
+      description "List of files in the unit with the filter applied.";
+    }
+  }
+
+// RPCs
+
+  rpc file-upload {
+    description "File upload over SFTP from equipment to NETCONF client";
+    input {
+      uses file-path-grouping;
+      uses credential-information;
+    }
+    output {
+      uses output-status-grouping;
+    }
+  }
+
+  rpc retrieve-file-list {
+    description "List all the files in the logical O-RAN unit (* is allowed as wild-card).";
+    input {
+      uses retrieve-input;
+
+    }
+    output {
+      uses retrieve-output;
+    }
+  }
+
+  notification file-upload-notification {
+    uses file-path-grouping;
+    uses output-status-grouping;
+    description "";
+  }
+
+  rpc file-download {
+    description
+      "Management plane triggered to generate the download file of O-RU.";
+    input {
+      uses file-path-grouping;
+      uses credential-information;
+    }
+    output {
+      uses output-status-grouping;
+    }
+  }
+
+  notification file-download-event {
+    uses file-path-grouping;
+    uses output-status-grouping;
+    description "";
+  }
+}
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 (file)
index 0000000..5142418
--- /dev/null
@@ -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 (file)
index 0000000..f62a405
--- /dev/null
@@ -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<M.";
+      }
+      enum FAULTY {
+        description
+          "The (sub-)components impacted by the critical alarm(s) impact the
+          ability of the equipment to continue operation (serve traffic).";
+      }
+    }
+    description
+      "Equipment's availability-state is derived by matching active faults
+       and their impact to module's operation and enables an equipment to indicate
+       that even though it may have one or more critical alarms, it can continue
+       to serve traffic.";
+  }
+
+  // common WG4 and croos-WG augmentations using O-RAN-RADIO identity
+
+  augment "/hw:hardware/hw:component" {
+    when "(derived-from-or-self(hw:class, 'o-ran-hw:O-RAN-RADIO')) or
+    (derived-from-or-self(hw:class, 'o-ran-hw:O-RAN-HW-COMPONENT'))";
+    description "New O-RAN parameters for o-ran hardware";
+
+    container label-content {
+      config false;
+      description
+        "Which set of attributes are printed on the Radio Unit's label";
+      leaf model-name {
+        type boolean;
+        description
+          "indicates whether model-name is included on the equipment's label";
+      }
+      leaf serial-number {
+        type boolean;
+        description
+          "indicates whether serial number is included on the equipment's label";
+      }
+    }
+    leaf product-code {
+      type string;
+      config false;
+      mandatory true;
+      description
+        "O-RAN term that is distinct from model-name in ietf-hardware.";
+    }
+    leaf energy-saving-enabled {
+      if-feature "ENERGYSAVING";
+      type boolean;
+      config true;
+      default false;
+      description
+        "This parameter can enable O-RAN unit to be switched to energy
+         saving mode.
+         TRUE indicates to switch the energy saving mode.
+         FALSE indicates to cancel the energy saving mode.
+         At the energy saving mode, all power of whole O-RAN unit becomes
+         lowest level whereas M-plane is still available";
+    }
+    leaf dying-gasp-support {
+      type boolean;
+      config false;
+      default false;
+      description
+        "indicates whether the O-RU supports the dying gasp
+        capability";
+    }
+    leaf last-service-date {
+      if-feature "or-feat:NON-PERSISTENT-MPLANE";
+      type yang:date-and-time;
+      description
+        "Date of last service or repair of hardware component. How this gets
+        populated is a vendor specific issue.";
+      reference
+        "3GPP 32.692";
+    }
+  }
+
+  augment "/hw:hardware/hw:component" {
+    when "(derived-from-or-self(hw:class, 'o-ran-hw:O-RAN-RADIO')) or
+    (derived-from-or-self(hw:class, 'ianahw:port')) or
+    (derived-from-or-self(hw:class, 'o-ran-hw:O-RAN-HW-COMPONENT'))";
+    description "New O-RAN parameters for o-ran naming";
+    leaf o-ran-name {
+      type leafref {
+        path "/hw:hardware/hw:component/hw:name";
+      }
+      must "re-match(current(),'[a-zA-Z0-9][a-zA-Z0-9\\.\\-_]{0,253}[a-zA-Z0-9]')" {
+        error-message "Name must match pattern and length.";
+      }
+      mandatory true;
+      description
+        "O-RAN name needed to bind and match with the name of hw element,
+        to be compliant with O-RAN naming convention.";
+    }
+  }
+
+  augment "/hw:hardware/hw:component/hw:state"  {
+    when "(derived-from-or-self(../hw:class, 'o-ran-hw:O-RAN-RADIO')) or
+    (derived-from-or-self(../hw:class, 'o-ran-hw:O-RAN-HW-COMPONENT'))";
+    description
+      "new O-RAN defined state";
+    leaf power-state {
+      if-feature "ENERGYSAVING";
+      type energysaving-state;
+      config false;
+      description
+        "The current power saving state for this component.
+        Note - hw:/hardware/compnent/state/standby-state defined in RFC 4268 is
+        used for redundancy purposes and not power saving operations.";
+    }
+    leaf availability-state {
+      type availability-type;
+      config false;
+      description
+        "Equipment's availability-state is derived by matching active faults
+         and their impact to module's operation and enables an equipment to indicate
+         that even though it may have one or more critical alarms, it can continue
+         to serve traffic.";
+    }
+  }
+
+
+// augmentations to Notifications
+
+  augment "/hw:hardware-state-oper-enabled"  {
+    description "new availability state";
+    leaf availability-state {
+      type leafref {
+        path "/hw:hardware/hw:component/hw:state/o-ran-hw:availability-state";
+      }
+      description
+        "The availability-state of the O-RU.";
+    }
+  }
+
+  augment "/hw:hardware-state-oper-disabled"  {
+    description "new availability state";
+    leaf availability-state {
+      type leafref {
+        path "/hw:hardware/hw:component/hw:state/o-ran-hw:availability-state";
+      }
+      description
+        "The availability-state of the O-RU.";
+    }
+  }
+}
diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-interfaces@2020-12-10.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-interfaces@2020-12-10.yang
new file mode 100644 (file)
index 0000000..78de3d1
--- /dev/null
@@ -0,0 +1,490 @@
+module o-ran-interfaces {
+  yang-version 1.1;
+  namespace "urn:o-ran:interfaces:1.0";
+  prefix "o-ran-int";
+
+
+  import ietf-inet-types {
+    prefix "inet";
+  }
+
+  import iana-if-type {
+    prefix "ianaift";
+  }
+
+  import ietf-interfaces {
+    prefix "if";
+  }
+
+  import ietf-ip {
+    prefix "ip";
+  }
+
+  import ietf-hardware {
+    prefix "hw";
+  }
+
+  import ietf-yang-types {
+    prefix "yang";
+  }
+
+  import iana-hardware {
+    prefix "ianahw";
+  }
+
+  organization "O-RAN Alliance";
+
+  contact
+    "www.o-ran.org";
+
+  description
+    "This module defines the YANG definitions for managng the O-RAN
+     interfaces.
+
+    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) new functionality to describe over subscribed resources";
+
+    reference "ORAN-WG4.M.0-v05.00";
+  }
+
+  revision "2020-04-17" {
+    description
+      "version 1.2.0
+
+      1) updated descriptions to clarify operation when vlan-tagging is false";
+
+    reference "ORAN-WG4.M.0-v03.00";
+  }
+  revision "2019-07-03" {
+    description
+      "version 1.1.0
+
+      1) increasing max elements for user plane DSCP markings to 64
+      2) re-organizing layout to facilitate cross-WG adoption, whilst ensuring
+      nodes are syntactically and semantically equivalent";
+
+    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 UDPIP-BASED-CU-PLANE {
+    description
+      "This feature indicates that the RU supports the UDP/IP based transport
+      for the CU plane.";
+  }
+
+  feature ALIASMAC-BASED-CU-PLANE {
+    description
+      "This feature indicates that the RU supports the alias MAC address
+       based transport for the CU plane.";
+  }
+
+  typedef pcp {
+    type uint8 {
+      range "0..7";
+    }
+    description
+      "Priority Code Point. PCP is a 3-bit field that refers to the
+      class of service applied to a VLAN tagged frame.  The
+      field specifies a priority value between 0 and 7, these values
+      can be used by quality of service (QoS) to prioritize
+      different classes of traffic.";
+    reference
+     "IEEE 802.1Q-2014: Virtual Bridged Local Area Networks";
+  }
+
+  grouping cos-marking {
+    description
+      "Configuration data for CU Plane ethernet CoS marking.
+      This grouping is only applicable to an interface when vlan-tagging is
+      set to TRUE for that interface. In other cases, it may be ignored.";
+    container class-of-service {
+      description
+        "CoS Configuration";
+      leaf u-plane-marking {
+        type pcp;
+        default 7;
+        description
+          "Marking used for default u-plane flows.
+          7 represents highest priority for u-plane marking";
+      }
+      leaf c-plane-marking {
+        type pcp;
+        default 7;
+        description "7 represents highest priority for c-plane marking";
+      }
+      leaf m-plane-marking {
+        type pcp;
+        default 2;
+        description "2 represents highest excellent effort for m-plane marking";
+      }
+      leaf s-plane-marking {
+        type pcp;
+        default 7;
+        description "7 represents highest priority for s-plane marking";
+      }
+      leaf other-marking {
+        type pcp;
+        default 1;
+        description "1 represents best effort for other marking";
+      }
+      list enhanced-uplane-markings{
+        key "up-marking-name";
+        max-elements 4;
+        description
+          "list of mappings for enhanced (non-default) u-plane markings";
+        leaf up-marking-name {
+          type string;
+          description "The name of the marking";
+        }
+        leaf enhanced-marking {
+          type pcp;
+          description "the enhanced u-plane marking";
+        }
+      }
+    }
+  }
+
+  grouping dscp-marking {
+    description
+      "Configuration data for CU Plane DSCP marking";
+    container diffserv-markings {
+      description
+        "DSCP Configuration";
+      leaf u-plane-marking {
+        type inet:dscp;
+        default 46;
+        description
+          "Marking used for default u-plane flows.
+          46 represents expedited forwarding";
+      }
+      leaf c-plane-marking {
+        type inet:dscp;
+        default 46;
+        description "46 represents expedited forwarding";
+      }
+      leaf s-plane-marking {
+        type inet:dscp;
+        default 46;
+        description "46 represents expedited forwarding";
+      }
+      leaf other-marking {
+        type inet:dscp;
+        default 0;
+        description "0 represents best effort forwarding";
+      }
+      list enhanced-uplane-markings{
+        key up-marking-name;
+        max-elements 64;
+        description
+          "list of mappings for enhanced (non-default) u-plane markings";
+        leaf up-marking-name {
+          type string;
+          description "The name of the marking";
+        }
+        leaf enhanced-marking {
+          type inet:dscp;
+          description "the enhanced u-plane marking";
+        }
+      }
+    }
+  }
+
+// Cross Working Group Augmentations Follow
+
+// Cross Working Group augmentations for basic Ethernet leafs
+
+  augment "/if:interfaces/if:interface" {
+    when "if:type = 'ianaift:ethernetCsmacd'" {
+      description "Applies to Ethernet interfaces";
+    }
+    description
+      "Augment the interface model with parameters for
+      base Ethernet interface";
+
+    leaf l2-mtu {
+      type uint16 {
+        range "64 .. 65535";
+      }
+      units bytes;
+      default 1500;
+      description
+        "The maximum size of layer 2 frames that may be transmitted
+        or received on the interface (excluding any FCS overhead).
+        For Ethernet interfaces it also excludes the
+        4-8 byte overhead of any known (i.e. explicitly matched by
+        a child sub-interface) 801.1Q VLAN tags.";
+    }
+    leaf vlan-tagging {
+      type boolean;
+      default true;
+      description
+        "Indicates if VLAN tagging is used.
+        Default true is used to enable equipment to autonomously discover that
+        it is connected to a trunk port.
+
+        This may be set to false, for example, when the O-RU is directly
+        connected to the O-DU. In such cases, native Ethernet frames may be
+        used across the O-RAN interface, i.e., any PCP markings defined
+        in the cos-markings grouping are NOT used by the O-RU and any default
+        value or configured value using those leafs may be ignored by the O-RAN
+        equipment.";
+    }
+    uses cos-marking;
+
+// interface-grouping insert - begin;
+
+    leaf-list interface-groups-id {
+      type leafref {
+        path "/if:interfaces/o-ran-int:interface-grouping/o-ran-int:interfaces-groups/o-ran-int:interface-group-id";
+      }
+      config false;
+      description
+        "an optional leaf used when the sustained rate able to be supported by an interface
+        is less than nominal bit rate indicated by o-ran-transceiver.yang
+
+        Identifies interface grouping particular physical hardware MAC address belongs to.";
+    }
+
+// interface-grouping insert - end;
+
+  }
+
+// Cross Working Group augmentation for l2vlan interfaces for VLAN definition
+
+  augment "/if:interfaces/if:interface" {
+    when "if:type = 'ianaift:l2vlan'";
+    description "augments for VLAN definition";
+    leaf base-interface {
+      type if:interface-ref;
+      must "/if:interfaces/if:interface[if:name = current()]"
+            + "/o-ran-int:vlan-tagging = 'true'" {
+        description
+          "The base interface must have VLAN tagging enabled.";
+      }
+      description
+        "The base interface for the VLAN sub-interafce.";
+    }
+    leaf vlan-id {
+      type uint16 {
+        range "1..4094";
+      }
+      description
+        "The VLAN-ID.";
+    }
+  }
+
+// Cross Working Group augmention for both ethernetCsmacd and l2vlan interfaces
+
+  augment "/if:interfaces/if:interface" {
+    when "(if:type = 'ianaift:ethernetCsmacd') or
+          (if:type = 'ianaift:l2vlan')" {
+      description "Applies to ethernetCsmacd and l2vlan interfaces";
+    }
+    description
+      "Augment the interface model with parameters for all
+      both ethernetCsmacd and l2vlan interfaces.";
+    leaf last-cleared {
+      type yang:date-and-time;
+      config false;
+      description
+        "Timestamp of the last time the interface counters were
+        cleared.";
+    }
+  }
+
+// Cross Working Group augmention to ietf-ip covering DSCP for M-Plane
+
+augment "/if:interfaces/if:interface/ip:ipv4" {
+  description "augments for IPv4 based M-Plane transport";
+  leaf m-plane-marking {
+    type inet:dscp;
+    default 18;
+    description "18 represents AF21 or 'immediate traffic'";
+  }
+}
+augment "/if:interfaces/if:interface/ip:ipv6" {
+  description "augments for IPv6 based M-Plane transport";
+  leaf m-plane-marking {
+    type inet:dscp;
+    default 18;
+    description "18 represents AF21 or 'immediate traffic'";
+  }
+}
+
+// WG4 Specific Augmentations Follow
+
+// WG4 Augmentation for basic Ethernet leafs
+
+  augment "/if:interfaces/if:interface" {
+    if-feature ALIASMAC-BASED-CU-PLANE;
+    when "if:type = 'ianaift:ethernetCsmacd'" {
+      description
+        "Applies to WG4 Ethernet interfaces for alias MAC based CU-Plane";
+    }
+    description
+      "Augment the interface model with parameters for
+      base Ethernet interface";
+
+    leaf-list alias-macs {
+      type yang:mac-address;
+
+      description
+        "Augments interfaces with range of alias MAC addresses.";
+    }
+
+  }
+
+// WG4 Augmention for both ethernetCsmacd and l2vlan interfaces
+
+  augment "/if:interfaces/if:interface" {
+    when "(if:type = 'ianaift:ethernetCsmacd') or
+          (if:type = 'ianaift:l2vlan')" {
+      description "Applies to ethernetCsmacd and l2vlan interfaces";
+    }
+    description
+      "Augment the interface model with parameters for all
+      both ethernetCsmacd and l2vlan interfaces.";
+    leaf mac-address {
+      type yang:mac-address;
+
+      description
+        "The MAC address of the interface.";
+    }
+
+    container port-reference {
+      description
+        "a port reference used by other O-RAN modules";
+      leaf port-name {
+        type leafref {
+          path '/hw:hardware/hw:component/hw:name';
+        }
+        must "derived-from-or-self(deref(current())/../hw:class, 'ianahw:port')";
+// TAKE NOTE - depending on version of pyang, this may generate various
+// warnings, e.g., warning: XPath for "port-name" does not exist
+        description
+          "O-RAN interfaces use a reference to a physical port component.
+
+          In this case, the component name referenced must be of class type
+          port, i.e., when /hw:hardware/hw:component/hw:class is derived from
+          ianahw:port";
+      }
+      leaf port-number {
+        type uint8;
+        description
+          "A number allocated by the server which identifies a port.
+          Port number value is 0 to N-1 where N is number of ports
+          in the device.
+
+          This value is fixed for the lifetime of the equipment, i.e., cannot be
+          changed during equipment reboots.";
+      }
+    }
+  }
+
+// WG4 specific augmention to ietf-ip covering DSCP for CUS Plane
+
+  augment "/if:interfaces/if:interface/ip:ipv4" {
+    if-feature UDPIP-BASED-CU-PLANE;
+    description "augments for IPv4 based CUS transport";
+    uses dscp-marking;
+  }
+  augment "/if:interfaces/if:interface/ip:ipv6" {
+    if-feature UDPIP-BASED-CU-PLANE;
+    description "augments for IPv6 based CUS transport";
+    uses dscp-marking;
+  }
+
+// Other Working Group Specific Augmentations Follow Here
+
+// interface-grouping insert - begin;
+
+  augment "/if:interfaces" {
+    description "augments interfaces for groupings of physical hardware addresses that can be used to group Ethernet ports";
+
+    container interface-grouping {
+
+      presence
+        "indicates maximum sustained throughput of an O-RU is less than the combined bandwidth of all physical ports";
+
+      config false;
+
+      description
+        "A container used by an O-RU where the maximum sustained throughput
+        of an O-RU is less than the combined bandwidth of all physical ports";
+
+      list interfaces-groups {
+        key interface-group-id;
+        description "List of interface groups.";
+
+        leaf interface-group-id {
+          type uint8;
+          description "interface group identifier.";
+        }
+
+        leaf max-sustainable-ingress-bandwidth {
+          type uint32;
+          units Mbps;
+          description
+            "Maximum sustainable ingress bandwidth the interface group can handle. The sustainable bandwidth is calculated
+            over one radio frame.
+
+            The peak ingress bandwidth may exceed the sustainable bandwidth for periods shorter than a radio frame period.";
+        }
+
+        leaf max-sustainable-egress-bandwidth {
+          type uint32;
+          units Mbps;
+          description
+            "Maximum sustainable egress bandwidth the interface group can handle. The sustainable bandwidth is calculated
+            over one radio frame.";
+        }
+      }
+    }
+  }
+// interface-grouping insert - end;
+
+
+  rpc reset-interface-counters {
+    description
+      "Management plane triggered restart of the interface counters.";
+  }
+}
diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-laa-operations@2019-07-03.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-laa-operations@2019-07-03.yang
new file mode 100644 (file)
index 0000000..0410c7f
--- /dev/null
@@ -0,0 +1,253 @@
+module o-ran-laa-operations {
+  yang-version 1.1;
+  namespace "urn:o-ran:laa-operations:1.0";
+  prefix "o-ran-laa-operations";
+
+  import o-ran-module-cap {
+    prefix "mcap";
+  }
+
+  organization "O-RAN Alliance";
+
+  contact
+    "www.o-ran.org";
+
+  description
+    "This module defines the operations for DFS measurement.
+
+    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) corrected error in module reference for LAA feature";
+
+    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 band-num {
+    type enumeration {
+      enum BAND_46_SUBBAND_A {
+        description
+          "46a: 5150 MHz       -       5250 MHz";
+      }
+      enum BAND_46_SUBBAND_B {
+        description
+          "46b: 5250 MHz       -       5350 MHz";
+      }
+      enum BAND_46_SUBBAND_C {
+        description
+          "46c: 5470 MHz       -       5725 MHz";
+      }
+      enum BAND_46_SUBBAND_D1 {
+        description
+          "46d1: 5725 MHz      -       5850 MHz";
+      }
+      enum BAND_46_SUBBAND_D2 {
+        description
+          "46d2: 5850 MHz      -       5925 MHz";
+      }
+    }
+    description
+      "This value indicates the list of bands supported as per the document,
+      3GPP TS 36.104 V14.2.0 (2016-12), 'Section 5.5 Operation bands'.";
+  }
+
+  grouping band-configuration {
+    description
+      "Grouping for band configuration";
+
+    leaf band-number {
+      type band-num;
+      description
+        "This value indicates the list of bands supported as per the document,
+        3GPP TS 36.104 V14.2.0 (2016-12), 'Section 5.5 Operation bands'.";
+    }
+    leaf-list channel-center-frequency {
+      type uint16;
+      units kilohertz;
+      description
+        "This value indicates carrier center frequency in KHz";
+    }
+  }
+
+  grouping measurement-parameters {
+    description
+      "Grouping for measurement parameters";
+
+    leaf duration-per-channel {
+      type uint16;
+      units milliseconds;
+      description
+        "This value indicates measurement duration per channel in milliseconds.";
+    }
+
+    leaf maximum-response-time {
+      type uint16;
+      units seconds;
+      description
+        "This value indicates maximum response time (i.e., timer) in seconds.";
+    }
+  }
+
+  grouping channel-result-element {
+    description
+      "Grouping for channel result element";
+
+    leaf measured-channel {
+      type uint16;
+      units kilohertz;
+      description
+        "This value indicates carrier center frequency for which the result is computed in KHz.";
+    }
+
+    leaf occupancy-ratio {
+      type uint8;
+      units percent;
+      description
+        "This value indicates occupancy ratio in percentage.";
+    }
+
+    leaf average-rssi {
+      type int8;
+      units dBm;
+      description
+        "This value indicates average RSSI in dBm";
+    }
+  }
+
+  grouping band-result-element {
+    description
+      "Grouping for band result element";
+
+    leaf band-number {
+      type band-num;
+      description
+        "This value indicates the band for which the result is computed.";
+    }
+
+    leaf measurement-success {
+      type boolean;
+      description
+        "This value indicates whether the measurement is successful for the given band.";
+    }
+    leaf failure-message {
+      when "../measurement-success='false'";
+      type enumeration {
+        enum TIMEOUT {
+          description "Timed out waiting for measurement completion.";
+        }
+      }
+      description "This value indicates the detailed error message for failure of the measurement at O-RU.";
+    }
+
+    list channel-result {
+      when "../measurement-success='true'";
+      key "measured-channel";
+      description "Results for a particular channel";
+
+      uses channel-result-element;
+    }
+  }
+
+  //rpc definitions
+  rpc start-measurements {
+    if-feature mcap:LAA;
+    description "Measurements for Carrier-Selection and Dynamic Frequency Selection (DFS)";
+    input {
+      list band-config {
+        key "band-number";
+        description "Per band configuration for measurements.";
+
+        uses band-configuration;
+      }
+
+      uses measurement-parameters;
+    }
+
+    output {
+      list band-config {
+        key "band-number";
+        description "Output list for all the bands requested for measurements.";
+
+        leaf band-number {
+          type band-num;
+          description
+            "This value indicates the list of bands supported as per the document,
+            3GPP TS 36.104 V14.2.0 (2016-12), 'Section 5.5 Operation bands'.";
+        }
+        leaf-list carrier-center-frequency {
+          type uint16;
+          units kilohertz;
+          description
+            "This value indicates carrier center frequency in KHz";
+        }
+        leaf status {
+          type enumeration {
+            enum ACCEPTED {
+              description "This indicates the measurements for particular sub band is accepted at O-RU.";
+            }
+            enum REJECTED {
+              description "This indicates the measurements for particular sub band is rejected at O-RU.";
+            }
+          }
+          description "This value indicates the status of the measurement acceptance at O-RU.";
+        }
+
+        leaf error-message {
+          when "../status='REJECTED'";
+          type string;
+          description
+            "This value indicates the detailed error message for the measurement being rejected at O-RU.";
+        }
+      }
+    }
+  }
+
+  // notifications
+  notification measurement-result {
+    if-feature mcap:LAA;
+    description "Notification to provide the results of carrier selection and DFS.";
+    list band-result {
+      key "band-number";
+      description "Results for a particular sub band under band 46.";
+
+      uses band-result-element;
+    }
+  }
+}
diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-laa@2019-07-03.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-laa@2019-07-03.yang
new file mode 100644 (file)
index 0000000..31e625a
--- /dev/null
@@ -0,0 +1,126 @@
+module o-ran-laa {
+  yang-version 1.1;
+  namespace "urn:o-ran:laa:1.0";
+  prefix "o-ran-laa";
+
+  import o-ran-module-cap {
+    prefix "mcap";
+    revision-date 2020-12-10;
+  }
+
+  organization "O-RAN Alliance";
+
+  contact
+    "www.o-ran.org";
+
+  description
+    "This module defines the configuration for Carrier-selection and dynamic frequency selection (DFS).
+    Also this module defines operations for DFS measurement.
+
+    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) 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.";
+
+    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 laa-configuration {
+    description
+      "Grouping for LAA configuration";
+
+    leaf number-of-laa-scarriers {
+      type uint8;
+      description "Number of LAA secondary carriers to be supported at O-RU.";
+    }
+
+    leaf multi-carrier-type {
+      type enumeration {
+        enum A1;
+        enum A2;
+        enum B1;
+        enum B2;
+      }
+      description
+        "This value indicates the list of multi carrier types which as per the document,
+        3GPP TS 36.213 V13.6.0 (2017-06) 15.1.5 Channel access procedure for transmission(s) on multiple carriers.";
+    }
+
+    leaf multi-carrier-tx {
+      type boolean;
+      description
+        "This value indicates whether self-deferral is activated or not.";
+    }
+
+    leaf multi-carrier-freeze {
+      when "../multi-carrier-type='A1'";
+      type boolean;
+      description "This value indicates if the absence of other technology in the unlicensed band can be guaranteed.";
+    }
+
+    leaf laa-ending-dwpts-supported {
+      type boolean;
+      description
+        "This value indicates whether LAA ending in DwPTS is supported.";
+    }
+
+    leaf laa-starting-in-second-slot-supported {
+      type boolean;
+      description
+        "This value indicates whether LAA starting in second slot is supported";
+    }
+  }
+
+  container laa-config {
+    must "number-of-laa-scarriers <= /mcap:module-capability/mcap:rw-sub-band-info/mcap:rw-number-of-laa-scarriers" {
+      error-message "number of laa secondary carriers must be less than supported number of laa scells.";
+    }
+    presence "indicates LAA configuration";
+    description "Container to specify all LAA specific configuration";
+
+    uses laa-configuration;
+  }
+}
diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-lbm@2019-02-04.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-lbm@2019-02-04.yang
new file mode 100644 (file)
index 0000000..359257c
--- /dev/null
@@ -0,0 +1,308 @@
+module o-ran-lbm {
+  yang-version 1.1;
+  namespace "urn:o-ran:lbm:1.0";
+  prefix "o-ran-lbm";
+
+  import ietf-yang-types {
+    prefix yang;
+    revision-date 2013-07-15;
+  }
+
+  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 the module capabilities for
+    the O-RAN Radio loop-back protocol (IEEE 802.1ag).
+    It is derived from MEF-38 (Service OAM Fault Management YANG Modules, April 2012)
+
+    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";
+  }
+
+  typedef priority-type {
+    type uint32 {
+      range "0..7";
+    }
+    description
+      "A 3 bit priority value to be used in the VLAN tag, if present
+       in the transmitted frame.";
+    reference "[802.1q] 12.14.7.3.2:e";
+  }
+
+  typedef mep-id-type {
+    type uint16 {
+      range "1..8191";
+    }
+    description
+      "Maintenance association End Point Identifier (MEPID): A small integer,
+       unique over a given Maintenance Association, identifying a
+       specific MEP.";
+    reference "[802.1q] 3.19 and 19.2.1";
+  }
+
+  typedef vlan-id-type {
+    type uint16 {
+      range "1..4094";
+    }
+    description
+      "The VLAN-ID that uniquely identifies a VLAN.  This is the 12-bit VLAN-ID
+       used in the VLAN Tag header.";
+    reference "[802.1q] 9.6";
+  }
+
+  typedef md-level-type {
+    type int32 {
+      range "0..7";
+    }
+    description
+      "Maintenance Domain Level (MD Level) identifier.  Higher numbers
+       correspond to higher Maintenance Domains, those with the greatest
+       physical reach, with the highest values for customers' CFM PDUs.
+       Lower numbers correspond to lower Maintenance Domains, those with
+       more limited physical reach, with the lowest values for CFM PDUs
+       protecting single bridges or physical links.";
+    reference "[802.1q] 18.3, 21.4.1, IEEE8021-CFM-MIB.Dot1agCfmMDLevel";
+  }
+
+  typedef lbm-transaction-id-type {
+    type uint32;
+    description
+      "A loopback transaction identifier";
+    reference "[802.1q] 21.7.3";
+  }
+
+// grouping
+
+  grouping md-group {
+    list maintenance-domain {
+      key "id";
+      description
+        "A Maintenance Domain managed object is required in order to create an MA
+         with a MAID that includes that Maintenance Domain's Name. From
+         this Maintenance Domain managed object, all Maintenance
+         Association managed objects associated with that Maintenance
+         Domain managed object can be accessed, and thus controlled.";
+      reference "[802.1q] 12.14.5";
+
+      leaf id {
+        type string;
+        description
+          "A unique identifier of a Maintenance Domain";
+        reference "[802.1q] 12.14.5";
+      }
+
+      leaf name {
+        type string;
+        description
+          "The value for the Maintenance Domain Name. Only the name-type
+          'character-string' is supported";
+        reference "[802.1q] 21.6.5.1 (Table 21-19), 12.14.5.3.2:a";
+      }
+
+      leaf md-level {
+        type md-level-type;
+        default 0;
+        description
+          "Integer identifying the Maintenance Domain Level (MD Level).  Higher
+           numbers correspond to higher Maintenance Domains, those with the
+           greatest physical reach, with the highest values for customers'
+           CFM PDUs.  Lower numbers correspond to lower Maintenance
+           Domains, those with more limited physical reach, with the lowest
+           values for CFM PDUs protecting single bridges or physical links.";
+        reference "[802.1q] 12.14.5.1.3:b";
+      }
+
+      list maintenance-association {
+        key "id";
+        description
+          "This list represents Maintenance Entity Groups (Y.1731) or
+           Maintenance Associations (802.1ag). MEGs/MAs are sets of
+           MEPs, each configured to the same service inside a common
+           OAM domain.";
+        leaf id {
+          type string;
+          description
+            "A unique identifier of a Maintenance Association";
+          reference "[802.1q] 12.14.6";
+        }
+        leaf name {
+          type string;
+
+          description
+            "The value for the Maintenance Association Name. Only the name-type
+            'character-string' is supported";
+          reference "[802.1q] 12.14.5.3.2:b, Table 21-20";
+        }
+
+        list component-list {
+          key "component-id";
+          description
+            "A list of components each of which can be managed in a manner
+             essentially equivalent to an 802.1Q bridge.";
+          reference "[802.1q] IEEE8021-CFM-V2-MIB.ieee8021CfmMaCompTable";
+
+          leaf component-id {
+            type uint32;
+            description
+              "The bridge component within the system to which the information
+               in this maintenance-association applies";
+            reference "[802.1q] IEEE8021-CFM-V2-MIB.ieee8021CfmMaComponentId";
+          }
+
+          leaf name {
+            type string;
+
+            description
+              "The value for the Maintenance Association Name. Only the name-type
+              'character-string' is supported";
+            reference "[802.1q] 12.14.5.3.2:b, Table 21-20";
+          }
+
+          leaf-list vid {
+            type leafref {
+              path "/if:interfaces/if:interface/o-ran-int:vlan-id";
+            }
+            min-elements 1;
+            ordered-by user;
+            description
+              "The VID(s) monitored by this MA, or 0, if the MA is not attached to any
+               VID. The first VID returned is the MA's Primary VID";
+            reference "[802.1q] 12.14.5.3.2:b";
+          }
+
+          leaf-list remote-meps {
+            type mep-id-type;
+            description
+              "A list of the MEPIDs of the MEPs in the MA.";
+            reference "[802.1q] 12.14.6.1.3:g";
+          }
+
+          list maintenance-association-end-point {
+            key "mep-identifier";
+            description
+              "The list of Maintenance association End Points in a specific Maintance
+              Association.";
+
+            leaf mep-identifier {
+              type mep-id-type;
+              description
+                "Integer that is unique among all the MEPs in the same MA. Other
+                definition is: a small integer, unique over a given
+                Maintenance Association, identifying a specific Maintenance
+                association End Point.";
+              reference "[802.1q] 12.14.6.3.2:b";
+            }
+
+            leaf interface {
+              type leafref {
+                path "/if:interfaces/if:interface/if:name";
+              }
+              mandatory true;
+              description
+              "An interface, either a Bridge Port or an aggregated IEEE 802.3 port
+               within a Bridge Port, to which the MEP is attached. Each interface in
+               the system is uniquely identified by an interface-name. The structure
+               and content of the name is outside the scope of this specification.";
+              reference "[802.1q] 12.14.7.1.3:b";
+            }
+
+            leaf primary-vid {
+              type leafref {
+                path "/if:interfaces/if:interface/o-ran-int:vlan-id";
+              }
+              mandatory true;
+              description
+              "The Primary VID of the MEP. The value 0 indicates that either the
+               Primary VID is that of the MEP's MA or that the MEP's MA is
+               associated with no VID";
+              reference "[802.1q] 12.14.7.1.3:d";
+            }
+
+            leaf administrative-state {
+              type boolean;
+              mandatory true;
+              description
+                "The administrative state of the MEP";
+              reference "[802.1q] 12.14.7.1.3:e";
+            }
+
+            leaf mac-address {
+              type leafref {
+                path "/if:interfaces/if:interface/o-ran-int:mac-address";
+              }
+              config false;
+              description
+                "The MAC address of the MEP";
+              reference "[802.1q] 12.14.7.1.3:i";
+            }
+
+            container loopback {
+              config false;
+              description
+                "Data definitions related to the Loopback function.";
+              leaf replies-transmitted {
+                type yang:counter32;
+                config false;
+                mandatory true;
+                description
+                  "The total number of LBRs transmitted.";
+                reference "[802.1q] 12.14.7.1.3:ad";
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+// top level container
+  container md-data-definitions {
+    description
+      "Data definitions related to the maineance domains used for supporting
+      Ethernet loopback connectivity checks";
+    uses md-group;
+  }
+}
diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-module-cap@2020-12-10.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-module-cap@2020-12-10.yang
new file mode 100644 (file)
index 0000000..fac5bc0
--- /dev/null
@@ -0,0 +1,857 @@
+module o-ran-module-cap {
+  yang-version 1.1;
+  namespace "urn:o-ran:module-cap:1.0";
+  prefix "o-ran-module-cap";
+
+  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.
+
+    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 support for optimising coupling-via-frequency-and-time-with-priorities
+      by adding enhancement to existing method through a new leaf node";
+
+    reference "ORAN-WG4.M.0-v05.00";
+  }
+
+  revision "2020-08-10" {
+    description
+      "version 4.0.0
+
+      1) added RO capability to expose O-RU's ability to support udCompLen record in U-Plane section header fields
+      2) feature indicating support for static PRACH configuration introduced
+      3) feature indicating support for static SRS configuration introduced
+      4) feature indicating support for TDD pattern configuration introduced
+      5) backward compatible change to introduce new O-RU's features related
+      to Section Description Priority to serve for CUS-Plane C";
+
+    reference "ORAN-WG4.M.0-v04.00";
+  }
+
+  revision "2020-04-17" {
+    description
+      "version 3.0.0
+
+      1) Adding optional little endian support
+      2) Added support for Dynamic Spectrum Sharing feature
+      3) Enable number-of-ru-ports to be different between dl and ul
+      4) Enable regularizationFactor to be signalled outside of section type 6
+      5) Enable PRACH preamble formats supported to be signalled by O-RU
+      6) adding support for selective RE sending
+      7) supporting new section extension for grouping multiple ports
+      8) signalling to enable O-RU to ndicate is requires unique ecpri sequence id
+        for eAxC_IDs serving for UL and DL for the same carrier component";
+
+    reference "ORAN-WG4.M.0-v03.00";
+  }
+
+  revision "2019-07-03" {
+    description
+      "version 1.1.0
+
+      1) backward compatible change to introduce new RW leafs for use in
+      constraints in uplane-config and laa models.
+      2) removing unnecessary relations to band 46 in uplink";
+
+    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 LAA {
+    description
+      "Indicates that the Radio Unit supports LAA.";
+  }
+
+  feature EAXC-ID-GROUP-SUPPORTED {
+    description
+      "indicates that the Radio Unit supports EAXC-ID-GROUP-SUPPORTED.";
+  }
+
+  feature TRANSPORT-FRAGMENTATION {
+    description
+      "This leaf is used to indicate whether the O-RU supports O-RAN Radio Transport Fragmentation";
+  }
+
+  feature DSS_LTE_NR {
+    description
+      "Indicates that the Radio Unit supports Dynamic Spectrum Sharing between LTE and NR.";
+  }
+
+  feature PRACH-STATIC-CONFIGURATION-SUPPORTED {
+    description
+      "This leaf is used to indicate O-RU's support for configuration of PRACH (Physical Random Access Channel) pattern in the static manner, so that PRACH U-Plane traffic can be processed by RU without receiving C-Plane messages conveying the PRACH configuration.";
+  }
+
+  feature SRS-STATIC-CONFIGURATION-SUPPORTED {
+    description
+      "This leaf is used to indicate O-RU's support for configuration of SRS (Sounding Reference Signal Channel) pattern in the static manner, so that SRS U-Plane traffic can be processed by RU without receiving C-Plane messages conveying the SRS configuration.";
+  }
+
+  feature CONFIGURABLE-TDD-PATTERN-SUPPORTED {
+    description
+      "This leaf is used to indicate O-RU's support for configurable TDD pattern.";
+  }
+
+  typedef sub-band-string {
+    type string {
+      pattern [ABCD];
+    }
+    description "Sub bands definition";
+  }
+
+  typedef scs-config-type {
+    type enumeration {
+      enum KHZ_15 {
+        value 0;
+        description
+          "15kHz sub carrier spacing";
+      }
+      enum KHZ_30 {
+        value 1;
+        description
+          "30kHz sub carrier spacing";
+      }
+      enum KHZ_60 {
+        value 2;
+        description
+          "60kHz sub carrier spacing";
+      }
+      enum KHZ_120 {
+        value 3;
+        description
+          "120kHz sub carrier spacing";
+      }
+      enum KHZ_240 {
+        value 4;
+        description
+          "240kHz sub carrier spacing";
+      }
+      enum KHZ_1_25 {
+        value 12;
+        description
+          "1,25kHz sub carrier spacing";
+      }
+      enum KHZ_3_75 {
+        value 13;
+        description
+          "3.75kHz sub carrier spacing";
+      }
+      enum KHZ_5 {
+        value 14;
+        description
+          "5kHz sub carrier spacing";
+      }
+      enum KHZ_7_5 {
+        value 15;
+        description
+          "7.5kHz sub carrier spacing";
+      }
+    }
+
+    description
+      "Scs configuration type definition";
+  }
+
+  grouping compression-method-grouping {
+    description
+      "Grouping for compression method.";
+
+    leaf compression-method {
+      type enumeration {
+        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.
+        An O-RU may further refine the applicability of compression
+        methods per endpoint using o-ran-uplane-conf.yang model";
+    }
+  }
+
+  grouping sub-band-max-min-ul-dl-frequency {
+    description
+    "Grouping for defining max and min supported frequency - dl and ul.";
+
+    leaf max-supported-frequency-dl {
+      type uint64;
+      description
+        "This value indicates Maximum supported downlink frequency in the
+        LAA subband. Value unit is Hz.";
+    }
+
+    leaf min-supported-frequency-dl {
+      type uint64;
+      description
+        "This value indicates Minimum supported downlink frequency in the
+        LAA subband. Value unit is Hz.";
+    }
+  }
+
+  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 cf:compression-details;
+
+      leaf-list fs-offset {
+        if-feature cf:CONFIGURABLE-FS-OFFSET;
+        type uint8;
+        default 0;
+        description
+          "List of fs offset values supported with this IQ format / compression method;
+           fs-offset 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";
+    }
+
+    leaf variable-bit-width-per-channel-supported {
+      when "/module-capability/ru-capabilities/format-of-iq-sample/realtime-variable-bit-width-supported = 'true'";
+      type boolean;
+
+      description
+        "Informs if variable bit width per channel is supported or not";
+    }
+
+    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 scs-a-b {
+    description
+      "Grouping for scs-a and scs-b";
+    leaf scs-a{
+      type scs-config-type;
+      description
+        "Sub-carrier spacing configuration";
+    }
+    leaf scs-b{
+      type scs-config-type;
+      description
+        "Sub-carrier spacing configuration";
+    }
+  }
+
+  grouping ul-mixed-num-required-guard-rbs {
+    description
+      "Required number of guard resource blocks for the combination of
+      subcarrier spacing values for uplink";
+    uses scs-a-b;
+    leaf number-of-guard-rbs-ul{
+      type uint8;
+      description
+        "This value indicates the required number of guard resource blocks
+         between the mixed numerologies, the RB using scs-a and the RB
+         using scs-b. It's number is based on scs-a";
+    }
+  }
+
+  grouping dl-mixed-num-required-guard-rbs {
+    description
+      "Required number of guard resource blocks for the combination of
+      subcarrier spacing values for uplink";
+    uses scs-a-b;
+    leaf number-of-guard-rbs-dl{
+      type uint8;
+      description
+        "This value indicates the required number of guard resource blocks
+         between the mixed numerologies, the RB using scs-a and the RB
+         using scs-b. It's number is based on scs-a";
+    }
+  }
+
+  grouping ru-capabilities {
+    description
+      "Structure representing set of capabilities.";
+
+    leaf ru-supported-category {
+      type enumeration {
+        enum CAT_A {
+          description
+            "Informs that precoding is not supported in O-RU";
+        }
+        enum CAT_B {
+          description
+            "Informs that precoding is supported in O-RU";
+        }
+      }
+
+      description
+        "Informs about which category O-RU supports";
+    }
+
+    leaf number-of-ru-ports {
+      type uint8;
+      status deprecated;
+      description
+        "Assuming all endpoints support time-managed traffic AND non-time-managed traffic (choice is as per configuration)
+         - the number of O-RU ports is the product of number of spatial streams (leaf number-of-spatial-streams) and number of numerologies O-RU supports.
+         For example, if the number of spatial streams is 4 then the number of O-RU ports is 8 when PUSCH and PRACH are processed in the different endpoints.
+         In case there are specific endpoints that support non-time-managed traffic only
+         - the number of O-RU ports calculated with above mentioned equation is extended by number of endpoints supporting only non-time-managed traffic.";
+    }
+    leaf number-of-ru-ports-ul {
+      type uint8;
+      description
+        "Assuming all endpoints support time-managed traffic AND non-time-managed traffic (choice is as per configuration)
+         - the number of O-RU ports for uplink is the product of number of spatial streams (leaf number-of-spatial-streams) and number of numerologies O-RU supports.
+         For example, if the number of spatial streams is 4 then the number of O-RU ports is 8 when PUSCH and PRACH are processed in the different endpoints.
+         In case there are specific endpoints that support non-time-managed traffic only
+         - the number of O-RU ports calculated with above mentioned equation is extended by number of endpoints supporting only non-time-managed traffic.";
+    }
+    leaf number-of-ru-ports-dl {
+      type uint8;
+      description
+        "Assuming all endpoints support time-managed traffic AND non-time-managed traffic (choice is as per configuration)
+         - the number of O-RU ports for downlink is the product of number of spatial streams (leaf number-of-spatial-streams) and number of numerologies O-RU supports.
+         For example, if the number of spatial streams is 4 then the number of O-RU ports is 8 when SSB and non-SSB are processed in the different endpoints.
+         In case there are specific endpoints that support non-time-managed traffic only
+         - the number of O-RU ports calculated with above mentioned equation is extended by number of endpoints supporting only non-time-managed traffic.";
+    }
+
+    leaf number-of-spatial-streams {
+      type uint8;
+      description
+        "This value indicates the number of spatial streams supported at O-RU for DL and UL.
+         For DL, it is same as the number of antenna ports specified in 3GPP TS38.214, Section 5.2 and 3GPP TS36.213, Section 5.2.";
+    }
+
+    leaf max-power-per-pa-antenna {
+      type decimal64{
+        fraction-digits 4;
+      }
+      description
+        "This value indicates Maximum Power per PA per antenna. Value unit is dBm.";
+    }
+
+    leaf min-power-per-pa-antenna {
+      type decimal64{
+        fraction-digits 4;
+      }
+      description
+        "This value indicates Minimum Power per PA per antenna. Value unit is dBm.";
+    }
+
+    leaf fronthaul-split-option {
+      type uint8 {
+        range "7";
+      }
+      description
+        "This value indicates the Fronthaul Split Option, i.e., 2 or 7 in this release.";
+    }
+
+    container format-of-iq-sample {
+      description
+        "Indicates module capabilities about IQ samples";
+
+      uses format-of-iq-sample;
+    }
+
+    list ul-mixed-num-required-guard-rbs {
+      key "scs-a scs-b";
+      description
+        "List of required number of guard resource blocks
+        for the combination of subcarrier spacing values for downlink";
+
+      uses ul-mixed-num-required-guard-rbs;
+    }
+    list dl-mixed-num-required-guard-rbs {
+      key "scs-a scs-b";
+      description
+        "List of required number of guard resource blocks
+        for the combination of subcarrier spacing values for uplink";
+
+      uses dl-mixed-num-required-guard-rbs;
+    }
+
+    leaf energy-saving-by-transmission-blanks {
+      type boolean;
+      mandatory true;
+      description
+        "Parameter informs if unit supports energy saving by transmission blanking";
+    }
+    container eaxcid-grouping-capabilities {
+      if-feature o-ran-module-cap:EAXC-ID-GROUP-SUPPORTED;
+      description
+        "a container with parameters for eaxcid grouping";
+      leaf max-num-tx-eaxc-id-groups {
+        type uint8;
+        description
+          "Maximum number of configurable tx-eaxc-id-group supported by O-RU.";
+      }
+      leaf max-num-tx-eaxc-ids-per-group {
+        type uint8;
+        description
+          "Maximum number of member-tx-eaxc-id in single tx-eaxc-id-group supported by O-RU.";
+      }
+      leaf max-num-rx-eaxc-id-groups {
+        type uint8;
+        description
+          "the maximum number of groups with the eAxC IDs those are assigned to low-level-rx-links.";
+      }
+      leaf max-num-rx-eaxc-ids-per-group {
+        type uint8;
+        description
+          "the maximum number of eAxC IDs per rx-eaxc-id-group.";
+      }
+    }
+
+    leaf dynamic-transport-delay-management-supported {
+      type boolean;
+      mandatory true;
+      description
+        "Parameter informs if unit supports dynamic transport delay management through eCPRI Msg 5";
+    }
+
+    leaf support-only-unique-ecpri-seqid-per-eaxc {
+      type boolean;
+      default false;
+      description
+        "Parameter informs if O-RU expects unique ecpri sequence id for eAxC_IDs serving
+        for UL and DL for the same carrier component.
+
+        Note: If this is set to TRUE, the O-DU can decide to either use different eAxC_IDs for UL and
+        DL or can generate unique sequence ID per eAxC_ID.
+
+        TAKE NOTE: This leaf is backwards compatible from an O-RU persepctive BUT an O-RU that
+        sets this leaf to TRUE may result in incompatibilities when operating with an O-DU
+        designed according to the O-RAN CUS-Plane Specification v02.00, e.g., if the O-DU is
+        incapable of using different eAxC values between UL and DL";
+    }
+
+    container coupling-methods {
+      description
+        "O-RU's capabilities related to supported C-Plane and U-Plane coupling methods";
+
+      leaf coupling-via-frequency-and-time {
+        type boolean;
+        description
+          "Coupling via frequency and time; see methods of coupling of C-plane and U-plane in CUS-Plane specification";
+      }
+
+      leaf coupling-via-frequency-and-time-with-priorities {
+        type boolean;
+        description
+          "Coupling via Frequency and time with priorities; see methods of coupling of C-plane and U-plane in CUS-Plane specification.
+          Note: If coupling-via-frequency-and-time-with-priorities is 'true' then coupling-via-frequency-and-time shall also be 'true'.";
+      }
+
+      leaf coupling-via-frequency-and-time-with-priorities-optimized {
+        type boolean;
+        description
+          "Coupling via Frequency and time with priorities optimized; see methods of coupling of C-plane and U-plane in CUS-Plane specification.
+          Note: If coupling-via-frequency-and-time-with-priorities-optmized is 'true' then coupling-via-frequency-and-time shall also be 'true'.";
+      }
+    }
+
+    leaf ud-comp-len-supported {
+      type boolean;
+      description
+        "This property informs if O-RU supports optional field udCompLen in U-Plane messages.
+         Only in case this leaf is present and its value is TRUE, O-RU supports U-Plane messages
+         containing udCompLen field in section header.";
+    }
+  }
+
+  grouping sub-band-info {
+    description "container for collection of leafs for LAA subband 46";
+    list sub-band-frequency-ranges {
+      key sub-band;
+      description "frequency information on a per sub-band basis";
+      leaf sub-band {
+        type sub-band-string;
+        description "Sub band when band 46";
+      }
+      uses sub-band-max-min-ul-dl-frequency;
+    }
+    leaf number-of-laa-scarriers {
+      type uint8;
+      description
+        "This value indicates the number of LAA secondary carriers supported at O-RU.";
+    }
+
+    leaf maximum-laa-buffer-size {
+      type uint16;
+      description
+        "Maximum O-RU buffer size in Kilobytes (KB) per CC. This parameter is
+         needed at the O-DU to know how much data can be sent in advance
+         and stored at the O-RU to address the LBT uncertainity.";
+    }
+
+    leaf maximum-processing-time {
+      type uint16;
+      units microseconds;
+      description
+        "Maximum O-RU Processing time in microseconds at the O-RU to handle the
+         received/transmitted packets from/to the O-DU. This parameter is
+         needed at the O-DU to determine the time where it needs to send
+         the data to the O-RU.";
+    }
+
+    leaf self-configure {
+      type boolean;
+      description "This value indicates that the O-RU can manage the contention window locally. ";
+    }
+  }
+
+  grouping support-for-dl {
+    description
+      "Grouping for DL specific parameters";
+
+    leaf max-supported-frequency-dl {
+      type uint64;
+      description
+        "This value indicates Maximum supported downlink frequency. Value unit is Hz.";
+    }
+
+    leaf min-supported-frequency-dl {
+      type uint64;
+      description
+        "This value indicates Minimum supported downlink frequency. Value unit is Hz.";
+    }
+
+    leaf max-supported-bandwidth-dl {
+      type uint64;
+      description
+        "This value indicates Maximum total downlink bandwidth in module. Value unit is Hz.";
+    }
+
+    leaf max-num-carriers-dl {
+      type uint32;
+      description
+        "This value indicates Maximum number of downlink carriers in module.";
+    }
+
+    leaf max-carrier-bandwidth-dl {
+      type uint64;
+      description
+        "This value indicates Maximum bandwidth per downlink carrier. Value unit is Hz.";
+    }
+
+    leaf min-carrier-bandwidth-dl {
+      type uint64;
+      description
+        "This value indicates Minimum bandwidth per downlink carrier. Value unit is Hz.";
+    }
+
+    leaf-list supported-technology-dl {
+      type enumeration{
+        enum LTE {
+          description "LTE is supported in DL path.";
+        }
+        enum NR {
+          description "NR is supported in DL path.";
+        }
+        enum DSS_LTE_NR {
+          if-feature DSS_LTE_NR;
+          description
+            "DSS is supported in the DL, which implicitly means LTE and NR are also
+            BOTH supported in the DL.";
+        }
+      }
+      min-elements 1;
+      description
+        "This list provides information regarding technologies supported in DL path";
+    }
+  }
+
+  grouping support-for-ul {
+    description
+      "Grouping for UL specific parameters";
+
+    leaf max-supported-frequency-ul {
+      type uint64;
+      description
+        "This value indicates Maximum supported uplink frequency. Value unit is Hz.";
+    }
+
+    leaf min-supported-frequency-ul {
+      type uint64;
+      description
+        "This value indicates Minimum supported uplink frequency. Value unit is Hz.";
+    }
+
+    leaf max-supported-bandwidth-ul {
+      type uint64;
+      description
+        "This value indicates Maximum total uplink bandwidth in module. Value unit is Hz.";
+    }
+
+    leaf max-num-carriers-ul {
+      type uint32;
+      description
+        "This value indicates Maximum number of uplink carriers in module.";
+    }
+
+    leaf max-carrier-bandwidth-ul {
+      type uint64;
+      description
+        "This value indicates Maximum bandwidth per uplink carrier. Value unit is Hz.";
+    }
+
+    leaf min-carrier-bandwidth-ul {
+      type uint64;
+      description
+        "This value indicates Minimum bandwidth per uplink carrier. Value unit is Hz.";
+    }
+
+    leaf-list supported-technology-ul {
+      type enumeration{
+        enum LTE {
+          description "LTE is supported in UL path.";
+        }
+        enum NR {
+          description "NR is supported in UL path.";
+        }
+        enum DSS_LTE_NR {
+          if-feature DSS_LTE_NR;
+          description
+            "DSS is supported in the UL, which implicitly means LTE and NR are also
+            BOTH supported in the UL.";
+        }
+      }
+      min-elements 1;
+      description
+        "This list provides information regarding technologies supported in UL path";
+    }
+  }
+
+  grouping band-capabilities {
+    description
+      "Capabilities that are needed to be defined per each band";
+
+    leaf band-number {
+      type uint16;
+      description
+        "Band number";
+    }
+
+    container sub-band-info {
+      when "../band-number = '46'";
+      if-feature "o-ran-module-cap:LAA";
+      description "container for collection of leafs for LAA subband 46";
+      uses sub-band-info;
+    }
+
+    uses support-for-dl;
+    uses support-for-ul;
+
+    leaf max-num-component-carriers {
+      type uint8;
+      description "maximum number of component carriers supported by the O-RU";
+    }
+
+    leaf max-num-bands {
+      type uint16;
+      description "maximum number of bands supported by the O-RU";
+    }
+
+    leaf max-num-sectors {
+      type uint8;
+      description "maximum number of sectors supported by the O-RU";
+    }
+
+    leaf max-power-per-antenna {
+      type decimal64{
+        fraction-digits 4;
+      }
+      description
+        "This value indicates Maximum Power per band per antenna. Value unit is dBm.";
+    }
+
+    leaf min-power-per-antenna {
+      type decimal64{
+        fraction-digits 4;
+      }
+      description
+        "This value indicates Minimum Power per band per antenna. Value unit is dBm.";
+    }
+
+    leaf codebook-configuration_ng {
+        type uint8;
+        description
+          "This parameter informs the precoder codebook_ng that are used for precoding";
+      }
+
+    leaf codebook-configuration_n1 {
+        type uint8;
+        description
+          "This parameter informs the precoder codebook_n1 that are used for precoding";
+      }
+
+    leaf codebook-configuration_n2 {
+        type uint8;
+        description
+          "This parameter informs the precoder codebook_n2 that are used for precoding";
+    }
+  }
+
+  container module-capability {
+
+    description
+      "module capability object responsible for providing module capability.";
+
+    container ru-capabilities {
+      config false;
+      description
+        "Structure representing set of capabilities.";
+
+      uses ru-capabilities;
+    }
+
+    list band-capabilities {
+      key band-number;
+      config false;
+      description
+        "Capabilities that are needed to be defined per each band";
+
+      uses band-capabilities;
+    }
+    container rw-sub-band-info {
+      if-feature "o-ran-module-cap:LAA";
+      description "config true leafrefs for use as constraints for config true leafs";
+      leaf rw-number-of-laa-scarriers {
+        type leafref {
+          path "/module-capability/band-capabilities/sub-band-info/number-of-laa-scarriers";
+          require-instance false;
+        }
+        description
+          "This value indicates the number of LAA secondary carriers supported at O-RU.";
+      }
+      leaf rw-self-configure {
+        type leafref {
+          path "/module-capability/band-capabilities/sub-band-info/self-configure";
+          require-instance false;
+        }
+        description
+          "This value indicates that the O-RU can manage the contention window locally.";
+      }
+    }
+  }
+}
diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-mplane-int@2019-07-03.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-mplane-int@2019-07-03.yang
new file mode 100644 (file)
index 0000000..84452cd
--- /dev/null
@@ -0,0 +1,232 @@
+module o-ran-mplane-int {
+  yang-version 1.1;
+  namespace "urn:o-ran:mplane-interfaces:1.0";
+  prefix "o-ran-mplane-int";
+
+  import ietf-inet-types {
+    prefix "inet";
+  }
+
+  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 the YANG definitions for managng the O-RAN Radio Unit
+     management plane interface.
+
+     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) enabling NETCONF clients to be configured.
+         2) shifting new container to correct position
+         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 vlan-id {
+    type uint16 {
+      range 1..4094;
+    }
+    description
+      "Type definition representing a single-tagged VLAN";
+  }
+
+  // Groupings
+
+  grouping mplane-group {
+    container searchable-mplane-access-vlans-info {
+      description
+        "These parameters shall be stored by the equipment in reset persistant memory
+        to enable it to be re-used to optimize VALN discovery procerdures.";
+      leaf-list searchable-access-vlans {
+        type vlan-id;
+        description
+          "A list of access VLANs that may be operational on the transport
+          network. Can be used by the equipment to optimize its VLAN searching - for
+          M-plane operations.";
+      }
+      container vlan-range {
+        description "the range of VLAN IDs that may be configured for M-Plane";
+        leaf lowest-vlan-id {
+          type vlan-id;
+          description
+            "Value of this parameter informs equipment about lowest VID to be used
+            in VLAN scan procedure";
+        }
+        leaf highest-vlan-id {
+          type vlan-id;
+          description
+            "Value of this parameter informs about highest VID to be used
+            in VLAN scan procedure";
+        }
+      }
+    }
+
+    container m-plane-interfaces {
+      description "information concerning m-plane interfaces";
+      list m-plane-sub-interfaces {
+        key "interface-name sub-interface";
+        description "list of m-plane information";
+        leaf interface-name {
+          type leafref {
+            path "/if:interfaces/if:interface/if:name";
+          }
+          description "the name of the interface";
+        }
+        leaf sub-interface {
+          type leafref {
+            path "/if:interfaces/if:interface[if:name = current()/../interface-name]/o-ran-int:vlan-id";
+          }
+          description
+            "vlans used to communicate with management plane servers.";
+        }
+        container client-info {
+          config false;
+          description
+            "the NETCONF client information, discovered by DHCP or manually
+             configured during installation.";
+          list mplane-ipv4-info {
+            key mplane-ipv4;
+            description "list of IPv4 NETCONF clients";
+            leaf mplane-ipv4 {
+              type inet:ipv4-address;
+              description "The IPv4 address of M-Plane client discovered by the O-RU
+              or manually configured.";
+            }
+            leaf port {
+              type inet:port-number;
+              description
+                "The call home port number discovered or manually configured.";
+            }
+          }
+          list mplane-ipv6-info {
+            key mplane-ipv6;
+            description "list of IPv6 NETCONF clients";
+            leaf mplane-ipv6 {
+              type inet:ipv6-address;
+              description "The IPv6 address of M-Plane client discovered by the O-RU
+              or manually configured.";
+            }
+            leaf port {
+              type inet:port-number;
+              description
+                "The call home port number discovered or manually configured.";
+            }
+          }
+          leaf-list mplane-fqdn {
+            type inet:domain-name;
+            description "The discovered FQDN(s) of M-Plane client(s).";
+          }
+        }
+      }
+
+      container m-plane-ssh-ports {
+        description "leafs for managing SSH ports";
+        leaf call-home-ssh-port {
+          type inet:port-number;
+          default 4334;
+          description "The configured call home server port number";
+        }
+        leaf server-ssh-port {
+          type inet:port-number;
+          default 830;
+          description "The configured SSH server port number";
+        }
+      }
+    }
+    container configured-client-info {
+      description
+        "the NETCONF client information that may be configured by another
+        NETCONF client. These clients are reported independently from clients
+        manually configured or discovered using DHCP.";
+      list mplane-ipv4-info {
+        key mplane-ipv4;
+        description "list of IPv4 NETCONF clients";
+        leaf mplane-ipv4 {
+          type inet:ipv4-address;
+          description "The IPv4 address of configured M-Plane client.";
+        }
+        leaf port {
+          type inet:port-number;
+          description
+            "The configured call home port number.";
+        }
+      }
+      list mplane-ipv6-info {
+        key mplane-ipv6;
+        description "list of IPv6 NETCONF clients";
+        leaf mplane-ipv6 {
+          type inet:ipv6-address;
+          description "The IPv6 address of configured M-Plane client..";
+        }
+        leaf port {
+          type inet:port-number;
+          description
+            "The configured call home port number.";
+        }
+      }
+      leaf-list mplane-fqdn {
+        type inet:domain-name;
+        description "The configured FQDN(s) of M-Plane client(s).";
+      }
+    }
+  }
+
+
+  // Top Level Container
+
+  container mplane-info {
+    description "top level container for management plane information";
+
+    uses mplane-group;
+  }
+}
diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-operations@2020-12-10.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-operations@2020-12-10.yang
new file mode 100644 (file)
index 0000000..4339fde
--- /dev/null
@@ -0,0 +1,306 @@
+module o-ran-operations {
+  yang-version 1.1;
+  namespace "urn:o-ran:operations:1.0";
+  prefix "o-ran-ops";
+
+  import ietf-yang-types {
+    prefix yang;
+  }
+
+  import ietf-netconf-acm {
+    prefix nacm;
+    reference
+      "RFC 8341: Network Configuration Access Control Model";
+  }
+
+  import ietf-hardware {
+    prefix hw;
+  }
+
+  import o-ran-wg4-features {
+    prefix or-feat;
+  }
+
+  organization "O-RAN Alliance";
+
+  contact
+    "www.o-ran.org";
+
+  description
+    "This module defines the YANG model used for O-RAN operations.
+
+    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 pnfRegistration and VES header version fields";
+
+    reference "ORAN-WG4.M.0-v05.00";
+  }
+
+  revision "2019-07-03" {
+    description
+      "version 2.0.0
+
+      1) added timezone-name
+      2) added ru-instance-id
+      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 timezone-name {
+    type string;
+    description
+      "A time zone name as used by the Time Zone Database,
+      sometimes referred to as the 'Olson Database'.
+
+      The complete set of valid values is defined in
+      https://www.iana.org/time-zones.
+
+      The exact set of supported values is an
+      implementation-specific matter.";
+
+    reference
+      "RFC 6557: Procedures for Maintaining the Time Zone Database
+      IANA Time Zone Database https://www.iana.org/time-zones ";
+  }
+
+  typedef version {
+    type string {
+      pattern '[0-9]+(\.[0-9]+){1,2}';
+    }
+    description
+      "this type definition is used to represent the version of the WG4
+      fronthaul interface.";
+  }
+
+  grouping operational-group {
+
+// Container used for WG4 specific declarations
+    container declarations {
+      //FIXME - determine whether it is acceptable to WG4 to change this to a presence
+      //container, where the presence indicates the NETCONF server supports WG4
+      //defined functionality
+      config false;
+      description "WG4 Specific Declarations of supported version of standards";
+
+      leaf ru-instance-id {
+        type string;
+        must "re-match(current(), concat(/hw:hardware/hw:component/hw:mfg-name,
+          '_', /hw:hardware/hw:component/hw:model-name, '_',
+          /hw:hardware/hw:component/hw:serial-num ))";
+        description
+          "a unique instance identifier that may be used to identify a
+          particular hardware instance, e.g., when used performing hierarchical
+          management via the O-DU.";
+      }
+
+      leaf supported-mplane-version {
+        type version;
+        default "1.0.0";
+        description "Parameter provides highest M-Plane specification version device is compliant with.";
+      }
+
+      leaf supported-cusplane-version {
+        type version;
+        default "1.0.0";
+        description "Parameter provides highest CUS-Plane specification version device is compliant with.";
+      }
+
+      list supported-header-mechanism {
+        description "list provides information regarding type and version of headers.";
+        key protocol;
+
+        leaf protocol {
+          type enumeration {
+            enum ECPRI {
+              description
+                "Indicates that an O-RU supports the ecpri header format
+                for the C/U plane";
+            }
+            enum IEEE-1914-3 {
+              description
+                "Indicates that an O-RU supports the 1914.3 header format
+                for the C/U plane";
+            }
+          }
+          description "Transport protocol type.";
+        }
+
+        leaf ecpri-concatenation-support {
+          when "../protocol = 'ECPRI'";
+          type boolean;
+          default false;
+          description
+            "This leaf is used to indicate whether the O-RU supports the optional
+            eCPRI concatenation capability";
+        }
+
+        leaf protocol-version {
+          type version;
+          default "1.0";
+          description "Header protocol version.";
+        }
+      }
+      leaf supported-common-event-header-version {
+        if-feature "or-feat:NON-PERSISTENT-MPLANE";
+        type version;
+        description "Parameter provides highest commonEventheader version device is compliant with.";
+      }
+      leaf supported-ves-event-listener-version {
+        if-feature "or-feat:NON-PERSISTENT-MPLANE";
+        type version;
+        description "Parameter provides highest vesEventListener version device is compliant with.";
+      }
+      leaf supported-pnf-registration-fields-version {
+        if-feature "or-feat:NON-PERSISTENT-MPLANE";
+        type version;
+        description "Parameter provides highest pnfRegistrationFields version device is compliant with.";
+      }
+    }
+
+    container operational-state {
+      config false;
+      description
+        "Operational state for the O-RAN network element";
+      leaf restart-cause {
+        type enumeration {
+          enum POWER-ON {
+            description
+              "Equipment restarted because it was powered on";
+          }
+          enum SUPERVISION-WATCHDOG {
+            description
+              "Equipment restarted because it's supervision wathcdog timer wasn't reset
+              by a NETCONF client (inferring loss of NETCONF connectivity)";
+          }
+          enum MPLANE-TRIGGERED-RESTART {
+            description
+              "Equipment restarted because of an M-plane issued  rpc";
+          }
+          enum SOFTWARE-FAILURE {
+            description
+              "Equipment restarted because of software failure";
+          }
+          enum OTHER-WATCHDOG-TIMER {
+            description
+              "Equipment restarted because of some other non NETCONF watchdog timer";
+          }
+          enum UNKNOWN {
+            description
+              "The restart reason for the Equipment is unknown";
+          }
+        }
+        description "the cause for the last restart of the O-RAN Network Element";
+      }
+      leaf restart-datetime {
+        type yang:date-and-time;
+        description
+          "The system date and time when the system last restarted.";
+      }
+    }
+
+
+// Common cross-WG container used for configuring clock and call home timers
+    container clock {
+      description
+        "System date and time properties used by all working groups.";
+
+      leaf timezone-name {
+        type timezone-name;
+        description
+          "An optional TZ database name to use for the system,
+           such as 'Europe/Stockholm'
+
+           Time zone name is an informative leaf and is NOT used in the
+           managed element to convert local time zone.
+
+           The managed element may include time zone name in measurement or
+           fault data.";
+      }
+
+      leaf timezone-utc-offset {
+        type int16 {
+          range "-720 .. 840";
+        }
+        units "minutes";
+        default 0;
+        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'.";
+      }
+    }
+
+    leaf re-call-home-no-ssh-timer {
+      type uint16;
+      units seconds;
+      default 60;
+      description
+        "A common timer used by the O-RAN equipment to trigger the repeated call
+        home procedure to all identified call home servers to which the O-RAN
+        equipment has not already an established SSH connection.
+
+        A value of 0 means that the O-RAN equipment shall disable operation
+        of the timer triggered NETCONF call home procedure.";
+    }
+  }
+
+// Top level container
+
+  container operational-info{
+    description
+      "a collection of operational infor for the O-RU";
+    uses operational-group;
+
+  }
+
+// RPCs
+
+  rpc reset {
+    nacm:default-deny-all;
+    description
+      "Management plane triggered restart of the radio unit.
+       A server SHOULD send an rpc reply to the client before
+       restarting the system.";
+
+  }
+}
diff --git a/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-performance-management@2020-12-10.yang b/ntsimulator/deploy/o-ran-ru-fh/yang/o-ran-performance-management@2020-12-10.yang
new file mode 100644 (file)
index 0000000..a1441ab
--- /dev/null
@@ -0,0 +1,1200 @@
+module o-ran-performance-management {
+  yang-version 1.1;
+  namespace "urn:o-ran:performance-management:1.0";
+  prefix "o-ran-pm";
+
+  import ietf-yang-types {
+    prefix "yang-types";
+    revision-date 2013-07-15;
+  }
+
+  // import idetifier for O-RU
+  import ietf-hardware {
+    prefix "hw";
+  }
+
+  // import ietf-interface
+  import ietf-interfaces {
+    prefix "if";
+  }
+
+  // import ietf-inet-type
+  import ietf-inet-types {
+    prefix "inet";
+  }
+
+  // import port-number
+  import o-ran-interfaces {
+    prefix "o-ran-int";
+  }
+
+  // import ru-mac-address, o-du-mac-address and vlan-id
+  import o-ran-processing-element {
+    prefix "o-ran-elements";
+  }
+
+  import o-ran-file-management {
+    prefix "o-ran-fm";
+  }
+
+  import iana-hardware {
+    prefix ianahw;
+  }
+
+  organization "O-RAN Alliance";
+
+  contact
+    "www.o-ran.org";
+
+  description
+    "This module defines the configuration for performance measurement for
+    transceiver and rx-window measurement objects.
+
+    NOTE, whereas this YANG model may define support of schema nodes associated
+    with O-RU measurements as optional, the CU-Plane specification may further
+    specify whether, according to a particular version of the CU plane
+    specification, which specific measurements are mandatory to support
+    from an O-RU perspective. In such a situation, the definition of mandatory
+    performance counters in sub-section 7.1 of the CU-plane specification shall
+    take precedence.
+
+    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) container epe-stats is changed deprecated
+       2) New list epe-statistics and measurement-object is added as key
+       3) bug fix by pyang --lint";
+
+    reference "ORAN-WG4.M.0-v05.00";
+  }
+
+  revision "2020-04-17" {
+    description
+      "version 3.0.0
+
+      1) updated top level model description concerning optionality of measurements
+      2) added new rx window counters
+      3) added new TX stats measurements
+      4) added new EPE measurements
+      5) fixed typo in enumeration - TX_POPWER
+      6) introduced config false data indicating which type of measurmeents are supported";
+
+    reference "ORAN-WG4.M.0-v03.00";
+  }
+
+  revision "2019-07-03" {
+    description
+      "version 2.0.0
+
+      1) added new measurement objects for QSFP
+      2) backward compatible changes to correct sFTP Server Authentication.
+      3) simplifying file management and authentication to reuse from o-ran-file-management module
+      4) minor fixes according to lack of descriptions and reference
+      5) added to descriptions to indicate applicability of leafs and Containers
+      to separate O-RAN use cases
+      6) 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";
+  }
+
+
+  feature GRANULARITY-TRANSPORT-MEASUREMENT {
+    description
+      "This feature indicates that the O-RU supports an optional object-unit TRANSPORT in rx-window-measurement.";
+  }
+
+  feature GRANULARITY-EAXC-ID-MEASUREMENT {
+    description
+      "This feature indicates that the O-RU supports an optional object-unit EAXC_ID in rx-window-measurement.";
+  }
+
+  grouping start-and-end-time {
+    description
+      "Definition for start and end time for an event";
+
+    leaf start-time {
+      type yang-types:date-and-time;
+      description
+        "Start time for measurement of object stats";
+    }
+    leaf end-time {
+      type yang-types:date-and-time;
+      description
+        "End time for measurement of object stats";
+    }
+  }
+
+  grouping epe-measurement-result-grouping {
+    description
+      "energy, power and environmental measurement-result are listed for O-RU";
+
+    list epe-measurement-result {
+      key "object-unit-id";
+      config false;
+      leaf object-unit-id {
+        type leafref {
+          path "/hw:hardware/hw:component/hw:class";
+        }
+
+        description
+          "the hardware component type is used for the object-unit-id for the
+           EPE measurements. For example, the object-unit-id will be set to
+           or-hw:O-RAN-RADIO if the measurement applies to the complete O-RU
+           self-contained sub-system.
+
+           Other hardware-classes include: or-hw:O-RU-POWER-AMPLIFIER,
+           ianahw:power-supply, ianahw:fan, ianahw:cpu";
+      }
+      leaf min {
+        type decimal64 {
+          fraction-digits 4;
+        }
+
+        description
+          "minimum value for the measurment-object";
+      }
+      leaf max {
+        type decimal64 {
+          fraction-digits 4;
+        }
+        description
+          "maximum value for the measurment-object";
+      }
+      leaf average {
+        type decimal64 {
+          fraction-digits 4;
+        }
+        description
+          "average value of the measurement-object";
+      }
+    }
+  }
+
+  grouping transceiver-measurement-result-grouping {
+    description
+      "transceiver-measurement-result are listed per port-number";
+
+    list transceiver-measurement-result {
+      key "object-unit-id";
+      config false;
+      leaf object-unit-id {
+        type leafref {
+          path "/if:interfaces/if:interface/o-ran-int:port-reference/o-ran-int:port-number";
+        }
+
+        description
+          "port-number is used for the object-unit-id for the
+           transceiver-measurement-result, for which object-unit is
+           PORT_NUMBER only";
+      }
+      container min {
+        description
+          "minimum value with recorded time are included for the
+           measurement-object";
+
+        leaf value {
+          type decimal64 {
+            fraction-digits 4;
+          }
+
+          description
+            "minimum value for the measurment-object";
+        }
+        leaf time {
+          type yang-types:date-and-time;
+
+          description
+            "recorded time for the minimum value";
+        }
+      }
+      container max {
+        description
+        "maximum value with recorded time are included for the
+         measurement-object";
+
+        leaf value {
+          type decimal64 {
+            fraction-digits 4;
+          }
+
+          description
+            "maximum value for the measurment-object";
+        }
+        leaf time {
+          type yang-types:date-and-time;
+
+          description
+            "recorded time for the maximum value";
+        }
+      }
+      container first {
+        description
+          "first value with the recorded time are included for the
+           measurement-object";
+
+        leaf value {
+          type decimal64 {
+            fraction-digits 4;
+          }
+
+          description
+            "first value of the measurement-object";
+        }
+        leaf time {
+          type yang-types:date-and-time;
+
+          description
+            "recorded time for the first value";
+        }
+      }
+      container latest {
+        description
+          "latest value with the recorded time are included for the
+           measurement-object";
+
+        leaf value {
+          type decimal64 {
+            fraction-digits 4;
+          }
+
+          description
+            "latest value of the measurement-object";
+        }
+        leaf time {
+          type yang-types:date-and-time;
+
+          description
+            "recorded time for the latest value";
+        }
+      }
+      leaf-list frequeny-table {
+        type uint32;
+
+        description
+          "frequency-table for the measurment-object are included per bin.
+           The configuration parameters for this frequency-table are defined
+           by bin-count, lower-bound and upper-bound";
+      }
+
+      description
+        "List of transceiver measurement results";
+    }
+  }
+
+  grouping rx-window-measurement-result-grouping{
+    description
+      "Group of measurement reasults for rx window measurements";
+
+    choice object-unit-id {
+      config false;
+      case RU {
+        leaf name{
+          type leafref {
+            path "/hw:hardware/hw:component/hw:name";
+          }
+
+          description
+            "the name of O-RU module or one of its child ports
+            in ietf-hardware/component is used when O-RU is selected as
+            object-unit for the reception window stats.";
+        }
+        leaf count {
+          type uint64;
+          mandatory true;
+
+          description
+            "the number of data packet are counted for the reception
+             window stats per O-RU.";
+        }
+      }
+
+      case TRANSPORT {
+        list tr-measured-result{
+          leaf name{
+            type leafref{
+              path "/o-ran-elements:processing-elements/o-ran-elements:ru-elements/o-ran-elements:name";
+            }
+
+            description
+              "the name of ru-elements in o-ran-processing-elements
+               when TRANSPORT is selected as object-unit for the reception
+               window stats.";
+          }
+          leaf count {
+            type uint64;
+            mandatory true;
+
+            description
+              "the number of data packet are counted for the reception
+               window stats.";
+          }
+
+          description
+            "the number of data packet are counted for the reception
+             window stats per TRANSPORT.";
+        }
+      }
+
+      case EAXC_ID {
+        list eaxc-measured-result {
+          leaf eaxc-id{
+            type uint16;
+
+            description
+              "eaxc-id is used
+               when EAXC_ID is selected as object-unit for the reception
+               window stats.
+               EAXC_ID consists of DU-Port-Id, Band-Selector, CC-id and
+               RU-Port-Id to be used in header of C/U-plane data packet.";
+          }
+          leaf count {
+            type uint64;
+            mandatory true;
+
+            description
+              "the number of data packet are counted for the reception
+               window stats.";
+          }
+          leaf transport-name {
+            type leafref{
+              path "/o-ran-elements:processing-elements/o-ran-elements:ru-elements/o-ran-elements:name";
+            }
+
+            description
+              "the name of ru-elements in o-ran-processing-elements for the
+               transport information corresponding to this eaxc-id";
+          }
+
+          description
+            "the number of data packet are counted for the reception
+             window stats per EAXC-ID.";
+        }
+      }
+
+      description
+        "measurement-result for the reception window stats depends on the
+         configured object-unit, RU, TRANSPORT or EAXC_ID";
+    }
+  }
+
+  grouping tx-measurement-result-grouping{
+    description
+      "Group of measurement reasults for tx stats";
+
+    choice object-unit-id {
+      config false;
+      case RU {
+        leaf name{
+          type leafref {
+            path "/hw:hardware/hw:component/hw:name";
+          }
+
+          description
+            "the name of O-RU module or one of its child ports
+            in ietf-hardware/component is used when O-RU is selected as
+            object-unit for the reception window stats.";
+        }
+        leaf count {
+          type uint64;
+          mandatory true;
+
+          description
+            "the number of data packet are counted for the tx stats per O-RU.";
+        }
+      }
+
+      case TRANSPORT {
+        list tr-measured-result{
+          leaf name{
+            type leafref{
+              path "/o-ran-elements:processing-elements/o-ran-elements:ru-elements/o-ran-elements:name";
+            }
+
+            description
+              "the name of ru-elements in o-ran-processing-elements
+               when TRANSPORT is selected as object-unit for the tx stats.";
+          }
+          leaf count {
+            type uint64;
+            mandatory true;
+
+            description
+              "the number of data packet are counted for the tx stats.";
+          }
+
+          description
+            "the number of data packet are counted for the tx stats per TRANSPORT.";
+        }
+      }
+
+      case EAXC_ID {
+        list eaxc-measured-result {
+          leaf eaxc-id{
+            type uint16;
+
+            description
+              "eaxc-id is used
+               when EAXC_ID is selected as object-unit for the tx stats.
+               EAXC_ID consists of DU-Port-Id, Band-Selector, CC-id and
+               RU-Port-Id to be used in header of C/U-plane data packet.";
+          }
+          leaf count {
+            type uint64;
+            mandatory true;
+
+            description
+              "the number of data packet are counted for the tx stats.";
+          }
+          leaf transport-name {
+            type leafref{
+              path "/o-ran-elements:processing-elements/o-ran-elements:ru-elements/o-ran-elements:name";
+            }
+
+            description
+              "the name of ru-elements in o-ran-processing-elements for the
+               transport information corresponding to this eaxc-id";
+          }
+
+          description
+            "the number of data packet are counted for the tx stats per EAXC-ID.";
+        }
+      }
+
+      description
+        "measurement-result for the tx stats depends on the
+         configured object-unit, RU, TRANSPORT or EAXC_ID";
+    }
+  }
+
+
+  grouping measurement-group {
+    description
+      "Group of measurement results";
+
+    uses measurement-capabilities;
+    leaf enable-SFTP-upload {
+      type boolean;
+      default false;
+      description
+        "Flag to enable upload of performance measurement result files.";
+    }
+
+    leaf enable-random-file-upload {
+      type boolean;
+      default false;
+      description
+        "Flag to enable upload of performance measurement result files at
+         random within file-upload-interval.";
+    }
+
+    list remote-SFTP-uploads {
+      key remote-SFTP-upload-path;
+      description
+        "SFTP upload can be done to one or more than one SFTP servers";
+
+      leaf remote-SFTP-upload-path {
+        type inet:uri;
+        description
+          "URI specifying the remote location where the files are to uploaded.
+          The following format is possible:
+          sftp://<username>@<host>[:<port>]/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 (file)
index 0000000..06dacbb
--- /dev/null
@@ -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 (file)
index 0000000..3c4d2a4
--- /dev/null
@@ -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 (file)
index 0000000..e9f3448
--- /dev/null
@@ -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://<username>@<host>[:<port>]/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 (file)
index 0000000..4956f9b
--- /dev/null
@@ -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 (file)
index 0000000..c8d8a74
--- /dev/null
@@ -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 <get> 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 (file)
index 0000000..5bfead9
--- /dev/null
@@ -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 (file)
index 0000000..93d83d8
--- /dev/null
@@ -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 (file)
index 0000000..ae09f8c
--- /dev/null
@@ -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 (file)
index 0000000..b65c453
--- /dev/null
@@ -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 (file)
index 0000000..57177f5
--- /dev/null
@@ -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 (file)
index 0000000..ed6f39a
--- /dev/null
@@ -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 (file)
index 0000000..3a08e15
--- /dev/null
@@ -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 (file)
index 0000000..5b183a3
--- /dev/null
@@ -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 (file)
index 0000000..3e19429
--- /dev/null
@@ -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: <https://www.onap.org>
+     Editors:
+        Alex Stancu <mailto:alexandru.stancu@highstreet-technologies.com>
+        Adrian Lita <mailto:adrian.lita@highstreet-technologies.com>
+        Martin Skorupski <mailto:martin.skorupski@highstreet-technologies.com>";
+  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 (file)
index 0000000..1888fb3
--- /dev/null
@@ -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"]
index 59166db..eb45979 100644 (file)
@@ -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",
             "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" : "<alarm-notif xmlns=\"urn:o-ran:fm:1.0\"><fault-id>$$uint16_counter$$</fault-id><fault-source>%%object%%</fault-source><affected-objects><name>%%affected-object%%</name></affected-objects><fault-severity>%%fault-severity%%</fault-severity><is-cleared>%%cleared%%</is-cleared><fault-text>%%text%%</fault-text><event-time>%%date-time%%</event-time></alarm-notif>",
         "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"
             }
         ]
     }
index e0c7ce8..ee93a5d 100644 (file)
@@ -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 (file)
index 0000000..7b501f4
--- /dev/null
@@ -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
similarity index 71%
rename from ntsimulator/deploy/nts-manager/ubuntu.Dockerfile
rename to ntsimulator/deploy/o-ran/local.Dockerfile
index 4978e0d..765bace 100644 (file)
 #### 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 (file)
index cd7eb88..0000000
+++ /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 (file)
index 0000000..f8883d3
--- /dev/null
@@ -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"]
index 72bac1d..aec6853 100644 (file)
@@ -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",
             "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
index e0c7ce8..ee93a5d 100644 (file)
@@ -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 (file)
index 0000000..7b501f4
--- /dev/null
@@ -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 (file)
index 0000000..6cf773e
--- /dev/null
@@ -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 (file)
index cd7eb88..0000000
+++ /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
index 6cf95b5..45f9ebf 100644 (file)
-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
index 051da85..23ea07d 100644 (file)
@@ -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 (executable)
index 0000000..3b4541b
--- /dev/null
@@ -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 (executable)
index 0000000..58694d0
--- /dev/null
@@ -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 (executable)
index 0000000..62619e1
--- /dev/null
@@ -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 (file)
index 0000000..35bcef5
--- /dev/null
@@ -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 <stdio.h>
+#include <assert.h>
+
+#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 (file)
index 0000000..3dec9c5
--- /dev/null
@@ -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);
+
index 4881661..cc522dc 100644 (file)
 #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;
index ad1f0a9..50ee1f3 100644 (file)
 
 #include <stdbool.h>
 #include <stdint.h>
-#include <libyang/libyang.h>
+#include <semaphore.h>
+#include <sysrepo.h>
+#include <sysrepo/values.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"
 
 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 (file)
index 0000000..a681e0b
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pthread.h>
+
+#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 (file)
index 0000000..d61cb96
--- /dev/null
@@ -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 <stdio.h>
+#include <assert.h>
+
+#include <sysrepo.h>
+#include <sysrepo/values.h>
+
+#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;
+}
index e382b02..c847a6c 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <assert.h>
+#include <pthread.h>
 
 #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 (file)
index 0000000..46717df
--- /dev/null
@@ -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 <stdio.h>
+#include <assert.h>
+
+#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;
+}
index 5a66d18..85d0409 100644 (file)
@@ -20,6 +20,7 @@
 #include "network_function.h"
 #include "utils/log_utils.h"
 #include "utils/sys_utils.h"
+#include "utils/nts_utils.h"
 #include <stdio.h>
 #include <pthread.h>
 #include <assert.h>
 #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, &current_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, &current_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 (file)
index 0000000..8612a08
--- /dev/null
@@ -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 <stdio.h>
+#include <assert.h>
+
+#include "core/framework.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+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 (file)
index 0000000..a714dee
--- /dev/null
@@ -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 (file)
index 0000000..a3e7b11
--- /dev/null
@@ -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 <sysrepo.h>
+#include <dirent.h>
+#include <assert.h>
+
+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 (file)
index 0000000..56b0029
--- /dev/null
@@ -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 <stdbool.h>
+#include <stdint.h>
+
+//init current container. used *only* with --container-init
+bool container_self_init(void);
index 8019662..be30e9c 100644 (file)
@@ -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 (file)
index 0000000..1fa255c
--- /dev/null
@@ -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 <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <assert.h>
+
+#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 (file)
index 0000000..f0b4208
--- /dev/null
@@ -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 <stdbool.h>
+#include <string.h>
+#include <libyang/libyang.h>
+
+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);
index 19f6ee9..8435397 100644 (file)
 #include <stdio.h>
 #include <assert.h>
 
+#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;
 }
index 3df3693..78468e2 100644 (file)
 #include <string.h>
 #include <stdint.h>
 #include <stdbool.h>
-#include <libyang/libyang.h>
 
-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 (file)
index d185083..0000000
+++ /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 <stdio.h>
-#include <inttypes.h>
-#include <assert.h>
-
-#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;
-    }
-}
index 93ae199..d30cdb6 100644 (file)
@@ -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;
+}
index 490c3ba..a8637a1 100644 (file)
@@ -20,7 +20,7 @@
 #include <string.h>
 #include <stdint.h>
 
-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);
index 7e8588d..25a9a83 100644 (file)
 #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 <sysrepo.h>
-#include <dirent.h>
 #include <assert.h>
 #include <sys/sysinfo.h>
 
 
 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;
index 0185594..a44cab6 100644 (file)
 #pragma once
 
 #include <stdbool.h>
-#include "core/app/manager.h"
+#include <stdint.h>
+
+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);
index 12ba223..c60e365 100644 (file)
@@ -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;
     }
index 9817a18..500360a 100644 (file)
@@ -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;
     }
 
index 879fb5a..9479b43 100644 (file)
@@ -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;
 }
index 032f99c..2711f37 100644 (file)
@@ -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;
             }
 
index e95deed..9340f87 100644 (file)
@@ -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;
     }
 
index c241468..c916d96 100644 (file)
 #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 = "<alexandru.stancu@highstreet-technologies.com> / <adrian.lita@highstreet-technologies.com>";
 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);
index be44555..2f169f0 100644 (file)
 #include <unistd.h>
 #include <signal.h>
 
-#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
index 43402eb..4357790 100644 (file)
@@ -21,6 +21,9 @@
 #include "utils/log_utils.h"
 #include "utils/sys_utils.h"
 #include "utils/http_client.h"
+
+#include <string.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <assert.h>
 
 #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, &current_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;
     }
     
index 1dc1f28..b62273d 100644 (file)
@@ -17,7 +17,9 @@
 
 #pragma once
 
-#include <string.h>
-#include <stdint.h>
+#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);
index 716bc56..3f64622 100644 (file)
@@ -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");
 }
index 8902984..52ed5ff 100644 (file)
 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;
index e76fa61..e768c73 100644 (file)
 #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;
 
index 6b2fd83..cbea12b 100644 (file)
@@ -19,4 +19,7 @@
 
 #include <sysrepo.h>
 
+int manual_notification_feature_get_status(void);
 int manual_notification_feature_start(sr_session_ctx_t *current_session);
+int manual_notification_feature_stop(void);
+
index b3bacb0..8952cb7 100644 (file)
 #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);
index 48a9661..2220dc8 100644 (file)
@@ -19,4 +19,5 @@
 
 #include <sysrepo.h>
 
+int netconf_call_home_feature_get_status(void);
 int netconf_call_home_feature_start(sr_session_ctx_t *current_session);
index 7cd56d5..af79d0e 100644 (file)
@@ -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;
     }
index 67f951a..8047127 100644 (file)
@@ -19,4 +19,6 @@
 
 #include <sysrepo.h>
 
+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);
index 4bfc075..74f7f62 100644 (file)
@@ -28,6 +28,7 @@
 #include <assert.h>
 #include <unistd.h>
 #include <pthread.h>
+#include <signal.h>
 
 #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;
         }
 
index 0cea6c7..b182821 100644 (file)
@@ -19,4 +19,6 @@
 
 #include <sysrepo.h>
 
+int ves_heartbeat_feature_get_status(void);
 int ves_heartbeat_feature_start(sr_session_ctx_t *current_session);
+int ves_heartbeat_feature_stop(void);
index 62ccd47..69e459e 100644 (file)
 
 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;
     }
index 0512ed0..50ad52e 100644 (file)
@@ -19,4 +19,5 @@
 
 #include <sysrepo.h>
 
+int ves_pnf_registration_feature_get_status(void);
 int ves_pnf_registration_feature_start(sr_session_ctx_t *current_session);
index 8139b17..0ae406a 100644 (file)
 
 #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;
index b3fb221..4a41740 100644 (file)
@@ -19,4 +19,6 @@
 
 #include <sysrepo.h>
 
+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);
index 61fc129..316fe0a 100644 (file)
 #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;
 }
index 245223f..d0d9827 100644 (file)
@@ -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! */
     }
 
index 7624036..b0e26af 100644 (file)
 #include <time.h>
 #include <assert.h>
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+
+
 #include <core/framework.h>
 
 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);
+}
index 59fd277..2b18099 100644 (file)
 #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, ...);
index f3cb997..03d11c3 100644 (file)
@@ -25,6 +25,7 @@
 #include <assert.h>
 
 #include "core/session.h"
+#include "core/nc_config.h"
 
 #include <libnetconf2/session.h>
 #include <libnetconf2/session_client.h>
@@ -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);
index c5f66b3..77bd2ef 100644 (file)
@@ -18,6 +18,7 @@
 #pragma once
 
 #define NC_ENABLED_SSH
+#define NC_ENABLED_TLS
 #include <libyang/libyang.h>
 #include <libnetconf2/session.h>
 #include <libnetconf2/session_client.h>
@@ -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);
index b3c7d5d..60fa015 100644 (file)
 #include <stdio.h>
 #include <assert.h>
 
-#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, &current_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, &current_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, &current_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;
+}
index 29f3944..01a43d7 100644 (file)
@@ -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);
index 6b1fd6f..06d746c 100644 (file)
@@ -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", &lt);
index 1007b62..3449d63 100644 (file)
@@ -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;
                 }
index 1221181..034bcf0 100644 (file)
@@ -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 (executable)
index d32ef57..0000000
+++ /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')