diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8cdc796a5b..5d37670c34 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -450,7 +450,7 @@ add_library(f1ap
${F1AP_DIR}/f1ap_handlers.c
${F1AP_DIR}/f1ap_itti_messaging.c)
target_include_directories(f1ap PUBLIC F1AP_DIR)
-target_link_libraries(f1ap PUBLIC asn1_f1ap L2_NR)
+target_link_libraries(f1ap PUBLIC asn1_f1ap GTPV1U)
target_link_libraries(f1ap PRIVATE ngap nr_rrc HASHTABLE f1ap_lib)
target_include_directories(f1ap PRIVATE ${F1AP_DIR}/lib)
@@ -1351,7 +1351,7 @@ target_link_libraries(L2_UE PRIVATE GTPV1U)
target_link_libraries(L2_UE PRIVATE asn1_lte_rrc_hdrs)
add_library( NR_L2_UE ${NR_L2_SRC_UE} ${MAC_NR_SRC_UE} )
-target_link_libraries(NR_L2_UE PRIVATE f1ap nr_rlc)
+target_link_libraries(NR_L2_UE PRIVATE nr_rlc)
target_link_libraries(NR_L2_UE PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs nr_common nr_ue_power_procedures nr_ue_ra_procedures)
target_link_libraries(NR_L2_UE PRIVATE nr_nas)
@@ -1885,14 +1885,14 @@ add_executable(nr-uesoftmodem
${OPENAIR2_DIR}/LAYER2/NR_MAC_COMMON/nr_mac_common.c
${OPENAIR2_DIR}/LAYER2/NR_MAC_COMMON/nr_mac_common_tdd.c
${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c
+ ${NFAPI_USER_DIR}/nfapi.c
${PHY_INTERFACE_DIR}/queue_t.c
)
target_link_libraries(nr-uesoftmodem PRIVATE
-Wl,--start-group
nr_rrc SECURITY UTIL HASHTABLE SCHED_RU_LIB SCHED_NR_UE_LIB
- PHY_COMMON PHY_NR_COMMON PHY_NR_UE NR_L2_UE MAC_NR_COMMON NFAPI_LIB NFAPI_PNF_LIB
- NFAPI_USER_LIB MISC_NFAPI_NR_LIB
+ PHY_COMMON PHY_NR_COMMON PHY_NR_UE NR_L2_UE MAC_NR_COMMON NFAPI_LIB
ITTI SIMU shlib_loader
-Wl,--end-group z dl)
diff --git a/ci-scripts/xml_files/container_5g_fdd_rfsim.xml b/ci-scripts/xml_files/container_5g_fdd_rfsim.xml
index 276bb5b9a3..1c43120131 100644
--- a/ci-scripts/xml_files/container_5g_fdd_rfsim.xml
+++ b/ci-scripts/xml_files/container_5g_fdd_rfsim.xml
@@ -43,7 +43,7 @@
Pull_Local_Registry
Pull Images from Local Registry
0
- oai-gnb-asan oai-nr-ue-asan
+ oai-gnb oai-nr-ue
Create_Workspace
@@ -134,7 +134,7 @@
true
Clean Test Images on Test Server
0
- oai-gnb-asan oai-nr-ue-asan
+ oai-gnb oai-nr-ue
diff --git a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml
index a6103a3815..8c4688262b 100644
--- a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml
+++ b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml
@@ -86,8 +86,7 @@ services:
cap_drop:
- ALL
environment:
- USE_ADDITIONAL_OPTIONS: -E --rfsim --log_config.global_log_options level,nocolor,time
- ASAN_OPTIONS: detect_leaks=0
+ USE_ADDITIONAL_OPTIONS: -E --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role server --vrtsim.timescale 0.5
depends_on:
- oai-ext-dn
networks:
@@ -95,11 +94,13 @@ services:
ipv4_address: 192.168.71.140
volumes:
- ../../conf_files/gnb.sa.band66.106prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf
+ - tmp_data:/tmp/
healthcheck:
test: /bin/bash -c "pgrep nr-softmodem"
interval: 10s
timeout: 5s
retries: 5
+ ipc: host
oai-nr-ue:
image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop}
container_name: rfsim5g-oai-nr-ue
@@ -109,7 +110,7 @@ services:
- NET_ADMIN # for interface bringup
- NET_RAW # for ping
environment:
- USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 --band 66 -C 2169090000 --CO -400000000 --ssb 378 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time
+ USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --uicc0.imsi 208990100001100 --band 66 -C 2169090000 --CO -400000000 --ssb 378 --log_config.global_log_options level,nocolor,time --device.name vrtsim
depends_on:
- oai-gnb
networks:
@@ -119,11 +120,13 @@ services:
- /dev/net/tun:/dev/net/tun
volumes:
- ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf
+ - tmp_data:/tmp/
healthcheck:
test: /bin/bash -c "pgrep nr-uesoftmodem"
interval: 10s
timeout: 5s
retries: 5
+ ipc: host
networks:
public_net:
@@ -142,3 +145,6 @@ networks:
- subnet: 192.168.72.128/26
driver_opts:
com.docker.network.bridge.name: "rfsim5g-traffic"
+
+volumes:
+ tmp_data:
diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai
index 27bb63ff89..92dce6d1cd 100755
--- a/cmake_targets/build_oai
+++ b/cmake_targets/build_oai
@@ -99,7 +99,7 @@ Options:
USRP, BLADERF, LMSSDR, IRIS, SIMU, AW2SORI, AERIAL, None (Default)
Adds this RF board support (in external packages installation and in compilation)
-t | --transport
- Selects the transport protocol type, options: None, Ethernet, benetel4g, benetel5g, oran_fhlib_5g
+ Selects the transport protocol type, options: None, Ethernet, benetel4g, benetel5g, oran_fhlib_5g, oran_fhlib_5g_mplane
-P | --phy_simulators
Makes the unitary tests Layer 1 simulators
-s | --check
@@ -304,6 +304,10 @@ function main() {
TARGET_LIST="$TARGET_LIST $2"
CMAKE_CMD="$CMAKE_CMD -DOAI_FHI72=ON"
;;
+ "oran_fhlib_5g_mplane")
+ TARGET_LIST="$TARGET_LIST $2"
+ CMAKE_CMD="$CMAKE_CMD -DOAI_FHI72=ON -DOAI_FHI72_MPLANE=ON"
+ ;;
"None")
;;
*)
@@ -485,7 +489,7 @@ function main() {
# add some default libraries that should always be built
# for eNB, gNB, UEs, simulators
if [[ $gNB == 1 || $eNB == 1 || $UE == 1 || $nrUE == 1 || $SIMUS_PHY == 1 || $RU == 1 ]]; then
- TARGET_LIST="$TARGET_LIST params_libconfig coding rfsimulator dfts params_yaml"
+ TARGET_LIST="$TARGET_LIST params_libconfig coding rfsimulator dfts params_yaml vrtsim"
fi
mkdir -p $DIR/$BUILD_DIR/build
@@ -504,12 +508,6 @@ function main() {
echo_info "Built Doxygen based documentation. The documentation file is located here: $DIR/$BUILD_DIR/build/doc/html/index.html"
fi
- # TODO: once we got the CMakeLists.txt file done for the ORAN files, remove the following lines
- if [[ $TARGET_LIST =~ "oran_fhlib_5g" ]]; then
- rm -f liboai_transpro.so
- ln -s liboran_fhlib_5g.so liboai_transpro.so
- fi
-
if [ "$UE" = 1 ] ; then
echo_info "Compiling UE specific part"
diff --git a/cmake_targets/tools/MODULES/FindLibXml2.cmake b/cmake_targets/tools/MODULES/FindLibXml2.cmake
deleted file mode 100755
index e18dc2e921..0000000000
--- a/cmake_targets/tools/MODULES/FindLibXml2.cmake
+++ /dev/null
@@ -1,53 +0,0 @@
-# - Try to find the LibXml2 xml processing library
-# Once done this will define
-#
-# LIBXML2_FOUND - System has LibXml2
-# LIBXML2_INCLUDE_DIR - The LibXml2 include directory
-# LIBXML2_LIBRARIES - The libraries needed to use LibXml2
-# LIBXML2_DEFINITIONS - Compiler switches required for using LibXml2
-# LIBXML2_XMLLINT_EXECUTABLE - The XML checking tool xmllint coming with LibXml2
-
-#=============================================================================
-# Copyright 2006-2009 Kitware, Inc.
-# Copyright 2006 Alexander Neundorf
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
-# (To distributed this file outside of CMake, substitute the full
-# License text for the above reference.)
-
-# use pkg-config to get the directories and then use these values
-# in the FIND_PATH() and FIND_LIBRARY() calls
-FIND_PACKAGE(PkgConfig)
-PKG_CHECK_MODULES(PC_LIBXML libxml-2.0)
-SET(LIBXML2_DEFINITIONS ${PC_LIBXML_CFLAGS_OTHER})
-
-FIND_PATH(LIBXML2_INCLUDE_DIR NAMES libxml/xpath.h
- HINTS
- ${PC_LIBXML_INCLUDEDIR}
- ${PC_LIBXML_INCLUDE_DIRS}
- PATH_SUFFIXES libxml2
- )
-
-FIND_LIBRARY(LIBXML2_LIBRARIES NAMES xml2 libxml2
- HINTS
- ${PC_LIBXML_LIBDIR}
- ${PC_LIBXML_LIBRARY_DIRS}
- )
-
-FIND_PROGRAM(LIBXML2_XMLLINT_EXECUTABLE xmllint)
-# for backwards compat. with KDE 4.0.x:
-SET(XMLLINT_EXECUTABLE "${LIBXML2_XMLLINT_EXECUTABLE}")
-
-# handle the QUIETLY and REQUIRED arguments and set LIBXML2_FOUND to TRUE if
-# all listed variables are TRUE
-INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibXml2 DEFAULT_MSG LIBXML2_LIBRARIES LIBXML2_INCLUDE_DIR)
-
-MARK_AS_ADVANCED(LIBXML2_INCLUDE_DIR LIBXML2_LIBRARIES LIBXML2_XMLLINT_EXECUTABLE)
-
diff --git a/cmake_targets/tools/MODULES/Findxran.cmake b/cmake_targets/tools/MODULES/Findxran.cmake
index 290a782350..1ade3ac522 100644
--- a/cmake_targets/tools/MODULES/Findxran.cmake
+++ b/cmake_targets/tools/MODULES/Findxran.cmake
@@ -75,7 +75,6 @@ endif()
find_path(xran_INCLUDE_DIR
NAMES
- xran_common.h
xran_compression.h
xran_cp_api.h
xran_ecpri_owd_measurements.h
@@ -84,7 +83,7 @@ find_path(xran_INCLUDE_DIR
xran_pkt_up.h
xran_sync_api.h
HINTS ${xran_LOCATION}
- PATH_SUFFIXES api include
+ PATH_SUFFIXES api
NO_DEFAULT_PATH
)
find_library(xran_LIBRARY
@@ -127,16 +126,19 @@ find_package_handle_standard_args(xran
VERSION_VAR xran_VERSION
)
+# in proper usage of cmake, include directory should only contain "api", but not header files under "src" directory;
+# however, we use xran_dev_get_ctx() and xran_dev_get_ctx_by_id() functions which are defined in xran_common.h;
+# since xran_common.h is under "src" directory, we have to include it in ${xran_INCLUDE_DIRS}
if(xran_FOUND)
set(xran_LIBRARIES ${xran_LIBRARY})
- set(xran_INCLUDE_DIRS ${xran_INCLUDE_DIR})
+ set(xran_INCLUDE_DIRS ${xran_INCLUDE_DIR} ${xran_INCLUDE_DIR}/../src)
endif()
if(xran_FOUND AND NOT TARGET xran::xran)
add_library(xran::xran UNKNOWN IMPORTED)
set_target_properties(xran::xran PROPERTIES
IMPORTED_LOCATION "${xran_LIBRARY}"
- INTERFACE_INCLUDE_DIRECTORIES "${xran_INCLUDE_DIR}"
+ INTERFACE_INCLUDE_DIRECTORIES "${xran_INCLUDE_DIRS}"
)
endif()
diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper
index 3fc1db7b56..057c4860d6 100755
--- a/cmake_targets/tools/build_helper
+++ b/cmake_targets/tools/build_helper
@@ -546,7 +546,10 @@ check_install_additional_tools (){
libforms-bin \
libforms-dev \
libxft-dev \
- xmlstarlet"
+ xmlstarlet \
+ libpcre3-dev \
+ libssh-dev \
+ libxml2-dev"
elif [[ "$OS_DISTRO" == "rhel" ]] || [[ "$OS_DISTRO" == "centos" ]] || [[ "$OS_DISTRO" == "rocky" ]] || [[ "$OS_DISTRO" == "fedora" ]]; then
PACKAGE_LIST="\
doxygen \
@@ -556,7 +559,10 @@ check_install_additional_tools (){
libXft-devel \
xforms \
xforms-devel \
- xmlstarlet"
+ xmlstarlet \
+ pcre-devel \
+ libssh-devel \
+ libxml2-devel"
fi
$SUDO $INSTALLER install -y $PACKAGE_LIST $optional_packages
}
diff --git a/common/utils/CMakeLists.txt b/common/utils/CMakeLists.txt
index ccb15bfd47..b311d0542f 100644
--- a/common/utils/CMakeLists.txt
+++ b/common/utils/CMakeLists.txt
@@ -21,3 +21,4 @@ if (ENABLE_TESTS)
endif()
add_subdirectory(barrier)
add_subdirectory(actor)
+add_subdirectory(shm_iq_channel)
diff --git a/common/utils/LOG/log.c b/common/utils/LOG/log.c
index 148da232ae..61003857ab 100644
--- a/common/utils/LOG/log.c
+++ b/common/utils/LOG/log.c
@@ -52,6 +52,13 @@
// main log variables
+/** @defgroup _max_length Maximum Length of LOG
+ * @ingroup _macro
+ * @brief the macros that describe the maximum length of LOG
+ * @{*/
+
+#define MAX_LOG_TOTAL 16384 /*!< \brief the maximum length of a log */
+
// Fixme: a better place to be shure it is called
void read_cpu_hardware (void) __attribute__ ((constructor));
#if !defined(__arm__) && !defined(__aarch64__)
@@ -877,31 +884,32 @@ static void log_output_memory(log_component_t *c, const char *file, const char *
* correctly. It was not a big problem because in practice MAX_LOG_TOTAL is
* big enough so that the buffer is never full.
*/
- char log_buffer[MAX_LOG_TOTAL];
+ static_assert(4 * MAX_LOG_TOTAL <= 65536, "log buffer limited to 64kB, please reduce MAX_LOG_TOTAL\n");
+ char log_buffer[4 * MAX_LOG_TOTAL];
// make sure that for log trace the extra info is only printed once, reset when the level changes
if (level < OAILOG_TRACE) {
- int n = log_header(c, log_buffer+len, MAX_LOG_TOTAL, file, func, line, level);
+ int n = log_header(c, log_buffer+len, sizeof(log_buffer), file, func, line, level);
if (n > 0) {
len += n;
- if (len > MAX_LOG_TOTAL) {
- len = MAX_LOG_TOTAL;
+ if (len > sizeof(log_buffer)) {
+ len = sizeof(log_buffer);
}
}
}
- int n = vsnprintf(log_buffer+len, MAX_LOG_TOTAL-len, format, args);
+ int n = vsnprintf(log_buffer+len, sizeof(log_buffer)-len, format, args);
if (n > 0) {
len += n;
- if (len > MAX_LOG_TOTAL) {
- len = MAX_LOG_TOTAL;
+ if (len > sizeof(log_buffer)) {
+ len = sizeof(log_buffer);
}
}
if (!((g_log->flag) & FLAG_NOCOLOR)) {
- int n = snprintf(log_buffer+len, MAX_LOG_TOTAL-len, "%s", log_level_highlight_end[level]);
+ int n = snprintf(log_buffer+len, sizeof(log_buffer)-len, "%s", log_level_highlight_end[level]);
if (n > 0) {
len += n;
- if (len > MAX_LOG_TOTAL) {
- len = MAX_LOG_TOTAL;
+ if (len > sizeof(log_buffer)) {
+ len = sizeof(log_buffer);
}
}
}
@@ -941,7 +949,7 @@ static void log_output_memory(log_component_t *c, const char *file, const char *
}
}
}else{
- AssertFatal(len >= 0 && len <= MAX_LOG_TOTAL, "Bad len %d\n", len);
+ AssertFatal(len >= 0 && len <= sizeof(log_buffer), "Bad len %d\n", len);
if (write(fileno(c->stream), log_buffer, len)) {};
}
}
diff --git a/common/utils/LOG/log.h b/common/utils/LOG/log.h
index d153a4aeaf..7b9b570a06 100644
--- a/common/utils/LOG/log.h
+++ b/common/utils/LOG/log.h
@@ -65,12 +65,6 @@
extern "C" {
#endif
-/** @defgroup _max_length Maximum Length of LOG
- * @ingroup _macro
- * @brief the macros that describe the maximum length of LOG
- * @{*/
-
-#define MAX_LOG_TOTAL 16384 /*!< \brief the maximum length of a log */
/** @}*/
/** @defgroup _log_level Message levels defined by LOG
diff --git a/common/utils/actor/CMakeLists.txt b/common/utils/actor/CMakeLists.txt
index 40057d347e..182f54651d 100644
--- a/common/utils/actor/CMakeLists.txt
+++ b/common/utils/actor/CMakeLists.txt
@@ -1,6 +1,6 @@
add_library(actor actor.c)
-target_include_directories(actor PUBLIC ./)
-target_link_libraries(actor PUBLIC thread-pool)
+# Only include header files due to issues with ODR in threadPool binaries
+target_include_directories(actor PUBLIC ./ ../threadPool/)
if (ENABLE_TESTS)
add_subdirectory(tests)
endif()
diff --git a/common/utils/oai_asn1.h b/common/utils/oai_asn1.h
index 0f202bf699..4d7ea6c73f 100644
--- a/common/utils/oai_asn1.h
+++ b/common/utils/oai_asn1.h
@@ -78,6 +78,10 @@
// Prints an error if ID not found in list.
#define RELEASE_IE_FROMLIST(SOURCE, TARGET, FIELD) \
do { \
+ if (!TARGET) { \
+ LOG_E(NR_MAC, "Target list not present, impossible to release element\n"); \
+ break; \
+ } \
for (int iI = 0; iI < SOURCE->list.count; iI++) { \
long eL = *SOURCE->list.array[iI]; \
int iJ; \
diff --git a/common/utils/shm_iq_channel/CMakeLists.txt b/common/utils/shm_iq_channel/CMakeLists.txt
new file mode 100644
index 0000000000..57c7d343ef
--- /dev/null
+++ b/common/utils/shm_iq_channel/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_library(shm_td_iq_channel shm_td_iq_channel.c)
+target_include_directories(shm_td_iq_channel PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
+
+if (ENABLE_TESTS)
+ add_subdirectory(tests)
+endif()
diff --git a/common/utils/shm_iq_channel/shm_td_iq_channel.c b/common/utils/shm_iq_channel/shm_td_iq_channel.c
new file mode 100644
index 0000000000..89e09ddb1f
--- /dev/null
+++ b/common/utils/shm_iq_channel/shm_td_iq_channel.c
@@ -0,0 +1,286 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#include "shm_td_iq_channel.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "assertions.h"
+#include "utils.h"
+#include "common/utils/threadPool/pthread_utils.h"
+
+#define CIRCULAR_BUFFER_SIZE (30720 * 14 * 20)
+
+typedef struct {
+ int magic;
+ int num_antennas_tx;
+ int num_antennas_rx;
+ uint64_t timestamp;
+ bool is_connected;
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+} ShmTDIQChannelData;
+
+typedef struct ShmTDIQChannel_s {
+ IQChannelType type;
+ ShmTDIQChannelData *data;
+ uint64_t last_timestamp;
+ char name[256];
+ sample_t *tx_iq_data;
+ sample_t *rx_iq_data;
+} ShmTDIQChannel;
+
+ShmTDIQChannel *shm_td_iq_channel_create(const char *name, int num_tx_ant, int num_rx_ant)
+{
+ // Create shared memory segment
+ int fd = shm_open(name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
+ AssertFatal(fd != -1, "shm_open failed: %s\n", strerror(errno));
+ size_t tx_buffer_size = CIRCULAR_BUFFER_SIZE * sizeof(sample_t) * num_tx_ant;
+ size_t rx_buffer_size = CIRCULAR_BUFFER_SIZE * sizeof(sample_t) * num_rx_ant;
+ size_t total_size = sizeof(ShmTDIQChannelData) + tx_buffer_size + rx_buffer_size;
+
+ // Set the size of the shared memory segment
+ int res = ftruncate(fd, total_size);
+ AssertFatal(res != -1, "ftruncate failed: %s\n", strerror(errno));
+
+ // Map shared memory segment to address space
+ ShmTDIQChannelData *shm_ptr = mmap(NULL, total_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ AssertFatal(shm_ptr != MAP_FAILED, "mmap failed: %s\n", strerror(errno));
+
+ // Initialize shared memory
+ memset(shm_ptr, 0, total_size);
+ shm_ptr->num_antennas_tx = num_tx_ant;
+ shm_ptr->num_antennas_rx = num_rx_ant;
+ shm_ptr->is_connected = false;
+ ShmTDIQChannel *channel = calloc_or_fail(1, sizeof(ShmTDIQChannel));
+ strncpy(channel->name, name, sizeof(channel->name) - 1);
+ channel->tx_iq_data = (sample_t *)(shm_ptr + 1);
+ channel->rx_iq_data = channel->tx_iq_data + tx_buffer_size / sizeof(sample_t);
+ channel->data = shm_ptr;
+ channel->type = IQ_CHANNEL_TYPE_SERVER;
+ channel->last_timestamp = 0;
+ pthread_mutexattr_t mutex_attr;
+ pthread_condattr_t cond_attr;
+ int ret = pthread_mutexattr_init(&mutex_attr);
+ AssertFatal(ret == 0, "pthread_mutexattr_init() failed: errno %d, %s\n", errno, strerror(errno));
+
+ ret = pthread_condattr_init(&cond_attr);
+ AssertFatal(ret == 0, "pthread_condattr_init() failed: errno %d, %s\n", errno, strerror(errno));
+
+ ret = pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED);
+ AssertFatal(ret == 0, "pthread_mutexattr_setpshared() failed: errno %d, %s\n", errno, strerror(errno));
+
+ ret = pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED);
+ AssertFatal(ret == 0, "pthread_condattr_setpshared() failed: errno %d, %s\n", errno, strerror(errno));
+
+ ret = pthread_mutex_init(&shm_ptr->mutex, &mutex_attr);
+ AssertFatal(ret == 0, "pthread_mutex_init() failed: errno %d, %s\n", errno, strerror(errno));
+
+ ret = pthread_cond_init(&shm_ptr->cond, &cond_attr);
+ AssertFatal(ret == 0, "pthread_cond_init() failed: errno %d, %s\n", errno, strerror(errno));
+
+ shm_ptr->magic = SHM_MAGIC_NUMBER;
+ close(fd);
+ return channel;
+}
+
+ShmTDIQChannel *shm_td_iq_channel_connect(const char *name, int timeout_in_seconds)
+{
+ // Create shared memory segment
+ int fd = -1;
+ while (timeout_in_seconds > 0 && fd == -1) {
+ fd = shm_open(name, O_RDWR, S_IRUSR | S_IWUSR);
+ timeout_in_seconds--;
+ printf("Waiting for server to create shared memory segment\n");
+ sleep(1);
+ }
+ AssertFatal(fd != -1, "shm_open() failed: errno %d, %s", errno, strerror(errno));
+
+ struct stat buf;
+ fstat(fd, &buf);
+ size_t total_size = buf.st_size;
+
+ // Map shared memory segment to address space
+ ShmTDIQChannelData *shm_ptr = mmap(NULL, total_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (shm_ptr == MAP_FAILED) {
+ perror("mmap");
+ exit(1);
+ }
+
+ ShmTDIQChannel *channel = calloc_or_fail(1, sizeof(ShmTDIQChannel));
+ channel->data = shm_ptr;
+ channel->tx_iq_data = (sample_t *)(shm_ptr + 1);
+ size_t tx_buffer_size = CIRCULAR_BUFFER_SIZE * sizeof(sample_t) * channel->data->num_antennas_tx;
+ channel->rx_iq_data = channel->tx_iq_data + tx_buffer_size / sizeof(sample_t);
+ channel->type = IQ_CHANNEL_TYPE_CLIENT;
+ channel->last_timestamp = 0;
+ while (shm_ptr->magic != SHM_MAGIC_NUMBER) {
+ printf("Waiting for server to initialize shared memory\n");
+ sleep(1);
+ }
+ shm_ptr->is_connected = true;
+ close(fd);
+ return channel;
+}
+
+IQChannelErrorType shm_td_iq_channel_tx(ShmTDIQChannel *channel,
+ uint64_t timestamp,
+ uint64_t num_samples,
+ int antenna,
+ const sample_t *tx_iq_data)
+{
+ ShmTDIQChannelData *data = channel->data;
+ if (data->is_connected == false) {
+ return CHANNEL_ERROR_NOT_CONNECTED;
+ }
+ // timestamp in the past
+ uint64_t current_time = data->timestamp;
+ if (timestamp < current_time) {
+ return CHANNEL_ERROR_TOO_LATE;
+ }
+ // timestamp is too far in the future
+ if (timestamp - current_time + num_samples >= CIRCULAR_BUFFER_SIZE) {
+ return CHANNEL_ERROR_TOO_EARLY;
+ }
+
+ sample_t *base_ptr;
+ if (channel->type == IQ_CHANNEL_TYPE_CLIENT) {
+ base_ptr = channel->rx_iq_data + antenna * CIRCULAR_BUFFER_SIZE;
+ } else {
+ base_ptr = channel->tx_iq_data + antenna * CIRCULAR_BUFFER_SIZE;
+ }
+
+ uint64_t first_sample = timestamp % CIRCULAR_BUFFER_SIZE;
+ uint64_t last_sample = first_sample + num_samples - 1;
+ if (last_sample >= CIRCULAR_BUFFER_SIZE) {
+ size_t num_samples_first_copy = CIRCULAR_BUFFER_SIZE - first_sample;
+ memcpy(base_ptr + first_sample, tx_iq_data, num_samples_first_copy * sizeof(sample_t));
+ memcpy(base_ptr, tx_iq_data + num_samples_first_copy, (num_samples - num_samples_first_copy) * sizeof(sample_t));
+ } else {
+ memcpy(base_ptr + first_sample, tx_iq_data, num_samples * sizeof(sample_t));
+ }
+ return CHANNEL_NO_ERROR;
+}
+
+IQChannelErrorType shm_td_iq_channel_rx(ShmTDIQChannel *channel,
+ uint64_t timestamp,
+ uint64_t num_samples,
+ int antenna,
+ sample_t *tx_iq_data)
+{
+ ShmTDIQChannelData *data = channel->data;
+ if (data->is_connected == false) {
+ return CHANNEL_ERROR_NOT_CONNECTED;
+ }
+ // timestamp in the future
+ uint64_t current_time = data->timestamp;
+ if (timestamp > current_time) {
+ return CHANNEL_ERROR_TOO_EARLY;
+ }
+ // timestamp is too far in the past
+ if (current_time - timestamp >= CIRCULAR_BUFFER_SIZE) {
+ return CHANNEL_ERROR_TOO_LATE;
+ }
+
+ sample_t *base_ptr;
+ if (channel->type == IQ_CHANNEL_TYPE_CLIENT) {
+ base_ptr = channel->tx_iq_data + antenna * CIRCULAR_BUFFER_SIZE;
+ } else {
+ base_ptr = channel->rx_iq_data + antenna * CIRCULAR_BUFFER_SIZE;
+ }
+
+ uint64_t first_sample = timestamp % CIRCULAR_BUFFER_SIZE;
+ uint64_t last_sample = first_sample + num_samples - 1;
+ if (last_sample >= CIRCULAR_BUFFER_SIZE) {
+ size_t num_samples_first_copy = CIRCULAR_BUFFER_SIZE - first_sample;
+ memcpy(tx_iq_data, base_ptr + first_sample, num_samples_first_copy * sizeof(sample_t));
+ memcpy(tx_iq_data + num_samples_first_copy, base_ptr, (num_samples - num_samples_first_copy) * sizeof(sample_t));
+ } else {
+ memcpy(tx_iq_data, base_ptr + first_sample, num_samples * sizeof(sample_t));
+ }
+ return CHANNEL_NO_ERROR;
+}
+
+void shm_td_iq_channel_produce_samples(ShmTDIQChannel *channel, size_t num_samples)
+{
+ ShmTDIQChannelData *data = channel->data;
+ if (channel->type != IQ_CHANNEL_TYPE_SERVER) {
+ return;
+ }
+ if (data->is_connected == false) {
+ return;
+ }
+ mutexlock(data->mutex);
+ data->timestamp += num_samples;
+ condbroadcast(data->cond);
+ mutexunlock(data->mutex);
+}
+
+void shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp)
+{
+ ShmTDIQChannelData *data = channel->data;
+ if (data->is_connected == false) {
+ abort();
+ return;
+ }
+
+ size_t current_timestamp = data->timestamp;
+ if (current_timestamp >= timestamp) {
+ return;
+ }
+ mutexlock(data->mutex);
+ while (current_timestamp < timestamp) {
+ condwait(data->cond, data->mutex);
+ current_timestamp = data->timestamp;
+ }
+ mutexunlock(data->mutex);
+ return;
+}
+
+uint64_t shm_td_iq_channel_get_current_sample(const ShmTDIQChannel *channel)
+{
+ ShmTDIQChannelData *data = channel->data;
+ return data->timestamp;
+}
+
+bool shm_td_iq_channel_is_connected(const ShmTDIQChannel *channel)
+{
+ return channel->data->is_connected;
+}
+
+void shm_td_iq_channel_destroy(ShmTDIQChannel *channel)
+{
+ ShmTDIQChannelData *data = channel->data;
+ size_t tx_buffer_size = CIRCULAR_BUFFER_SIZE * sizeof(sample_t) * data->num_antennas_tx;
+ size_t rx_buffer_size = CIRCULAR_BUFFER_SIZE * sizeof(sample_t) * data->num_antennas_rx;
+ size_t total_size = sizeof(ShmTDIQChannelData) + tx_buffer_size + rx_buffer_size;
+ munmap(data, total_size);
+ if (channel->type == IQ_CHANNEL_TYPE_SERVER) {
+ shm_unlink(channel->name);
+ }
+ free(channel);
+}
diff --git a/common/utils/shm_iq_channel/shm_td_iq_channel.h b/common/utils/shm_iq_channel/shm_td_iq_channel.h
new file mode 100644
index 0000000000..7c5a730914
--- /dev/null
+++ b/common/utils/shm_iq_channel/shm_td_iq_channel.h
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+#ifndef SHM_IQ_CHANNEL_H
+#define SHM_IQ_CHANNEL_H
+
+#include "../threadPool/pthread_utils.h"
+#include
+#include
+#include
+
+#define SHM_MAGIC_NUMBER 0x12345678
+
+/**
+ * ShmTdIqChannel is a shared memory bidirectional time domain IQ channel with a single clock
+ * source. The server (clock source) shall create the channel while the client should connect to
+ * it.
+ *
+ * To write samples, send them via a pointer passed to shm_td_iq_channel_tx.
+ * To read samples, receive them via a pointer passed to shm_td_iq_channel_rx. You can either wait until
+ * the sample are available using shm_td_iq_channel_wait or poll using shm_td_iq_channel_rx until the return
+ * value is not CHANNEL_ERROR_TOO_EARLY.
+ * To indicate that samples are ready to be read by the client, call shm_td_iq_channel_produce_samples
+ * (server only).
+ *
+ * The timestamps used in the API are in absolute samples from the time the client/server connection started.
+ */
+
+typedef enum IQChannelType { IQ_CHANNEL_TYPE_SERVER, IQ_CHANNEL_TYPE_CLIENT } IQChannelType;
+typedef uint32_t sample_t;
+typedef enum IQChannelErrorType {
+ CHANNEL_NO_ERROR,
+ CHANNEL_ERROR_TOO_LATE,
+ CHANNEL_ERROR_TOO_EARLY,
+ CHANNEL_ERROR_NOT_CONNECTED
+} IQChannelErrorType;
+
+typedef struct ShmTDIQChannel_s ShmTDIQChannel;
+
+/**
+ * @brief Creates a shared memory IQ channel.
+ *
+ * @param name The name of the shared memory segment.
+ * @param num_tx_ant The number of TX antennas.
+ * @param num_rx_ant The number of RX antennas.
+ * @return A pointer to the created ShmTDIQChannel structure.
+ */
+ShmTDIQChannel *shm_td_iq_channel_create(const char *name, int num_tx_ant, int num_rx_ant);
+
+/**
+ * @brief Connects to an existing shared memory IQ channel.
+ *
+ * @param name The name of the shared memory segment.
+ * @param timeout_in_seconds The timeout in seconds for the connection attempt.
+ * @return A pointer to the connected ShmTDIQChannel structure.
+ */
+ShmTDIQChannel *shm_td_iq_channel_connect(const char *name, int timeout_in_seconds);
+
+/**
+ * @brief Transmit data in the channel
+ *
+ * @param channel The ShmTDIQChannel structure.
+ * @param timestamp The timestamp for which to get the TX IQ data slot.
+ * @param num_samples The number of samples to write.
+ * @param antenna The antenna index.
+ * @param tx_iq_data The TX IQ data to write.
+ *
+ * @return CHANNEL_NO_ERROR if successful, error type otherwise
+ */
+IQChannelErrorType shm_td_iq_channel_tx(ShmTDIQChannel *channel,
+ uint64_t timestamp,
+ uint64_t num_samples,
+ int antenna,
+ const sample_t *tx_iq_data);
+
+/**
+ * @brief Receive iq data from the channel
+ *
+ * @param channel The ShmTDIQChannel structure.
+ * @param timestamp The timestamp for which to get the RX IQ data slot.
+ * @param num_samples The number of samples to read.
+ * @param antenna The antenna index.
+ * @param tx_iq_data pointer to the RX IQ data slot.
+ * @return CHANNEL_NO_ERROR if successful, error type otherwise
+ */
+IQChannelErrorType shm_td_iq_channel_rx(ShmTDIQChannel *channel,
+ uint64_t timestamp,
+ uint64_t num_samples,
+ int antenna,
+ sample_t *tx_iq_data);
+
+/**
+ * @brief Advances the time in the channel by specified number of samples
+ *
+ * @param channel The ShmTDIQChannel structure.
+ * @param num_symbols The number of samples to produce.
+ */
+void shm_td_iq_channel_produce_samples(ShmTDIQChannel *channel, uint64_t num_samples);
+
+/**
+ * @brief Wait until sample at the specified timestamp is available
+ *
+ * @param channel The ShmTDIQChannel structure.
+ */
+void shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp);
+
+/**
+ * @brief Checks if the IQ channel is connected.
+ *
+ * @param channel The ShmTDIQChannel structure.
+ * @return True if the channel is connected, false otherwise.
+ */
+bool shm_td_iq_channel_is_connected(const ShmTDIQChannel *channel);
+
+/**
+ * @brief Destroys the shared memory IQ channel.
+ *
+ * @param channel The ShmTDIQChannel structure.
+ */
+void shm_td_iq_channel_destroy(ShmTDIQChannel *channel);
+
+/**
+ * @brief Returns current sample
+ *
+ * @param channel The ShmTDIQChannel structure.
+ *
+ * @return Current time as sample count since beginning of transmission
+ */
+uint64_t shm_td_iq_channel_get_current_sample(const ShmTDIQChannel *channel);
+
+#endif
diff --git a/common/utils/shm_iq_channel/tests/CMakeLists.txt b/common/utils/shm_iq_channel/tests/CMakeLists.txt
new file mode 100644
index 0000000000..f80f9cffbc
--- /dev/null
+++ b/common/utils/shm_iq_channel/tests/CMakeLists.txt
@@ -0,0 +1,5 @@
+add_executable(test_shm_td_iq_channel test_shm_td_iq_channel.c)
+target_link_libraries(test_shm_td_iq_channel shm_td_iq_channel minimal_lib pthread)
+add_dependencies(tests test_shm_td_iq_channel)
+# Commented out due to issues with ASAN in the unit test docker container
+#add_test(test_shm_td_iq_channel ./test_shm_td_iq_channel)
diff --git a/common/utils/shm_iq_channel/tests/test_shm_td_iq_channel.c b/common/utils/shm_iq_channel/tests/test_shm_td_iq_channel.c
new file mode 100644
index 0000000000..f5170b8144
--- /dev/null
+++ b/common/utils/shm_iq_channel/tests/test_shm_td_iq_channel.c
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "assertions.h"
+
+#define SHM_CHANNEL_NAME "shm_iq_channel_test_file"
+#include "shm_td_iq_channel.h"
+
+void server(void);
+int client(void);
+
+enum { MODE_SERVER, MODE_CLIENT, MODE_FORK };
+int main(int argc, char *argv[])
+{
+ int mode = MODE_FORK;
+ if (argc == 2) {
+ if (strcmp(argv[1], "server") == 0) {
+ mode = MODE_SERVER;
+ } else if (strcmp(argv[1], "client") == 0) {
+ mode = MODE_CLIENT;
+ }
+ } else if (argc > 2) {
+ printf("Usage: %s [server|client]\n", argv[0]);
+ return 1;
+ }
+ switch (mode) {
+ case MODE_SERVER:
+ server();
+ break;
+ case MODE_CLIENT:
+ return client();
+ break;
+ case MODE_FORK: {
+ char file[256];
+ snprintf(file, sizeof(file), "/dev/shm/%s", SHM_CHANNEL_NAME);
+ remove(file);
+ int pid = fork();
+ if (pid == 0) {
+ server();
+ } else {
+ return client();
+ }
+ } break;
+ }
+
+ return 0;
+}
+
+const int num_updates = 50;
+const int num_samples_per_update = 30720;
+void *produce_symbols(void *arg)
+{
+ ShmTDIQChannel *channel = (ShmTDIQChannel *)arg;
+ for (int i = 0; i < num_updates; i++) {
+ shm_td_iq_channel_produce_samples(channel, num_samples_per_update);
+ usleep(20000);
+ }
+ return 0;
+}
+
+void server(void)
+{
+ int num_ant_tx = 1;
+ int num_ant_rx = 1;
+ ShmTDIQChannel *channel = shm_td_iq_channel_create(SHM_CHANNEL_NAME, num_ant_tx, num_ant_rx);
+ for (int i = 0; i < 10; i++) {
+ if (shm_td_iq_channel_is_connected(channel)) {
+ printf("Server connected\n");
+ break;
+ }
+ printf("Waiting for client\n");
+ sleep(1);
+ }
+ AssertFatal(shm_td_iq_channel_is_connected(channel), "Server failed to connect\n");
+
+ pthread_t producer_thread;
+ int ret = pthread_create(&producer_thread, NULL, produce_symbols, channel);
+ AssertFatal(ret == 0, "pthread_create() failed: errno %d, %s\n", errno, strerror(errno));
+
+ uint64_t timestamp = 0;
+ int iq_contents = 0;
+ while (timestamp < num_samples_per_update * num_updates) {
+ shm_td_iq_channel_wait(channel, timestamp + num_samples_per_update);
+ uint64_t target_timestamp = timestamp + num_samples_per_update;
+ timestamp += num_samples_per_update;
+ uint32_t iq_data[num_samples_per_update];
+ for (int i = 0; i < num_samples_per_update; i++) {
+ iq_data[i] = iq_contents;
+ }
+ int result = shm_td_iq_channel_tx(channel, target_timestamp, num_samples_per_update, 0, iq_data);
+ AssertFatal(result == CHANNEL_NO_ERROR, "Failed to write data\n");
+ iq_contents++;
+ }
+
+ printf("Finished writing data\n");
+
+ ret = pthread_join(producer_thread, NULL);
+ AssertFatal(ret == 0, "pthread_join() failed: errno %d, %s\n", errno, strerror(errno));
+ shm_td_iq_channel_destroy(channel);
+}
+
+int client(void)
+{
+ int total_errors = 0;
+ ShmTDIQChannel *channel = shm_td_iq_channel_connect(SHM_CHANNEL_NAME, 10);
+ for (int i = 0; i < 10; i++) {
+ if (shm_td_iq_channel_is_connected(channel)) {
+ printf("Client connected\n");
+ break;
+ }
+ printf("Waiting for server\n");
+ sleep(1);
+ }
+ AssertFatal(shm_td_iq_channel_is_connected(channel), "Client failed to connect\n");
+
+ uint64_t timestamp = 0;
+ int iq_contents = 0;
+
+ while (timestamp < num_samples_per_update * num_updates) {
+ shm_td_iq_channel_wait(channel, timestamp + num_samples_per_update);
+ // Server starts producing from second slot
+ if (timestamp > num_samples_per_update) {
+ uint64_t target_timestamp = timestamp - num_samples_per_update;
+ uint32_t iq_data[num_samples_per_update];
+ int result = shm_td_iq_channel_rx(channel, target_timestamp, num_samples_per_update, 0, iq_data);
+ AssertFatal(result == CHANNEL_NO_ERROR, "Failed to read data\n");
+ int num_errors = 0;
+ for (int i = 0; i < num_samples_per_update; i++) {
+ if (iq_data[i] != iq_contents) {
+ num_errors++;
+ }
+ }
+ if (num_errors) {
+ printf("Found %d errors, value = %d, reference = %d\n", num_errors, iq_data[0], iq_contents);
+ total_errors += num_errors;
+ }
+ iq_contents++;
+ }
+ timestamp += num_samples_per_update;
+ }
+
+ printf("Finished reading data\n");
+ shm_td_iq_channel_destroy(channel);
+ return total_errors;
+}
diff --git a/doc/ORAN_FHI7.2_Tutorial.md b/doc/ORAN_FHI7.2_Tutorial.md
index c28f75a2cf..b3bd8ce146 100644
--- a/doc/ORAN_FHI7.2_Tutorial.md
+++ b/doc/ORAN_FHI7.2_Tutorial.md
@@ -72,6 +72,7 @@ tested any RU without S-plane. Radio units we are testing/integrating:
|LiteON RU |01.00.08/02.00.03 |
|Benetel 650 |RAN650-1v1.0.4-dda1bf5|
|Benetel 550 CAT-A|RAN550-1v1.0.4-605a25a|
+|Foxconn RPQN |v3.1.15q.551_rc10 |
Tested libxran releases:
@@ -671,6 +672,40 @@ The RU configuration is stored in `/etc/rumanager.conf`. The required modificati
At this stage, RU must be rebooted so the changes apply.
+### Foxconn RPQN RU
+
+**Version v3.1.15q.551_rc10**
+
+The OAI configuration file [`gnb.sa.band78.273prb.fhi72.4X4-foxconn.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4X4-foxconn.conf) corresponds to:
+- TDD pattern `DDDSU`, 2.5ms
+- Bandwidth 100MHz
+- MTU 8000
+
+#### RU configuration
+
+After switching on or rebooting the RU, the `/home/root/test/init_rrh_config_enable_cuplane` script should be run.
+
+The RU configuration file is located in `/home/root/test/RRHconfig_xran.xml`. The required modifications:
+1. `RRH_DST_MAC_ADDR`
+2. `RRH_SRC_MAC_ADDR`
+3. `RRH_EAXC_ID_TYPE1`
+4. `RRH_EAXC_ID_TYPE3`
+5. `RRH_CMPR_HDR_PRESENT` -> `0`
+6. `RRH_C_PLANE_VLAN_TAG`
+7. `RRH_U_PLANE_VLAN_TAG`
+8. `RRH_LO_FREQUENCY_KHZ` -> `3750000, 0`
+9. `RRH_DISABLE_USING_CAL_TABLES` -> `YES`
+10. `RRH_TX_ATTENUATION` -> must be larger than 10dB
+11. `RRH_RX_ATTENUATION` -> must be lower than 30dB
+
+RU must be rebooted so the changes apply.
+
+**Note**
+
+- The RU was tested with the `2024.w30` tag of OAI.
+- The measured throughput was **520 Mbps DL** and **40 Mbps UL**.
+- With newer OAI versions, throughput degrades. This issue is currently under investigation.
+
## Configure Network Interfaces and DPDK VFs
The 7.2 fronthaul uses the xran library, which requires DPDK. In this step, we
@@ -942,10 +977,8 @@ Edit the sample OAI gNB configuration file and check following parameters:
including the advantages and disadvantages of each mode, refer to
[Memory in DPDK](https://www.dpdk.org/memory-in-dpdk-part-2-deep-dive-into-iova/)
* `owdm_enable`: used for eCPRI One-Way Delay Measurements; it depends if the RU supports it; if not set to 1 (enabled), default value is 0 (disabled)
- * `fh_config`: parameters that need to match RU parameters
- * timing parameters (starting with `T`) depend on the RU: `Tadv_cp_dl` is a
- single number, the rest pairs of numbers `(x, y)` specifying minimum and
- maximum delays
+ * `fh_config`
+ * DU delay profile (`T1a` and `Ta4`): pairs of numbers `(x, y)` specifying minimum and maximum delays
* `ru_config`: RU-specific configuration:
* `iq_width`: Width of DL/UL IQ samples: if 16, no compression, if <16, applies
compression
@@ -966,7 +999,7 @@ Layer mapping (eAxC offsets) happens as follows:
**Note**
- At the moment, OAI is compatible with CAT A O-RU only. Therefore, SRS is not supported.
-- XRAN retreives DU MAC address with `rte_eth_macaddr_get()` function. Hence, `fhi_72.du_addr` parameter is not taken into account.
+- XRAN retrieves DU MAC address with `rte_eth_macaddr_get()` function. Hence, `fhi_72.du_addr` parameter is not taken into account.
# Start and Operation of OAI gNB
@@ -1094,10 +1127,10 @@ fhi_72 = {
// mtu
fh_config = (
{
- // timing, ru_config, prach_config of RU1
+ // DU delay profile, ru_config, prach_config of RU1
},
{
- // timing, ru_config, prach_config of RU2
+ // DU delay profile, ru_config, prach_config of RU2
}
);
};
@@ -1121,11 +1154,6 @@ fhi_72 = {
fh_config = (
# RAN650 #1
{
- Tadv_cp_dl = 125;
- T2a_cp_dl = (259, 500);
- T2a_cp_ul = (25, 500);
- T2a_up = (134, 375);
- Ta3 = (152, 160);
T1a_cp_dl = (419, 470);
T1a_cp_ul = (285, 336);
T1a_up = (294, 345);
@@ -1137,11 +1165,6 @@ fhi_72 = {
},
# RAN650 #2
{
- Tadv_cp_dl = 125;
- T2a_cp_dl = (259, 500);
- T2a_cp_ul = (25, 500);
- T2a_up = (134, 375);
- Ta3 = (152, 160);
T1a_cp_dl = (419, 470);
T1a_cp_ul = (285, 336);
T1a_up = (294, 345);
@@ -1185,6 +1208,815 @@ Note the eight entries after `avg_IO`.
You should be able to connect a UE now.
+
+# OAI Management Plane
+We support Configuration Management in OAI gNB, where gNB configures CU-planes, interfaces, TX/RX antennas, and TX/RX carriers for the RU.
+The reference specifications:
+* `O-RAN.WG4.MP.0-v05.00`
+* `O-RAN.WG4.MP-YANGs-v04.00`
+
+## M-plane prerequisites
+Before proceeding, please make sure you have a support for 7.2 interface, as described in [Prerequisites](#prerequisites).
+
+### DHCP server
+The M-plane requires a DHCP server, where the M-plane connection can be established over untagged or tagged VLAN. We tested with untagged (the default VLAN is 1).
+Please modify `/etc/dhcp/dhcpd.conf` configuration based on your testbed.
+
+
+Example DHCP server configuration
+
+```
+class "vendor-class" {
+ match option vendor-class-identifier;
+}
+subclass "vendor-class" "o-ran-ru2/Benetel" {
+ vendor-option-space VC;
+}
+option space VC;
+option VC.server-address code 129 = array of ip-address;
+option VC.server-fqdn code 130 = string;
+# Netconf client IP address - DHCP option 43
+option VC.server-address 192.168.80.1;
+option VC.server-fqdn "o_du_1.operator.com";
+set vendor-string = option vendor-class-identifier;
+# option 143 - DHCPv4 SZTP Redirect Option (RFC8572)
+# 2 bytes of URI's length + URI
+option sztp code 143 = { unsigned integer 16, string };
+option sztp 15 "https://192.168.80.1";
+# port is optional in URI, e.g. "https://192.168.80.1:222"
+#option sztp 20 "https://192.168.80.1:2222";
+subnet 192.168.80.0 netmask 255.255.255.0 {
+ option routers 192.168.80.1;
+ option subnet-mask 255.255.255.0;
+ option domain-name "oai.com";
+ option domain-name-servers 172.21.3.100;
+ host benetel_ru {
+ # RU MAC address
+ hardware ethernet ;
+ # RU IP address
+ fixed-address ;
+ }
+}
+```
+
+
+Please, configure the interface as:
+```bash
+sudo ip address add 192.168.80.1/24 dev
+```
+
+### Mandatory packages
+* On Fedora (we haven't yet tested RHEL):
+```bash
+sudo dnf install pcre-devel libssh-devel libxml2-devel libyang2-devel libnetconf2-devel
+```
+
+* On Ubuntu:
+```bash
+sudo apt-get install libpcre3-dev libssh-dev libxml2-dev
+```
+
+On Ubuntu, please note: `sudo apt-get install libyang2-dev libnetconf2-dev` will install unsupported versions (i.e. v2.0.112/v2.0.24 for `libyang2-dev`/`libnetconf2-dev`, but minimum required are v2.1.4/v2.1.25).
+Therefore, please compile these libraries from source, as following:
+
+
+Installing latest v2 libyang2 and libnetconf2 libraries
+
+```
+rm -rf /tmp/build_mplane_v2
+mkdir /tmp/build_mplane_v2
+
+# libyang
+cd /tmp/build_mplane_v2
+git clone https://github.com/CESNET/libyang.git
+cd libyang
+git checkout v2.1.111
+mkdir build && cd build
+cmake -DENABLE_TESTS=OFF \
+ -DENABLE_VALGRIND_TESTS=OFF \
+ -DCMAKE_INSTALL_PREFIX=/usr/local \
+ -DCMAKE_INSTALL_RPATH=/usr/local/lib \
+ -DPLUGINS_DIR=/usr/local/lib/libyang \
+ -DPLUGINS_DIR_EXTENSIONS=/usr/local/lib/libyang/extensions \
+ -DPLUGINS_DIR_TYPES=/usr/local/lib/libyang/types \
+ -DYANG_MODULE_DIR=/usr/local/share/yang/modules/libyang ..
+make -j8
+sudo make install
+sudo ldconfig
+
+#libnetconf
+cd /tmp/build_mplane_v2
+git clone https://github.com/CESNET/libnetconf2.git
+cd libnetconf2
+git checkout v2.1.37
+mkdir build && cd build
+cmake -DENABLE_TESTS=OFF \
+ -DENABLE_EXAMPLES=OFF \
+ -DENABLE_VALGRIND_TESTS=OFF \
+ -DCLIENT_SEARCH_DIR=/usr/local/share/yang/modules \
+ -DCMAKE_INSTALL_PREFIX=/usr/local \
+ -DCMAKE_INSTALL_RPATH=/usr/local/lib \
+ -DLIBYANG_INCLUDE_DIR=/usr/local/include \
+ -DLIBYANG_LIBRARY=/usr/local/lib/libyang.so \
+ -DLY_VERSION_PATH=/usr/local/include \
+ -DYANG_MODULE_DIR=/usr/local/share/yang/modules/libnetconf2 ..
+make -j8
+sudo make install
+sudo ldconfig
+
+# to uninstall libraries
+# cd /tmp/build_mplane_v2/libyang/build && sudo make uninstall
+# cd /tmp/build_mplane_v2/libnetconf2/build && sudo make uninstall
+# cd
+# rm -rf /tmp/build_mplane_v2
+```
+
+
+If you would like to install these libraries in the custom path, please replace `/usr/local` default path to e.g. `/opt/mplane-v2`.
+
+## Benetel O-RU
+Note: Only v1.2.2 RAN550 and RAN650 have been successfully tested.
+
+### One time steps
+Connect to the RU as user `root`, enable the mplane service, and reboot:
+```bash
+ssh root@
+systemctl enable mplane
+reboot
+```
+Once the mplane service is successfully enabled on the RU, two new users are being added in `/etc/passwd`:
+```bash
+...
+oranbenetel:x:1000:1000::/home/oranbenetel:/bin/sh
+oranext:x:1001:1001::/home/oranext:/bin/sh
+```
+Create `oranbenetel` home directory:
+```bash
+mkdir /home/oranbenetel && chown oranbenetel:oranbenetel /home/oranbenetel
+```
+Connect to the RU as user `oranbenetel`, generate ssh keys, and copy DU public key into RU for NETCONF authentication:
+```bash
+ssh oranbenetel@
+ssh-keygen
+echo "" >> ~/.ssh/authorized_keys
+```
+
+
+## gNB configuration
+The reference gNB configuration file for one Benetel RAN550:
+[`gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf)
+The reference DU configuration file for two Benetel RAN650:
+[gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf)
+
+In order to run gNB/DU with M-plane, we need to modify the `fhi_72` section in the configuration file.
+Example for one RU:
+```bash
+fhi_72 = {
+ dpdk_devices = ("0000:c3:11.0", "0000:c3:11.1"); # one VF can be used as well
+ system_core = 0;
+ io_core = 1;
+ worker_cores = (2);
+ du_key_pair = ("/.ssh/id_rsa.pub", "/.ssh/id_rsa");
+ du_addr = ("00:11:22:33:44:66", "00:11:22:33:44:67"); # only one needed if one VF configured
+ vlan_tag = (9, 9); # only one needed if one VF configured
+ ru_ip_addr = ("192.168.80.9");
+ fh_config = ({
+ T1a_cp_dl = (419, 470);
+ T1a_cp_ul = (285, 336);
+ T1a_up = (294, 345);
+ Ta4 = (0, 200);
+ });
+};
+```
+Example for two RUs:
+```bash
+fhi_72 = {
+ dpdk_devices = ("0000:c3:11.0", "0000:c3:11.1", "0000:c3:11.2", "0000:c3:11.3"); # two VFs can be used as well
+ system_core = 0;
+ io_core = 1;
+ worker_cores = (2);
+ du_key_pair = ("/home/oaicicd/.ssh/id_rsa.pub", "/home/oaicicd/.ssh/id_rsa");
+ du_addr = ("00:11:22:33:44:66", "00:11:22:33:44:67", "00:11:22:33:44:68", "00:11:22:33:44:69"); # only two needed if two VFs configured
+ vlan_tag = (9, 9, 11, 11); # only two needed if two VFs configured
+ ru_ip_addr = ("192.168.80.9", "192.168.80.10");
+ fh_config = (
+# RAN550 #1
+ {
+ T1a_cp_dl = (419, 470);
+ T1a_cp_ul = (285, 336);
+ T1a_up = (294, 345);
+ Ta4 = (0, 200);
+ },
+# RAN550 #2
+ {
+ T1a_cp_dl = (419, 470);
+ T1a_cp_ul = (285, 336);
+ T1a_up = (294, 345);
+ Ta4 = (0, 200);
+ });
+};
+```
+
+* `fhi_72` :
+ * `dpdk_devices`: [*]
+ * `system_core`: [*]
+ * `io_core`: [*]
+ * `worker_cores`: [*]
+ * `file_prefix`: [*]
+ * `du_key_pair`: ssh public and private keys to authenticate RU with NETCONF
+ * `du_addr`: DU MAC address(es) to create CU-plane interface(s) in the RU
+ * `vlan_tag`: VLAN U and C plane tags to create CU-plane interface(s) in the RU
+ * `ru_ip_addr`: RU IP address to connect to the RU via M-plane
+ * `dpdk_mem_size`: [*]
+ * `dpdk_iova_mode`: [*]
+ * `owdm_enable`: [*]
+ * `fh_config`: only DU delay profile (`T1a` and `Ta4`)
+
+[*] see [Configure OAI gNB](#configure-oai-gnb) for more details
+
+The following parameters are retrieved from the RU and forwarded to the xran:
+* `MTU`
+* `RU MAC address`
+* `IQ compression`: if RU supports multiple, the first value in the list is taken; please note that the same value is used for PxSCH/PRACH
+* `PRACH offset`: hardcoded based on the RU vendor (i.e. for Benetel `max(Nrx,Ntx)`)
+
+## Build and compile gNB
+The following cmake options are available:
+* `OAI_FHI72` = CUS support
+* `OAI_FHI72_MPLANE` = M support
+
+Compiled libraries:
+* `OAI_FHI72` <=> `oran_fhlib_5g`
+* `OAI_FHI72` && `OAI_FHI72_MPLANE` <=> `oran_fhlib_5g` (CUS) && `oran_fhlib_5g_mplane` (CUSM)
+
+### Using build_oai script
+```bash
+git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ~/openairinterface5g
+cd ~/openairinterface5g/cmake_targets/
+./build_oai -I # if you never installed OAI, use this command once before the next line
+./build_oai --install-optional-packages # for pcre/libpcre3, libssh, and libxml2 library installation
+./build_oai --gNB --ninja -t oran_fhlib_5g_mplane --cmake-opt -Dxran_LOCATION=$HOME/phy/fhi_lib/lib
+# if libyang2 and libnetconf2 are installed in `/opt/mplane-v2`, please use the following command:
+PKG_CONFIG_PATH=/opt/mplane-v2/lib/pkgconfig ./build_oai --gNB --ninja -t oran_fhlib_5g_mplane --cmake-opt -Dxran_LOCATION=$HOME/phy/fhi_lib/lib
+```
+
+### Using cmake directly
+```bash
+git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ~/openairinterface5g
+cd ~/openairinterface5g/
+mkdir build && cd build
+cmake .. -GNinja -DOAI_FHI72=ON -DOAI_FHI72_MPLANE=ON -Dxran_LOCATION=$HOME/phy/fhi_lib/lib
+# if libyang2 and libnetconf2 are installed in `/opt/mplane-v2`, please use the following command:
+PKG_CONFIG_PATH=/opt/mplane-v2/lib/pkgconfig cmake .. -GNinja -DOAI_FHI72=ON -DOAI_FHI72_MPLANE=ON -Dxran_LOCATION=$HOME/phy/fhi_lib/lib
+ninja nr-softmodem oran_fhlib_5g_mplane params_libconfig
+```
+
+## Start the gNB
+Run the `nr-softmodem` from the build directory:
+```bash
+cd ~/openairinterface5g/cmake_targets/ran_build/build
+sudo ./nr-softmodem -O --thread-pool
+```
+
+**Warning**: Make sure that the configuration file you add after the `-O` option is adapted to your machine, especially to its isolated cores.
+
+M-plane sequence diagram:
+
+```mermaid
+sequenceDiagram
+ participant dhcp as DHCP server
+ participant du as O-DU
+ participant ru as O-RU
+
+ dhcp->ru: 1. Transport Layer Initialization
+ note over dhcp,ru: (a) perform VLAN scan (untagged or tagged VLAN)
(b) DHCP assigns IP address to RU
(c) DHCP sends DU IP address to RU
+
+ du->ru: 2. NETCONF/SSH connect
+
+ du->>ru: 3. DU retrieves RU info
+ note left of du:
+
+ note over du: Check if RU is PTP synced
+
+ du->>ru: 4. DU subscribes to all RU notifications
+ note left of du:
+
+ du->>ru: 5. DU updates the supervision timer
+ note left of du:
+
+ note over du: Store RU MAC, MTU, IQ bitwidth, and PRACH offset info for xran
+
+ note over du: Store all the RU U-plane info - interface name, TX/RX carrier, and TX/RX endpoint names
+
+ du->>ru: 6. DU loads yang models
+ note left of du:
+ note right of ru: ietf-netconf-monitoring.yang
+
+ du->>ru: 7. DU performs CU-plane configuration
+ note left of du:
+
+ note over ru: (1) o-ran-interface.yang - create new interface with VLAN tag, DU and RU MAC addresses
(2)(opt.) o-ran-transceiver.yang - for file upload
(3) o-ran-processing-elements.yang - element with which RU ports should be assigned
(4) o-ran-uplane-conf.yang
#8193;(4a) low-level-tx/rx-endpoints - PxSCH, PRACH
#8193;(4b) tx/rx-array-carriers - center frequency, BW, gain, ACTIVE,...
#8193;(4c) low-level-tx/rx-links - mapping endpoints, carriers and processing element
#8193;(4d)(opt.) if CAT B, SRS configuration
#8193;(4e)(opt.) TDD configuration
+
+ du->>ru: 8. DU checks if CU-plane configuration is valid
+ note left of du:
+
+ du->>ru: 9. If valid, DU commits the changes
+ note left of du:
+
+ du->>ru: 10. DU retrieves RU states
+ note right of ru: ietf-hardware.yang
+ note left of du:
+ note over ru: admin-state, power-state, oper-state,
availability-state, usage-state
+
+ ru->>du: 11. RU notifies DU about the configuration change
+
+ note over du: DU configures xran
+
+ du->ru: 12. DU and RU exchange packets
+```
+
+
+
+4x4 MIMO and 100MHz BW with Benetel 550 RU example run
+
+```
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = with username "oranbenetel" and port ID "830".
+[HW] [MPLANE] Successfuly connected to RU "192.168.80.9" with username "oranbenetel" and port ID "830".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = operational datastore.
+[HW] [MPLANE] Successfully retrieved operational datastore from RU "192.168.80.9".
+[HW] [MPLANE] RU is already PTP synchronized.
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = with stream "NETCONF" and filter "(null)".
+[HW] [MPLANE] RPC reply = OK.
+[HW] [MPLANE] Successfully subscribed to all notifications from RU "192.168.80.9".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = "
+65535
+65535
+".
+[HW] [MPLANE] Successfully updated supervision timer to (65535+65535)[s] for RU "192.168.80.9".
+[HW] [MPLANE] Watchdog timer answer:
+ 2025-03-30T08:52:31+02:00
+
+[HW] [MPLANE] Interface MTU 1500 unreliable/not correctly reported by Benetel O-RU, hardcoding to 9600.
+[HW] [MPLANE] IQ bitwidth 16 unreliable/not correctly reported by Benetel O-RU, hardcoding to 9.
+[HW] [MPLANE] Storing the following information to forward to xran:
+ RU MAC address 8c:1f:64:d1:11:c0
+ MTU 9600
+ IQ bitwidth 9
+ PRACH offset 4
+ DU port bitmask 61440
+ Band sector bitmask 3840
+ CC ID bitmask 240
+ RU port ID bitmask 15
+ DU port ID 0
+ Band sector ID 0
+ CC ID 0
+ RU port ID 0
+[HW] [MPLANE] Successfully retrieved all the U-plane info - interface name, TX/RX carrier names, and TX/RX endpoint names.
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "ietf-yang-metadata".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "yang".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "ietf-inet-types".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "ietf-yang-types".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "ietf-yang-schema-mount".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "ietf-yang-structure-ext".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "ietf-datastores".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "sysrepo".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "ietf-netconf-acm".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "ietf-factory-default".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "sysrepo-factory-default".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "ietf-yang-library".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "sysrepo-monitoring".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "sysrepo-plugind".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "ietf-netconf".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "ietf-netconf-with-defaults".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "ietf-netconf-notifications".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "ietf-origin".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "ietf-netconf-monitoring".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "ietf-netconf-nmda".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "nc-notifications".
+[HW] [MPLANE] [LIBYANG] ERROR: Data model "notifications" not found in local searchdirs. (path: (null)).
+[HW] [MPLANE] [LIBYANG] ERROR: Loading "notifications" module failed. (path: (null)).
+[HW] [MPLANE] [LIBYANG] ERROR: Parsing module "nc-notifications" failed. (path: (null)).
+[HW] [MPLANE] Unable to load module "nc-notifications" from RU "192.168.80.9".
+[HW] [MPLANE] Unable to load all yang modules from operational datastore for RU "192.168.80.9". Using yang models present in "models" subfolder.
+[HW] [MPLANE] Successfully loaded all yang modules for RU "192.168.80.9".
+[HW] [MPLANE] The VLAN tags for C and U plane for the RU "192.168.80.9" are the same. Therefore, configuring one common interface and one processing element.
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = :
+
+
+ INTERFACE_0
+ ianaift:l2vlan
+ true
+ 8c:1f:64:d1:11:c0
+ eth0
+ 9
+
+
+
+ ETH-INTERFACE
+
+ PLANE_0
+
+ INTERFACE_0
+
+ 8c:1f:64:d1:11:c0
+ 9
+ 00:11:22:33:44:66
+
+
+
+
+
+
+ PdschLink0
+ PLANE_0
+ TxArray0
+ LowLevelTxEndpoint0
+
+
+ PdschLink1
+ PLANE_0
+ TxArray0
+ LowLevelTxEndpoint1
+
+
+ PdschLink2
+ PLANE_0
+ TxArray0
+ LowLevelTxEndpoint2
+
+
+ PdschLink3
+ PLANE_0
+ TxArray0
+ LowLevelTxEndpoint3
+
+
+ PuschLink0
+ PLANE_0
+ RxArray0
+ LowLevelRxEndpoint0
+
+
+ PrachLink0
+ PLANE_0
+ RxArray0
+ LowLevelRxPrachEndpoint0
+
+
+ PuschLink1
+ PLANE_0
+ RxArray0
+ LowLevelRxEndpoint1
+
+
+ PrachLink1
+ PLANE_0
+ RxArray0
+ LowLevelRxPrachEndpoint1
+
+
+ PuschLink2
+ PLANE_0
+ RxArray0
+ LowLevelRxEndpoint2
+
+
+ PrachLink2
+ PLANE_0
+ RxArray0
+ LowLevelRxPrachEndpoint2
+
+
+ PuschLink3
+ PLANE_0
+ RxArray0
+ LowLevelRxEndpoint3
+
+
+ PrachLink3
+ PLANE_0
+ RxArray0
+ LowLevelRxPrachEndpoint3
+
+
+ LowLevelTxEndpoint0
+
+ 9
+ STATIC
+
+ 0
+ 0
+ 0
+
+ 61440
+ 3840
+ 240
+ 15
+ 0
+
+
+
+ LowLevelTxEndpoint1
+
+ 9
+ STATIC
+
+ 0
+ 0
+ 0
+
+ 61440
+ 3840
+ 240
+ 15
+ 1
+
+
+
+ LowLevelTxEndpoint2
+
+ 9
+ STATIC
+
+ 0
+ 0
+ 0
+
+ 61440
+ 3840
+ 240
+ 15
+ 2
+
+
+
+ LowLevelTxEndpoint3
+
+ 9
+ STATIC
+
+ 0
+ 0
+ 0
+
+ 61440
+ 3840
+ 240
+ 15
+ 3
+
+
+
+ LowLevelRxEndpoint0
+
+ 9
+ STATIC
+
+ 0
+ 0
+ 0
+
+ 61440
+ 3840
+ 240
+ 15
+ 0
+
+
+
+ LowLevelRxPrachEndpoint0
+
+ 9
+ STATIC
+
+ 0
+ 0
+ 0
+
+ 61440
+ 3840
+ 240
+ 15
+ 4
+
+
+
+ LowLevelRxEndpoint1
+
+ 9
+ STATIC
+
+ 0
+ 0
+ 0
+
+ 61440
+ 3840
+ 240
+ 15
+ 1
+
+
+
+ LowLevelRxPrachEndpoint1
+
+ 9
+ STATIC
+
+ 0
+ 0
+ 0
+
+ 61440
+ 3840
+ 240
+ 15
+ 5
+
+
+
+ LowLevelRxEndpoint2
+
+ 9
+ STATIC
+
+ 0
+ 0
+ 0
+
+ 61440
+ 3840
+ 240
+ 15
+ 2
+
+
+
+ LowLevelRxPrachEndpoint2
+
+ 9
+ STATIC
+
+ 0
+ 0
+ 0
+
+ 61440
+ 3840
+ 240
+ 15
+ 6
+
+
+
+ LowLevelRxEndpoint3
+
+ 9
+ STATIC
+
+ 0
+ 0
+ 0
+
+ 61440
+ 3840
+ 240
+ 15
+ 3
+
+
+
+ LowLevelRxPrachEndpoint3
+
+ 9
+ STATIC
+
+ 0
+ 0
+ 0
+
+ 61440
+ 3840
+ 240
+ 15
+ 7
+
+
+
+ TxArray0
+ 663360
+ 3950400000
+ 100000000
+ ACTIVE
+ 0.0
+ 0
+ 0
+
+
+ RxArray0
+ 663360
+ 3950400000
+ 100000000
+ ACTIVE
+ 0
+ 0
+ 0.0
+ 0
+
+
+
+[HW] [MPLANE] RPC reply = OK.
+[HW] [MPLANE] Successfully edited the candidate datastore for RU "192.168.80.9".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = candidate datastore.
+[HW] [MPLANE] RPC reply = OK.
+[HW] [MPLANE] Successfully validated candidate datastore for RU "192.168.80.9".
+[HW] [MPLANE] RPC request to RU "192.168.80.9" = candidate datastore.
+[HW] [MPLANE] RPC reply = OK.
+[HW] [MPLANE] Successfully commited CU-planes configuration into running datastore for RU "192.168.80.9".
+[HW] [MPLANE] Usage state = "idle" for RU "192.168.80.9".
+[HW] [MPLANE] Received notification from RU "192.168.80.9" at (2025-03-29T12:40:23.049085102+00:00)
+{
+ "o-ran-uplane-conf:rx-array-carriers-state-change": {
+ "rx-array-carriers": [
+ {
+ "name": "RxArray0",
+ "state": "BUSY"
+ }
+ ]
+ }
+}
+
+[HW] [MPLANE] Received notification from RU "192.168.80.9" at (2025-03-29T12:40:23.058136880+00:00)
+{
+ "o-ran-uplane-conf:tx-array-carriers-state-change": {
+ "tx-array-carriers": [
+ {
+ "name": "TxArray0",
+ "state": "BUSY"
+ }
+ ]
+ }
+}
+
+[HW] [MPLANE] Received notification from RU "192.168.80.9" at (2025-03-29T12:40:23.078776163+00:00)
+{
+ "o-ran-uplane-conf:rx-array-carriers-state-change": {
+ "rx-array-carriers": [
+ {
+ "name": "RxArray0",
+ "state": "READY"
+ }
+ ]
+ }
+}
+
+[HW] [MPLANE] Received notification from RU "192.168.80.9" at (2025-03-29T12:40:23.093039138+00:00)
+{
+ "o-ran-uplane-conf:tx-array-carriers-state-change": {
+ "tx-array-carriers": [
+ {
+ "name": "TxArray0",
+ "state": "READY"
+ }
+ ]
+ }
+}
+
+[HW] [MPLANE] Received notification from RU "192.168.80.9" at (2025-03-29T12:40:23.452751936+00:00)
+{
+ "ietf-netconf-notifications:netconf-config-change": {
+ "changed-by": {
+ "username": "root",
+ "session-id": 0
+ },
+ "datastore": "running",
+ "edit": [
+ {
+ "target": "/ietf-interfaces:interfaces/interface[name='INTERFACE_0']",
+ "operation": "create"
+ },
+ {
+ "target": "/ietf-interfaces:interfaces/interface[name='INTERFACE_0']/name",
+ "operation": "create"
+ },
+...
+}
+
+[HW] [MPLANE] RU "192.168.80.9" is now ready.
+```
+
+
+
+Note: If you wish to run the fronthaul without M-plane, no need for recompilation, as the library `oran_fhlib_5g` already exists.
+The only mandatory step is to link `oran_fhlib_5g` to `oai_transpro` library.
+```bash
+cd ~/openairinterface5g/cmake_targets/ran_build/build
+rm liboai_transpro.so
+ln -s liboran_fhlib_5g.so liboai_transpro.so
+sudo ./nr-softmodem -O --thread-pool
+```
+
+
# Contact in case of questions
You can ask your question on the [mailing lists](https://gitlab.eurecom.fr/oai/openairinterface5g/-/wikis/MailingList).
diff --git a/doc/README.md b/doc/README.md
index 4786458a66..cee2620f95 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -118,6 +118,7 @@ Some directories under `radio` contain READMEs:
- [BladeRF](../radio/BLADERF/README)
- [IQPlayer](../radio/iqplayer/DOC/iqrecordplayer_usage.md), and [general documentation](./iqrecordplayer_usage.md)
- [fhi_72](../radio/fhi_72/README.md)
+- [vrtsim](../radio/vrtsim/README.md)
The other SDRs (AW2S, LimeSDR, ...) have no READMEs.
diff --git a/docker/Dockerfile.gNB.rhel9 b/docker/Dockerfile.gNB.rhel9
index 894d1f6aa7..824e3b3833 100644
--- a/docker/Dockerfile.gNB.rhel9
+++ b/docker/Dockerfile.gNB.rhel9
@@ -72,6 +72,7 @@ COPY --from=gnb-build \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_ci.so \
/oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \
+ /oai-ran/cmake_targets/ran_build/build/libvrtsim.so \
/usr/local/lib/
COPY --from=gnb-base \
diff --git a/docker/Dockerfile.gNB.rocky b/docker/Dockerfile.gNB.rocky
index 5c17c78e57..225432fdab 100644
--- a/docker/Dockerfile.gNB.rocky
+++ b/docker/Dockerfile.gNB.rocky
@@ -69,6 +69,7 @@ COPY --from=gnb-build \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_ci.so \
/oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \
+ /oai-ran/cmake_targets/ran_build/build/libvrtsim.so \
/usr/local/lib/
COPY --from=gnb-base \
diff --git a/docker/Dockerfile.gNB.ubuntu22 b/docker/Dockerfile.gNB.ubuntu22
index da2074c64b..68c903450a 100644
--- a/docker/Dockerfile.gNB.ubuntu22
+++ b/docker/Dockerfile.gNB.ubuntu22
@@ -110,6 +110,7 @@ COPY --from=gnb-build \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_5Gue.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_rrc.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_o1.so \
+ /oai-ran/cmake_targets/ran_build/build/libvrtsim.so \
/usr/local/lib/
# Now we are copying from builder-image the UHD files.
diff --git a/docker/Dockerfile.nrUE.rhel9 b/docker/Dockerfile.nrUE.rhel9
index 8ab486bd85..3a2900da27 100644
--- a/docker/Dockerfile.nrUE.rhel9
+++ b/docker/Dockerfile.nrUE.rhel9
@@ -75,6 +75,7 @@ COPY --from=nr-ue-build \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_5Gue.so \
/oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \
+ /oai-ran/cmake_targets/ran_build/build/libvrtsim.so \
/usr/local/lib/
COPY --from=nr-ue-base \
diff --git a/docker/Dockerfile.nrUE.rocky b/docker/Dockerfile.nrUE.rocky
index d0455527fa..7f112af53a 100644
--- a/docker/Dockerfile.nrUE.rocky
+++ b/docker/Dockerfile.nrUE.rocky
@@ -72,6 +72,7 @@ COPY --from=nr-ue-build \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_5Gue.so \
/oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \
+ /oai-ran/cmake_targets/ran_build/build/libvrtsim.so \
/usr/local/lib/
COPY --from=nr-ue-base \
diff --git a/docker/Dockerfile.nrUE.ubuntu22 b/docker/Dockerfile.nrUE.ubuntu22
index 45ad4bbe03..c3b6592753 100644
--- a/docker/Dockerfile.nrUE.ubuntu22
+++ b/docker/Dockerfile.nrUE.ubuntu22
@@ -110,6 +110,7 @@ COPY --from=nr-ue-build \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_ciUE.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_5Gue.so \
/oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \
+ /oai-ran/cmake_targets/ran_build/build/libvrtsim.so \
/usr/local/lib/
# Now we are copying from builder-image the UHD files.
diff --git a/executables/nr-ue.c b/executables/nr-ue.c
index d1b9ba648f..b8888708aa 100644
--- a/executables/nr-ue.c
+++ b/executables/nr-ue.c
@@ -872,18 +872,22 @@ static inline void apply_ntn_config(PHY_VARS_NR_UE *UE,
if (*update_ntn_system_information) {
*update_ntn_system_information = false;
- *duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX + UE->ntn_config_message->ntn_config_params.cell_specific_k_offset;
- UE->timing_advance = fp->samples_per_subframe * UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms;
- *timing_advance +=
- fp->get_samples_slot_timestamp(slot_nr,
- fp,
- UE->ntn_config_message->ntn_config_params.cell_specific_k_offset - *ntn_koffset);
- *ntn_koffset = UE->ntn_config_message->ntn_config_params.cell_specific_k_offset;
+ double total_ta_ms = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms;
+ UE->timing_advance = fp->samples_per_subframe * total_ta_ms;
+
+ int mu = fp->numerology_index;
+ int koffset = UE->ntn_config_message->ntn_config_params.cell_specific_k_offset;
+ if (*ntn_koffset != koffset) {
+ *duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX + (koffset << mu);
+ *timing_advance += fp->get_samples_slot_timestamp(slot_nr, fp, (koffset - *ntn_koffset) << mu);
+ *ntn_koffset = koffset;
+ }
LOG_I(PHY,
- "cell_specific_k_offset = %d ms, ntn_total_time_advance_ms = %f ms (%d samples)\n",
+ "k_offset = %d ms (%d slots), ntn_total_time_advance_ms = %f ms (%d samples)\n",
*ntn_koffset,
- UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms,
+ *ntn_koffset << mu,
+ total_ta_ms,
UE->timing_advance);
}
}
@@ -1080,7 +1084,7 @@ void *UE_thread(void *arg)
if (UE->ntn_config_message->update) {
UE->ntn_config_message->update = false;
update_ntn_system_information = true;
- nr_slot_tx_offset = UE->ntn_config_message->ntn_config_params.cell_specific_k_offset;
+ nr_slot_tx_offset = UE->ntn_config_message->ntn_config_params.cell_specific_k_offset << fp->numerology_index;
}
int slot_nr = absolute_slot % nb_slot_frame;
@@ -1214,7 +1218,7 @@ void init_NR_UE(int nb_inst, char *uecap_file, char *reconfig_file, char *rbconf
NR_UE_MAC_INST_t *mac = get_mac_inst(i);
mac->if_module = nr_ue_if_module_init(i);
AssertFatal(mac->if_module, "can not initialize IF module\n");
- if (!IS_SA_MODE(get_softmodem_params()) || !get_softmodem_params()->sl_mode) {
+ if (!IS_SA_MODE(get_softmodem_params()) && !get_softmodem_params()->sl_mode) {
init_nsa_message(&rrc_inst[i], reconfig_file, rbconfig_file);
nr_rlc_activate_srb0(mac_inst[i].crnti, NULL, send_srb0_rrc);
}
diff --git a/nfapi/oai_integration/aerial/fapi_vnf_p7.c b/nfapi/oai_integration/aerial/fapi_vnf_p7.c
index 263df7bd8a..cb8fa4550f 100644
--- a/nfapi/oai_integration/aerial/fapi_vnf_p7.c
+++ b/nfapi/oai_integration/aerial/fapi_vnf_p7.c
@@ -309,11 +309,8 @@ uint8_t aerial_unpack_nr_srs_indication(uint8_t **ppReadPackedMsg,
nfapi_nr_srs_indication_t *srs_ind = (nfapi_nr_srs_indication_t *)msg;
for (uint8_t pdu_idx = 0; pdu_idx < srs_ind->number_of_pdus; pdu_idx++) {
nfapi_nr_srs_indication_pdu_t *pdu = &srs_ind->pdu_list[pdu_idx];
- nfapi_srs_report_tlv_t *report_tlv = &pdu->report_tlv;
- for (int i = 0; i < (report_tlv->length + 3) / 4; i++) {
- if (!pull32(pDataMsg, &report_tlv->value[i], data_end)) {
- return 0;
- }
+ if (!unpack_nr_srs_report_tlv_value(&pdu->report_tlv, pDataMsg, data_end)) {
+ return 0;
}
}
return retval;
diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c
index 10d635562f..21b3e1e90e 100644
--- a/nfapi/oai_integration/nfapi_pnf.c
+++ b/nfapi/oai_integration/nfapi_pnf.c
@@ -54,7 +54,6 @@
#include "PHY/INIT/phy_init.h"
#include "PHY/INIT/nr_phy_init.h"
#include "PHY/LTE_TRANSPORT/transport_proto.h"
-#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
#include "openair1/SCHED_NR/fapi_nr_l1.h"
#include "openair1/PHY/NR_TRANSPORT/nr_dlsch.h"
#include "openair1/PHY/defs_gNB.h"
diff --git a/nfapi/open-nFAPI/common/public_inc/nfapi.h b/nfapi/open-nFAPI/common/public_inc/nfapi.h
index 99c7d7ec7e..2cb9cee996 100644
--- a/nfapi/open-nFAPI/common/public_inc/nfapi.h
+++ b/nfapi/open-nFAPI/common/public_inc/nfapi.h
@@ -36,6 +36,18 @@ uint8_t pull8(uint8_t **in, uint8_t *out, uint8_t *end);
uint8_t pulls8(uint8_t **in, int8_t *out, uint8_t *end);
uint8_t pull16(uint8_t **in, uint16_t *out, uint8_t *end);
uint8_t pulls16(uint8_t **in, int16_t *out, uint8_t *end);
+
+ /*! \brief Pull an arbitrary amount of bytes ( 0 to 4 ) into an uint32_t
+ * \param length the amount of bytes to pull
+ * \param in the buffer from where to pull the bytes
+ * \param out a pointer to the destination uint32_t
+ * \param end a pointer to the end of the buffer in
+ *
+ * This function is used to pull `length` amount of bytes from `in` into `out`.
+ * Used where pulling the full 32 bits would cause the `in` pointer to go over `end`.
+ * It's currently used to pull the last bytes of a payload where the buffer does not contain padding at the end.
+ */
+uint8_t pullx32(uint8_t length, uint8_t **in, uint32_t *out, uint8_t *end);
uint8_t pull32(uint8_t **in, uint32_t *out, uint8_t *end);
uint8_t pulls32(uint8_t **in, int32_t *out, uint8_t *end);
diff --git a/nfapi/open-nFAPI/common/src/nfapi.c b/nfapi/open-nFAPI/common/src/nfapi.c
index 97352b98f7..716387ae7d 100644
--- a/nfapi/open-nFAPI/common/src/nfapi.c
+++ b/nfapi/open-nFAPI/common/src/nfapi.c
@@ -259,6 +259,31 @@ uint8_t pulls16(uint8_t **in, int16_t *out, uint8_t *end)
}
}
+uint8_t pullx32(uint8_t length, uint8_t **in, uint32_t *out, uint8_t *end)
+{
+ uint8_t *pIn = *in;
+ if (length > 4) {
+ NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s Can't pull more than 4 bytes (%d) into a uint32_t\n", __FUNCTION__, length);
+ on_error();
+ return 0;
+ }
+ if ((end - pIn) >= length) {
+ for (int i = 0; i < length; i++) {
+#ifdef FAPI_BYTE_ORDERING_BIG_ENDIAN
+ *out |= ((uint32_t)pIn[i] << (8 * i));
+#else
+ *out = ((uint32_t)pIn[i] << (8 * (length - 1 - i)));
+#endif
+ }
+ (*in) += length;
+ return length;
+ } else {
+ NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+ on_error();
+ return 0;
+ }
+}
+
uint8_t pull32(uint8_t **in, uint32_t *out, uint8_t *end)
{
uint8_t *pIn = *in;
diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7.h
index 76e2043f2d..c2701acb5f 100644
--- a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7.h
+++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7.h
@@ -50,6 +50,7 @@ uint8_t pack_nr_uci_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e
uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config);
uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config);
uint8_t unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config);
+uint8_t unpack_nr_srs_report_tlv_value(nfapi_srs_report_tlv_t *report_tlv, uint8_t **ppReadPackedMsg, uint8_t *end);
uint8_t pack_nr_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config);
uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config);
#endif // OPENAIRINTERFACE_NR_FAPI_P7_H
diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c
index a247541315..7b840fc126 100644
--- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c
+++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c
@@ -2300,6 +2300,28 @@ uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e
return 1;
}
+uint8_t unpack_nr_srs_report_tlv_value(nfapi_srs_report_tlv_t *report_tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+#ifndef ENABLE_AERIAL
+ for (int i = 0; i < (report_tlv->length + 3) / 4; i++) {
+ if (!pull32(ppReadPackedMsg, &report_tlv->value[i], end)) {
+ return 0;
+ }
+ }
+#else
+ const uint16_t last_idx = ((report_tlv->length + 3) / 4) - 1;
+ for (int i = 0; i < last_idx; i++) {
+ if (!pull32(ppReadPackedMsg, &report_tlv->value[i], end)) {
+ return 0;
+ }
+ }
+ // Pull last bytes according to how much padding it would need to be 32-bit aligned
+ const uint8_t padding = get_tlv_padding(report_tlv->length);
+ pullx32(4 - padding, ppReadPackedMsg, &report_tlv->value[last_idx], end);
+#endif
+ return 1;
+}
+
static uint8_t unpack_nr_srs_report_tlv(nfapi_srs_report_tlv_t *report_tlv, uint8_t **ppReadPackedMsg, uint8_t *end) {
if(!(pull16(ppReadPackedMsg, &report_tlv->tag, end) &&
@@ -2307,10 +2329,8 @@ static uint8_t unpack_nr_srs_report_tlv(nfapi_srs_report_tlv_t *report_tlv, uint
return 0;
}
#ifndef ENABLE_AERIAL
- for (int i = 0; i < (report_tlv->length + 3) / 4; i++) {
- if (!pull32(ppReadPackedMsg, &report_tlv->value[i], end)) {
- return 0;
- }
+ if (!unpack_nr_srs_report_tlv_value(report_tlv, ppReadPackedMsg, end)) {
+ return 0;
}
#endif
return 1;
diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c
index c753cbcb1c..9939a6f535 100644
--- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c
+++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c
@@ -2684,6 +2684,18 @@ void dump_uci_indication(const nfapi_nr_uci_indication_t *msg)
}
}
+static void dump_srs_report_tlv(const nfapi_srs_report_tlv_t* tlv, int depth)
+{
+ depth++;
+ INDENTED_PRINTF("TAG = 0x%02x\n", tlv->tag);
+ INDENTED_PRINTF("LENGTH = 0x%02x\n", tlv->length);
+ INDENTED_PRINTF("VALUE = ");
+ for (int i = 0; i < ((tlv->length + 3) / 4); ++i) {
+ printf("0x%04x ", tlv->value[i]);
+ }
+ printf("\n");
+}
+
void dump_srs_indication(const nfapi_nr_srs_indication_t *msg)
{
int depth = 0;
@@ -2704,7 +2716,7 @@ void dump_srs_indication(const nfapi_nr_srs_indication_t *msg)
INDENTED_PRINTF("Timing advance offset in nanoseconds = 0x%02x\n", pdu->timing_advance_offset_nsec);
INDENTED_PRINTF("SRS usage = 0x%02x\n", pdu->srs_usage);
INDENTED_PRINTF("Report Type = 0x%02x\n", pdu->report_type);
- /* call to dump_srs_report_tlv */
+ dump_srs_report_tlv(&pdu->report_tlv, depth);
depth--;
}
}
diff --git a/nfapi/open-nFAPI/pnf/src/pnf.c b/nfapi/open-nFAPI/pnf/src/pnf.c
index 3880e53c6c..4cef8e6412 100644
--- a/nfapi/open-nFAPI/pnf/src/pnf.c
+++ b/nfapi/open-nFAPI/pnf/src/pnf.c
@@ -41,7 +41,6 @@
#include "NR_BCCH-BCH-Message.h"
#include "NR_ServingCellConfigCommon.h"
-#include "LAYER2/NR_MAC_gNB/mac_proto.h"
#include "SCHED_NR/phy_frame_config_nr.h"
#include "NR_MIB.h"
diff --git a/nfapi/tests/p7/nr_fapi_srs_indication_test.c b/nfapi/tests/p7/nr_fapi_srs_indication_test.c
index 49b73fd8f5..1271606b77 100644
--- a/nfapi/tests/p7/nr_fapi_srs_indication_test.c
+++ b/nfapi/tests/p7/nr_fapi_srs_indication_test.c
@@ -24,11 +24,14 @@
static void fil_srs_indication_report_tlv(nfapi_srs_report_tlv_t *tlv)
{
- tlv->tag = rand16_range(0,3);
- tlv->length = rand32_range(0,sizeof(tlv->value));
- for (int i = 0; i < (tlv->length + 3) / 4; ++i) {
+ tlv->tag = rand16_range(0, 3);
+ tlv->length = rand32_range(1, sizeof(tlv->value));
+ const uint16_t last_idx = ((tlv->length + 3) / 4) - 1;
+ for (int i = 0; i < last_idx; ++i) {
tlv->value[i] = rand32();
}
+ const uint8_t num_bytes = 4 - get_tlv_padding(tlv->length);
+ tlv->value[last_idx] = rand32_range(0, 1 << (8 * num_bytes));
}
static void fill_srs_indication_PDU(nfapi_nr_srs_indication_pdu_t *pdu)
diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
index e585c28d04..b6161e0e27 100644
--- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
+++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
@@ -575,8 +575,8 @@ c32_t nr_pbch_dmrs_correlation(const NR_DL_FRAME_PARMS *fp,
DEBUG_PBCH("PBCH DMRS Correlation : gNB_id %d , OFDM size %d, Ncp=%d, k=%u symbol %d\n",
proc->gNB_id,
- ue->frame_parms.ofdm_symbol_size,
- ue->frame_parms.Ncp,
+ fp->ofdm_symbol_size,
+ fp->Ncp,
k,
symbol);
@@ -590,8 +590,8 @@ c32_t nr_pbch_dmrs_correlation(const NR_DL_FRAME_PARMS *fp,
c16_t *pil = pilot;
const c16_t *rxF = &rxdataF[aarx][symbol_offset + k];
- DEBUG_PBCH("pbch ch est pilot RB_DL %d\n", ue->frame_parms.N_RB_DL);
- DEBUG_PBCH("k %u, first_carrier %d\n", k, ue->frame_parms.first_carrier_offset);
+ DEBUG_PBCH("pbch ch est pilot RB_DL %d\n", fp->N_RB_DL);
+ DEBUG_PBCH("k %u, first_carrier %d\n", k, fp->first_carrier_offset);
// Treat first 2 pilots specially (left edge)
computed_val = c32x16maddShift(*pil, rxF[re_offset], computed_val, 15);
@@ -769,7 +769,7 @@ int nr_pbch_channel_estimation(const NR_DL_FRAME_PARMS *fp,
multaddRealVectorComplexScalar(fr, ch, dl_ch, 16);
pil++;
re_offset = (re_offset + 4) % fp->ofdm_symbol_size;
- dl_ch += 24;
+ dl_ch += 12;
for (int pilot_cnt = 3; pilot_cnt < (3 * num_rbs); pilot_cnt += 3) {
// if (pilot_cnt == 30)
@@ -779,7 +779,7 @@ int nr_pbch_channel_estimation(const NR_DL_FRAME_PARMS *fp,
if (dmrss == 1 && pilot_cnt == 12) {
pilot_cnt=48;
re_offset = (re_offset + 144) % fp->ofdm_symbol_size;
- dl_ch += 288;
+ dl_ch += 144;
}
ch = c16mulShift(*pil, rxF[re_offset], 15);
DEBUG_PBCH("pilot %u: rxF= (%d,%d), ch= (%d,%d), pil=(%d,%d)\n",
diff --git a/openair1/SIMULATION/TOOLS/sim.h b/openair1/SIMULATION/TOOLS/sim.h
index d6b20a9eb9..34cae4ba55 100644
--- a/openair1/SIMULATION/TOOLS/sim.h
+++ b/openair1/SIMULATION/TOOLS/sim.h
@@ -50,6 +50,7 @@ typedef enum {
#define CHANMODEL_FREE_RSQRT_6 1<<1
#define CHANMODEL_FREE_RSQRT_NTAPS 1<<2
#define CHANMODEL_FREE_AMPS 1<<3
+#define SHR3 (jz = jsr, jsr ^= (jsr << 13), jsr ^= (jsr >> 17), jsr ^= (jsr << 5), jz + jsr)
typedef enum {
CORR_LEVEL_LOW,
diff --git a/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt b/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt
index 578bf489df..27497ae873 100644
--- a/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt
+++ b/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt
@@ -6,13 +6,14 @@ add_library(e2_ran_func_cuup STATIC
O-RAN/ran_func_kpm_subs.c
O-RAN/ran_func_rc.c
O-RAN/ran_func_rc_subs.c
+ ../flexric/src/sm/rc_sm/ie/rc_data_ie.c
CUSTOMIZED/ran_func_gtp.c # GTP SM not yet implemented in CU-UP
CUSTOMIZED/ran_func_pdcp.c
CUSTOMIZED/ran_func_tc.c # currently, not implemented; therefore, filling rnd data
../flexric/test/rnd/fill_rnd_data_tc.c
)
-target_link_libraries(e2_ran_func_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj sm_common_ie_obj ds)
+target_link_libraries(e2_ran_func_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj e2sm_rc_ir_obj sm_common_ie_obj ds alg)
target_compile_definitions(e2_ran_func_cuup PUBLIC ${E2AP_VERSION} ${KPM_VERSION} NGRAN_GNB_CUUP)
diff --git a/openair2/F1AP/f1ap_du_rrc_message_transfer.c b/openair2/F1AP/f1ap_du_rrc_message_transfer.c
index 7fd83ecd78..4b9b9e1947 100644
--- a/openair2/F1AP/f1ap_du_rrc_message_transfer.c
+++ b/openair2/F1AP/f1ap_du_rrc_message_transfer.c
@@ -49,7 +49,6 @@
#include "openair2/RRC/NR/rrc_gNB_UE_context.h"
#include "asn1_msg.h"
#include "intertask_interface.h"
-#include "LAYER2/NR_MAC_gNB/mac_proto.h"
#include "openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h"
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
index d30c51ecc1..49709543e6 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
@@ -30,7 +30,8 @@
*/
-#include "LAYER2/NR_MAC_gNB/mac_proto.h"
+#include "nr_mac.h"
+#include "nr_mac_common.h"
#include "common/utils/nr/nr_common.h"
#include
#include
@@ -2431,6 +2432,19 @@ uint8_t get_pusch_nb_antenna_ports(NR_PUSCH_Config_t *pusch_Config,
return n_antenna_port;
}
+static int binomial(int n, int k)
+{
+ if (k > n - k)
+ k = n - k;
+ int c = 1;
+ for (int i = 1; i <= k; i++, n--) {
+ if (c / i > UINT_MAX/n) // return 0 on overflow
+ return 0;
+ c = c / i * n + c % i * n / i;
+ }
+ return c;
+}
+
// #define DEBUG_SRS_RESOURCE_IND
uint8_t compute_srs_resource_indicator(long *maxMIMO_Layers,
NR_PUSCH_Config_t *pusch_Config,
@@ -3422,21 +3436,6 @@ uint8_t get_pusch_mcs_table(long *mcs_Table,
}
-int binomial(int n, int k) {
- int c = 1, i;
-
- if (k > n-k)
- k = n-k;
-
- for (i = 1; i <= k; i++, n--) {
- if (c/i > UINT_MAX/n) // return 0 on overflow
- return 0;
-
- c = c / i * n + c % i * n / i;
- }
- return c;
-}
-
/* extract PTRS values from RC and validate it based upon 38.214 5.1.6.3 */
bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config,
uint16_t rbSize,uint8_t mcsIndex, uint8_t mcsTable,
@@ -4357,127 +4356,132 @@ bool set_ul_ptrs_values(NR_PTRS_UplinkConfig_t *ul_ptrs_config,
}
//! Calculating number of bits set
-uint8_t number_of_bits_set(uint8_t buf) {
+static uint8_t number_of_bits_set(uint8_t buf)
+{
uint8_t nb_of_bits_set = 0;
uint8_t mask = 0xff;
- uint8_t index = 0;
-
- for (index=7; (buf & mask) && (index>=0) ; index--){
- if (buf & (1<= 0); index--) {
+ if (buf & (1 << index))
nb_of_bits_set++;
-
- mask>>=1;
+ mask >>= 1;
}
return nb_of_bits_set;
}
-void compute_rsrp_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig,
- uint8_t nb_resources,
- nr_csi_report_t *csi_report) {
-
+static void compute_rsrp_bitlen(const NR_CSI_ReportConfig_t *csi_reportconfig, uint8_t nb_resources, nr_csi_report_t *csi_report)
+{
if (NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled == csi_reportconfig->groupBasedBeamReporting.present) {
- if (NULL != csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS)
- csi_report->CSI_report_bitlen.nb_ssbri_cri = *(csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1;
+ if (csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS)
+ csi_report->CSI_report_bitlen.nb_ssbri_cri = *(csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS) + 1;
else
/*! From Spec 38.331
* nrofReportedRS
- * The number (N) of measured RS resources to be reported per report setting in a non-group-based report. N <= N_max, where N_max is either 2 or 4 depending on UE
+ * The number (N) of measured RS resources to be reported per report setting in a non-group-based report.
+ * N <= N_max, where N_max is either 2 or 4 depending on UE
* capability. FFS: The signaling mechanism for the gNB to select a subset of N beams for the UE to measure and report.
* When the field is absent the UE applies the value 1
*/
- csi_report->CSI_report_bitlen.nb_ssbri_cri= 1;
+ csi_report->CSI_report_bitlen.nb_ssbri_cri = 1;
} else
- csi_report->CSI_report_bitlen.nb_ssbri_cri= 2;
+ csi_report->CSI_report_bitlen.nb_ssbri_cri = 2;
if (nb_resources) {
csi_report->CSI_report_bitlen.cri_ssbri_bitlen =ceil(log2 (nb_resources));
- csi_report->CSI_report_bitlen.rsrp_bitlen = 7; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP
- csi_report->CSI_report_bitlen.diff_rsrp_bitlen =4; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP
+ csi_report->CSI_report_bitlen.rsrp_bitlen = 7; // From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP
+ csi_report->CSI_report_bitlen.diff_rsrp_bitlen = 4; // From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP
} else {
- csi_report->CSI_report_bitlen.cri_ssbri_bitlen =0;
+ csi_report->CSI_report_bitlen.cri_ssbri_bitlen = 0;
csi_report->CSI_report_bitlen.rsrp_bitlen = 0;
- csi_report->CSI_report_bitlen.diff_rsrp_bitlen =0;
+ csi_report->CSI_report_bitlen.diff_rsrp_bitlen = 0;
}
}
-uint8_t compute_ri_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig,
- nr_csi_report_t *csi_report)
+static uint8_t compute_ri_bitlen(const NR_CSI_ReportConfig_t *csi_reportconfig, nr_csi_report_t *csi_report)
{
-
struct NR_CodebookConfig *codebookConfig = csi_reportconfig->codebookConfig;
uint8_t nb_allowed_ri, ri_bitlen;
- uint8_t ri_restriction = 0;
if (codebookConfig == NULL) {
csi_report->csi_meas_bitlen.ri_bitlen = 0;
- return ri_restriction;
+ return 0;
}
+ struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel *type1single = NULL;
+ struct NR_CodebookConfig__codebookType__type1 *type1 = NULL;
+ if (codebookConfig->codebookType.present == NR_CodebookConfig__codebookType_PR_type1)
+ type1 = codebookConfig->codebookType.choice.type1;
+ else
+ LOG_E(NR_MAC, "Only type1 codebook configuration is supported\n");
+ if (type1 && type1->subType.present == NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel)
+ type1single = type1->subType.choice.typeI_SinglePanel;
+ else
+ LOG_E(NR_MAC, "Only type1 single panel codebook configuration is supported\n");
+
+ if (!type1single)
+ return -1;
+
+ uint8_t ri_restriction = type1single->typeI_SinglePanel_ri_Restriction.buf[0];
+
// codebook type1 single panel
- if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel == codebookConfig->codebookType.choice.type1->subType.present) {
- struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel *type1single = codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel;
- if (type1single->nrOfAntennaPorts.present == NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_two) {
-
- ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0];
-
+ if (type1single->nrOfAntennaPorts.present == NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_two) {
+ nb_allowed_ri = number_of_bits_set(ri_restriction);
+ ri_bitlen = ceil(log2(nb_allowed_ri));
+ // from the spec 38.212 and table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel
+ ri_bitlen = ri_bitlen < 1 ? ri_bitlen : 1;
+ csi_report->csi_meas_bitlen.ri_bitlen = ri_bitlen;
+ }
+ if (type1single->nrOfAntennaPorts.present == NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_moreThanTwo) {
+ if (type1single->nrOfAntennaPorts.choice.moreThanTwo->n1_n2.present ==
+ NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_two_one_TypeI_SinglePanel_Restriction) {
+ // 4 ports
nb_allowed_ri = number_of_bits_set(ri_restriction);
ri_bitlen = ceil(log2(nb_allowed_ri));
-
- ri_bitlen = ri_bitlen < 1 ? ri_bitlen : 1; //from the spec 38.212 and table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel
+ // from the spec 38.212 and table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel
+ ri_bitlen = ri_bitlen < 2 ? ri_bitlen : 2;
csi_report->csi_meas_bitlen.ri_bitlen = ri_bitlen;
}
- if (type1single->nrOfAntennaPorts.present == NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_moreThanTwo){
- if (type1single->nrOfAntennaPorts.choice.moreThanTwo->n1_n2.present ==
- NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_two_one_TypeI_SinglePanel_Restriction) {
- // 4 ports
-
- ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0];
-
- nb_allowed_ri = number_of_bits_set(ri_restriction);
- ri_bitlen = ceil(log2(nb_allowed_ri));
-
- ri_bitlen = ri_bitlen < 2 ? ri_bitlen : 2; //from the spec 38.212 and table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel
- csi_report->csi_meas_bitlen.ri_bitlen = ri_bitlen;
- }
- else {
- // more than 4 ports
-
- ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0];
-
- nb_allowed_ri = number_of_bits_set(ri_restriction);
- ri_bitlen = ceil(log2(nb_allowed_ri));
-
- csi_report->csi_meas_bitlen.ri_bitlen = ri_bitlen;
- }
- }
- return ri_restriction;
- }
- else
- AssertFatal(1==0,"Other configurations not yet implemented\n");
- return -1;
-}
-
-void compute_li_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig,
- uint8_t ri_restriction,
- nr_csi_report_t *csi_report) {
-
- struct NR_CodebookConfig *codebookConfig = csi_reportconfig->codebookConfig;
- for(int i=0; i<8; i++) {
- if (codebookConfig == NULL || ((ri_restriction>>i)&0x01) == 0)
- csi_report->csi_meas_bitlen.li_bitlen[i]=0;
else {
- // codebook type1 single panel
- if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel==codebookConfig->codebookType.choice.type1->subType.present)
- csi_report->csi_meas_bitlen.li_bitlen[i]=ceil(log2(i+1))<2?ceil(log2(i+1)):2;
+ // more than 4 ports
+ nb_allowed_ri = number_of_bits_set(ri_restriction);
+ ri_bitlen = ceil(log2(nb_allowed_ri));
+ csi_report->csi_meas_bitlen.ri_bitlen = ri_bitlen;
+ }
+ }
+ return ri_restriction;
+}
+
+static void compute_li_bitlen(const NR_CSI_ReportConfig_t *csi_reportconfig, uint8_t ri_restriction, nr_csi_report_t *csi_report)
+{
+ struct NR_CodebookConfig *codebookConfig = csi_reportconfig->codebookConfig;
+ for(int i = 0; i < 8; i++) {
+ if (codebookConfig == NULL || ((ri_restriction >> i) & 0x01) == 0)
+ csi_report->csi_meas_bitlen.li_bitlen[i] = 0;
+ else {
+ struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel *type1single = NULL;
+ struct NR_CodebookConfig__codebookType__type1 *type1 = NULL;
+ if (codebookConfig && codebookConfig->codebookType.present == NR_CodebookConfig__codebookType_PR_type1)
+ type1 = codebookConfig->codebookType.choice.type1;
else
- AssertFatal(1==0,"Other configurations not yet implemented\n");
+ LOG_E(NR_MAC, "Only type1 codebook configuration is supported\n");
+ if (type1 && type1->subType.present == NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel)
+ type1single = type1->subType.choice.typeI_SinglePanel;
+ else
+ LOG_E(NR_MAC, "Only type1 single panel codebook configuration is supported\n");
+ // codebook type1 single panel
+ if (type1single)
+ csi_report->csi_meas_bitlen.li_bitlen[i] = ceil(log2(i + 1)) < 2 ? ceil(log2(i + 1)) : 2;
+ else
+ csi_report->csi_meas_bitlen.li_bitlen[i] = 0;
}
}
}
-void get_n1n2_o1o2_singlepanel(int *n1, int *n2, int *o1, int *o2,
- struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo *morethantwo) {
-
+static void get_n1n2_o1o2_singlepanel(int *n1,
+ int *n2,
+ int *o1,
+ int *o2,
+ const struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo *morethantwo)
+{
// Table 5.2.2.2.1-2 in 38.214 for supported configurations
switch(morethantwo->n1_n2.present){
case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_two_one_TypeI_SinglePanel_Restriction):
@@ -4559,7 +4563,7 @@ void get_n1n2_o1o2_singlepanel(int *n1, int *n2, int *o1, int *o2,
*o2 = 1;
break;
default:
- AssertFatal(1==0,"Not supported configuration for n1_n2 in codebook configuration");
+ AssertFatal(false, "Not supported configuration for n1_n2 in codebook configuration");
}
}
@@ -4691,15 +4695,13 @@ static void set_bitlen_size_singlepanel(CSI_Meas_bitlen_t *csi_bitlen, int n1, i
}
break;
default:
- AssertFatal(1==0,"Invalid rank in x1 x2 bit length computation\n");
+ AssertFatal(false, "Invalid rank in x1 x2 bit length computation\n");
}
csi_bitlen->pmi_x1_bitlen[i] = csi_bitlen->pmi_i11_bitlen[i] + csi_bitlen->pmi_i12_bitlen[i] + csi_bitlen->pmi_i13_bitlen[i];
}
-void compute_pmi_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig,
- uint8_t ri_restriction,
- nr_csi_report_t *csi_report)
+static void compute_pmi_bitlen(const NR_CSI_ReportConfig_t *csi_reportconfig, uint8_t ri_restriction, nr_csi_report_t *csi_report)
{
NR_CodebookConfig_t *codebookConfig = csi_reportconfig->codebookConfig;
for(int i = 0; i < 8; i++) {
@@ -4731,45 +4733,51 @@ void compute_pmi_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig,
}
}
else
- AssertFatal(1==0,"Type1 Multi-panel Codebook Config not yet implemented\n");
+ AssertFatal(false, "Type1 Multi-panel Codebook Config not yet implemented\n");
}
else
- AssertFatal(1==0,"Type2 Codebook Config not yet implemented\n");
+ AssertFatal(false, "Type2 Codebook Config not yet implemented\n");
}
}
}
-void compute_cqi_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig,
- uint8_t ri_restriction,
- nr_csi_report_t *csi_report) {
+static void compute_cqi_bitlen(const NR_CSI_ReportConfig_t *csi_reportconfig, uint8_t ri_restriction, nr_csi_report_t *csi_report)
+{
+ NR_CodebookConfig_t *codebookConfig = csi_reportconfig->codebookConfig;
+ struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel *type1single = NULL;
+ struct NR_CodebookConfig__codebookType__type1 *type1 = NULL;
+ if (codebookConfig && codebookConfig->codebookType.present == NR_CodebookConfig__codebookType_PR_type1)
+ type1 = codebookConfig->codebookType.choice.type1;
+ else
+ LOG_E(NR_MAC, "Only type1 codebook configuration is supported\n");
+ if (type1 && type1->subType.present == NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel)
+ type1single = type1->subType.choice.typeI_SinglePanel;
+ else
+ LOG_E(NR_MAC, "Only type1 single panel codebook configuration is supported\n");
- struct NR_CodebookConfig *codebookConfig = csi_reportconfig->codebookConfig;
struct NR_CSI_ReportConfig__reportFreqConfiguration *freq_config = csi_reportconfig->reportFreqConfiguration;
+ if (!freq_config
+ || *freq_config->cqi_FormatIndicator != NR_CSI_ReportConfig__reportFreqConfiguration__cqi_FormatIndicator_widebandCQI) {
+ LOG_E(NR_MAC, "Only wide-band CQI reporting is supported\n");
+ return;
+ }
- if (*freq_config->cqi_FormatIndicator == NR_CSI_ReportConfig__reportFreqConfiguration__cqi_FormatIndicator_widebandCQI) {
- for(int i=0; i<8; i++) {
- if ((ri_restriction>>i)&0x01) {
- csi_report->csi_meas_bitlen.cqi_bitlen[i] = 4;
- if(codebookConfig != NULL) {
- if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel == codebookConfig->codebookType.choice.type1->subType.present){
- struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel *type1single = codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel;
- if (type1single->nrOfAntennaPorts.present == NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_moreThanTwo) {
- if (type1single->nrOfAntennaPorts.choice.moreThanTwo->n1_n2.present >
- NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_two_one_TypeI_SinglePanel_Restriction) {
- // more than 4 antenna ports
- if (i > 4)
- csi_report->csi_meas_bitlen.cqi_bitlen[i] += 4; // CQI for second TB
- }
- }
- }
+ for(int i = 0; i < 8; i++) {
+ if ((ri_restriction >> i) & 0x01) {
+ csi_report->csi_meas_bitlen.cqi_bitlen[i] = 4;
+ if (!type1single)
+ continue;
+ if (type1single->nrOfAntennaPorts.present == NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_moreThanTwo) {
+ if (type1single->nrOfAntennaPorts.choice.moreThanTwo->n1_n2.present >
+ NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_two_one_TypeI_SinglePanel_Restriction) {
+ // more than 4 antenna ports
+ if (i > 4)
+ csi_report->csi_meas_bitlen.cqi_bitlen[i] += 4; // CQI for second TB
}
}
- else
- csi_report->csi_meas_bitlen.cqi_bitlen[i] = 0;
- }
+ } else
+ csi_report->csi_meas_bitlen.cqi_bitlen[i] = 0;
}
- else
- AssertFatal(1==0,"Sub-band CQI reporting not yet supported");
}
//!TODO : same function can be written to handle csi_resources
@@ -4779,12 +4787,16 @@ void compute_csi_bitlen(const NR_CSI_MeasConfig_t *csi_MeasConfig, nr_csi_report
uint8_t nb_resources = 0;
NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type;
NR_CSI_ResourceConfigId_t csi_ResourceConfigId;
- struct NR_CSI_ResourceConfig *csi_resourceconfig;
+ NR_CSI_ResourceConfig_t *csi_resourceconfig;
+ if (!csi_MeasConfig->csi_ReportConfigToAddModList) {
+ LOG_E(NR_MAC, "csi_ReportConfigToAddModList is NULL, not expected\n");
+ return;
+ }
// for each CSI measurement report configuration (list of CSI-ReportConfig)
LOG_D(NR_MAC,"Searching %d csi_reports\n",csi_MeasConfig->csi_ReportConfigToAddModList->list.count);
for (csi_report_id = 0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++) {
- struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
+ NR_CSI_ReportConfig_t *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
// MAC structure for CSI measurement reports (per UE and per report)
nr_csi_report_t *csi_report = &csi_report_template[csi_report_id];
// csi-ResourceConfigId of a CSI-ResourceConfig included in the configuration
@@ -4848,18 +4860,18 @@ void compute_csi_bitlen(const NR_CSI_MeasConfig_t *csi_MeasConfig, nr_csi_report
compute_rsrp_bitlen(csi_reportconfig, nb_resources, csi_report);
break;
case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI):
- csi_report->csi_meas_bitlen.cri_bitlen=ceil(log2(nb_resources));
+ csi_report->csi_meas_bitlen.cri_bitlen = ceil(log2(nb_resources));
csi_report->csi_meas_bitlen.ri_restriction = compute_ri_bitlen(csi_reportconfig, csi_report);
compute_cqi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
break;
case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI):
- csi_report->csi_meas_bitlen.cri_bitlen=ceil(log2(nb_resources));
+ csi_report->csi_meas_bitlen.cri_bitlen = ceil(log2(nb_resources));
csi_report->csi_meas_bitlen.ri_restriction = compute_ri_bitlen(csi_reportconfig, csi_report);
compute_cqi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
compute_pmi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
break;
case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI):
- csi_report->csi_meas_bitlen.cri_bitlen=ceil(log2(nb_resources));
+ csi_report->csi_meas_bitlen.cri_bitlen = ceil(log2(nb_resources));
csi_report->csi_meas_bitlen.ri_restriction = compute_ri_bitlen(csi_reportconfig, csi_report);
compute_li_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
compute_cqi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
index b8d1fae38c..487e81ac40 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
@@ -290,33 +290,6 @@ bool set_ul_ptrs_values(NR_PTRS_UplinkConfig_t *ul_ptrs_config,
@returns transformPrecoding value */
long get_transformPrecoding(const NR_UE_UL_BWP_t *current_UL_BWP, nr_dci_format_t dci_format, uint8_t configuredGrant);
-uint8_t number_of_bits_set(uint8_t buf);
-
-void compute_rsrp_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig,
- uint8_t nb_resources,
- nr_csi_report_t *csi_report);
-
-uint8_t compute_ri_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig,
- nr_csi_report_t *csi_report);
-
-void compute_li_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig,
- uint8_t ri_restriction,
- nr_csi_report_t *csi_report);
-
-void get_n1n2_o1o2_singlepanel(int *n1, int *n2, int *o1, int *o2,
- struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo *morethantwo);
-
-void get_x1x2_bitlen_singlepanel(int n1, int n2, int o1, int o2,
- int *x1, int *x2, int rank, int codebook_mode);
-
-void compute_pmi_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig,
- uint8_t ri_restriction,
- nr_csi_report_t *csi_report);
-
-void compute_cqi_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig,
- uint8_t ri_restriction,
- nr_csi_report_t *csi_report);
-
void compute_csi_bitlen(const NR_CSI_MeasConfig_t *csi_MeasConfig, nr_csi_report_t *csi_report_template);
uint16_t nr_get_csi_bitlen(nr_csi_report_t *csi_report);
diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c
index 1f0e552ba0..1b5518f0bc 100644
--- a/openair2/LAYER2/NR_MAC_UE/config_ue.c
+++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c
@@ -34,7 +34,6 @@
#define SPEED_OF_LIGHT 299792458
#include "mac_defs.h"
-#include
#include "NR_MAC_UE/mac_proto.h"
#include "NR_MAC-CellGroupConfig.h"
#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h"
@@ -306,6 +305,13 @@ void configure_ntn_ta(module_id_t module_id, ntn_timing_advance_componets_t *ntn
ntn_ta->ntn_ta_commondrift = *ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17 * 0.2e-3;
}
ntn_ta->ntn_params_changed = true;
+
+ LOG_D(NR_MAC,
+ "SIB19 Rxd. k_offset:%ld, N_Common_Ta:%f,drift:%f,N_UE_TA:%f \n",
+ ntn_ta->cell_specific_k_offset,
+ ntn_ta->N_common_ta_adj,
+ ntn_ta->ntn_ta_commondrift,
+ ntn_ta->N_UE_TA_adj);
}
static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t *scc, int cc_idP)
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
index cfa3952759..838d1989f0 100644
--- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h
+++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
@@ -649,9 +649,9 @@ static inline double GET_COMPLETE_TIME_ADVANCE_MS(const ntn_timing_advance_compo
return ntn_ta->N_common_ta_adj + ntn_ta->N_UE_TA_adj;
}
-static inline long GET_DURATION_RX_TO_TX(const ntn_timing_advance_componets_t *ntn_ta)
+static inline long GET_DURATION_RX_TO_TX(const ntn_timing_advance_componets_t *ntn_ta, int scs)
{
- return NR_UE_CAPABILITY_SLOT_RX_TO_TX + ntn_ta->cell_specific_k_offset;
+ return NR_UE_CAPABILITY_SLOT_RX_TO_TX + (ntn_ta->cell_specific_k_offset << scs);
}
/*@}*/
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c
index 3817e06759..9ebf2dbeb4 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c
@@ -415,6 +415,8 @@ void get_monitoring_period_offset(const NR_SearchSpace_t *ss, int *period, int *
bool is_ss_monitor_occasion(const int frame, const int slot, const int slots_per_frame, const NR_SearchSpace_t *ss)
{
+ if (!ss)
+ return false;
const int duration = ss->duration ? *ss->duration : 1;
bool monitor = false;
int period, offset;
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
index 83bbcadbe5..c0cda918d1 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
@@ -927,10 +927,10 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
const uint16_t feedback_ti = 1 + dci->pdsch_to_harq_feedback_timing_indicator.val + ntn_ue_koffset;
if (rnti_type != TYPE_RA_RNTI_ && rnti_type != TYPE_SI_RNTI_) {
- AssertFatal(feedback_ti > GET_DURATION_RX_TO_TX(&mac->ntn_ta),
+ AssertFatal(feedback_ti > GET_DURATION_RX_TO_TX(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing),
"PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%ld).\n",
feedback_ti,
- GET_DURATION_RX_TO_TX(&mac->ntn_ta));
+ GET_DURATION_RX_TO_TX(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing));
// set the harq status at MAC for feedback
const int tpc[] = {-1, 0, 1, 3};
set_harq_status(mac,
@@ -1220,11 +1220,11 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing);
const uint16_t feedback_ti = pucch_Config->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0] + ntn_ue_koffset;
- AssertFatal(feedback_ti > GET_DURATION_RX_TO_TX(&mac->ntn_ta),
+ AssertFatal(feedback_ti > GET_DURATION_RX_TO_TX(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing),
"PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%ld). Min feedback time set in config "
"file (min_rxtxtime).\n",
feedback_ti,
- GET_DURATION_RX_TO_TX(&mac->ntn_ta));
+ GET_DURATION_RX_TO_TX(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing));
// set the harq status at MAC for feedback
const int tpc[] = {-1, 0, 1, 3};
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
index edd3bc1db7..3c18360d21 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
@@ -1037,9 +1037,11 @@ void nr_ue_aperiodic_srs_scheduling(NR_UE_MAC_INST_t *mac, long resource_trigger
return;
}
- AssertFatal(slot_offset > GET_DURATION_RX_TO_TX(&mac->ntn_ta),
+ int scs = mac->current_UL_BWP->scs;
+ AssertFatal(slot_offset > GET_DURATION_RX_TO_TX(&mac->ntn_ta, scs),
"Slot offset between DCI and aperiodic SRS (%d) needs to be higher than DURATION_RX_TO_TX (%ld)\n",
- slot_offset, GET_DURATION_RX_TO_TX(&mac->ntn_ta));
+ slot_offset,
+ GET_DURATION_RX_TO_TX(&mac->ntn_ta, scs));
int n_slots_frame = mac->frame_structure.numb_slots_frame;
int sched_slot = (slot + slot_offset) % n_slots_frame;
if (!is_ul_slot(sched_slot, &mac->frame_structure)) {
@@ -1563,23 +1565,24 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac,
AssertFatal(1 == 0, "Invalid numerology %i\n", mu);
}
- AssertFatal((k2 + delta) > GET_DURATION_RX_TO_TX(&mac->ntn_ta),
- "Slot offset (%ld) for Msg3 needs to be higher than DURATION_RX_TO_TX (%ld). Please set min_rxtxtime at least to %ld in gNB config file or gNBs.[0].min_rxtxtime=%ld via command line.\n",
+ AssertFatal((k2 + delta) > GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu),
+ "Slot offset (%ld) for Msg3 needs to be higher than DURATION_RX_TO_TX (%ld). Please set min_rxtxtime at least to "
+ "%ld in gNB config file or gNBs.[0].min_rxtxtime=%ld via command line.\n",
k2,
- GET_DURATION_RX_TO_TX(&mac->ntn_ta),
- GET_DURATION_RX_TO_TX(&mac->ntn_ta),
- GET_DURATION_RX_TO_TX(&mac->ntn_ta));
+ GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu),
+ GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu),
+ GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu));
*slot_tx = (current_slot + k2 + delta) % slots_per_frame;
*frame_tx = (current_frame + (current_slot + k2 + delta) / slots_per_frame) % MAX_FRAME_NUMBER;
} else {
-
- AssertFatal(k2 > GET_DURATION_RX_TO_TX(&mac->ntn_ta),
- "Slot offset K2 (%ld) needs to be higher than DURATION_RX_TO_TX (%ld). Please set min_rxtxtime at least to %ld in gNB config file or gNBs.[0].min_rxtxtime=%ld via command line.\n",
+ AssertFatal(k2 > GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu),
+ "Slot offset K2 (%ld) needs to be higher than DURATION_RX_TO_TX (%ld). Please set min_rxtxtime at least to %ld in "
+ "gNB config file or gNBs.[0].min_rxtxtime=%ld via command line.\n",
k2,
- GET_DURATION_RX_TO_TX(&mac->ntn_ta),
- GET_DURATION_RX_TO_TX(&mac->ntn_ta),
- GET_DURATION_RX_TO_TX(&mac->ntn_ta));
+ GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu),
+ GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu),
+ GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu));
if (k2 < 0) { // This can happen when a false DCI is received
LOG_W(PHY, "%d.%d. Received k2 %ld\n", current_frame, current_slot, k2);
@@ -2203,7 +2206,7 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t
add_slots++;
}
nr_timer_setup(&ra->response_window_timer,
- ra->response_window_setup_time + add_slots + GET_DURATION_RX_TO_TX(&mac->ntn_ta),
+ ra->response_window_setup_time + add_slots + GET_DURATION_RX_TO_TX(&mac->ntn_ta, mac->current_DL_BWP->scs),
1);
nr_timer_start(&ra->response_window_timer);
} else if (ra->ra_type == RA_2_STEP) {
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
index 0092c388b6..39aae6db49 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
@@ -1032,9 +1032,9 @@ void nr_schedule_ue_spec(module_id_t module_id,
harq->round,
nr_get_rv(harq->round % 4),
harq->ndi,
- pucch->timing_indicator,
- pucch->frame,
- pucch->ul_slot,
+ pucch ? pucch->timing_indicator : 0,
+ pucch ? pucch->frame : 0,
+ pucch ? pucch->ul_slot : 0,
sched_pdsch->pucch_allocation,
sched_ctrl->tpc1);
@@ -1222,7 +1222,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
dci_payload.ndi,
dci_payload.rv,
dci_payload.tpc,
- pucch->timing_indicator);
+ pucch ? pucch->timing_indicator : 0);
const int rnti_type = TYPE_C_RNTI_;
fill_dci_pdu_rel15(&UE->sc_info,
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
index 1845335e73..7cad2d883d 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
@@ -650,6 +650,11 @@ static void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
// verify if report with current id has been scheduled for this frame and slot
if ((n_slots_frame*frame + slot - offset)%period == 0) {
reportQuantity_type = csi_report->reportQuantity_type;
+ // phy-test has hardcoded allocation, so no use to handle CSI reports except RSRP
+ if (get_softmodem_params()->phy_test
+ && reportQuantity_type != NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP
+ && reportQuantity_type != NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP)
+ continue;
LOG_D(MAC,"SFN/SF:%d/%d reportQuantity type = %d\n",frame,slot,reportQuantity_type);
switch(reportQuantity_type) {
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP:
@@ -869,8 +874,7 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, frame_t frame, slot_t slot, c
}
free(uci_234->harq.harq_payload);
}
- /* phy-test has hardcoded allocation, so no use to handle CSI reports */
- if ((uci_234->pduBitmap >> 2) & 0x01 && !get_softmodem_params()->phy_test) {
+ if ((uci_234->pduBitmap >> 2) & 0x01) {
LOG_D(NR_MAC, "CSI CRC %d\n", uci_234->csi_part1.csi_part1_crc);
if (uci_234->csi_part1.csi_part1_crc != 1) {
// API to parse the csi report and store it into sched_ctrl
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
index 4ce1f1126c..65c5aba9f1 100644
--- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
@@ -337,8 +337,6 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP,
unsigned char drx_cmd,
unsigned char *ue_cont_res_id);
-int binomial(int n, int k);
-
/* \brief Function to indicate a received SDU on ULSCH.
@param Mod_id Instance ID of gNB
@param CC_id Component carrier index
diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c
index 796ef4a3e1..e39dd3581f 100644
--- a/openair2/RRC/NR/nr_rrc_config.c
+++ b/openair2/RRC/NR/nr_rrc_config.c
@@ -2460,17 +2460,6 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc,
asn1cSeqAdd(&sib1->si_SchedulingInfo->schedulingInfoList.list,schedulingInfo);*/
- const NR_FreqBandIndicatorNR_t band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
- if (is_ntn_band(band)) {
- sib1->nonCriticalExtension = CALLOC(1, sizeof(struct NR_SIB1_v1610_IEs));
- sib1->nonCriticalExtension->nonCriticalExtension = CALLOC(1, sizeof(struct NR_SIB1_v1630_IEs));
- sib1->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension = CALLOC(1, sizeof(struct NR_SIB1_v1700_IEs));
- // If cell provides NTN access, set cellBarredNTN to notBarred.
- struct NR_SIB1_v1700_IEs *sib1_v1700 = sib1->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension;
- sib1_v1700->cellBarredNTN_r17 = CALLOC(1, sizeof(long));
- *sib1_v1700->cellBarredNTN_r17 = NR_SIB1_v1700_IEs__cellBarredNTN_r17_notBarred;
- }
-
// servingCellConfigCommon
asn1cCalloc(sib1->servingCellConfigCommon, ServCellCom);
NR_BWP_DownlinkCommon_t *initialDownlinkBWP = &ServCellCom->downlinkConfigCommon.initialDownlinkBWP;
@@ -2485,6 +2474,7 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc,
frequencyInfoDL->frequencyBandList.list.array[i];
}
+ const NR_FreqBandIndicatorNR_t band = *frequencyInfoDL->frequencyBandList.list.array[0];
frequency_range_t frequency_range = get_freq_range_from_band(band);
sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.offsetToPointA = get_ssb_offset_to_pointA(*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB,
scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA,
@@ -2712,6 +2702,12 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc,
asn1cSeqAdd(&si_schedulinginfo2_r17->sib_MappingInfo_r17.list, sib_type_info);
asn1cSeqAdd(&sib_v17_scheduling_info->schedulingInfoList2_r17.list, si_schedulinginfo2_r17);
sib1_1700->si_SchedulingInfo_v1700 = sib_v17_scheduling_info;
+
+ if (is_ntn_band(band)) {
+ // If cell provides NTN access, set cellBarredNTN to notBarred.
+ sib1_1700->cellBarredNTN_r17 = CALLOC(1, sizeof(long));
+ *sib1_1700->cellBarredNTN_r17 = NR_SIB1_v1700_IEs__cellBarredNTN_r17_notBarred;
+ }
}
}
diff --git a/radio/CMakeLists.txt b/radio/CMakeLists.txt
index fb9086e2eb..654fb037f0 100644
--- a/radio/CMakeLists.txt
+++ b/radio/CMakeLists.txt
@@ -37,3 +37,8 @@ add_boolean_option(OAI_USRP OFF "Activate OAI's USRP driver" OFF)
if(OAI_USRP)
add_subdirectory(USRP)
endif()
+
+add_boolean_option(VRTSIM_RADIO ON "Activate OAI's shared memory radio driver" OFF)
+if(VRTSIM_RADIO)
+ add_subdirectory(vrtsim)
+endif()
diff --git a/radio/fhi_72/CMakeLists.txt b/radio/fhi_72/CMakeLists.txt
index 3fab4f5d47..8b047a9316 100644
--- a/radio/fhi_72/CMakeLists.txt
+++ b/radio/fhi_72/CMakeLists.txt
@@ -30,18 +30,19 @@ endif()
add_compile_options(-Wno-packed-not-aligned)
set_target_properties(oran_fhlib_5g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -march=native")
-target_link_libraries(oran_fhlib_5g PRIVATE xran::xran)
-target_link_libraries(oran_fhlib_5g PRIVATE ${dpdk_LINK_LIBRARIES})
+target_link_libraries(oran_fhlib_5g PRIVATE xran::xran ${dpdk_LINK_LIBRARIES} ${T_LIB} pthread dl rt m numa)
target_include_directories(oran_fhlib_5g PRIVATE ${dpdk_INCLUDE_DIRS})
-target_link_libraries(oran_fhlib_5g PRIVATE pthread dl rt m numa)
-target_link_libraries(oran_fhlib_5g PRIVATE ${T_LIB})
-
-# TODO: can be removed?
-target_include_directories(oran_fhlib_5g PRIVATE ${xran_INCLUDE_DIRS}/../src/)
add_boolean_option(OAI_FHI72_USE_POLLING OFF "Enable polling in FHI72 driver" ON)
+message(STATUS "Building FHI72 CUS library")
+
set_target_properties(oran_fhlib_5g PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
add_custom_command(TARGET oran_fhlib_5g POST_BUILD
COMMAND ${CMAKE_COMMAND} -E create_symlink liboran_fhlib_5g.so liboai_transpro.so
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
+
+add_boolean_option(OAI_FHI72_MPLANE OFF "Activate OAI's FHI 7.2 M-plane support" OFF)
+if(OAI_FHI72_MPLANE)
+ add_subdirectory(mplane)
+endif()
diff --git a/radio/fhi_72/mplane/CMakeLists.txt b/radio/fhi_72/mplane/CMakeLists.txt
new file mode 100644
index 0000000000..a6bd7e62d7
--- /dev/null
+++ b/radio/fhi_72/mplane/CMakeLists.txt
@@ -0,0 +1,73 @@
+add_library(oran_fhlib_5g_mplane MODULE
+ ../oran_isolate.c
+ ../oaioran.c
+ ../oran-config.c
+ ../oran-init.c
+)
+add_dependencies(oran_fhlib_5g_mplane oran_fhlib_5g)
+
+if(xran_VERSION VERSION_EQUAL 5.1.4)
+ target_compile_definitions(oran_fhlib_5g_mplane PRIVATE E_RELEASE)
+elseif(xran_VERSION VERSION_EQUAL 6.1.1)
+ target_compile_definitions(oran_fhlib_5g_mplane PRIVATE F_RELEASE)
+endif()
+
+# Ignore xran-specific warning: we don't care/can't change the following warning, so suppress
+# alignment 1 of 'struct XYZ' is less than 2
+add_compile_options(-Wno-packed-not-aligned)
+
+set_target_properties(oran_fhlib_5g_mplane PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -march=native")
+target_link_libraries(oran_fhlib_5g_mplane PRIVATE xran::xran ${dpdk_LINK_LIBRARIES} ${T_LIB} pthread dl rt m numa)
+target_include_directories(oran_fhlib_5g_mplane PRIVATE ${dpdk_INCLUDE_DIRS})
+
+target_compile_definitions(oran_fhlib_5g_mplane PRIVATE OAI_MPLANE)
+
+###################################################
+
+target_sources(oran_fhlib_5g_mplane PRIVATE
+ init-mplane.c
+ connect-mplane.c
+ rpc-send-recv.c
+ get-mplane.c
+ subscribe-mplane.c
+ config-mplane.c
+ ru-mplane-api.c
+ xml/get-xml.c
+ yang/get-yang.c
+ yang/create-yang-config.c
+)
+
+pkg_check_modules(libyang REQUIRED libyang)
+pkg_check_modules(libnetconf2 REQUIRED libnetconf2)
+
+if(libyang_VERSION VERSION_LESS_EQUAL 1.0.240 AND libnetconf2_VERSION VERSION_LESS_EQUAL 1.1.46)
+ target_compile_definitions(oran_fhlib_5g_mplane PRIVATE MPLANE_V1)
+elseif((libyang_VERSION VERSION_GREATER 1.0.240 AND libyang_VERSION VERSION_LESS 2.1.4))
+ message(FATAL_ERROR "Minimum libyang v2 subversion required is v2.1.4, but found ${libyang_VERSION}")
+elseif((libnetconf2_VERSION VERSION_GREATER 1.1.46 AND libnetconf2_VERSION VERSION_LESS 2.1.25))
+ message(FATAL_ERROR "Minimum libnetconf2 v2 subversion required is v2.1.25, but found ${libnetconf2_VERSION}")
+elseif((libyang_VERSION VERSION_GREATER_EQUAL 2.1.4 AND libyang_VERSION VERSION_LESS_EQUAL 2.1.111) AND (libnetconf2_VERSION VERSION_GREATER_EQUAL 2.1.25 AND libnetconf2_VERSION VERSION_LESS_EQUAL 2.1.37))
+ target_compile_definitions(oran_fhlib_5g_mplane PRIVATE MPLANE_V2)
+else()
+ message(FATAL_ERROR "Unknown libyang version ${libyang_VERSION} and libnetconf2 version ${libnetconf2_VERSION}")
+endif()
+
+target_include_directories(oran_fhlib_5g_mplane PRIVATE ${libyang_INCLUDE_DIRS} ${libnetconf2_INCLUDE_DIRS})
+target_link_libraries(oran_fhlib_5g_mplane PRIVATE ${libyang_LDFLAGS} ${libyang_LINK_LIBRARIES} ${libnetconf2_LINK_LIBRARIES})
+
+pkg_check_modules(libssh REQUIRED libssh)
+target_include_directories(oran_fhlib_5g_mplane PRIVATE ${libssh_INCLUDE_DIRS})
+target_link_libraries(oran_fhlib_5g_mplane PRIVATE ${libssh_LINK_LIBRARIES})
+
+find_package(LibXml2 REQUIRED)
+target_link_libraries(oran_fhlib_5g_mplane PRIVATE LibXml2::LibXml2)
+
+set(YANG_MODELS "${CMAKE_SOURCE_DIR}/radio/fhi_72/mplane/yang/models")
+target_compile_definitions(oran_fhlib_5g_mplane PRIVATE YANG_MODELS="${YANG_MODELS}")
+
+message(STATUS "Building FHI72 CUSM library")
+
+set_target_properties(oran_fhlib_5g_mplane PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
+add_custom_command(TARGET oran_fhlib_5g_mplane POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E create_symlink liboran_fhlib_5g_mplane.so liboai_transpro.so
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
diff --git a/radio/fhi_72/mplane/config-mplane.c b/radio/fhi_72/mplane/config-mplane.c
new file mode 100644
index 0000000000..69ff1fd2b3
--- /dev/null
+++ b/radio/fhi_72/mplane/config-mplane.c
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#include "config-mplane.h"
+#include "rpc-send-recv.h"
+#include "yang/get-yang.h"
+#include "yang/create-yang-config.h"
+#include "common/utils/assertions.h"
+
+#include
+#include
+
+bool edit_config_mplane(ru_session_t *ru_session, const char *buffer, const openair0_config_t *oai, const size_t num_rus)
+{
+ int timeout = CLI_RPC_REPLY_TIMEOUT;
+ struct nc_rpc *rpc;
+ NC_WD_MODE wd = NC_WD_ALL;
+ NC_PARAMTYPE param = NC_PARAMTYPE_CONST;
+ NC_DATASTORE target = NC_DATASTORE_CANDIDATE;
+ NC_RPC_EDIT_DFLTOP op = NC_RPC_EDIT_DFLTOP_MERGE;
+ NC_RPC_EDIT_TESTOPT test = NC_RPC_EDIT_TESTOPT_UNKNOWN;
+ NC_RPC_EDIT_ERROPT err = NC_RPC_EDIT_ERROPT_UNKNOWN;
+
+ bool success = false;
+
+ struct ly_ctx *ctx = NULL;
+ success = load_yang_models(ru_session, buffer, &ctx);
+ AssertError(success, return false, "[MPLANE] Unable to continue.\n");
+
+ char *content = NULL;
+ success = configure_ru_from_yang(&ctx, ru_session, oai, num_rus, &content);
+ AssertError(success, return false, "[MPLANE] Unable to create content for RPC.\n");
+
+ MP_LOG_I("RPC request to RU \"%s\" = :\n%s\n", ru_session->ru_ip_add, content);
+ rpc = nc_rpc_edit(target, op, test, err, content, param);
+ AssertError(rpc != NULL, return false, "[MPLANE] RPC creation failed.\n");
+
+ success = rpc_send_recv((struct nc_session *)ru_session->session, rpc, wd, timeout, NULL);
+ AssertError(success, return false, "[MPLANE] Failed to edit configuration for the candidate datastore.\n");
+
+ MP_LOG_I("Successfully edited the candidate datastore for RU \"%s\".\n", ru_session->ru_ip_add);
+
+ nc_rpc_free(rpc);
+ free(content);
+#ifdef MPLANE_V1
+ ly_ctx_destroy(ctx, NULL);
+#elif defined MPLANE_V2
+ ly_ctx_destroy(ctx);
+#endif
+
+ return true;
+}
+
+bool validate_config_mplane(ru_session_t *ru_session)
+{
+ int timeout = CLI_RPC_REPLY_TIMEOUT;
+ struct nc_rpc *rpc;
+ NC_WD_MODE wd = NC_WD_ALL;
+ NC_PARAMTYPE param = NC_PARAMTYPE_CONST;
+ char *src_start = NULL;
+ NC_DATASTORE source = NC_DATASTORE_CANDIDATE;
+
+ MP_LOG_I("RPC request to RU \"%s\" = candidate datastore.\n", ru_session->ru_ip_add);
+ rpc = nc_rpc_validate(source, src_start, param);
+ AssertError(rpc != NULL, return false, "[MPLANE] RPC creation failed.\n");
+
+ bool success = rpc_send_recv((struct nc_session *)ru_session->session, rpc, wd, timeout, NULL);
+ AssertError(success, return false, "[MPLANE] Failed to validate candidate datastore.\n");
+
+ MP_LOG_I("Successfully validated candidate datastore for RU \"%s\".\n", ru_session->ru_ip_add);
+
+ nc_rpc_free(rpc);
+
+ return true;
+}
+
+bool commit_config_mplane(ru_session_t *ru_session)
+{
+ int timeout = CLI_RPC_REPLY_TIMEOUT;
+ struct nc_rpc *rpc;
+ NC_WD_MODE wd = NC_WD_ALL;
+ NC_PARAMTYPE param = NC_PARAMTYPE_CONST;
+ int confirmed = 0;
+ int32_t confirm_timeout = 0;
+ char *persist = NULL, *persist_id = NULL;
+
+ MP_LOG_I("RPC request to RU \"%s\" = candidate datastore.\n", ru_session->ru_ip_add);
+ rpc = nc_rpc_commit(confirmed, confirm_timeout, persist, persist_id, param);
+ AssertError(rpc != NULL, return false, "[MPLANE] RPC creation failed.\n");
+
+ bool success = rpc_send_recv((struct nc_session *)ru_session->session, rpc, wd, timeout, NULL);
+ AssertError(success, return false, "[MPLANE] Failed to commit candidate datastore.\n");
+
+ MP_LOG_I("Successfully commited CU-planes configuration into running datastore for RU \"%s\".\n", ru_session->ru_ip_add);
+
+ nc_rpc_free(rpc);
+
+ return true;
+}
diff --git a/radio/fhi_72/mplane/config-mplane.h b/radio/fhi_72/mplane/config-mplane.h
new file mode 100644
index 0000000000..c8451ca8a0
--- /dev/null
+++ b/radio/fhi_72/mplane/config-mplane.h
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#ifndef CONFIGURE_MPLANE_H
+#define CONFIGURE_MPLANE_H
+
+#include "ru-mplane-api.h"
+#include "radio/COMMON/common_lib.h"
+
+bool edit_config_mplane(ru_session_t *ru_session, const char *buffer, const openair0_config_t *oai, const size_t num_rus);
+
+bool validate_config_mplane(ru_session_t *ru_session);
+
+bool commit_config_mplane(ru_session_t *ru_session);
+
+#endif /* CONFIGURE_MPLANE_H */
diff --git a/radio/fhi_72/mplane/connect-mplane.c b/radio/fhi_72/mplane/connect-mplane.c
new file mode 100644
index 0000000000..08b758bef1
--- /dev/null
+++ b/radio/fhi_72/mplane/connect-mplane.c
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#include "connect-mplane.h"
+#include "common/utils/assertions.h"
+
+#include
+#include
+
+static int my_auth_hostkey_check(const char *hostname, ssh_session session, void *priv)
+{
+ (void)hostname;
+ (void)session;
+ (void)priv;
+
+ return 0;
+}
+
+bool connect_mplane(ru_session_t *ru_session)
+{
+ int port = NC_PORT_SSH;
+ char *user = "oranbenetel";
+
+ nc_client_ssh_set_username(user);
+
+ nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 1); // ssh-key identification
+ nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1);
+ nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, -1);
+
+ nc_client_ssh_set_auth_hostkey_check_clb(my_auth_hostkey_check, "DATA"); // host-key identification
+
+ MP_LOG_I("RPC request to RU \"%s\" = with username \"%s\" and port ID \"%d\".\n", ru_session->ru_ip_add, user, port);
+ ru_session->session = nc_connect_ssh(ru_session->ru_ip_add, port, NULL);
+ AssertError(ru_session->session != NULL, return false, "[MPLANE] RU IP address %s unreachable. Maybe M-plane is disabled on the RU?\n", ru_session->ru_ip_add);
+
+ MP_LOG_I("Successfuly connected to RU \"%s\" with username \"%s\" and port ID \"%d\".\n", ru_session->ru_ip_add, user, port);
+
+ return true;
+}
+
+void disconnect_mplane(void *rus_disconnect)
+{
+ ru_session_list_t *ru_session_list = (ru_session_list_t *)rus_disconnect;
+
+ for (size_t i = 0; i num_rus; i++) {
+ ru_session_t *ru_session = &ru_session_list->ru_session[i];
+ if (ru_session->session == NULL)
+ continue;
+ MP_LOG_I("Disconnecting from RU \"%s\".\n", ru_session->ru_ip_add);
+ nc_session_free(ru_session->session, NULL);
+ ru_session->session = NULL;
+ }
+
+ nc_client_destroy();
+}
diff --git a/radio/fhi_72/mplane/connect-mplane.h b/radio/fhi_72/mplane/connect-mplane.h
new file mode 100644
index 0000000000..e46aa60f19
--- /dev/null
+++ b/radio/fhi_72/mplane/connect-mplane.h
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#ifndef CONNECT_MPLANE_H
+#define CONNECT_MPLANE_H
+
+#include "ru-mplane-api.h"
+
+bool connect_mplane(ru_session_t *ru_session);
+
+void disconnect_mplane(void *rus_disconnect);
+
+#endif /* CONNECT_MPLANE_H */
diff --git a/radio/fhi_72/mplane/get-mplane.c b/radio/fhi_72/mplane/get-mplane.c
new file mode 100644
index 0000000000..06aa6d0317
--- /dev/null
+++ b/radio/fhi_72/mplane/get-mplane.c
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#include "get-mplane.h"
+#include "rpc-send-recv.h"
+
+#include "common/utils/assertions.h"
+
+bool get_mplane(ru_session_t *ru_session, char **answer)
+{
+ int timeout = CLI_RPC_REPLY_TIMEOUT;
+ struct nc_rpc *rpc;
+ char *filter = NULL; // e.g. "/o-ran-delay-management:delay-management";
+ NC_WD_MODE wd = NC_WD_ALL;
+ NC_PARAMTYPE param = NC_PARAMTYPE_CONST;
+
+ MP_LOG_I("RPC request to RU \"%s\" = operational datastore.\n", ru_session->ru_ip_add);
+ rpc = nc_rpc_get(filter, wd, param);
+ AssertError(rpc != NULL, return false, "[MPLANE] RPC creation failed.\n");
+
+ bool success = rpc_send_recv((struct nc_session *)ru_session->session, rpc, wd, timeout, answer);
+ AssertError(success, return false, "[MPLANE] Unable to retrieve operational datastore.\n");
+
+ MP_LOG_I("Successfully retrieved operational datastore from RU \"%s\".\n", ru_session->ru_ip_add);
+
+ nc_rpc_free(rpc);
+
+ return true;
+}
diff --git a/radio/fhi_72/mplane/get-mplane.h b/radio/fhi_72/mplane/get-mplane.h
new file mode 100644
index 0000000000..a47abdc8f5
--- /dev/null
+++ b/radio/fhi_72/mplane/get-mplane.h
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#ifndef GET_MPLANE_H
+#define GET_MPLANE_H
+
+#include "ru-mplane-api.h"
+
+bool get_mplane(ru_session_t *ru_session, char **answer);
+
+#endif /* GET_MPLANE_H */
diff --git a/radio/fhi_72/mplane/init-mplane.c b/radio/fhi_72/mplane/init-mplane.c
new file mode 100644
index 0000000000..39e8cfb995
--- /dev/null
+++ b/radio/fhi_72/mplane/init-mplane.c
@@ -0,0 +1,205 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#include "init-mplane.h"
+#include "radio/fhi_72/oran-params.h"
+#include "get-mplane.h"
+#include "subscribe-mplane.h"
+#include "config-mplane.h"
+#include "xml/get-xml.h"
+
+#include
+#include
+
+static void lnc2_print_clb(NC_VERB_LEVEL level, const char *msg)
+{
+ switch (level) {
+ case NC_VERB_ERROR:
+ MP_LOG_I("[LIBNETCONF2] ERROR: %s.\n", msg);
+ break;
+ case NC_VERB_WARNING:
+ MP_LOG_I("[LIBNETCONF2] WARNING: %s.\n", msg);
+ break;
+ case NC_VERB_VERBOSE:
+ MP_LOG_I("[LIBNETCONF2] VERBOSE: %s.\n", msg);
+ break;
+ case NC_VERB_DEBUG:
+ case NC_VERB_DEBUG_LOWLVL:
+ MP_LOG_I("[LIBNETCONF2] DEBUG: %s.\n", msg);
+ break;
+ default:
+ assert(false && "[LIBNETCONF2] Unknown log level.");
+ }
+}
+
+static void ly_print_clb(LY_LOG_LEVEL level, const char *msg, const char *path)
+{
+ switch (level) {
+ case LY_LLERR:
+ MP_LOG_I("[LIBYANG] ERROR: %s (path: %s).\n", msg, path);
+ break;
+ case LY_LLWRN:
+ MP_LOG_I("[LIBYANG] WARNING: %s (path: %s).\n", msg, path);
+ break;
+ case LY_LLVRB:
+ MP_LOG_I("[LIBYANG] VERBOSE: %s (path: %s).\n", msg, path);
+ break;
+ case LY_LLDBG:
+ MP_LOG_I("[LIBYANG] DEBUG: %s (path: %s).\n", msg, path);
+ break;
+ default:
+ assert(false && "[LIBYANG] Unknown log level.");
+ }
+}
+
+static const paramdef_t *gpd(const paramdef_t *pd, int num, const char *name)
+{
+ /* the config module does not know const-correctness... */
+ int idx = config_paramidx_fromname((paramdef_t *)pd, num, (char *)name);
+ DevAssert(idx >= 0);
+ return &pd[idx];
+}
+
+bool init_mplane(ru_session_list_t *ru_session_list)
+{
+ paramdef_t fhip[] = ORAN_GLOBALPARAMS_DESC;
+ int nump = sizeofArray(fhip);
+ int ret = config_get(config_get_if(), fhip, nump, CONFIG_STRING_ORAN);
+ if (ret <= 0) {
+ MP_LOG_I("Problem reading section \"%s\".\n", CONFIG_STRING_ORAN);
+ return false;
+ }
+
+ ru_session_list->du_key_pair = gpd(fhip, nump, ORAN_CONFIG_DU_KEYPAIR)->strlistptr;
+ int num_keys = gpd(fhip, nump, ORAN_CONFIG_DU_KEYPAIR)->numelt;
+ AssertError(num_keys == 2, return false, "[MPLANE] Expected {pub-key-path, priv-key-path}. Loaded {%s, %s}.\n", ru_session_list->du_key_pair[0], ru_session_list->du_key_pair[1]);
+
+ char **ru_ip_addrs = gpd(fhip, nump, ORAN_CONFIG_RU_IP_ADDR)->strlistptr;
+ int num_rus = gpd(fhip, nump, ORAN_CONFIG_RU_IP_ADDR)->numelt;
+ char **du_mac_addr = gpd(fhip, nump, ORAN_CONFIG_DU_ADDR)->strlistptr;
+ int num_dus = gpd(fhip, nump, ORAN_CONFIG_DU_ADDR)->numelt;
+ int32_t *vlan_tag = gpd(fhip, nump, ORAN_CONFIG_VLAN_TAG)->iptr;
+ int num_vlan_tags = gpd(fhip, nump, ORAN_CONFIG_VLAN_TAG)->numelt;
+
+ AssertError(num_dus == num_vlan_tags, return false, "[MPLANE] Number of DU MAC addresses should be equal to the number of VLAN tags.\n");
+
+ int num_cu_planes = num_dus / num_rus;
+
+ ru_session_list->num_rus = num_rus;
+ ru_session_list->ru_session = calloc(num_rus, sizeof(ru_session_t));
+ for (size_t i = 0; i < num_rus; i++) {
+ ru_session_t *ru_session = &ru_session_list->ru_session[i];
+ ru_session->session = NULL;
+ ru_session->ru_ip_add = calloc(strlen(ru_ip_addrs[i]) + 1, sizeof(char));
+ memcpy(ru_session->ru_ip_add, ru_ip_addrs[i], strlen(ru_ip_addrs[i]) + 1);
+
+ // store DU MAC addresses and VLAN tags
+ ru_session->ru_mplane_config.num_cu_planes = num_cu_planes;
+ ru_session->ru_mplane_config.du_mac_addr = calloc_or_fail(num_cu_planes, sizeof(char*));
+ ru_session->ru_mplane_config.vlan_tag = calloc_or_fail(num_cu_planes, sizeof(int32_t));
+ for (int j = 0; j < num_cu_planes; j++) {
+ const int idx = i*num_cu_planes+j;
+ ru_session->ru_mplane_config.du_mac_addr[j] = calloc(1, strlen(du_mac_addr[idx]) + 1);
+ memcpy(ru_session->ru_mplane_config.du_mac_addr[j], du_mac_addr[idx], strlen(du_mac_addr[idx]) + 1);
+ ru_session->ru_mplane_config.vlan_tag[j] = vlan_tag[idx];
+ }
+ }
+
+ nc_client_init();
+ int keypair_ret = nc_client_ssh_add_keypair(ru_session_list->du_key_pair[0], ru_session_list->du_key_pair[1]);
+ AssertError(keypair_ret == 0, return false, "[MPLANE] Unable to add DU ssh key pair.\n");
+
+ // logs for netconf2 and yang libraries
+ nc_set_print_clb(lnc2_print_clb);
+ ly_set_log_clb(ly_print_clb, 1);
+
+ return true;
+}
+
+bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus)
+{
+ bool success = false;
+
+ char *operational_ds = NULL;
+ success = get_mplane(ru_session, &operational_ds);
+ AssertError(success, return false, "[MPLANE] Unable to continue: could not get RU answer via get_mplane().\n");
+
+ bool ptp_state = false;
+ const char *sync_state = get_ru_xml_node(operational_ds, "sync-state");
+ if (strcmp(sync_state, "LOCKED") == 0) {
+ MP_LOG_I("RU is already PTP synchronized.\n");
+ ptp_state = true;
+ }
+
+ /* 1) as per M-plane spec, RU must be in supervised mode,
+ where stream = NULL && filter = "/o-ran-supervision:supervision-notification";
+ 2) additionally, we want to subscribe to PTP state change,
+ where stream = NULL && filter = "/o-ran-sync:synchronization-state-change";
+ => since more than one subscription at the time within one session is not possible, we will subscribe to all notifications */
+ const char *stream = "NETCONF";
+ const char *filter = NULL;
+ ru_session->ru_notif.ptp_state = ptp_state;
+ success = subscribe_mplane(ru_session, stream, filter, (void *)&ru_session->ru_notif);
+ AssertError(success, return false, "[MPLANE] Unable to continue: could not get RU answer via subscribe_mplane().\n");
+
+ // when subscribed to the supervision notification, the watchdog timer needs to be updated
+ char *watchdog_answer = NULL;
+ success = update_timer_mplane(ru_session, &watchdog_answer);
+ AssertError(success, return false, "[MPLANE] Unable to update the watchdog timer. RU will do a reset after default supervision timer of (60+10)[s] expires.\n");
+ MP_LOG_I("Watchdog timer answer: \n\t%s\n", watchdog_answer);
+
+ // save RU info for xran
+ const int max_num_ant = max(oai->tx_num_channels/num_rus, oai->rx_num_channels/num_rus);
+ success = get_config_for_xran(operational_ds, max_num_ant, &ru_session->xran_mplane);
+ AssertError(success, return false, "[MPLANE] Unable to retrieve required info for xran from RU \"%s\".\n", ru_session->ru_ip_add);
+
+ // save the U-plane info
+ success = get_uplane_info(operational_ds, &ru_session->ru_mplane_config);
+ AssertError(success, return false, "[MPLANE] Unable to get U-plane info from RU operational datastore.\n");
+
+ if (ru_session->ru_notif.ptp_state) {
+ success = edit_config_mplane(ru_session, operational_ds, oai, num_rus);
+ AssertError(success, return false, "[MPLANE] Unable to edit the RU configuration.\n");
+
+ success = validate_config_mplane(ru_session);
+ AssertError(success, return false, "[MPLANE] Unable to validate the RU configuration.\n");
+
+ success = commit_config_mplane(ru_session);
+ AssertError(success, return false, "[MPLANE] Unable to commit the RU configuration.\n");
+ }
+
+ const char *usage_state = get_ru_xml_node(operational_ds, "usage-state");
+ MP_LOG_I("Usage state = \"%s\" for RU \"%s\".\n", usage_state, ru_session->ru_ip_add);
+ if (strcmp(usage_state, "busy") == 0) { // carriers are already activated
+ ru_session->ru_notif.rx_carrier_state = true;
+ ru_session->ru_notif.tx_carrier_state = true;
+ ru_session->ru_notif.config_change = true;
+ } else {
+ ru_session->ru_notif.rx_carrier_state = false;
+ ru_session->ru_notif.tx_carrier_state = false;
+ ru_session->ru_notif.config_change = false;
+ }
+
+ free(operational_ds);
+ free(watchdog_answer);
+
+ return true;
+}
diff --git a/radio/fhi_72/mplane/init-mplane.h b/radio/fhi_72/mplane/init-mplane.h
new file mode 100644
index 0000000000..5077908d64
--- /dev/null
+++ b/radio/fhi_72/mplane/init-mplane.h
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#ifndef OAI_MPLANE_H
+#define OAI_MPLANE_H
+
+#include "ru-mplane-api.h"
+#include "radio/COMMON/common_lib.h"
+
+bool init_mplane(ru_session_list_t *ru_session_list);
+
+bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus);
+
+#endif /* OAI_MPLANE_H */
diff --git a/radio/fhi_72/mplane/rpc-send-recv.c b/radio/fhi_72/mplane/rpc-send-recv.c
new file mode 100644
index 0000000000..4b218fc164
--- /dev/null
+++ b/radio/fhi_72/mplane/rpc-send-recv.c
@@ -0,0 +1,296 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#include "rpc-send-recv.h"
+
+#include "common/utils/assertions.h"
+
+
+#ifdef MPLANE_V1
+static bool recv_v1(struct nc_session *session, struct nc_rpc *rpc, NC_MSG_TYPE msgtype, const uint64_t msgid, const NC_WD_MODE wd_mode, const int timeout_ms, char **answer)
+{
+ struct nc_reply *reply;
+ struct nc_reply_data *data_rpl;
+ struct nc_reply_error *error;
+ LYD_FORMAT output_format = LYD_XML;
+ uint32_t ly_wd;
+
+ while (1) {
+ msgtype = nc_recv_reply(session, rpc, msgid, timeout_ms, 0, &reply);
+ if (msgtype == NC_MSG_ERROR) {
+ AssertError(false, return false, "[MPLANE] Failed to receive a reply.\n");
+ } else if (msgtype == NC_MSG_WOULDBLOCK) {
+ AssertError(false, return false, "[MPLANE] Timeout for receiving a reply expired.\n");
+ } else if (msgtype == NC_MSG_NOTIF) {
+ /* read again */
+ continue;
+ } else if (msgtype == NC_MSG_REPLY_ERR_MSGID) {
+ /* unexpected message, try reading again to get the correct reply */
+ MP_LOG_I("Unexpected reply received - ignoring and waiting for the correct reply.\n");
+ nc_reply_free(reply);
+ continue;
+ }
+ break;
+ }
+
+ switch (reply->type) {
+ case NC_RPL_OK:
+ MP_LOG_I("RPC reply = OK.\n");
+ break;
+ case NC_RPL_DATA:
+ data_rpl = (struct nc_reply_data *)reply;
+
+ switch (wd_mode) {
+ case NC_WD_ALL:
+ ly_wd = LYP_WD_ALL;
+ break;
+ case NC_WD_ALL_TAG:
+ ly_wd = LYP_WD_ALL_TAG;
+ break;
+ case NC_WD_TRIM:
+ ly_wd = LYP_WD_TRIM;
+ break;
+ case NC_WD_EXPLICIT:
+ ly_wd = LYP_WD_EXPLICIT;
+ break;
+ default:
+ ly_wd = 0; // when wd_mode = NC_WD_UNKNOWN
+ break;
+ }
+
+ if (nc_rpc_get_type(rpc) == NC_RPC_GETSCHEMA) {
+ AssertError((!data_rpl->data || (data_rpl->data->schema->nodetype != LYS_RPC) || (data_rpl->data->child == NULL)
+ || (data_rpl->data->child->schema->nodetype != LYS_ANYXML)), return false, "[MPLANE] Cannot get schema.\n");
+
+ struct lyd_node_anydata *any = (struct lyd_node_anydata *)data_rpl->data->child;
+ switch (any->value_type) {
+ case LYD_ANYDATA_CONSTSTRING:
+ case LYD_ANYDATA_STRING:
+ *answer = strdup(any->value.str);
+ break;
+ case LYD_ANYDATA_DATATREE:
+ lyd_print_mem(answer, any->value.tree, output_format, LYP_WITHSIBLINGS);
+ break;
+ case LYD_ANYDATA_XML:
+ lyxml_print_mem(answer, any->value.xml, LYXML_PRINT_SIBLINGS);
+ break;
+ default:
+ AssertError(false, return false, "[MPLANE] Unknown yang type.\n");
+ }
+ break;
+ } else if (nc_rpc_get_type(rpc) == NC_RPC_GETCONFIG || nc_rpc_get_type(rpc) == NC_RPC_GET) {
+ const char *tag = nc_rpc_get_type(rpc) == NC_RPC_GETCONFIG ? "config" : "data";
+ char *buffer = NULL;
+ lyd_print_mem(&buffer, data_rpl->data, output_format, LYP_WITHSIBLINGS | LYP_NETCONF | ly_wd);
+ *answer = calloc(strlen(buffer)+128, sizeof(char));
+ sprintf(*answer, "<%s xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n%s%s>", tag, buffer, tag);
+ } else {
+ AssertError(false, return false, "[MPLANE] Unknown RPC type.\n");
+ }
+
+ break;
+ case NC_RPL_ERROR:
+ error = (struct nc_reply_error *)reply;
+ for (int i = 0; i < error->count; ++i) {
+ const struct nc_err *err = &error->err[i];
+ MP_LOG_I("RPC reply = ERROR\n\
+ \ttype: %s\n\
+ \ttag: %s\n\
+ \tseverity: %s\n\
+ \tapp-tag: %s\n\
+ \tpath: %s\n\
+ \tmessage: %s\n\
+ \tSID: %s\n",
+ err->type,
+ err->tag,
+ err->severity,
+ err->apptag,
+ err->path,
+ err->message,
+ err->sid);
+
+ for (int j = 0; j < err->attr_count; ++j) {
+ MP_LOG_I("\tbad-attr #%d: %s\n", j + 1, err->attr[j]);
+ }
+ for (int j = 0; j < err->elem_count; ++j) {
+ MP_LOG_I("\tbad-elem #%d: %s\n", j + 1, err->elem[j]);
+ }
+ for (int j = 0; j < err->ns_count; ++j) {
+ MP_LOG_I("\tbad-ns #%d: %s\n", j + 1, err->ns[j]);
+ }
+ for (int j = 0; j < err->other_count; ++j) {
+ char *str = NULL;
+ lyxml_print_mem(&str, err->other[j], 0);
+ MP_LOG_I("\tother #%d:\n%s\n", j + 1, str);
+ free(str);
+ }
+ }
+ AssertError(false, return false, "[MPLANE] Unable to continue.\n");
+ break;
+ default:
+ AssertError(false, return false, "[MPLANE] Internal error.\n");
+ nc_reply_free(reply);
+ }
+ nc_reply_free(reply);
+
+ return true;
+}
+#elif defined MPLANE_V2
+static bool recv_v2(struct nc_session *session, struct nc_rpc *rpc, NC_MSG_TYPE msgtype, const uint64_t msgid, const NC_WD_MODE wd_mode, const int timeout_ms, char **answer)
+{
+ struct lyd_node *envp, *op, *err;
+ LYD_FORMAT output_format = LYD_XML;
+ uint32_t ly_wd;
+
+ while (1) {
+ msgtype = nc_recv_reply(session, rpc, msgid, timeout_ms, &envp, &op);
+ if (msgtype == NC_MSG_ERROR) {
+ AssertError(false, return false, "[MPLANE] Failed to receive a reply.\n");
+ } else if (msgtype == NC_MSG_WOULDBLOCK) {
+ AssertError(false, return false, "[MPLANE] Timeout for receiving a reply for RPC expired.\n");
+ } else if (msgtype == NC_MSG_NOTIF) { // for SUBSCRIBE
+ /* read again */
+ continue;
+ } else if (msgtype == NC_MSG_REPLY_ERR_MSGID) {
+ /* unexpected message, try reading again to get the correct reply */
+ MP_LOG_I("Unexpected reply received - ignoring and waiting for the correct reply.\n");
+ lyd_free_tree(envp);
+ lyd_free_tree(op);
+ continue;
+ }
+ break;
+ }
+
+ /* get functionality */
+ if (op) {
+ /* data reply */
+ if (nc_rpc_get_type(rpc) == NC_RPC_GETSCHEMA) {
+ /* special case */
+ if (!lyd_child(op) || (lyd_child(op)->schema->nodetype != LYS_ANYXML)) {
+ AssertError(false, return false, "[MPLANE] Cannot get schema.");
+ }
+ struct lyd_node_any *any = (struct lyd_node_any *)lyd_child(op);
+ switch (any->value_type) {
+ case LYD_ANYDATA_STRING:
+ case LYD_ANYDATA_XML:
+ *answer = strdup(any->value.str);
+ break;
+ case LYD_ANYDATA_DATATREE:
+ lyd_print_mem(answer, any->value.tree, output_format, LYD_PRINT_WITHSIBLINGS);
+ break;
+ default:
+ AssertError(false, return false, "[MPLANE] Unexpected yang type.");
+ }
+ } else {
+ switch (wd_mode) {
+ case NC_WD_ALL:
+ ly_wd = LYD_PRINT_WD_ALL;
+ break;
+ case NC_WD_ALL_TAG:
+ ly_wd = LYD_PRINT_WD_ALL_TAG;
+ break;
+ case NC_WD_TRIM:
+ ly_wd = LYD_PRINT_WD_TRIM;
+ break;
+ case NC_WD_EXPLICIT:
+ ly_wd = LYD_PRINT_WD_EXPLICIT;
+ break;
+ default:
+ ly_wd = 0; // when wd_mode = NC_WD_UNKNOWN
+ break;
+ }
+ lyd_print_mem(answer, lyd_child(op), output_format, LYD_PRINT_WITHSIBLINGS | ly_wd);
+ }
+ /* edit/validate/commit functionalities */
+ } else if (!strcmp(LYD_NAME(lyd_child(envp)), "ok")) {
+ MP_LOG_I("RPC reply = OK.\n");
+ } else {
+ LY_LIST_FOR(lyd_child(envp), err) {
+ struct lyd_node *type, *tag, *severity, *app_tag, *path, *er_msg, *info = NULL;
+ lyd_find_sibling_opaq_next(lyd_child(err), "error-type", &type);
+ lyd_find_sibling_opaq_next(lyd_child(err), "error-tag", &tag);
+ lyd_find_sibling_opaq_next(lyd_child(err), "error-severity", &severity);
+ lyd_find_sibling_opaq_next(lyd_child(err), "error-app-tag", &app_tag);
+ lyd_find_sibling_opaq_next(lyd_child(err), "error-path", &path);
+ lyd_find_sibling_opaq_next(lyd_child(err), "error-message", &er_msg);
+
+ MP_LOG_I("RPC reply = ERROR\n\
+ \ttype: %s\n\
+ \ttag: %s\n\
+ \tseverity: %s\n\
+ \tapp-tag: %s\n\
+ \tpath: %s\n\
+ \tmessage: %s\n",
+ (type ? ((struct lyd_node_opaq *)type)->value : NULL),
+ (tag ? ((struct lyd_node_opaq *)tag)->value : NULL),
+ (severity ? ((struct lyd_node_opaq *)severity)->value : NULL),
+ (app_tag ? ((struct lyd_node_opaq *)app_tag)->value : NULL),
+ (path ? ((struct lyd_node_opaq *)path)->value : NULL),
+ (er_msg ? ((struct lyd_node_opaq *)er_msg)->value : NULL));
+
+ info = lyd_child(err);
+ while (!lyd_find_sibling_opaq_next(info, "error-info", &info)) {
+ char *str = NULL;
+ lyd_print_mem(&str, lyd_child(info), output_format, LYD_PRINT_WITHSIBLINGS);
+ MP_LOG_I("\tinfo: %s\n", str);
+ info = info->next;
+ free(str);
+ }
+ lyd_free_tree(type);
+ lyd_free_tree(tag);
+ lyd_free_tree(severity);
+ lyd_free_tree(app_tag);
+ lyd_free_tree(path);
+ lyd_free_tree(er_msg);
+ lyd_free_tree(info);
+ }
+ lyd_free_tree(envp);
+ lyd_free_tree(op);
+ AssertError(false, return false, "[MPLANE] Unable to continue.\n");
+ }
+
+ lyd_free_tree(envp);
+ lyd_free_tree(op);
+
+ return true;
+}
+#endif
+
+bool rpc_send_recv(struct nc_session *session, struct nc_rpc *rpc, const NC_WD_MODE wd_mode, const int timeout_ms, char **answer)
+{
+ uint64_t msgid;
+ NC_MSG_TYPE msgtype;
+
+ msgtype = nc_send_rpc(session, rpc, 1000, &msgid);
+ if (msgtype == NC_MSG_ERROR) {
+ AssertError(false, return false, "[MPLANE] Failed to send the RPC.\n");
+ } else if (msgtype == NC_MSG_WOULDBLOCK) {
+ AssertError(false, return false, "[MPLANE] Timeout for sending the RPC expired.\n");
+ }
+
+#ifdef MPLANE_V1
+ return recv_v1(session, rpc, msgtype, msgid, wd_mode, timeout_ms, answer);
+#elif defined MPLANE_V2
+ return recv_v2(session, rpc, msgtype, msgid, wd_mode, timeout_ms, answer);
+#else
+ AssertError(false, return false, "[MPLANE] Unknown M-plane version found. Tried \"MPLANE_V1\" and \"MPLANE_V2\".\n");
+#endif
+}
diff --git a/radio/fhi_72/mplane/rpc-send-recv.h b/radio/fhi_72/mplane/rpc-send-recv.h
new file mode 100644
index 0000000000..4cf2095713
--- /dev/null
+++ b/radio/fhi_72/mplane/rpc-send-recv.h
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#ifndef RPC_SEND_RECEIVE_MPLANE_H
+#define RPC_SEND_RECEIVE_MPLANE_H
+
+#include "ru-mplane-api.h"
+
+#include
+#include
+
+#define CLI_RPC_REPLY_TIMEOUT 60000 // time [ms] to wait for server reply
+
+bool rpc_send_recv(struct nc_session *session, struct nc_rpc *rpc, const NC_WD_MODE wd_mode, const int timeout_ms, char **answer);
+
+#endif /* RPC_SEND_RECEIVE_MPLANE_H */
diff --git a/radio/fhi_72/mplane/ru-mplane-api.c b/radio/fhi_72/mplane/ru-mplane-api.c
new file mode 100644
index 0000000000..d387a40864
--- /dev/null
+++ b/radio/fhi_72/mplane/ru-mplane-api.c
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#include "ru-mplane-api.h"
+#include "xml/get-xml.h"
+#include "common/utils/assertions.h"
+
+#include
+
+static void free_match_list(char **match_list, size_t count)
+{
+ for (size_t i = 0; i < count; i++) {
+ free(match_list[i]);
+ }
+ free(match_list);
+}
+
+static void fix_benetel_setting(xran_mplane_t *xran_mplane, const uint32_t interface_mtu, const int16_t first_iq_width, const int max_num_ant)
+{
+ if (interface_mtu == 1500) {
+ MP_LOG_I("Interface MTU %d unreliable/not correctly reported by Benetel O-RU, hardcoding to 9600.\n", interface_mtu);
+ xran_mplane->mtu = 9600;
+ } else {
+ xran_mplane->mtu = interface_mtu;
+ }
+
+ if (first_iq_width != 9) {
+ MP_LOG_I("IQ bitwidth %d unreliable/not correctly reported by Benetel O-RU, hardcoding to 9.\n", first_iq_width);
+ xran_mplane->iq_width = 9;
+ } else {
+ xran_mplane->iq_width = first_iq_width;
+ }
+
+ xran_mplane->prach_offset = max_num_ant;
+}
+
+bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_t *xran_mplane)
+{
+ /* some O-RU vendors are not fully compliant as per M-plane specifications */
+ const char *ru_vendor = get_ru_xml_node(buffer, "mfg-name");
+
+ // RU MAC
+ xran_mplane->ru_mac_addr = get_ru_xml_node(buffer, "mac-address"); // TODO: support for VVDN, as it defines multiple MAC addresses
+
+ // MTU
+ const uint32_t interface_mtu = (uint32_t)atoi(get_ru_xml_node(buffer, "interface-mtu"));
+
+ // IQ bitwidth
+ char **match_list = NULL;
+ size_t count = 0;
+ get_ru_xml_list(buffer, "iq-bitwidth", &match_list, &count);
+ const int16_t first_iq_width = (int16_t)atoi((char *)match_list[0]);
+ free_match_list(match_list, count);
+
+ // PRACH offset
+ // xran_mplane->prach_offset
+
+ // DU port ID bitmask
+ xran_mplane->du_port_bitmask = 0xf000;
+ // Band sector bitmask
+ xran_mplane->band_sector_bitmask = 0x0f00;
+ // CC ID bitmask
+ xran_mplane->ccid_bitmask = 0x00f0;
+ // RU port ID bitmask
+ xran_mplane->ru_port_bitmask = 0x000f;
+
+ // DU port ID
+ xran_mplane->du_port = 0;
+ // Band sector
+ xran_mplane->band_sector = 0;
+ // CC ID
+ xran_mplane->ccid = 0;
+ // RU port ID
+ xran_mplane->ru_port = 0;
+
+ if (strcasecmp(ru_vendor, "BENETEL") == 0 /* || strcmp(ru_vendor, "VVDN-LPRU") == 0 || strcmp(ru_vendor, "Metanoia") == 0 */) {
+ fix_benetel_setting(xran_mplane, interface_mtu, first_iq_width, max_num_ant);
+ } else {
+ AssertError(false, return false, "[MPLANE] %s RU currently not supported.\n", ru_vendor);
+ }
+
+ MP_LOG_I("Storing the following information to forward to xran:\n\
+ RU MAC address %s\n\
+ MTU %d\n\
+ IQ bitwidth %d\n\
+ PRACH offset %d\n\
+ DU port bitmask %d\n\
+ Band sector bitmask %d\n\
+ CC ID bitmask %d\n\
+ RU port ID bitmask %d\n\
+ DU port ID %d\n\
+ Band sector ID %d\n\
+ CC ID %d\n\
+ RU port ID %d\n",
+ xran_mplane->ru_mac_addr,
+ xran_mplane->mtu,
+ xran_mplane->iq_width,
+ xran_mplane->prach_offset,
+ xran_mplane->du_port_bitmask,
+ xran_mplane->band_sector_bitmask,
+ xran_mplane->ccid_bitmask,
+ xran_mplane->ru_port_bitmask,
+ xran_mplane->du_port,
+ xran_mplane->band_sector,
+ xran_mplane->ccid,
+ xran_mplane->ru_port);
+
+ return true;
+}
+
+bool get_uplane_info(const char *buffer, ru_mplane_config_t *ru_mplane_config)
+{
+ // Interface name
+ ru_mplane_config->interface_name = get_ru_xml_node(buffer, "interface");
+
+ // PDSCH
+ uplane_info_t *tx_end = &ru_mplane_config->tx_endpoints;
+ get_ru_xml_list(buffer, "static-low-level-tx-endpoints", &tx_end->name, &tx_end->num);
+ AssertError(tx_end->name != NULL, return false, "[MPLANE] Cannot get TX endpoint names.\n");
+
+ // TX carriers
+ uplane_info_t *tx_carriers = &ru_mplane_config->tx_carriers;
+ get_ru_xml_list(buffer, "tx-arrays", &tx_carriers->name, &tx_carriers->num);
+ AssertError(tx_carriers->name != NULL, return false, "[MPLANE] Cannot get TX carrier names.\n");
+
+ // PUSCH and PRACH
+ uplane_info_t *rx_end = &ru_mplane_config->rx_endpoints;
+ get_ru_xml_list(buffer, "static-low-level-rx-endpoints", &rx_end->name, &rx_end->num);
+ AssertError(rx_end->name != NULL, return false, "[MPLANE] Cannot get RX endpoint names.\n");
+
+ // RX carriers
+ uplane_info_t *rx_carriers = &ru_mplane_config->rx_carriers;
+ get_ru_xml_list(buffer, "rx-arrays", &rx_carriers->name, &rx_carriers->num);
+ AssertError(rx_carriers->name != NULL, return false, "[MPLANE] Cannot get RX carrier names.\n");
+
+ MP_LOG_I("Successfully retrieved all the U-plane info - interface name, TX/RX carrier names, and TX/RX endpoint names.\n");
+
+ return true;
+}
diff --git a/radio/fhi_72/mplane/ru-mplane-api.h b/radio/fhi_72/mplane/ru-mplane-api.h
new file mode 100644
index 0000000000..70857adea6
--- /dev/null
+++ b/radio/fhi_72/mplane/ru-mplane-api.h
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#ifndef RU_MPLANE_API_H
+#define RU_MPLANE_API_H
+
+#include
+#include
+#include
+
+#include "common/utils/LOG/log.h"
+
+#define MP_LOG_I(x, args...) LOG_I(HW, "[MPLANE] " x, ##args)
+#define MP_LOG_W(x, args...) LOG_W(HW, "[MPLANE] " x, ##args)
+
+typedef struct {
+ bool ptp_state;
+ bool rx_carrier_state;
+ bool tx_carrier_state;
+ bool config_change;
+ // to be extended with any notification callback
+
+} ru_notif_t;
+
+typedef struct {
+ char *ru_mac_addr;
+ uint32_t mtu;
+ int16_t iq_width;
+ uint8_t prach_offset;
+
+ // DU sends to RU and xran
+ uint16_t du_port_bitmask;
+ uint16_t band_sector_bitmask;
+ uint16_t ccid_bitmask;
+ uint16_t ru_port_bitmask;
+
+ // DU retrieves from RU, and sends to xran
+ uint8_t du_port;
+ uint8_t band_sector;
+ uint8_t ccid;
+ uint8_t ru_port;
+
+} xran_mplane_t;
+
+typedef struct {
+ size_t num;
+ char **name;
+} uplane_info_t;
+
+typedef struct {
+ size_t num_cu_planes;
+ char **du_mac_addr; // one or two VF(s) for CU-planes
+ int32_t *vlan_tag; // one or two VF(s) for CU-planes
+ char *interface_name;
+ uplane_info_t tx_endpoints;
+ uplane_info_t rx_endpoints;
+ uplane_info_t tx_carriers;
+ uplane_info_t rx_carriers;
+
+} ru_mplane_config_t;
+
+typedef struct {
+ char *ru_ip_add;
+ ru_mplane_config_t ru_mplane_config;
+ void *session;
+ xran_mplane_t xran_mplane;
+ ru_notif_t ru_notif;
+
+} ru_session_t;
+
+typedef struct {
+ size_t num_rus;
+ ru_session_t *ru_session;
+ char **du_key_pair;
+
+} ru_session_list_t;
+
+bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_t *xran_mplane);
+
+bool get_uplane_info(const char *buffer, ru_mplane_config_t *ru_mplane_config);
+
+#endif /* RU_MPLANE_API_H */
diff --git a/radio/fhi_72/mplane/subscribe-mplane.c b/radio/fhi_72/mplane/subscribe-mplane.c
new file mode 100644
index 0000000000..9a8e28c4c1
--- /dev/null
+++ b/radio/fhi_72/mplane/subscribe-mplane.c
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#include "subscribe-mplane.h"
+#include "rpc-send-recv.h"
+#include "common/utils/assertions.h"
+
+#include
+#include
+
+#ifdef MPLANE_V1
+static void recv_notif_v1(const struct nc_notif *notif, ru_notif_t *answer)
+{
+ const char *node_name = notif->tree->child->attr->name;
+ const char *value = notif->tree->child->attr->value_str;
+ if (strcmp(node_name, "sync-state")) {
+ if (strcmp(value, "LOCKED") == 0) {
+ answer->ptp_state = true;
+ } else {
+ answer->ptp_state = false;
+ }
+ }
+
+ // carriers state - to be filled
+}
+
+static void notif_clb_v1(struct nc_session *session, const struct nc_notif *notif)
+{
+ ru_notif_t *answer = nc_session_get_data(session);
+ LYD_FORMAT output_format = LYD_JSON;
+
+ char *subs_reply = NULL;
+ lyd_print_mem(&subs_reply, notif->tree, output_format, LYP_WITHSIBLINGS);
+ MP_LOG_I("\nReceived notification at (%s)\n%s\n", notif->datetime, subs_reply);
+
+ recv_notif_v1(notif, answer);
+}
+#elif MPLANE_V2
+static void recv_notif_v2(struct lyd_node_inner *op, ru_notif_t *answer)
+{
+ const char *notif = op->schema->name;
+
+ if (strcmp(notif, "synchronization-state-change") == 0) {
+ const char *value = lyd_get_value(op->child);
+ if (strcmp(value, "LOCKED") == 0) {
+ answer->ptp_state = true;
+ } else { // "FREERUN" or "HOLDOVER"
+ answer->ptp_state = false;
+ }
+ } else if (strcmp(notif, "rx-array-carriers-state-change") == 0) {
+ const char *value = lyd_get_value(lyd_child(op->child)->next);
+ if (strcmp(value, "READY") == 0) {
+ answer->rx_carrier_state = true;
+ } else { // "DISABLED" or "BUSY"
+ answer->rx_carrier_state = false;
+ }
+ } else if (strcmp(notif, "tx-array-carriers-state-change") == 0) {
+ const char *value = lyd_get_value(lyd_child(op->child)->next);
+ if (strcmp(value, "READY") == 0) {
+ answer->tx_carrier_state = true;
+ } else { // "DISABLED" or "BUSY"
+ answer->tx_carrier_state = false;
+ }
+ } else if (strcmp(notif, "netconf-config-change") == 0) {
+ answer->config_change = true;
+ }
+}
+
+static void notif_clb_v2(struct nc_session *session, const struct lyd_node *envp, const struct lyd_node *op, void *user_data)
+{
+ ru_notif_t *answer = (ru_notif_t *)user_data;
+ LYD_FORMAT output_format = LYD_JSON;
+
+ char *subs_reply = NULL;
+ lyd_print_mem(&subs_reply, op, output_format, LYD_PRINT_WITHSIBLINGS);
+ const char *ru_ip_add = nc_session_get_host(session);
+ MP_LOG_I("Received notification from RU \"%s\" at (%s)\n%s\n", ru_ip_add, ((struct lyd_node_opaq *)lyd_child(envp))->value, subs_reply);
+
+ recv_notif_v2((struct lyd_node_inner *)op, answer);
+}
+#endif
+
+bool subscribe_mplane(ru_session_t *ru_session, const char *stream, const char *filter, void *answer)
+{
+ int timeout = CLI_RPC_REPLY_TIMEOUT;
+ struct nc_rpc *rpc;
+ NC_WD_MODE wd = NC_WD_ALL;
+ NC_PARAMTYPE param = NC_PARAMTYPE_CONST;
+ char *start_time = NULL, *stop_time = NULL;
+
+ MP_LOG_I("RPC request to RU \"%s\" = with stream \"%s\" and filter \"%s\".\n", ru_session->ru_ip_add, stream, filter);
+ rpc = nc_rpc_subscribe(stream, NULL, start_time, stop_time, param);
+ AssertError(rpc != NULL, return false, "[MPLANE] RPC creation failed.\n");
+
+ /* create notification thread so that notifications can immediately be received */
+#ifdef MPLANE_V1
+ if (!nc_session_ntf_thread_running(ru_session->session)) {
+ nc_session_set_data(ru_session->session, answer);
+ int ret = nc_recv_notif_dispatch(ru_session->session, notif_clb_v1);
+ AssertError(ret == 0, return false, "[MPLANE] Failed to create notification thread.\n");
+ } else {
+ MP_LOG_I("Notification thread is already running for RU %s.\n", ru_session->ru_ip_add);
+ }
+#elif MPLANE_V2
+ int ret = nc_recv_notif_dispatch_data(ru_session->session, notif_clb_v2, answer, NULL);
+ AssertError(ret == 0, return false, "[MPLANE] Failed to create notification thread.\n");
+#endif
+
+ bool success = rpc_send_recv((struct nc_session *)ru_session->session, rpc, wd, timeout, NULL);
+ AssertError(success, return false, "[MPLANE] Failed to subscribe to: stream \"%s\", filter \"%s\".\n", stream, filter);
+
+ MP_LOG_I("Successfully subscribed to all notifications from RU \"%s\".\n", ru_session->ru_ip_add);
+
+ nc_rpc_free(rpc);
+
+ return true;
+}
+
+bool update_timer_mplane(ru_session_t *ru_session, char **answer)
+{
+ int timeout = CLI_RPC_REPLY_TIMEOUT;
+ struct nc_rpc *rpc;
+ NC_WD_MODE wd = NC_WD_ALL;
+ NC_PARAMTYPE param = NC_PARAMTYPE_CONST;
+ const char *content = "\n\
+65535\n\
+65535\n\
+";
+
+ MP_LOG_I("RPC request to RU \"%s\" = \"%s\".\n", ru_session->ru_ip_add, content);
+ rpc = nc_rpc_act_generic_xml(content, param);
+ AssertError(rpc != NULL, return false, "[MPLANE] RPC creation failed.\n");
+
+ bool success = rpc_send_recv((struct nc_session *)ru_session->session, rpc, wd, timeout, answer);
+ AssertError(success, return false, "[MPLANE] Failed to update the watchdog timer.\n");
+
+ MP_LOG_I("Successfully updated supervision timer to (65535+65535)[s] for RU \"%s\".\n", ru_session->ru_ip_add);
+
+ nc_rpc_free(rpc);
+
+ return true;
+}
diff --git a/radio/fhi_72/mplane/subscribe-mplane.h b/radio/fhi_72/mplane/subscribe-mplane.h
new file mode 100644
index 0000000000..6cb7a10310
--- /dev/null
+++ b/radio/fhi_72/mplane/subscribe-mplane.h
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#ifndef SUBSCRIBE_MPLANE_H
+#define SUBSCRIBE_MPLANE_H
+
+#include "ru-mplane-api.h"
+
+#include
+
+bool subscribe_mplane(ru_session_t *ru_session, const char *stream, const char *filter, void *answer);
+
+bool update_timer_mplane(ru_session_t *ru_session, char **answer);
+
+#endif /* SUBSCRIBE_MPLANE_H */
diff --git a/radio/fhi_72/mplane/xml/get-xml.c b/radio/fhi_72/mplane/xml/get-xml.c
new file mode 100644
index 0000000000..616d2e480f
--- /dev/null
+++ b/radio/fhi_72/mplane/xml/get-xml.c
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#include "get-xml.h"
+
+#include
+#include
+
+static char *find_ru_xml_node(xmlNode *node, const char *filter)
+{
+ for (xmlNode *cur_node = node; cur_node; cur_node = cur_node->next) {
+ if (cur_node->type != XML_ELEMENT_NODE)
+ continue;
+
+ if (strcmp((const char *)cur_node->name, filter) == 0) {
+ xmlNode *target_node = cur_node;
+
+ for(xmlNode *cur_node2 = cur_node->children; cur_node2; cur_node2 = cur_node2->next) {
+ if (cur_node2->type == XML_ELEMENT_NODE && strcmp((const char *)cur_node2->name, "name") == 0) {
+ target_node = cur_node2;
+ break;
+ }
+ }
+ return (char *)xmlNodeGetContent(target_node);
+ }
+ char *answer = find_ru_xml_node(cur_node->children, filter);
+ if (answer != NULL) {
+ return answer;
+ }
+ }
+ return NULL;
+}
+
+char *get_ru_xml_node(const char *buffer, const char *filter)
+{
+ // Initialize the xml file
+ size_t len = strlen(buffer) + 1;
+ xmlDoc *doc = xmlReadMemory(buffer, len, NULL, NULL, 0);
+ xmlNode *root_element = xmlDocGetRootElement(doc);
+
+ return find_ru_xml_node(root_element->children, filter);
+}
+
+static void find_ru_xml_list(xmlNode *node, const char *filter, char ***match_list, size_t *count)
+{
+ for (xmlNode *cur_node = node; cur_node; cur_node = cur_node->next) {
+ if (cur_node->type != XML_ELEMENT_NODE)
+ continue;
+ if (strcmp((const char *)cur_node->name, filter) == 0) {
+ xmlNode *name_node = NULL;
+
+ for (xmlNode *cur_node2 = cur_node->children; cur_node2; cur_node2 = cur_node2->next) {
+ if (cur_node2->type == XML_ELEMENT_NODE && strcmp((const char *)cur_node2->name, "name") == 0) {
+ name_node = cur_node2;
+ break;
+ }
+ }
+ const char *content = (const char *)xmlNodeGetContent(name_node ? name_node : cur_node);
+ if (content) {
+ *match_list = realloc(*match_list, (*count + 1) * sizeof(char *));
+ (*match_list)[*count] = strdup(content);
+ (*count)++;
+ }
+ }
+ find_ru_xml_list(cur_node->children, filter, match_list, count);
+ }
+}
+
+void get_ru_xml_list(const char *buffer, const char *filter, char ***match_list, size_t *count)
+{
+ // Initialize the xml file
+ size_t len = strlen(buffer) + 1;
+ xmlDoc *doc = xmlReadMemory(buffer, len, NULL, NULL, 0);
+ xmlNode *root_element = xmlDocGetRootElement(doc);
+
+ find_ru_xml_list(root_element->children, filter, match_list, count);
+}
diff --git a/radio/fhi_72/mplane/xml/get-xml.h b/radio/fhi_72/mplane/xml/get-xml.h
new file mode 100644
index 0000000000..5241e64af6
--- /dev/null
+++ b/radio/fhi_72/mplane/xml/get-xml.h
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#ifndef GET_MPLANE_INFO_XML_H
+#define GET_MPLANE_INFO_XML_H
+
+#include
+#include
+
+/**
+ * @brief retrieves the node value that matches filter.
+ *
+ * @param[in] buffer Buffer in xml format.
+ * @param[in] filter The node name (matching criteria).
+ * @return Expected one string that matches the node name.
+ */
+char *get_ru_xml_node(const char *buffer, const char *filter);
+
+/**
+ * @brief retrieves the node values that matches filter.
+ *
+ * @param[in] buffer Buffer in xml format.
+ * @param[in] filter The node name (matching criteria).
+ * @param[out] match_list Resulting list containing node values.
+ * @param[out] count The number of nodes that match criteria.
+ * @return Void.
+ */
+void get_ru_xml_list(const char *buffer, const char *filter, char ***match_list, size_t *count);
+
+#endif /* GET_MPLANE_INFO_XML_H */
diff --git a/radio/fhi_72/mplane/yang/create-yang-config.c b/radio/fhi_72/mplane/yang/create-yang-config.c
new file mode 100644
index 0000000000..7276b9fae0
--- /dev/null
+++ b/radio/fhi_72/mplane/yang/create-yang-config.c
@@ -0,0 +1,392 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#include "create-yang-config.h"
+#include "common/utils/nr/nr_common.h"
+
+#define VERIFY_SUCCESS(var, message, args...) AssertError(var, return false, message, ##args)
+
+#ifdef MPLANE_V2
+static bool create_cu_interface_v2(struct ly_ctx **ctx, const ru_session_t *ru_session, const size_t idx, const char *int_name, struct lyd_node **root)
+{
+ LY_ERR ret = LY_SUCCESS;
+
+ ret = lyd_new_path(NULL, *ctx, "/ietf-interfaces:interfaces", NULL, 0, root);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create root \"interfaces\" node.\n");
+
+ struct lyd_node *interface_node = NULL;
+ ret = lyd_new_list(*root, NULL, "interface", 0, &interface_node, int_name);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"interface\" node.\n");
+
+ struct lyd_node *type_node = NULL;
+ ret = lyd_new_term(interface_node, NULL, "type", "iana-if-type:l2vlan", 0, &type_node);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"type\" node.\n");
+
+ ret = lyd_new_term(interface_node, NULL, "enabled", "true", 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"enabled\" node.\n");
+
+ const struct lys_module *oran_int_mod = ly_ctx_get_module_implemented(*ctx, "o-ran-interfaces");
+ VERIFY_SUCCESS(oran_int_mod != NULL, "[MPLANE] Failed to get \"o-ran-interfaces\" module.\n");
+
+ struct lyd_node *base_int = NULL;
+ ret = lyd_new_term(interface_node, oran_int_mod, "base-interface", ru_session->ru_mplane_config.interface_name, 0, &base_int);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"base-interface\" node with name \"%s\".\n", ru_session->ru_mplane_config.interface_name);
+
+ struct lyd_node *vlan_id = NULL;
+ char vlan_tag_str[8];
+ snprintf(vlan_tag_str, sizeof(vlan_tag_str), "%d", ru_session->ru_mplane_config.vlan_tag[idx]);
+ ret = lyd_new_term(interface_node, oran_int_mod, "vlan-id", vlan_tag_str, 0, &vlan_id);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"vlan-id\" node with \"%d\".\n", ru_session->ru_mplane_config.vlan_tag[idx]);
+
+ struct lyd_node *ru_mac_addr = NULL;
+ ret = lyd_new_term(interface_node, oran_int_mod, "mac-address", ru_session->xran_mplane.ru_mac_addr, 0, &ru_mac_addr);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"mac-address\" node with \"%s\".\n", ru_session->xran_mplane.ru_mac_addr);
+
+ return true;
+}
+
+static bool create_proc_elem_v2(struct ly_ctx **ctx, const ru_session_t *ru_session, const size_t idx, const char *int_name, struct lyd_node **root)
+{
+ LY_ERR ret = LY_SUCCESS;
+
+ ret = lyd_new_path(NULL, *ctx, "/o-ran-processing-element:processing-elements", NULL, 0, root);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create root \"processing-elements\" node.\n");
+
+ ret = lyd_new_term(*root, NULL, "transport-session-type", "ETH-INTERFACE", 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"transport-session-type\" node.\n");
+
+ struct lyd_node *ru_elem_node = NULL;
+ char plane_name[8];
+ snprintf(plane_name, sizeof(plane_name), "PLANE_%ld", idx);
+ ret = lyd_new_list(*root, NULL, "ru-elements", 0, &ru_elem_node, plane_name);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"ru-elements\" node.\n");
+
+ struct lyd_node *transp_flow = NULL;
+ ret = lyd_new_inner(ru_elem_node, NULL, "transport-flow", 0, &transp_flow);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"transport-flow\" node.\n");
+
+ ret = lyd_new_term(transp_flow, NULL, "interface-name", int_name, 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"interface-name\" node.\n");
+
+ struct lyd_node *eth_flow = NULL;
+ ret = lyd_new_inner(transp_flow, NULL, "eth-flow", 0, ð_flow);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"eth-flow\" node.\n");
+
+ char vlan_tag_str[8];
+ snprintf(vlan_tag_str, sizeof(vlan_tag_str), "%d", ru_session->ru_mplane_config.vlan_tag[idx]);
+ ret = lyd_new_term(eth_flow, NULL, "vlan-id", vlan_tag_str, 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"vlan-id\" node.\n");
+
+ ret = lyd_new_term(eth_flow, NULL, "ru-mac-address", ru_session->xran_mplane.ru_mac_addr, 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"ru-mac-address\" node.\n");
+
+ ret = lyd_new_term(eth_flow, NULL, "o-du-mac-address", ru_session->ru_mplane_config.du_mac_addr[idx], 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"o-du-mac-address\" node.\n");
+
+ return true;
+}
+
+static bool fill_uplane_ch_v2(const xran_mplane_t *xran_mplane, const size_t idx, struct lyd_node **root)
+{
+ LY_ERR ret = LY_SUCCESS;
+
+ ret = lyd_new_term(*root, NULL, "cp-length", "0", 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"cp-length\" node.\n");
+
+ ret = lyd_new_term(*root, NULL, "cp-length-other", "0", 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"cp-length-other\" node.\n");
+
+ // to we actually store this from DU config file?
+ ret = lyd_new_term(*root, NULL, "offset-to-absolute-frequency-center", "0", 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"offset-to-absolute-frequency-center\" node.\n");
+
+ struct lyd_node *compression_node = NULL;
+ ret = lyd_new_inner(*root, NULL, "compression", 0, &compression_node);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"compression\" node.\n");
+
+ char iq_width_str[8];
+ snprintf(iq_width_str, sizeof(iq_width_str), "%d", xran_mplane->iq_width);
+ ret = lyd_new_term(compression_node, NULL, "iq-bitwidth", iq_width_str, 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"iq-bitwidth\" node.\n");
+
+ if (xran_mplane->iq_width < 16) {
+ ret = lyd_new_term(compression_node, NULL, "compression-type", "STATIC", 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"compression-type\" node.\n");
+
+ // ret = lyd_new_term(compression_node, NULL, "compression-method", "BLOCK_FLOATING_POINT", 0, NULL);
+ // VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"compression-method\" node.\n");
+ }
+
+ struct lyd_node *eaxc_conf = NULL;
+ ret = lyd_new_inner(*root, NULL, "e-axcid", 0, &eaxc_conf);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"e-axcid\" node.\n");
+
+ char eaxc_id[8];
+ snprintf(eaxc_id, sizeof(eaxc_id), "%ld", idx);
+ ret = lyd_new_term(eaxc_conf, NULL, "eaxc-id", eaxc_id, 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"eaxc-id\" node.\n");
+
+ char du_port_bitmask[16];
+ snprintf(du_port_bitmask, sizeof(du_port_bitmask), "%d", xran_mplane->du_port_bitmask);
+ ret = lyd_new_term(eaxc_conf, NULL, "o-du-port-bitmask", du_port_bitmask, 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"o-du-port-bitmask\" node.\n");
+
+ char band_sector_bitmask[8];
+ snprintf(band_sector_bitmask, sizeof(band_sector_bitmask), "%d", xran_mplane->band_sector_bitmask);
+ ret = lyd_new_term(eaxc_conf, NULL, "band-sector-bitmask", band_sector_bitmask, 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"band-sector-bitmask\" node.\n");
+
+ char ccid_bitmask[8];
+ snprintf(ccid_bitmask, sizeof(ccid_bitmask), "%d", xran_mplane->ccid_bitmask);
+ ret = lyd_new_term(eaxc_conf, NULL, "ccid-bitmask", ccid_bitmask, 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"ccid-bitmask\" node.\n");
+
+ char ru_port_bitmask[8];
+ snprintf(ru_port_bitmask, sizeof(ru_port_bitmask), "%d", xran_mplane->ru_port_bitmask);
+ ret = lyd_new_term(eaxc_conf, NULL, "ru-port-bitmask", ru_port_bitmask, 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"ru-port-bitmask\" node.\n");
+
+ return true;
+}
+
+static bool create_uplane_conf_v2(struct ly_ctx **ctx, const ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus, const char *u_proc_elem, struct lyd_node **root)
+{
+ LY_ERR ret = LY_SUCCESS;
+ bool success = true;
+
+ ret = lyd_new_path(NULL, *ctx, "/o-ran-uplane-conf:user-plane-configuration", NULL, 0, root);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create root \"user-plane-configuration\" node.\n");
+
+ if (ru_session->ru_mplane_config.rx_carriers.num != 1 || ru_session->ru_mplane_config.tx_carriers.num !=1)
+ MP_LOG_I("Only one carrier supported at the moment.\n");
+
+ // RX carriers
+ struct lyd_node *rx_carrier_node = NULL;
+ ret = lyd_new_list(*root, NULL, "rx-array-carriers", 0, &rx_carrier_node, ru_session->ru_mplane_config.rx_carriers.name[0]);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"rx-array-carriers\" node.\n");
+
+ char rx_freq[16];
+ snprintf(rx_freq, sizeof(rx_freq), "%.0f", oai->rx_freq[0]);
+ ret = lyd_new_term(rx_carrier_node, NULL, "center-of-channel-bandwidth", rx_freq, 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"center-of-channel-bandwidth\" node.\n");
+
+ char rx_arfcn[16];
+ snprintf(rx_arfcn, sizeof(rx_arfcn), "%d", to_nrarfcn(oai->nr_band, oai->rx_freq[0], oai->nr_scs_for_raster, oai->rx_bw));
+ ret = lyd_new_term(rx_carrier_node, NULL, "absolute-frequency-center", rx_arfcn, 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"absolute-frequency-center\" node.\n");
+
+ char rx_bw[16];
+ snprintf(rx_bw, sizeof(rx_bw), "%.0f", oai->rx_bw);
+ ret = lyd_new_term(rx_carrier_node, NULL, "channel-bandwidth", rx_bw, 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"channel-bandwidth\" node.\n");
+
+ ret = lyd_new_term(rx_carrier_node, NULL, "downlink-radio-frame-offset", "0", 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"downlink-radio-frame-offset\" node.\n");
+
+ ret = lyd_new_term(rx_carrier_node, NULL, "downlink-sfn-offset", "0", 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"downlink-sfn-offset\" node.\n");
+
+ // oai->rx_gain_offset is this the correction? if yes, test it later
+ ret = lyd_new_term(rx_carrier_node, NULL, "gain-correction", "0", 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"gain-correction\" node.\n");
+
+ ret = lyd_new_term(rx_carrier_node, NULL, "n-ta-offset", "0", 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"n-ta-offset\" node.\n");
+
+ ret = lyd_new_term(rx_carrier_node, NULL, "active", "ACTIVE", 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"active\" node.\n");
+
+ // TX carriers
+ struct lyd_node *tx_carrier_node = NULL;
+ ret = lyd_new_list(*root, NULL, "tx-array-carriers", 0, &tx_carrier_node, ru_session->ru_mplane_config.tx_carriers.name[0]);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"tx-array-carriers\" node.\n");
+
+ char tx_freq[16];
+ snprintf(tx_freq, sizeof(tx_freq), "%.0f", oai->tx_freq[0]);
+ ret = lyd_new_term(tx_carrier_node, NULL, "center-of-channel-bandwidth", tx_freq, 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"center-of-channel-bandwidth\" node.\n");
+
+ char tx_arfcn[16];
+ snprintf(tx_arfcn, sizeof(tx_arfcn), "%d", to_nrarfcn(oai->nr_band, oai->tx_freq[0], oai->nr_scs_for_raster, oai->tx_bw));
+ ret = lyd_new_term(tx_carrier_node, NULL, "absolute-frequency-center", tx_arfcn, 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"absolute-frequency-center\" node.\n");
+
+ char tx_bw[16];
+ snprintf(tx_bw, sizeof(tx_bw), "%.0f", oai->tx_bw);
+ ret = lyd_new_term(tx_carrier_node, NULL, "channel-bandwidth", tx_bw, 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"channel-bandwidth\" node.\n");
+
+ // oai->tx_gain to be tested
+ ret = lyd_new_term(tx_carrier_node, NULL, "gain", "0", 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"gain\" node.\n");
+
+ ret = lyd_new_term(tx_carrier_node, NULL, "downlink-radio-frame-offset", "0", 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"downlink-radio-frame-offset\" node.\n");
+
+ ret = lyd_new_term(tx_carrier_node, NULL, "downlink-sfn-offset", "0", 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"downlink-sfn-offset\" node.\n");
+
+ ret = lyd_new_term(tx_carrier_node, NULL, "active", "ACTIVE", 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"active\" node.\n");
+
+ // PUSCH & PRACH endpoints
+ const size_t num_rx_ch = oai->rx_num_channels / num_rus;
+ for (size_t i = 0; i < num_rx_ch; i++) {
+ struct lyd_node *pusch_node = NULL;
+ ret = lyd_new_list(*root, NULL, "low-level-rx-endpoints", 0, &pusch_node, ru_session->ru_mplane_config.rx_endpoints.name[i]);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"low-level-rx-endpoints\" node.\n");
+
+ success = fill_uplane_ch_v2(&ru_session->xran_mplane, i, &pusch_node);
+ VERIFY_SUCCESS(success, "[MPLANE] Failed to fill \"low-level-rx-endpoints\" node for %s.\n", ru_session->ru_mplane_config.rx_endpoints.name[i]);
+
+ const size_t prach_endpoint_name_offset = i + (ru_session->ru_mplane_config.rx_endpoints.num / 2);
+ struct lyd_node *prach_node = NULL;
+ ret = lyd_new_list(*root, NULL, "low-level-rx-endpoints", 0, &prach_node, ru_session->ru_mplane_config.rx_endpoints.name[prach_endpoint_name_offset]);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"low-level-rx-endpoints\" node.\n");
+
+ success = fill_uplane_ch_v2(&ru_session->xran_mplane, i + ru_session->xran_mplane.prach_offset, &prach_node);
+ VERIFY_SUCCESS(success, "[MPLANE] Failed to fill \"low-level-rx-endpoints\" node for %s.\n", ru_session->ru_mplane_config.rx_endpoints.name[prach_endpoint_name_offset]);
+ }
+
+ // PDSCH endpoints
+ const size_t num_tx_ch = oai->tx_num_channels / num_rus;
+ for (size_t i = 0; i < num_tx_ch; i++) {
+ struct lyd_node *pdsch_node = NULL;
+ ret = lyd_new_list(*root, NULL, "low-level-tx-endpoints", 0, &pdsch_node, ru_session->ru_mplane_config.tx_endpoints.name[i]);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"low-level-tx-endpoints\" node.\n");
+
+ success = fill_uplane_ch_v2(&ru_session->xran_mplane, i, &pdsch_node);
+ VERIFY_SUCCESS(success, "[MPLANE] Failed to fill \"low-level-tx-endpoints\" node for %s.\n", ru_session->ru_mplane_config.tx_endpoints.name[i]);
+ }
+
+ // PUSCH and PRACH links
+ for (size_t i = 0; i < num_rx_ch; i++) {
+ // PUSCH
+ struct lyd_node *pusch_link_node = NULL;
+ char pusch_link[16];
+ snprintf(pusch_link, sizeof(pusch_link), "%s%ld", "PuschLink", i);
+ ret = lyd_new_list(*root, NULL, "low-level-rx-links", 0, &pusch_link_node, pusch_link);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"low-level-rx-links\" node.\n");
+
+ ret = lyd_new_term(pusch_link_node, NULL, "processing-element", u_proc_elem, 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"processing-element\" node.\n");
+
+ ret = lyd_new_term(pusch_link_node, NULL, "rx-array-carrier", ru_session->ru_mplane_config.rx_carriers.name[0], 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"rx-array-carrier\" node.\n");
+
+ ret = lyd_new_term(pusch_link_node, NULL, "low-level-rx-endpoint", ru_session->ru_mplane_config.rx_endpoints.name[i], 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"low-level-rx-endpoint\" node.\n");
+
+ // PRACH
+ struct lyd_node *prach_link_node = NULL;
+ char prach_link[16];
+ snprintf(prach_link, sizeof(prach_link), "%s%ld", "PrachLink", i);
+ ret = lyd_new_list(*root, NULL, "low-level-rx-links", 0, &prach_link_node, prach_link);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"low-level-rx-links\" node.\n");
+
+ ret = lyd_new_term(prach_link_node, NULL, "processing-element", u_proc_elem, 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"processing-element\" node.\n");
+
+ ret = lyd_new_term(prach_link_node, NULL, "rx-array-carrier", ru_session->ru_mplane_config.rx_carriers.name[0], 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"rx-array-carrier\" node.\n");
+
+ const size_t prach_endpoint_name_offset = i + (ru_session->ru_mplane_config.rx_endpoints.num / 2);
+ ret = lyd_new_term(prach_link_node, NULL, "low-level-rx-endpoint", ru_session->ru_mplane_config.rx_endpoints.name[prach_endpoint_name_offset], 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"low-level-rx-endpoint\" node.\n");
+ }
+
+ // PDSCH links
+ for (size_t i = 0; i < num_tx_ch; i++) {
+ struct lyd_node *pdsch_link_node = NULL;
+ char pdsch_link[16];
+ snprintf(pdsch_link, sizeof(pdsch_link), "%s%ld", "PdschLink", i);
+ ret = lyd_new_list(*root, NULL, "low-level-tx-links", 0, &pdsch_link_node, pdsch_link);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"low-level-tx-links\" node.\n");
+
+ ret = lyd_new_term(pdsch_link_node, NULL, "processing-element", u_proc_elem, 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"processing-element\" node.\n");
+
+ ret = lyd_new_term(pdsch_link_node, NULL, "tx-array-carrier", ru_session->ru_mplane_config.tx_carriers.name[0], 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"tx-array-carrier\" node.\n");
+
+ ret = lyd_new_term(pdsch_link_node, NULL, "low-level-tx-endpoint", ru_session->ru_mplane_config.tx_endpoints.name[i], 0, NULL);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"low-level-tx-endpoint\" node.\n");
+ }
+
+ return true;
+}
+#endif
+
+bool configure_ru_from_yang(struct ly_ctx **ctx, const ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus, char **result)
+{
+ bool success = false;
+
+#ifdef MPLANE_V1
+ VERIFY_SUCCESS(success, "[MPLANE] To be implemented and tested.\n");
+#elif defined MPLANE_V2
+ const ru_mplane_config_t *ru_config = &ru_session->ru_mplane_config;
+ size_t num_cu_planes = ru_config->num_cu_planes;
+ if (num_cu_planes == 2 && ru_config->vlan_tag[0] == ru_config->vlan_tag[1]) {
+ MP_LOG_I("The VLAN tags for C and U plane for the RU \"%s\" are the same. Therefore, configuring one common interface and one processing element.\n", ru_session->ru_ip_add);
+ num_cu_planes = 1;
+ }
+
+ struct lyd_node *all_merge = NULL;
+ LY_ERR ret = LY_SUCCESS;
+
+ for (size_t i = 0; i < num_cu_planes; i++) {
+ //
+ struct lyd_node *cu_interface = NULL;
+ char int_name[12];
+ snprintf(int_name, sizeof(int_name), "INTERFACE_%ld", i);
+ success = create_cu_interface_v2(ctx, ru_session, i, int_name, &cu_interface);
+ VERIFY_SUCCESS(success, "[MPLANE] Cannot create CU-plane interface.\n");
+
+ //
+ struct lyd_node *proc_elem = NULL;
+ success = create_proc_elem_v2(ctx, ru_session, i, int_name, &proc_elem);
+ VERIFY_SUCCESS(success, "[MPLANE] Cannot create CU-plane processing element.\n");
+
+ ret = lyd_merge_siblings(&all_merge, cu_interface, 0);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Cannot merge CU-plane interface.\n");
+ ret = lyd_merge_siblings(&all_merge, proc_elem, 0);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Cannot merge processing element.\n");
+
+ lyd_free_tree(cu_interface);
+ lyd_free_tree(proc_elem);
+ }
+
+ //
+ struct lyd_node *uplane_conf = NULL;
+ success = create_uplane_conf_v2(ctx, ru_session, oai, num_rus, "PLANE_0", &uplane_conf);
+ VERIFY_SUCCESS(success, "[MPLANE] Cannot create U-plane configuration.\n");
+
+ ret = lyd_merge_siblings(&uplane_conf, all_merge, 0);
+ VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Cannot merge CU-plane interface, processing element and U-plane configuration.\n");
+
+ lyd_print_mem(result, uplane_conf, LYD_XML, LYD_PRINT_WITHSIBLINGS);
+
+ lyd_free_siblings(all_merge);
+ lyd_free_siblings(uplane_conf);
+#endif
+
+ return true;
+}
diff --git a/radio/fhi_72/mplane/yang/create-yang-config.h b/radio/fhi_72/mplane/yang/create-yang-config.h
new file mode 100644
index 0000000000..9e06bdc923
--- /dev/null
+++ b/radio/fhi_72/mplane/yang/create-yang-config.h
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#ifndef CREATE_MPLANE_YANG_CONFIG_H
+#define CREATE_MPLANE_YANG_CONFIG_H
+
+#include "../ru-mplane-api.h"
+#include "radio/COMMON/common_lib.h"
+
+#include
+
+bool configure_ru_from_yang(struct ly_ctx **ctx, const ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus, char **result);
+
+#endif /* CREATE_MPLANE_YANG_CONFIG_H */
diff --git a/radio/fhi_72/mplane/yang/get-yang.c b/radio/fhi_72/mplane/yang/get-yang.c
new file mode 100644
index 0000000000..c27454136f
--- /dev/null
+++ b/radio/fhi_72/mplane/yang/get-yang.c
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#include "get-yang.h"
+#include "../rpc-send-recv.h"
+#include "common/utils/assertions.h"
+
+#include
+
+static bool store_schemas(xmlNode *node, ru_session_t *ru_session, struct ly_ctx **ctx)
+{
+ int timeout = CLI_RPC_REPLY_TIMEOUT;
+ NC_WD_MODE wd = NC_WD_ALL;
+ NC_PARAMTYPE param = NC_PARAMTYPE_CONST;
+ LYS_INFORMAT ly_format = LYS_IN_YANG;
+
+#ifdef MPLANE_V1
+ *ctx = ly_ctx_new(NULL, 0);
+#elif defined MPLANE_V2
+ ly_ctx_new(NULL, 0, ctx);
+#endif
+
+ for (xmlNode *cur_node = node; cur_node; cur_node = cur_node->next) {
+ if (strcmp((const char *)cur_node->name, "schema") == 0) {
+
+ xmlNode *name_node = xmlFirstElementChild(cur_node);
+ char *module_name = (char *)xmlNodeGetContent(name_node);
+ xmlNode *revision_node = xmlNextElementSibling(name_node);
+ char *module_revision = (char *)xmlNodeGetContent(revision_node);
+ xmlNode *format_node = xmlNextElementSibling(revision_node);
+ char *module_format = (char *)xmlNodeGetContent(format_node);
+
+ if (strcmp(module_format, "yang") != 0)
+ continue;
+
+ MP_LOG_I("RPC request to RU \"%s\" = for module \"%s\".\n", ru_session->ru_ip_add, module_name);
+ struct nc_rpc *get_schema_rpc = nc_rpc_getschema(module_name, module_revision, "yang", param);
+ char *schema_data = NULL;
+ bool success = rpc_send_recv((struct nc_session *)ru_session->session, get_schema_rpc, wd, timeout, &schema_data);
+ AssertError(success, return false, "[MPLANE] Unable to get schema for module \"%s\" from RU \"%s\".\n", module_name, ru_session->ru_ip_add);
+
+ if (schema_data) {
+#ifdef MPLANE_V1
+ const struct lys_module *mod = lys_parse_mem(*ctx, schema_data, ly_format);
+#elif defined MPLANE_V2
+ struct lys_module *mod = NULL;
+ lys_parse_mem(*ctx, schema_data, ly_format, &mod);
+#endif
+ free(schema_data);
+ if (!mod) {
+ MP_LOG_W("Unable to load module \"%s\" from RU \"%s\".\n", module_name, ru_session->ru_ip_add);
+ nc_rpc_free(get_schema_rpc);
+ ly_ctx_destroy(*ctx);
+ return false;
+ }
+ }
+ nc_rpc_free(get_schema_rpc);
+ }
+ }
+
+ return true;
+}
+
+static bool load_from_operational_ds(xmlNode *node, ru_session_t *ru_session, struct ly_ctx **ctx)
+{
+ for (xmlNode *schemas_node = node; schemas_node; schemas_node = schemas_node->next) {
+ if(schemas_node->type != XML_ELEMENT_NODE)
+ continue;
+ if (strcmp((const char *)schemas_node->name, "schemas") == 0) {
+ return store_schemas(schemas_node->children, ru_session, ctx);
+ } else {
+ bool success = load_from_operational_ds(schemas_node->children, ru_session, ctx);
+ if (success)
+ return true;
+ }
+ }
+ return false;
+}
+
+bool load_yang_models(ru_session_t *ru_session, const char *buffer, struct ly_ctx **ctx)
+{
+ // Initialize the xml file
+ size_t len = strlen(buffer) + 1;
+ xmlDoc *doc = xmlReadMemory(buffer, len, NULL, NULL, 0);
+ xmlNode *root_element = xmlDocGetRootElement(doc);
+
+ bool success = load_from_operational_ds(root_element->children, ru_session, ctx);
+ if (success) {
+ MP_LOG_I("Successfully loaded all yang modules from operational datastore for RU \"%s\".\n", ru_session->ru_ip_add);
+ return true;
+ } else {
+ MP_LOG_W("Unable to load all yang modules from operational datastore for RU \"%s\". Using yang models present in \"models\" subfolder.\n", ru_session->ru_ip_add);
+ }
+
+ /* ideally, we should load the yang models from the operational datastore, but the issues are following:
+ 1) the yang models order is not good - the dependancy models have to be loaded first
+ 2) earlier O-RAN yang versions (e.g. v4) is not properly defined (i.e. optional parameters should not be included by default) */
+ const char *yang_dir = YANG_MODELS;
+ const char *yang_models[] = {"ietf-interfaces", "iana-if-type", "ietf-ip", "iana-hardware", "ietf-hardware", "o-ran-interfaces", "o-ran-module-cap", "o-ran-compression-factors", "o-ran-processing-element", "o-ran-uplane-conf"};
+
+#ifdef MPLANE_V1
+ *ctx = ly_ctx_new(yang_dir, 0);
+ AssertError(*ctx != NULL, return false, "[MPLANE] Unable to create libyang context: %s.\n", ly_errmsg(*ctx));
+#elif defined MPLANE_V2
+ LY_ERR ret = ly_ctx_new(yang_dir, 0, ctx);
+ AssertError(ret == LY_SUCCESS, return false, "[MPLANE] Unable to create libyang context: %s.\n", ly_errmsg(*ctx));
+#endif
+
+ const size_t num_models = sizeof(yang_models) / sizeof(yang_models[0]);
+ for (size_t i = 0; i < num_models; ++i) {
+#ifdef MPLANE_V1
+ const struct lys_module *mod = ly_ctx_load_module(*ctx, yang_models[i], NULL);
+ AssertError(mod != NULL, return false, "[MPLANE] Failed to load yang model %s.\n", yang_models[i]);
+#elif defined MPLANE_V2
+ const struct lys_module *mod = ly_ctx_load_module(*ctx, yang_models[i], NULL, NULL);
+ AssertError(mod != NULL, return false, "[MPLANE] Failed to load yang model %s.\n", yang_models[i]);
+#endif
+ }
+
+ MP_LOG_I("Successfully loaded all yang modules for RU \"%s\".\n", ru_session->ru_ip_add);
+
+ return true;
+}
diff --git a/radio/fhi_72/mplane/yang/get-yang.h b/radio/fhi_72/mplane/yang/get-yang.h
new file mode 100644
index 0000000000..5956bde203
--- /dev/null
+++ b/radio/fhi_72/mplane/yang/get-yang.h
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#ifndef GET_MPLANE_YANG_MODELS_H
+#define GET_MPLANE_YANG_MODELS_H
+
+#include "../ru-mplane-api.h"
+
+#include
+
+bool load_yang_models(ru_session_t *ru_session, const char *buffer, struct ly_ctx **ctx);
+
+#endif /* GET_MPLANE_YANG_MODELS_H */
diff --git a/radio/fhi_72/mplane/yang/models/iana-hardware.yang b/radio/fhi_72/mplane/yang/models/iana-hardware.yang
new file mode 100755
index 0000000000..52bcaf3a03
--- /dev/null
+++ b/radio/fhi_72/mplane/yang/models/iana-hardware.yang
@@ -0,0 +1,180 @@
+module iana-hardware {
+yang-version 1.1;
+namespace "urn:ietf:params:xml:ns:yang:iana-hardware";
+prefix ianahw;
+
+organization "IANA";
+contact
+ " Internet Assigned Numbers Authority
+ Postal: ICANN
+ 12025 Waterfront Drive, Suite 300
+ Los Angeles, CA 90094-2536
+ United States of America
+ Tel: +1 310 301 5800
+ E-Mail: iana@iana.org>";
+
+description
+ "IANA-defined identities for hardware class.
+ The latest revision of this YANG module can be obtained from
+ the IANA website.
+ Requests for new values should be made to IANA via
+ email (iana@iana.org).
+ Copyright (c) 2018 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+ Redistribution and use in source and binary forms, with or
+ without modification, is permitted pursuant to, and subject
+ to the license terms contained in, the Simplified BSD License
+ set forth in Section 4.c of the IETF Trust's Legal Provisions
+ Relating to IETF Documents
+ (https://trustee.ietf.org/license-info).
+ The initial version of this YANG module is part of RFC 8348;
+ see the RFC itself for full legal notices.";
+reference
+ "https://www.iana.org/assignments/yang-parameters";
+
+revision 2018-03-13 {
+ description
+ "Initial revision.";
+ reference
+ "RFC 8348: A YANG Data Model for Hardware Management";
+}
+
+/*
+ * Identities
+ */
+
+identity hardware-class {
+ description
+ "This identity is the base for all hardware class
+ identifiers.";
+}
+
+identity unknown {
+ base ianahw:hardware-class;
+ description
+ "This identity is applicable if the hardware class is unknown
+ to the server.";
+}
+
+identity chassis {
+ base ianahw:hardware-class;
+ description
+ "This identity is applicable if the hardware class is an
+ overall container for networking equipment. Any class of
+ physical component, except a stack, may be contained within a
+ chassis; a chassis may only be contained within a stack.";
+}
+
+identity backplane {
+ base ianahw:hardware-class;
+ description
+ "This identity is applicable if the hardware class is some sort
+ of device for aggregating and forwarding networking traffic,
+ such as a shared backplane in a modular ethernet switch. Note
+ that an implementation may model a backplane as a single
+ physical component, which is actually implemented as multiple
+ discrete physical components (within a chassis or stack).";
+}
+
+identity container {
+ base ianahw:hardware-class;
+ description
+ "This identity is applicable if the hardware class is capable
+ of containing one or more removable physical entities,
+ possibly of different types. For example, each (empty or
+ full) slot in a chassis will be modeled as a container. Note
+ that all removable physical components should be modeled
+ within a container component, such as field-replaceable
+ modules, fans, or power supplies. Note that all known
+ containers should be modeled by the agent, including empty
+ containers.";
+}
+
+identity power-supply {
+ base ianahw:hardware-class;
+ description
+ "This identity is applicable if the hardware class is a
+ power-supplying component.";
+}
+
+identity fan {
+ base ianahw:hardware-class;
+ description
+ "This identity is applicable if the hardware class is a fan or
+ other heat-reduction component.";
+}
+
+identity sensor {
+ base ianahw:hardware-class;
+ description
+ "This identity is applicable if the hardware class is some sort
+ of sensor, such as a temperature sensor within a router
+ chassis.";
+}
+
+identity module {
+ base ianahw:hardware-class;
+ description
+ "This identity is applicable if the hardware class is some sort
+ of self-contained sub-system. If a module component is
+ removable, then it should be modeled within a container
+ component; otherwise, it should be modeled directly within
+ another physical component (e.g., a chassis or another
+ module).";
+}
+
+identity port {
+ base ianahw:hardware-class;
+ description
+ "This identity is applicable if the hardware class is some sort
+ of networking port capable of receiving and/or transmitting
+ networking traffic.";
+}
+
+identity stack {
+ base ianahw:hardware-class;
+ description
+ "This identity is applicable if the hardware class is some sort
+ of super-container (possibly virtual) intended to group
+ together multiple chassis entities. A stack may be realized
+ by a virtual cable, a real interconnect cable attached to
+ multiple chassis, or multiple interconnect cables. A stack
+ should not be modeled within any other physical components,
+ but a stack may be contained within another stack. Only
+ chassis components should be contained within a stack.";
+}
+
+identity cpu {
+ base ianahw:hardware-class;
+ description
+ "This identity is applicable if the hardware class is some sort
+ of central processing unit.";
+}
+
+identity energy-object {
+ base ianahw:hardware-class;
+ description
+ "This identity is applicable if the hardware class is some sort
+ of energy object, i.e., it is a piece of equipment that is
+ part of or attached to a communications network that is
+ monitored, it is controlled, or it aids in the management of
+ another device for Energy Management.";
+}
+
+identity battery {
+ base ianahw:hardware-class;
+ description
+ "This identity is applicable if the hardware class is some sort
+ of battery.";
+}
+
+identity storage-drive {
+ base ianahw:hardware-class;
+ description
+ "This identity is applicable if the hardware class is some sort
+ of component with data storage capability as its main
+ functionality, e.g., hard disk drive (HDD), solid-state device
+ (SSD), solid-state hybrid drive (SSHD), object storage device
+ (OSD), or other.";
+}
+}
diff --git a/radio/fhi_72/mplane/yang/models/iana-if-type.yang b/radio/fhi_72/mplane/yang/models/iana-if-type.yang
new file mode 100644
index 0000000000..24d04e60fe
--- /dev/null
+++ b/radio/fhi_72/mplane/yang/models/iana-if-type.yang
@@ -0,0 +1,1611 @@
+module iana-if-type {
+ namespace "urn:ietf:params:xml:ns:yang:iana-if-type";
+ prefix ianaift;
+
+ import ietf-interfaces {
+ prefix if;
+ }
+
+ organization "IANA";
+ contact
+ " Internet Assigned Numbers Authority
+ Postal: ICANN
+ 12025 Waterfront Drive, Suite 300
+ Los Angeles, CA 90094-2536
+ United States
+ Tel: +1 310 301 5800
+ ";
+ description
+ "This YANG module defines YANG identities for IANA-registered
+ interface types.
+ This YANG module is maintained by IANA and reflects the
+ 'ifType definitions' registry.
+ The latest revision of this YANG module can be obtained from
+ the IANA web site.
+ Requests for new values should be made to IANA via
+ email (iana&iana.org).
+ Copyright (c) 2014 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+ Redistribution and use in source and binary forms, with or
+ without modification, is permitted pursuant to, and subject
+ to the license terms contained in, the Simplified BSD License
+ set forth in Section 4.c of the IETF Trust's Legal Provisions
+ Relating to IETF Documents
+ (http://trustee.ietf.org/license-info).
+ The initial version of this YANG module is part of RFC 7224;
+ see the RFC itself for full legal notices.";
+ reference
+ "IANA 'ifType definitions' registry.
+ ";
+
+ revision 2017-01-19 {
+ description
+ "Registered ifType 289.";
+ }
+
+ revision 2016-11-23 {
+ description
+ "Registered ifTypes 283-288.";
+ }
+
+ revision 2016-06-09 {
+ description
+ "Registered ifType 282.";
+ }
+ revision 2016-05-03 {
+ description
+ "Registered ifType 281.";
+ }
+ revision 2015-06-12 {
+ description
+ "Corrected formatting issue.";
+ }
+ revision 2014-09-24 {
+ description
+ "Registered ifType 280.";
+ }
+ revision 2014-09-19 {
+ description
+ "Registered ifType 279.";
+ }
+ revision 2014-07-03 {
+ description
+ "Registered ifTypes 277-278.";
+ }
+ revision 2014-05-19 {
+ description
+ "Updated the contact address.";
+ }
+ revision 2014-05-08 {
+ description
+ "Initial revision.";
+ reference
+ "RFC 7224: IANA Interface Type YANG Module";
+ }
+
+ identity iana-interface-type {
+ base if:interface-type;
+ description
+ "This identity is used as a base for all interface types
+ defined in the 'ifType definitions' registry.";
+ }
+
+ identity other {
+ base iana-interface-type;
+ }
+ identity regular1822 {
+ base iana-interface-type;
+ }
+ identity hdh1822 {
+ base iana-interface-type;
+ }
+ identity ddnX25 {
+ base iana-interface-type;
+ }
+ identity rfc877x25 {
+ base iana-interface-type;
+ reference
+ "RFC 1382 - SNMP MIB Extension for the X.25 Packet Layer";
+ }
+ identity ethernetCsmacd {
+ base iana-interface-type;
+ description
+ "For all Ethernet-like interfaces, regardless of speed,
+ as per RFC 3635.";
+ reference
+ "RFC 3635 - Definitions of Managed Objects for the
+ Ethernet-like Interface Types";
+ }
+ identity iso88023Csmacd {
+ base iana-interface-type;
+ status deprecated;
+ description
+ "Deprecated via RFC 3635.
+ Use ethernetCsmacd(6) instead.";
+ reference
+ "RFC 3635 - Definitions of Managed Objects for the
+ Ethernet-like Interface Types";
+ }
+ identity iso88024TokenBus {
+ base iana-interface-type;
+ }
+ identity iso88025TokenRing {
+ base iana-interface-type;
+ }
+ identity iso88026Man {
+ base iana-interface-type;
+ }
+ identity starLan {
+ base iana-interface-type;
+ status deprecated;
+ description
+ "Deprecated via RFC 3635.
+ Use ethernetCsmacd(6) instead.";
+ reference
+ "RFC 3635 - Definitions of Managed Objects for the
+ Ethernet-like Interface Types";
+ }
+ identity proteon10Mbit {
+ base iana-interface-type;
+ }
+ identity proteon80Mbit {
+ base iana-interface-type;
+ }
+ identity hyperchannel {
+ base iana-interface-type;
+ }
+ identity fddi {
+ base iana-interface-type;
+ reference
+ "RFC 1512 - FDDI Management Information Base";
+ }
+ identity lapb {
+ base iana-interface-type;
+ reference
+ "RFC 1381 - SNMP MIB Extension for X.25 LAPB";
+ }
+ identity sdlc {
+ base iana-interface-type;
+ }
+ identity ds1 {
+ base iana-interface-type;
+ description
+ "DS1-MIB.";
+ reference
+ "RFC 4805 - Definitions of Managed Objects for the
+ DS1, J1, E1, DS2, and E2 Interface Types";
+ }
+ identity e1 {
+ base iana-interface-type;
+ status obsolete;
+ description
+ "Obsolete; see DS1-MIB.";
+ reference
+ "RFC 4805 - Definitions of Managed Objects for the
+ DS1, J1, E1, DS2, and E2 Interface Types";
+ }
+ identity basicISDN {
+ base iana-interface-type;
+ description
+ "No longer used. See also RFC 2127.";
+ }
+ identity primaryISDN {
+ base iana-interface-type;
+ description
+ "No longer used. See also RFC 2127.";
+ }
+ identity propPointToPointSerial {
+ base iana-interface-type;
+ description
+ "Proprietary serial.";
+ }
+ identity ppp {
+ base iana-interface-type;
+ }
+ identity softwareLoopback {
+ base iana-interface-type;
+ }
+ identity eon {
+ base iana-interface-type;
+ description
+ "CLNP over IP.";
+ }
+ identity ethernet3Mbit {
+ base iana-interface-type;
+ }
+ identity nsip {
+ base iana-interface-type;
+ description
+ "XNS over IP.";
+ }
+ identity slip {
+ base iana-interface-type;
+ description
+ "Generic SLIP.";
+ }
+ identity ultra {
+ base iana-interface-type;
+ description
+ "Ultra Technologies.";
+ }
+ identity ds3 {
+ base iana-interface-type;
+ description
+ "DS3-MIB.";
+ reference
+ "RFC 3896 - Definitions of Managed Objects for the
+ DS3/E3 Interface Type";
+ }
+ identity sip {
+ base iana-interface-type;
+ description
+ "SMDS, coffee.";
+ reference
+ "RFC 1694 - Definitions of Managed Objects for SMDS
+ Interfaces using SMIv2";
+ }
+ identity frameRelay {
+ base iana-interface-type;
+ description
+ "DTE only.";
+ reference
+ "RFC 2115 - Management Information Base for Frame Relay
+ DTEs Using SMIv2";
+ }
+ identity rs232 {
+ base iana-interface-type;
+ reference
+ "RFC 1659 - Definitions of Managed Objects for RS-232-like
+ Hardware Devices using SMIv2";
+ }
+ identity para {
+ base iana-interface-type;
+ description
+ "Parallel-port.";
+ reference
+ "RFC 1660 - Definitions of Managed Objects for
+ Parallel-printer-like Hardware Devices using
+ SMIv2";
+ }
+ identity arcnet {
+ base iana-interface-type;
+ description
+ "ARCnet.";
+ }
+ identity arcnetPlus {
+ base iana-interface-type;
+ description
+ "ARCnet Plus.";
+ }
+ identity atm {
+ base iana-interface-type;
+ description
+ "ATM cells.";
+ }
+ identity miox25 {
+ base iana-interface-type;
+ reference
+ "RFC 1461 - SNMP MIB extension for Multiprotocol
+ Interconnect over X.25";
+ }
+ identity sonet {
+ base iana-interface-type;
+ description
+ "SONET or SDH.";
+ }
+ identity x25ple {
+ base iana-interface-type;
+ reference
+ "RFC 2127 - ISDN Management Information Base using SMIv2";
+ }
+ identity iso88022llc {
+ base iana-interface-type;
+ }
+ identity localTalk {
+ base iana-interface-type;
+ }
+ identity smdsDxi {
+ base iana-interface-type;
+ }
+ identity frameRelayService {
+ base iana-interface-type;
+ description
+ "FRNETSERV-MIB.";
+ reference
+ "RFC 2954 - Definitions of Managed Objects for Frame
+ Relay Service";
+ }
+ identity v35 {
+ base iana-interface-type;
+ }
+ identity hssi {
+ base iana-interface-type;
+ }
+ identity hippi {
+ base iana-interface-type;
+ }
+ identity modem {
+ base iana-interface-type;
+ description
+ "Generic modem.";
+ }
+ identity aal5 {
+ base iana-interface-type;
+ description
+ "AAL5 over ATM.";
+ }
+ identity sonetPath {
+ base iana-interface-type;
+ }
+ identity sonetVT {
+ base iana-interface-type;
+ }
+ identity smdsIcip {
+ base iana-interface-type;
+ description
+ "SMDS InterCarrier Interface.";
+ }
+ identity propVirtual {
+ base iana-interface-type;
+ description
+ "Proprietary virtual/internal.";
+ reference
+ "RFC 2863 - The Interfaces Group MIB";
+ }
+ identity propMultiplexor {
+ base iana-interface-type;
+ description
+ "Proprietary multiplexing.";
+ reference
+ "RFC 2863 - The Interfaces Group MIB";
+ }
+ identity ieee80212 {
+ base iana-interface-type;
+ description
+ "100BaseVG.";
+ }
+ identity fibreChannel {
+ base iana-interface-type;
+ description
+ "Fibre Channel.";
+ }
+ identity hippiInterface {
+ base iana-interface-type;
+ description
+ "HIPPI interfaces.";
+ }
+ identity frameRelayInterconnect {
+ base iana-interface-type;
+ status obsolete;
+ description
+ "Obsolete; use either
+ frameRelay(32) or frameRelayService(44).";
+ }
+ identity aflane8023 {
+ base iana-interface-type;
+ description
+ "ATM Emulated LAN for 802.3.";
+ }
+ identity aflane8025 {
+ base iana-interface-type;
+ description
+ "ATM Emulated LAN for 802.5.";
+ }
+ identity cctEmul {
+ base iana-interface-type;
+ description
+ "ATM Emulated circuit.";
+ }
+ identity fastEther {
+ base iana-interface-type;
+ status deprecated;
+ description
+ "Obsoleted via RFC 3635.
+ ethernetCsmacd(6) should be used instead.";
+ reference
+ "RFC 3635 - Definitions of Managed Objects for the
+ Ethernet-like Interface Types";
+ }
+ identity isdn {
+ base iana-interface-type;
+ description
+ "ISDN and X.25.";
+ reference
+ "RFC 1356 - Multiprotocol Interconnect on X.25 and ISDN
+ in the Packet Mode";
+ }
+ identity v11 {
+ base iana-interface-type;
+ description
+ "CCITT V.11/X.21.";
+ }
+ identity v36 {
+ base iana-interface-type;
+ description
+ "CCITT V.36.";
+ }
+ identity g703at64k {
+ base iana-interface-type;
+ description
+ "CCITT G703 at 64Kbps.";
+ }
+ identity g703at2mb {
+ base iana-interface-type;
+ status obsolete;
+ description
+ "Obsolete; see DS1-MIB.";
+ }
+ identity qllc {
+ base iana-interface-type;
+ description
+ "SNA QLLC.";
+ }
+ identity fastEtherFX {
+ base iana-interface-type;
+ status deprecated;
+ description
+ "Obsoleted via RFC 3635.
+ ethernetCsmacd(6) should be used instead.";
+ reference
+ "RFC 3635 - Definitions of Managed Objects for the
+ Ethernet-like Interface Types";
+ }
+ identity channel {
+ base iana-interface-type;
+ description
+ "Channel.";
+ }
+ identity ieee80211 {
+ base iana-interface-type;
+ description
+ "Radio spread spectrum.";
+ }
+ identity ibm370parChan {
+ base iana-interface-type;
+ description
+ "IBM System 360/370 OEMI Channel.";
+ }
+ identity escon {
+ base iana-interface-type;
+ description
+ "IBM Enterprise Systems Connection.";
+ }
+ identity dlsw {
+ base iana-interface-type;
+ description
+ "Data Link Switching.";
+ }
+ identity isdns {
+ base iana-interface-type;
+ description
+ "ISDN S/T interface.";
+ }
+ identity isdnu {
+ base iana-interface-type;
+ description
+ "ISDN U interface.";
+ }
+ identity lapd {
+ base iana-interface-type;
+ description
+ "Link Access Protocol D.";
+ }
+ identity ipSwitch {
+ base iana-interface-type;
+ description
+ "IP Switching Objects.";
+ }
+ identity rsrb {
+ base iana-interface-type;
+ description
+ "Remote Source Route Bridging.";
+ }
+ identity atmLogical {
+ base iana-interface-type;
+ description
+ "ATM Logical Port.";
+ reference
+ "RFC 3606 - Definitions of Supplemental Managed Objects
+ for ATM Interface";
+ }
+ identity ds0 {
+ base iana-interface-type;
+ description
+ "Digital Signal Level 0.";
+ reference
+ "RFC 2494 - Definitions of Managed Objects for the DS0
+ and DS0 Bundle Interface Type";
+ }
+ identity ds0Bundle {
+ base iana-interface-type;
+ description
+ "Group of ds0s on the same ds1.";
+ reference
+ "RFC 2494 - Definitions of Managed Objects for the DS0
+ and DS0 Bundle Interface Type";
+ }
+ identity bsc {
+ base iana-interface-type;
+ description
+ "Bisynchronous Protocol.";
+ }
+ identity async {
+ base iana-interface-type;
+ description
+ "Asynchronous Protocol.";
+ }
+ identity cnr {
+ base iana-interface-type;
+ description
+ "Combat Net Radio.";
+ }
+ identity iso88025Dtr {
+ base iana-interface-type;
+ description
+ "ISO 802.5r DTR.";
+ }
+ identity eplrs {
+ base iana-interface-type;
+ description
+ "Ext Pos Loc Report Sys.";
+ }
+ identity arap {
+ base iana-interface-type;
+ description
+ "Appletalk Remote Access Protocol.";
+ }
+ identity propCnls {
+ base iana-interface-type;
+ description
+ "Proprietary Connectionless Protocol.";
+ }
+ identity hostPad {
+ base iana-interface-type;
+ description
+ "CCITT-ITU X.29 PAD Protocol.";
+ }
+ identity termPad {
+ base iana-interface-type;
+ description
+ "CCITT-ITU X.3 PAD Facility.";
+ }
+ identity frameRelayMPI {
+ base iana-interface-type;
+ description
+ "Multiproto Interconnect over FR.";
+ }
+ identity x213 {
+ base iana-interface-type;
+ description
+ "CCITT-ITU X213.";
+ }
+ identity adsl {
+ base iana-interface-type;
+ description
+ "Asymmetric Digital Subscriber Loop.";
+ }
+ identity radsl {
+ base iana-interface-type;
+ description
+ "Rate-Adapt. Digital Subscriber Loop.";
+ }
+ identity sdsl {
+ base iana-interface-type;
+ description
+ "Symmetric Digital Subscriber Loop.";
+ }
+ identity vdsl {
+ base iana-interface-type;
+ description
+ "Very H-Speed Digital Subscrib. Loop.";
+ }
+ identity iso88025CRFPInt {
+ base iana-interface-type;
+ description
+ "ISO 802.5 CRFP.";
+ }
+ identity myrinet {
+ base iana-interface-type;
+ description
+ "Myricom Myrinet.";
+ }
+ identity voiceEM {
+ base iana-interface-type;
+ description
+ "Voice recEive and transMit.";
+ }
+ identity voiceFXO {
+ base iana-interface-type;
+ description
+ "Voice Foreign Exchange Office.";
+ }
+ identity voiceFXS {
+ base iana-interface-type;
+ description
+ "Voice Foreign Exchange Station.";
+ }
+ identity voiceEncap {
+ base iana-interface-type;
+ description
+ "Voice encapsulation.";
+ }
+ identity voiceOverIp {
+ base iana-interface-type;
+ description
+ "Voice over IP encapsulation.";
+ }
+ identity atmDxi {
+ base iana-interface-type;
+ description
+ "ATM DXI.";
+ }
+ identity atmFuni {
+ base iana-interface-type;
+ description
+ "ATM FUNI.";
+ }
+ identity atmIma {
+ base iana-interface-type;
+ description
+ "ATM IMA.";
+ }
+ identity pppMultilinkBundle {
+ base iana-interface-type;
+ description
+ "PPP Multilink Bundle.";
+ }
+ identity ipOverCdlc {
+ base iana-interface-type;
+ description
+ "IBM ipOverCdlc.";
+ }
+ identity ipOverClaw {
+ base iana-interface-type;
+ description
+ "IBM Common Link Access to Workstn.";
+ }
+ identity stackToStack {
+ base iana-interface-type;
+ description
+ "IBM stackToStack.";
+ }
+ identity virtualIpAddress {
+ base iana-interface-type;
+ description
+ "IBM VIPA.";
+ }
+ identity mpc {
+ base iana-interface-type;
+ description
+ "IBM multi-protocol channel support.";
+ }
+ identity ipOverAtm {
+ base iana-interface-type;
+ description
+ "IBM ipOverAtm.";
+ reference
+ "RFC 2320 - Definitions of Managed Objects for Classical IP
+ and ARP Over ATM Using SMIv2 (IPOA-MIB)";
+ }
+ identity iso88025Fiber {
+ base iana-interface-type;
+ description
+ "ISO 802.5j Fiber Token Ring.";
+ }
+ identity tdlc {
+ base iana-interface-type;
+ description
+ "IBM twinaxial data link control.";
+ }
+ identity gigabitEthernet {
+ base iana-interface-type;
+ status deprecated;
+ description
+ "Obsoleted via RFC 3635.
+ ethernetCsmacd(6) should be used instead.";
+ reference
+ "RFC 3635 - Definitions of Managed Objects for the
+ Ethernet-like Interface Types";
+ }
+ identity hdlc {
+ base iana-interface-type;
+ description
+ "HDLC.";
+ }
+ identity lapf {
+ base iana-interface-type;
+ description
+ "LAP F.";
+ }
+ identity v37 {
+ base iana-interface-type;
+ description
+ "V.37.";
+ }
+ identity x25mlp {
+ base iana-interface-type;
+ description
+ "Multi-Link Protocol.";
+ }
+ identity x25huntGroup {
+ base iana-interface-type;
+ description
+ "X25 Hunt Group.";
+ }
+ identity transpHdlc {
+ base iana-interface-type;
+ description
+ "Transp HDLC.";
+ }
+ identity interleave {
+ base iana-interface-type;
+ description
+ "Interleave channel.";
+ }
+ identity fast {
+ base iana-interface-type;
+ description
+ "Fast channel.";
+ }
+ identity ip {
+ base iana-interface-type;
+ description
+ "IP (for APPN HPR in IP networks).";
+ }
+ identity docsCableMaclayer {
+ base iana-interface-type;
+ description
+ "CATV Mac Layer.";
+ }
+ identity docsCableDownstream {
+ base iana-interface-type;
+ description
+ "CATV Downstream interface.";
+ }
+ identity docsCableUpstream {
+ base iana-interface-type;
+ description
+ "CATV Upstream interface.";
+ }
+ identity a12MppSwitch {
+ base iana-interface-type;
+ description
+ "Avalon Parallel Processor.";
+ }
+ identity tunnel {
+ base iana-interface-type;
+ description
+ "Encapsulation interface.";
+ }
+ identity coffee {
+ base iana-interface-type;
+ description
+ "Coffee pot.";
+ reference
+ "RFC 2325 - Coffee MIB";
+ }
+ identity ces {
+ base iana-interface-type;
+ description
+ "Circuit Emulation Service.";
+ }
+ identity atmSubInterface {
+ base iana-interface-type;
+ description
+ "ATM Sub Interface.";
+ }
+ identity l2vlan {
+ base iana-interface-type;
+ description
+ "Layer 2 Virtual LAN using 802.1Q.";
+ }
+ identity l3ipvlan {
+ base iana-interface-type;
+ description
+ "Layer 3 Virtual LAN using IP.";
+ }
+ identity l3ipxvlan {
+ base iana-interface-type;
+ description
+ "Layer 3 Virtual LAN using IPX.";
+ }
+ identity digitalPowerline {
+ base iana-interface-type;
+ description
+ "IP over Power Lines.";
+ }
+ identity mediaMailOverIp {
+ base iana-interface-type;
+ description
+ "Multimedia Mail over IP.";
+ }
+ identity dtm {
+ base iana-interface-type;
+ description
+ "Dynamic synchronous Transfer Mode.";
+ }
+ identity dcn {
+ base iana-interface-type;
+ description
+ "Data Communications Network.";
+ }
+ identity ipForward {
+ base iana-interface-type;
+ description
+ "IP Forwarding Interface.";
+ }
+ identity msdsl {
+ base iana-interface-type;
+ description
+ "Multi-rate Symmetric DSL.";
+ }
+ identity ieee1394 {
+ base iana-interface-type;
+
+ description
+ "IEEE1394 High Performance Serial Bus.";
+ }
+ identity if-gsn {
+ base iana-interface-type;
+ description
+ "HIPPI-6400.";
+ }
+ identity dvbRccMacLayer {
+ base iana-interface-type;
+ description
+ "DVB-RCC MAC Layer.";
+ }
+ identity dvbRccDownstream {
+ base iana-interface-type;
+ description
+ "DVB-RCC Downstream Channel.";
+ }
+ identity dvbRccUpstream {
+ base iana-interface-type;
+ description
+ "DVB-RCC Upstream Channel.";
+ }
+ identity atmVirtual {
+ base iana-interface-type;
+ description
+ "ATM Virtual Interface.";
+ }
+ identity mplsTunnel {
+ base iana-interface-type;
+ description
+ "MPLS Tunnel Virtual Interface.";
+ }
+ identity srp {
+ base iana-interface-type;
+ description
+ "Spatial Reuse Protocol.";
+ }
+ identity voiceOverAtm {
+ base iana-interface-type;
+ description
+ "Voice over ATM.";
+ }
+ identity voiceOverFrameRelay {
+ base iana-interface-type;
+ description
+ "Voice Over Frame Relay.";
+ }
+ identity idsl {
+ base iana-interface-type;
+ description
+ "Digital Subscriber Loop over ISDN.";
+ }
+ identity compositeLink {
+ base iana-interface-type;
+ description
+ "Avici Composite Link Interface.";
+ }
+ identity ss7SigLink {
+ base iana-interface-type;
+ description
+ "SS7 Signaling Link.";
+ }
+ identity propWirelessP2P {
+ base iana-interface-type;
+ description
+ "Prop. P2P wireless interface.";
+ }
+ identity frForward {
+ base iana-interface-type;
+ description
+ "Frame Forward Interface.";
+ }
+ identity rfc1483 {
+ base iana-interface-type;
+ description
+ "Multiprotocol over ATM AAL5.";
+ reference
+ "RFC 1483 - Multiprotocol Encapsulation over ATM
+ Adaptation Layer 5";
+ }
+ identity usb {
+ base iana-interface-type;
+ description
+ "USB Interface.";
+ }
+ identity ieee8023adLag {
+ base iana-interface-type;
+ description
+ "IEEE 802.3ad Link Aggregate.";
+ }
+ identity bgppolicyaccounting {
+ base iana-interface-type;
+ description
+ "BGP Policy Accounting.";
+ }
+ identity frf16MfrBundle {
+ base iana-interface-type;
+ description
+ "FRF.16 Multilink Frame Relay.";
+ }
+ identity h323Gatekeeper {
+ base iana-interface-type;
+ description
+ "H323 Gatekeeper.";
+ }
+ identity h323Proxy {
+ base iana-interface-type;
+ description
+ "H323 Voice and Video Proxy.";
+ }
+ identity mpls {
+ base iana-interface-type;
+ description
+ "MPLS.";
+ }
+ identity mfSigLink {
+ base iana-interface-type;
+ description
+ "Multi-frequency signaling link.";
+ }
+ identity hdsl2 {
+ base iana-interface-type;
+ description
+ "High Bit-Rate DSL - 2nd generation.";
+ }
+ identity shdsl {
+ base iana-interface-type;
+ description
+ "Multirate HDSL2.";
+ }
+ identity ds1FDL {
+ base iana-interface-type;
+ description
+ "Facility Data Link (4Kbps) on a DS1.";
+ }
+ identity pos {
+ base iana-interface-type;
+ description
+ "Packet over SONET/SDH Interface.";
+ }
+ identity dvbAsiIn {
+ base iana-interface-type;
+ description
+ "DVB-ASI Input.";
+ }
+ identity dvbAsiOut {
+ base iana-interface-type;
+ description
+ "DVB-ASI Output.";
+ }
+ identity plc {
+ base iana-interface-type;
+ description
+ "Power Line Communications.";
+ }
+ identity nfas {
+ base iana-interface-type;
+ description
+ "Non-Facility Associated Signaling.";
+ }
+ identity tr008 {
+ base iana-interface-type;
+ description
+ "TR008.";
+ }
+ identity gr303RDT {
+ base iana-interface-type;
+ description
+ "Remote Digital Terminal.";
+ }
+ identity gr303IDT {
+ base iana-interface-type;
+ description
+ "Integrated Digital Terminal.";
+ }
+ identity isup {
+ base iana-interface-type;
+ description
+ "ISUP.";
+ }
+ identity propDocsWirelessMaclayer {
+ base iana-interface-type;
+ description
+ "Cisco proprietary Maclayer.";
+ }
+ identity propDocsWirelessDownstream {
+ base iana-interface-type;
+ description
+ "Cisco proprietary Downstream.";
+ }
+ identity propDocsWirelessUpstream {
+ base iana-interface-type;
+ description
+ "Cisco proprietary Upstream.";
+ }
+ identity hiperlan2 {
+ base iana-interface-type;
+ description
+ "HIPERLAN Type 2 Radio Interface.";
+ }
+ identity propBWAp2Mp {
+ base iana-interface-type;
+ description
+ "PropBroadbandWirelessAccesspt2Multipt (use of this value
+ for IEEE 802.16 WMAN interfaces as per IEEE Std 802.16f
+ is deprecated, and ieee80216WMAN(237) should be used
+ instead).";
+ }
+ identity sonetOverheadChannel {
+ base iana-interface-type;
+ description
+ "SONET Overhead Channel.";
+ }
+ identity digitalWrapperOverheadChannel {
+ base iana-interface-type;
+ description
+ "Digital Wrapper.";
+ }
+ identity aal2 {
+ base iana-interface-type;
+ description
+ "ATM adaptation layer 2.";
+ }
+ identity radioMAC {
+ base iana-interface-type;
+ description
+ "MAC layer over radio links.";
+ }
+ identity atmRadio {
+ base iana-interface-type;
+ description
+ "ATM over radio links.";
+ }
+ identity imt {
+ base iana-interface-type;
+ description
+ "Inter-Machine Trunks.";
+ }
+ identity mvl {
+ base iana-interface-type;
+ description
+ "Multiple Virtual Lines DSL.";
+ }
+ identity reachDSL {
+ base iana-interface-type;
+ description
+ "Long Reach DSL.";
+ }
+ identity frDlciEndPt {
+ base iana-interface-type;
+ description
+ "Frame Relay DLCI End Point.";
+ }
+ identity atmVciEndPt {
+ base iana-interface-type;
+ description
+ "ATM VCI End Point.";
+ }
+ identity opticalChannel {
+ base iana-interface-type;
+ description
+ "Optical Channel.";
+ }
+ identity opticalTransport {
+ base iana-interface-type;
+ description
+ "Optical Transport.";
+ }
+ identity propAtm {
+ base iana-interface-type;
+ description
+ "Proprietary ATM.";
+ }
+ identity voiceOverCable {
+ base iana-interface-type;
+ description
+ "Voice Over Cable Interface.";
+ }
+ identity infiniband {
+ base iana-interface-type;
+ description
+ "Infiniband.";
+ }
+ identity teLink {
+ base iana-interface-type;
+ description
+ "TE Link.";
+ }
+ identity q2931 {
+ base iana-interface-type;
+ description
+ "Q.2931.";
+ }
+ identity virtualTg {
+ base iana-interface-type;
+ description
+ "Virtual Trunk Group.";
+ }
+ identity sipTg {
+ base iana-interface-type;
+ description
+ "SIP Trunk Group.";
+ }
+ identity sipSig {
+ base iana-interface-type;
+ description
+ "SIP Signaling.";
+ }
+ identity docsCableUpstreamChannel {
+ base iana-interface-type;
+ description
+ "CATV Upstream Channel.";
+ }
+ identity econet {
+ base iana-interface-type;
+ description
+ "Acorn Econet.";
+ }
+ identity pon155 {
+ base iana-interface-type;
+ description
+ "FSAN 155Mb Symetrical PON interface.";
+ }
+ identity pon622 {
+ base iana-interface-type;
+ description
+ "FSAN 622Mb Symetrical PON interface.";
+ }
+ identity bridge {
+ base iana-interface-type;
+ description
+ "Transparent bridge interface.";
+ }
+ identity linegroup {
+ base iana-interface-type;
+ description
+ "Interface common to multiple lines.";
+ }
+ identity voiceEMFGD {
+ base iana-interface-type;
+ description
+ "Voice E&M Feature Group D.";
+ }
+ identity voiceFGDEANA {
+ base iana-interface-type;
+ description
+ "Voice FGD Exchange Access North American.";
+ }
+ identity voiceDID {
+ base iana-interface-type;
+ description
+ "Voice Direct Inward Dialing.";
+ }
+ identity mpegTransport {
+ base iana-interface-type;
+ description
+ "MPEG transport interface.";
+ }
+ identity sixToFour {
+ base iana-interface-type;
+ status deprecated;
+ description
+ "6to4 interface (DEPRECATED).";
+ reference
+ "RFC 4087 - IP Tunnel MIB";
+ }
+ identity gtp {
+ base iana-interface-type;
+ description
+ "GTP (GPRS Tunneling Protocol).";
+ }
+ identity pdnEtherLoop1 {
+ base iana-interface-type;
+ description
+ "Paradyne EtherLoop 1.";
+ }
+ identity pdnEtherLoop2 {
+ base iana-interface-type;
+ description
+ "Paradyne EtherLoop 2.";
+ }
+ identity opticalChannelGroup {
+ base iana-interface-type;
+ description
+ "Optical Channel Group.";
+ }
+ identity homepna {
+ base iana-interface-type;
+ description
+ "HomePNA ITU-T G.989.";
+ }
+ identity gfp {
+ base iana-interface-type;
+ description
+ "Generic Framing Procedure (GFP).";
+ }
+ identity ciscoISLvlan {
+ base iana-interface-type;
+ description
+ "Layer 2 Virtual LAN using Cisco ISL.";
+ }
+ identity actelisMetaLOOP {
+ base iana-interface-type;
+ description
+ "Acteleis proprietary MetaLOOP High Speed Link.";
+ }
+ identity fcipLink {
+ base iana-interface-type;
+ description
+ "FCIP Link.";
+ }
+ identity rpr {
+ base iana-interface-type;
+ description
+ "Resilient Packet Ring Interface Type.";
+ }
+ identity qam {
+ base iana-interface-type;
+ description
+ "RF Qam Interface.";
+ }
+ identity lmp {
+ base iana-interface-type;
+ description
+ "Link Management Protocol.";
+ reference
+ "RFC 4327 - Link Management Protocol (LMP) Management
+ Information Base (MIB)";
+ }
+ identity cblVectaStar {
+ base iana-interface-type;
+ description
+ "Cambridge Broadband Networks Limited VectaStar.";
+ }
+ identity docsCableMCmtsDownstream {
+ base iana-interface-type;
+ description
+ "CATV Modular CMTS Downstream Interface.";
+ }
+ identity adsl2 {
+ base iana-interface-type;
+ status deprecated;
+ description
+ "Asymmetric Digital Subscriber Loop Version 2
+ (DEPRECATED/OBSOLETED - please use adsl2plus(238)
+ instead).";
+ reference
+ "RFC 4706 - Definitions of Managed Objects for Asymmetric
+ Digital Subscriber Line 2 (ADSL2)";
+ }
+ identity macSecControlledIF {
+ base iana-interface-type;
+ description
+ "MACSecControlled.";
+ }
+ identity macSecUncontrolledIF {
+ base iana-interface-type;
+ description
+ "MACSecUncontrolled.";
+ }
+ identity aviciOpticalEther {
+ base iana-interface-type;
+ description
+ "Avici Optical Ethernet Aggregate.";
+ }
+ identity atmbond {
+ base iana-interface-type;
+ description
+ "atmbond.";
+ }
+ identity voiceFGDOS {
+ base iana-interface-type;
+ description
+ "Voice FGD Operator Services.";
+ }
+ identity mocaVersion1 {
+ base iana-interface-type;
+ description
+ "MultiMedia over Coax Alliance (MoCA) Interface
+ as documented in information provided privately to IANA.";
+ }
+ identity ieee80216WMAN {
+ base iana-interface-type;
+ description
+ "IEEE 802.16 WMAN interface.";
+ }
+ identity adsl2plus {
+ base iana-interface-type;
+ description
+ "Asymmetric Digital Subscriber Loop Version 2 -
+ Version 2 Plus and all variants.";
+ }
+ identity dvbRcsMacLayer {
+ base iana-interface-type;
+ description
+ "DVB-RCS MAC Layer.";
+ reference
+ "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+ }
+ identity dvbTdm {
+ base iana-interface-type;
+ description
+ "DVB Satellite TDM.";
+ reference
+ "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+ }
+ identity dvbRcsTdma {
+ base iana-interface-type;
+ description
+ "DVB-RCS TDMA.";
+ reference
+ "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+ }
+ identity x86Laps {
+ base iana-interface-type;
+ description
+ "LAPS based on ITU-T X.86/Y.1323.";
+ }
+ identity wwanPP {
+ base iana-interface-type;
+ description
+ "3GPP WWAN.";
+ }
+ identity wwanPP2 {
+ base iana-interface-type;
+ description
+ "3GPP2 WWAN.";
+ }
+ identity voiceEBS {
+ base iana-interface-type;
+ description
+ "Voice P-phone EBS physical interface.";
+ }
+ identity ifPwType {
+ base iana-interface-type;
+ description
+ "Pseudowire interface type.";
+ reference
+ "RFC 5601 - Pseudowire (PW) Management Information Base (MIB)";
+ }
+ identity ilan {
+ base iana-interface-type;
+ description
+ "Internal LAN on a bridge per IEEE 802.1ap.";
+ }
+ identity pip {
+ base iana-interface-type;
+ description
+ "Provider Instance Port on a bridge per IEEE 802.1ah PBB.";
+ }
+ identity aluELP {
+ base iana-interface-type;
+ description
+ "Alcatel-Lucent Ethernet Link Protection.";
+ }
+ identity gpon {
+ base iana-interface-type;
+ description
+ "Gigabit-capable passive optical networks (G-PON) as per
+ ITU-T G.948.";
+ }
+ identity vdsl2 {
+ base iana-interface-type;
+ description
+ "Very high speed digital subscriber line Version 2
+ (as per ITU-T Recommendation G.993.2).";
+ reference
+ "RFC 5650 - Definitions of Managed Objects for Very High
+ Speed Digital Subscriber Line 2 (VDSL2)";
+ }
+ identity capwapDot11Profile {
+ base iana-interface-type;
+ description
+ "WLAN Profile Interface.";
+ reference
+ "RFC 5834 - Control and Provisioning of Wireless Access
+ Points (CAPWAP) Protocol Binding MIB for
+ IEEE 802.11";
+ }
+ identity capwapDot11Bss {
+ base iana-interface-type;
+ description
+ "WLAN BSS Interface.";
+ reference
+ "RFC 5834 - Control and Provisioning of Wireless Access
+ Points (CAPWAP) Protocol Binding MIB for
+ IEEE 802.11";
+ }
+ identity capwapWtpVirtualRadio {
+ base iana-interface-type;
+ description
+ "WTP Virtual Radio Interface.";
+ reference
+ "RFC 5833 - Control and Provisioning of Wireless Access
+ Points (CAPWAP) Protocol Base MIB";
+ }
+ identity bits {
+ base iana-interface-type;
+ description
+ "bitsport.";
+ }
+ identity docsCableUpstreamRfPort {
+ base iana-interface-type;
+ description
+ "DOCSIS CATV Upstream RF Port.";
+ }
+ identity cableDownstreamRfPort {
+ base iana-interface-type;
+ description
+ "CATV downstream RF Port.";
+ }
+ identity vmwareVirtualNic {
+ base iana-interface-type;
+ description
+ "VMware Virtual Network Interface.";
+ }
+ identity ieee802154 {
+ base iana-interface-type;
+ description
+ "IEEE 802.15.4 WPAN interface.";
+ reference
+ "IEEE 802.15.4-2006";
+ }
+ identity otnOdu {
+ base iana-interface-type;
+ description
+ "OTN Optical Data Unit.";
+ }
+ identity otnOtu {
+ base iana-interface-type;
+ description
+ "OTN Optical channel Transport Unit.";
+ }
+ identity ifVfiType {
+ base iana-interface-type;
+ description
+ "VPLS Forwarding Instance Interface Type.";
+ }
+ identity g9981 {
+ base iana-interface-type;
+ description
+ "G.998.1 bonded interface.";
+ }
+ identity g9982 {
+ base iana-interface-type;
+ description
+ "G.998.2 bonded interface.";
+ }
+ identity g9983 {
+ base iana-interface-type;
+ description
+ "G.998.3 bonded interface.";
+ }
+
+ identity aluEpon {
+ base iana-interface-type;
+ description
+ "Ethernet Passive Optical Networks (E-PON).";
+ }
+ identity aluEponOnu {
+ base iana-interface-type;
+ description
+ "EPON Optical Network Unit.";
+ }
+ identity aluEponPhysicalUni {
+ base iana-interface-type;
+ description
+ "EPON physical User to Network interface.";
+ }
+ identity aluEponLogicalLink {
+ base iana-interface-type;
+ description
+ "The emulation of a point-to-point link over the EPON
+ layer.";
+ }
+ identity aluGponOnu {
+ base iana-interface-type;
+ description
+ "GPON Optical Network Unit.";
+ reference
+ "ITU-T G.984.2";
+ }
+ identity aluGponPhysicalUni {
+ base iana-interface-type;
+ description
+ "GPON physical User to Network interface.";
+ reference
+ "ITU-T G.984.2";
+ }
+ identity vmwareNicTeam {
+ base iana-interface-type;
+ description
+ "VMware NIC Team.";
+ }
+ identity docsOfdmDownstream {
+ base iana-interface-type;
+ description
+ "CATV Downstream OFDM interface.";
+ }
+ identity docsOfdmaUpstream {
+ base iana-interface-type;
+ description
+ "CATV Upstream OFDMA interface.";
+ }
+ identity gfast {
+ base iana-interface-type;
+ description
+ "G.fast port.";
+ reference
+ "ITU-T G.9701";
+ }
+ identity sdci {
+ base iana-interface-type;
+ description
+ "SDCI (IO-Link).";
+ reference
+ "IEC 61131-9 Edition 1.0 2013-09";
+ }
+ identity xboxWireless {
+ base iana-interface-type;
+ description
+ "Xbox wireless.";
+ }
+ identity fastdsl {
+ base iana-interface-type;
+ description
+ "FastDSL.";
+ reference
+ "BBF TR-355";
+ }
+ identity docsCableScte55d1FwdOob {
+ base iana-interface-type;
+ description
+ "Cable SCTE 55-1 OOB Forward Channel.";
+ }
+ identity docsCableScte55d1RetOob {
+ base iana-interface-type;
+ description
+ "Cable SCTE 55-1 OOB Return Channel.";
+ }
+ identity docsCableScte55d2DsOob {
+ base iana-interface-type;
+ description
+ "Cable SCTE 55-2 OOB Downstream Channel.";
+ }
+ identity docsCableScte55d2UsOob {
+ base iana-interface-type;
+ description
+ "Cable SCTE 55-2 OOB Upstream Channel.";
+ }
+ identity docsCableNdf {
+ base iana-interface-type;
+ description
+ "Cable Narrowband Digital Forward.";
+ }
+ identity docsCableNdr {
+ base iana-interface-type;
+ description
+ "Cable Narrowband Digital Return.";
+ }
+ identity ptm {
+ base iana-interface-type;
+ description
+ "Packet Transfer Mode.";
+ }
+}
diff --git a/radio/fhi_72/mplane/yang/models/ietf-hardware.yang b/radio/fhi_72/mplane/yang/models/ietf-hardware.yang
new file mode 100755
index 0000000000..f444e26ee6
--- /dev/null
+++ b/radio/fhi_72/mplane/yang/models/ietf-hardware.yang
@@ -0,0 +1,1141 @@
+module ietf-hardware {
+yang-version 1.1;
+namespace "urn:ietf:params:xml:ns:yang:ietf-hardware";
+prefix hw;
+
+import ietf-inet-types {
+ prefix inet;
+}
+import ietf-yang-types {
+ prefix yang;
+}
+import iana-hardware {
+ prefix ianahw;
+}
+
+organization
+ "IETF NETMOD (Network Modeling) Working Group";
+
+contact
+ "WG Web:
+ WG List:
+ Editor: Andy Bierman
+
+ Editor: Martin Bjorklund
+
+ Editor: Jie Dong
+
+ Editor: Dan Romascanu
+ ";
+
+description
+ "This module contains a collection of YANG definitions for
+ managing hardware.
+ This data model is designed for the Network Management Datastore
+ Architecture (NMDA) defined in RFC 8342.
+ Copyright (c) 2018 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+ Redistribution and use in source and binary forms, with or
+ without modification, is permitted pursuant to, and subject
+ to the license terms contained in, the Simplified BSD License
+ set forth in Section 4.c of the IETF Trust's Legal Provisions
+ Relating to IETF Documents
+ (https://trustee.ietf.org/license-info).
+ This version of this YANG module is part of RFC 8348; see
+ the RFC itself for full legal notices.";
+
+revision 2018-03-13 {
+ description
+ "Initial revision.";
+ reference
+ "RFC 8348: A YANG Data Model for Hardware Management";
+}
+
+/*
+ * Features
+ */
+
+feature entity-mib {
+ description
+ "This feature indicates that the device implements
+ the ENTITY-MIB.";
+ reference
+ "RFC 6933: Entity MIB (Version 4)";
+}
+
+feature hardware-state {
+ description
+ "Indicates that ENTITY-STATE-MIB objects are supported";
+ reference
+ "RFC 4268: Entity State MIB";
+}
+
+feature hardware-sensor {
+ description
+ "Indicates that ENTITY-SENSOR-MIB objects are supported";
+ reference
+ "RFC 3433: Entity Sensor Management Information Base";
+}
+
+/*
+ * Typedefs
+ */
+
+typedef admin-state {
+ type enumeration {
+ enum unknown {
+ value 1;
+ description
+ "The resource is unable to report administrative state.";
+ }
+ enum locked {
+ value 2;
+ description
+ "The resource is administratively prohibited from use.";
+ }
+ enum shutting-down {
+ value 3;
+ description
+ "The resource usage is administratively limited to current
+ instances of use.";
+ }
+ enum unlocked {
+ value 4;
+ description
+ "The resource is not administratively prohibited from
+ use.";
+ }
+ }
+ description
+ "Represents the various possible administrative states.";
+ reference
+ "RFC 4268: Entity State MIB - EntityAdminState";
+}
+
+typedef oper-state {
+ type enumeration {
+ enum unknown {
+ value 1;
+ description
+ "The resource is unable to report its operational state.";
+ }
+ enum disabled {
+ value 2;
+ description
+ "The resource is totally inoperable.";
+ }
+ enum enabled {
+ value 3;
+
+ description
+ "The resource is partially or fully operable.";
+ }
+ enum testing {
+ value 4;
+ description
+ "The resource is currently being tested and cannot
+ therefore report whether or not it is operational.";
+ }
+ }
+ description
+ "Represents the possible values of operational states.";
+ reference
+ "RFC 4268: Entity State MIB - EntityOperState";
+}
+
+typedef usage-state {
+ type enumeration {
+ enum unknown {
+ value 1;
+ description
+ "The resource is unable to report usage state.";
+ }
+ enum idle {
+ value 2;
+ description
+ "The resource is servicing no users.";
+ }
+ enum active {
+ value 3;
+ description
+ "The resource is currently in use, and it has sufficient
+ spare capacity to provide for additional users.";
+ }
+ enum busy {
+ value 4;
+ description
+ "The resource is currently in use, but it currently has no
+ spare capacity to provide for additional users.";
+ }
+ }
+ description
+ "Represents the possible values of usage states.";
+ reference
+ "RFC 4268: Entity State MIB - EntityUsageState";
+}
+
+typedef alarm-state {
+ type bits {
+ bit unknown {
+ position 0;
+ description
+ "The resource is unable to report alarm state.";
+ }
+ bit under-repair {
+ position 1;
+ description
+ "The resource is currently being repaired, which, depending
+ on the implementation, may make the other values in this
+ bit string not meaningful.";
+ }
+ bit critical {
+ position 2;
+ description
+ "One or more critical alarms are active against the
+ resource.";
+ }
+ bit major {
+ position 3;
+ description
+ "One or more major alarms are active against the
+ resource.";
+ }
+ bit minor {
+ position 4;
+ description
+ "One or more minor alarms are active against the
+ resource.";
+ }
+ bit warning {
+ position 5;
+ description
+ "One or more warning alarms are active against the
+ resource.";
+ }
+ bit indeterminate {
+ position 6;
+ description
+ "One or more alarms of whose perceived severity cannot be
+ determined are active against this resource.";
+ }
+ }
+ description
+ "Represents the possible values of alarm states. An alarm is a
+ persistent indication of an error or warning condition.
+ When no bits of this attribute are set, then no active alarms
+ are known against this component and it is not under repair.";
+ reference
+ "RFC 4268: Entity State MIB - EntityAlarmStatus";
+}
+
+typedef standby-state {
+ type enumeration {
+ enum unknown {
+ value 1;
+ description
+ "The resource is unable to report standby state.";
+ }
+ enum hot-standby {
+ value 2;
+ description
+ "The resource is not providing service, but it will be
+ immediately able to take over the role of the resource to
+ be backed up, without the need for initialization
+ activity, and will contain the same information as the
+ resource to be backed up.";
+ }
+ enum cold-standby {
+ value 3;
+ description
+ "The resource is to back up another resource, but it will
+ not be immediately able to take over the role of a
+ resource to be backed up and will require some
+ initialization activity.";
+ }
+ enum providing-service {
+ value 4;
+ description
+ "The resource is providing service.";
+ }
+ }
+ description
+ "Represents the possible values of standby states.";
+ reference
+ "RFC 4268: Entity State MIB - EntityStandbyStatus";
+}
+
+typedef sensor-value-type {
+ type enumeration {
+ enum other {
+ value 1;
+ description
+ "A measure other than those listed below.";
+ }
+ enum unknown {
+ value 2;
+ description
+ "An unknown measurement or arbitrary, relative numbers";
+ }
+ enum volts-AC {
+ value 3;
+ description
+ "A measure of electric potential (alternating current).";
+ }
+ enum volts-DC {
+ value 4;
+ description
+ "A measure of electric potential (direct current).";
+ }
+ enum amperes {
+ value 5;
+ description
+ "A measure of electric current.";
+ }
+ enum watts {
+ value 6;
+ description
+ "A measure of power.";
+ }
+ enum hertz {
+ value 7;
+ description
+ "A measure of frequency.";
+ }
+ enum celsius {
+ value 8;
+ description
+ "A measure of temperature.";
+ }
+ enum percent-RH {
+ value 9;
+ description
+ "A measure of percent relative humidity.";
+ }
+ enum rpm {
+ value 10;
+ description
+ "A measure of shaft revolutions per minute.";
+ }
+ enum cmm {
+ value 11;
+ description
+ "A measure of cubic meters per minute (airflow).";
+ }
+ enum truth-value {
+ value 12;
+ description
+ "Value is one of 1 (true) or 2 (false)";
+ }
+ }
+ description
+ "A node using this data type represents the sensor measurement
+ data type associated with a physical sensor value. The actual
+ data units are determined by examining a node of this type
+ together with the associated sensor-value-scale node.
+ A node of this type SHOULD be defined together with nodes of
+ type sensor-value-scale and type sensor-value-precision.
+ These three types are used to identify the semantics of a node
+ of type sensor-value.";
+ reference
+ "RFC 3433: Entity Sensor Management Information Base -
+ EntitySensorDataType";
+}
+
+typedef sensor-value-scale {
+ type enumeration {
+ enum yocto {
+ value 1;
+ description
+ "Data scaling factor of 10^-24.";
+ }
+ enum zepto {
+ value 2;
+ description
+ "Data scaling factor of 10^-21.";
+ }
+ enum atto {
+ value 3;
+ description
+ "Data scaling factor of 10^-18.";
+ }
+ enum femto {
+ value 4;
+ description
+ "Data scaling factor of 10^-15.";
+ }
+ enum pico {
+ value 5;
+ description
+ "Data scaling factor of 10^-12.";
+ }
+ enum nano {
+ value 6;
+ description
+ "Data scaling factor of 10^-9.";
+ }
+ enum micro {
+ value 7;
+ description
+ "Data scaling factor of 10^-6.";
+ }
+ enum milli {
+ value 8;
+ description
+ "Data scaling factor of 10^-3.";
+ }
+ enum units {
+ value 9;
+ description
+ "Data scaling factor of 10^0.";
+ }
+ enum kilo {
+ value 10;
+ description
+ "Data scaling factor of 10^3.";
+ }
+ enum mega {
+ value 11;
+ description
+ "Data scaling factor of 10^6.";
+ }
+ enum giga {
+ value 12;
+ description
+ "Data scaling factor of 10^9.";
+ }
+ enum tera {
+ value 13;
+ description
+ "Data scaling factor of 10^12.";
+ }
+ enum peta {
+ value 14;
+ description
+ "Data scaling factor of 10^15.";
+ }
+ enum exa {
+ value 15;
+ description
+ "Data scaling factor of 10^18.";
+ }
+ enum zetta {
+ value 16;
+ description
+ "Data scaling factor of 10^21.";
+ }
+ enum yotta {
+ value 17;
+ description
+ "Data scaling factor of 10^24.";
+ }
+ }
+ description
+ "A node using this data type represents a data scaling factor,
+ represented with an International System of Units (SI) prefix.
+ The actual data units are determined by examining a node of
+ this type together with the associated sensor-value-type.
+ A node of this type SHOULD be defined together with nodes of
+ type sensor-value-type and type sensor-value-precision.
+ Together, associated nodes of these three types are used to
+ identify the semantics of a node of type sensor-value.";
+ reference
+ "RFC 3433: Entity Sensor Management Information Base -
+ EntitySensorDataScale";
+}
+
+typedef sensor-value-precision {
+ type int8 {
+ range "-8 .. 9";
+ }
+ description
+ "A node using this data type represents a sensor value
+ precision range.
+ A node of this type SHOULD be defined together with nodes of
+ type sensor-value-type and type sensor-value-scale. Together,
+ associated nodes of these three types are used to identify the
+ semantics of a node of type sensor-value.
+ If a node of this type contains a value in the range 1 to 9,
+ it represents the number of decimal places in the fractional
+ part of an associated sensor-value fixed-point number.
+ If a node of this type contains a value in the range -8 to -1,
+ it represents the number of accurate digits in the associated
+ sensor-value fixed-point number.
+ The value zero indicates the associated sensor-value node is
+ not a fixed-point number.
+ Server implementers must choose a value for the associated
+ sensor-value-precision node so that the precision and accuracy
+ of the associated sensor-value node is correctly indicated.
+ For example, a component representing a temperature sensor
+ that can measure 0 to 100 degrees C in 0.1 degree
+ increments, +/- 0.05 degrees, would have a
+ sensor-value-precision value of '1', a sensor-value-scale
+ value of 'units', and a sensor-value ranging from '0' to
+ '1000'. The sensor-value would be interpreted as
+ 'degrees C * 10'.";
+ reference
+ "RFC 3433: Entity Sensor Management Information Base -
+ EntitySensorPrecision";
+}
+
+typedef sensor-value {
+ type int32 {
+ range "-1000000000 .. 1000000000";
+ }
+ description
+ "A node using this data type represents a sensor value.
+ A node of this type SHOULD be defined together with nodes of
+ type sensor-value-type, type sensor-value-scale, and
+ type sensor-value-precision. Together, associated nodes of
+ those three types are used to identify the semantics of a node
+ of this data type.
+ The semantics of a node using this data type are determined by
+ the value of the associated sensor-value-type node.
+ If the associated sensor-value-type node is equal to 'voltsAC',
+ 'voltsDC', 'amperes', 'watts', 'hertz', 'celsius', or 'cmm',
+ then a node of this type MUST contain a fixed-point number
+ ranging from -999,999,999 to +999,999,999. The value
+ -1000000000 indicates an underflow error. The value
+ +1000000000 indicates an overflow error. The
+ sensor-value-precision indicates how many fractional digits
+ are represented in the associated sensor-value node.
+ If the associated sensor-value-type node is equal to
+ 'percentRH', then a node of this type MUST contain a number
+ ranging from 0 to 100.
+ If the associated sensor-value-type node is equal to 'rpm',
+ then a node of this type MUST contain a number ranging from
+ -999,999,999 to +999,999,999.
+ If the associated sensor-value-type node is equal to
+ 'truth-value', then a node of this type MUST contain either the
+ value 1 (true) or the value 2 (false).
+ If the associated sensor-value-type node is equal to 'other' or
+ 'unknown', then a node of this type MUST contain a number
+ ranging from -1000000000 to 1000000000.";
+ reference
+ "RFC 3433: Entity Sensor Management Information Base -
+ EntitySensorValue";
+}
+
+typedef sensor-status {
+ type enumeration {
+ enum ok {
+ value 1;
+ description
+ "Indicates that the server can obtain the sensor value.";
+ }
+ enum unavailable {
+ value 2;
+ description
+ "Indicates that the server presently cannot obtain the
+ sensor value.";
+ }
+ enum nonoperational {
+ value 3;
+ description
+ "Indicates that the server believes the sensor is broken.
+ The sensor could have a hard failure (disconnected wire)
+ or a soft failure such as out-of-range, jittery, or wildly
+ fluctuating readings.";
+ }
+ }
+ description
+ "A node using this data type represents the operational status
+ of a physical sensor.";
+ reference
+ "RFC 3433: Entity Sensor Management Information Base -
+ EntitySensorStatus";
+}
+
+/*
+ * Data nodes
+ */
+
+container hardware {
+ description
+ "Data nodes representing components.
+ If the server supports configuration of hardware components,
+ then this data model is instantiated in the configuration
+ datastores supported by the server. The leaf-list 'datastore'
+ for the module 'ietf-hardware' in the YANG library provides
+ this information.";
+
+ leaf last-change {
+ type yang:date-and-time;
+ config false;
+ description
+ "The time the '/hardware/component' list changed in the
+ operational state.";
+ }
+
+ list component {
+ key name;
+ description
+ "List of components.
+ When the server detects a new hardware component, it
+ initializes a list entry in the operational state.
+ If the server does not support configuration of hardware
+ components, list entries in the operational state are
+ initialized with values for all nodes as detected by the
+ implementation.
+ Otherwise, this procedure is followed:
+ 1. If there is an entry in the '/hardware/component' list
+ in the intended configuration with values for the nodes
+ 'class', 'parent', and 'parent-rel-pos' that are equal
+ to the detected values, then the list entry in the
+ operational state is initialized with the configured
+ values, including the 'name'.
+ 2. Otherwise (i.e., there is no matching configuration
+ entry), the list entry in the operational state is
+ initialized with values for all nodes as detected by
+ the implementation.
+ If the '/hardware/component' list in the intended
+ configuration is modified, then the system MUST behave as if
+ it re-initializes itself and follow the procedure in (1).";
+ reference
+ "RFC 6933: Entity MIB (Version 4) - entPhysicalEntry";
+
+ leaf name {
+ type string;
+ description
+ "The name assigned to this component.
+ This name is not required to be the same as
+ entPhysicalName.";
+ }
+
+ leaf class {
+ type identityref {
+ base ianahw:hardware-class;
+ }
+ mandatory true;
+ description
+ "An indication of the general hardware type of the
+ component.";
+ reference
+ "RFC 6933: Entity MIB (Version 4) - entPhysicalClass";
+ }
+
+ leaf physical-index {
+ if-feature entity-mib;
+ type int32 {
+ range "1..2147483647";
+ }
+ config false;
+ description
+ "The entPhysicalIndex for the entPhysicalEntry represented
+ by this list entry.";
+ reference
+ "RFC 6933: Entity MIB (Version 4) - entPhysicalIndex";
+ }
+
+ leaf description {
+ type string;
+ config false;
+ description
+ "A textual description of the component. This node should
+ contain a string that identifies the manufacturer's name
+ for the component and should be set to a distinct value
+ for each version or model of the component.";
+ reference
+ "RFC 6933: Entity MIB (Version 4) - entPhysicalDescr";
+ }
+
+ leaf parent {
+ type leafref {
+ path "../../component/name";
+ require-instance false;
+ }
+ description
+ "The name of the component that physically contains this
+ component.
+ If this leaf is not instantiated, it indicates that this
+ component is not contained in any other component.
+ In the event that a physical component is contained by
+ more than one physical component (e.g., double-wide
+ modules), this node contains the name of one of these
+ components. An implementation MUST use the same name
+ every time this node is instantiated.";
+ reference
+ "RFC 6933: Entity MIB (Version 4) - entPhysicalContainedIn";
+ }
+
+ leaf parent-rel-pos {
+ type int32 {
+ range "0 .. 2147483647";
+ }
+ description
+ "An indication of the relative position of this child
+ component among all its sibling components. Sibling
+ components are defined as components that:
+ o share the same value of the 'parent' node and
+ o share a common base identity for the 'class' node.
+ Note that the last rule gives implementations flexibility
+ in how components are numbered. For example, some
+ implementations might have a single number series for all
+ components derived from 'ianahw:port', while some others
+ might have different number series for different
+ components with identities derived from 'ianahw:port' (for
+ example, one for registered jack 45 (RJ45) and one for
+ small form-factor pluggable (SFP)).";
+
+ reference
+ "RFC 6933: Entity MIB (Version 4) -
+ entPhysicalParentRelPos";
+ }
+
+ leaf-list contains-child {
+ type leafref {
+ path "../../component/name";
+ }
+ config false;
+ description
+ "The name of the contained component.";
+ reference
+ "RFC 6933: Entity MIB (Version 4) - entPhysicalChildIndex";
+ }
+
+ leaf hardware-rev {
+ type string;
+ config false;
+ description
+ "The vendor-specific hardware revision string for the
+ component. The preferred value is the hardware revision
+ identifier actually printed on the component itself (if
+ present).";
+ reference
+ "RFC 6933: Entity MIB (Version 4) -
+ entPhysicalHardwareRev";
+ }
+
+ leaf firmware-rev {
+ type string;
+ config false;
+ description
+ "The vendor-specific firmware revision string for the
+ component.";
+ reference
+ "RFC 6933: Entity MIB (Version 4) -
+ entPhysicalFirmwareRev";
+ }
+
+ leaf software-rev {
+ type string;
+ config false;
+
+ description
+ "The vendor-specific software revision string for the
+ component.";
+ reference
+ "RFC 6933: Entity MIB (Version 4) -
+ entPhysicalSoftwareRev";
+ }
+
+ leaf serial-num {
+ type string;
+ config false;
+ description
+ "The vendor-specific serial number string for the
+ component. The preferred value is the serial number
+ string actually printed on the component itself (if
+ present).";
+ reference
+ "RFC 6933: Entity MIB (Version 4) - entPhysicalSerialNum";
+ }
+
+ leaf mfg-name {
+ type string;
+ config false;
+ description
+ "The name of the manufacturer of this physical component.
+ The preferred value is the manufacturer name string
+ actually printed on the component itself (if present).
+ Note that comparisons between instances of the
+ 'model-name', 'firmware-rev', 'software-rev', and
+ 'serial-num' nodes are only meaningful amongst components
+ with the same value of 'mfg-name'.
+ If the manufacturer name string associated with the
+ physical component is unknown to the server, then this
+ node is not instantiated.";
+ reference
+ "RFC 6933: Entity MIB (Version 4) - entPhysicalMfgName";
+ }
+
+ leaf model-name {
+ type string;
+ config false;
+ description
+ "The vendor-specific model name identifier string
+ associated with this physical component. The preferred
+ value is the customer-visible part number, which may be
+ printed on the component itself.
+ If the model name string associated with the physical
+ component is unknown to the server, then this node is not
+ instantiated.";
+ reference
+ "RFC 6933: Entity MIB (Version 4) - entPhysicalModelName";
+ }
+
+ leaf alias {
+ type string;
+ description
+ "An 'alias' name for the component, as specified by a
+ network manager, that provides a non-volatile 'handle' for
+ the component.
+ If no configured value exists, the server MAY set the
+ value of this node to a locally unique value in the
+ operational state.
+ A server implementation MAY map this leaf to the
+ entPhysicalAlias MIB object. Such an implementation needs
+ to use some mechanism to handle the differences in size
+ and characters allowed between this leaf and
+ entPhysicalAlias. The definition of such a mechanism is
+ outside the scope of this document.";
+ reference
+ "RFC 6933: Entity MIB (Version 4) - entPhysicalAlias";
+ }
+
+ leaf asset-id {
+ type string;
+ description
+ "This node is a user-assigned asset tracking identifier for
+ the component.
+ A server implementation MAY map this leaf to the
+ entPhysicalAssetID MIB object. Such an implementation
+ needs to use some mechanism to handle the differences in
+ size and characters allowed between this leaf and
+ entPhysicalAssetID. The definition of such a mechanism is
+ outside the scope of this document.";
+ reference
+ "RFC 6933: Entity MIB (Version 4) - entPhysicalAssetID";
+ }
+
+ leaf is-fru {
+ type boolean;
+ config false;
+
+ description
+ "This node indicates whether or not this component is
+ considered a 'field-replaceable unit' by the vendor. If
+ this node contains the value 'true', then this component
+ identifies a field-replaceable unit. For all components
+ that are permanently contained within a field-replaceable
+ unit, the value 'false' should be returned for this
+ node.";
+ reference
+ "RFC 6933: Entity MIB (Version 4) - entPhysicalIsFRU";
+ }
+
+ leaf mfg-date {
+ type yang:date-and-time;
+ config false;
+ description
+ "The date of manufacturing of the managed component.";
+ reference
+ "RFC 6933: Entity MIB (Version 4) - entPhysicalMfgDate";
+ }
+
+ leaf-list uri {
+ type inet:uri;
+ description
+ "This node contains identification information about the
+ component.";
+ reference
+ "RFC 6933: Entity MIB (Version 4) - entPhysicalUris";
+ }
+
+ leaf uuid {
+ type yang:uuid;
+ config false;
+ description
+ "A Universally Unique Identifier of the component.";
+ reference
+ "RFC 6933: Entity MIB (Version 4) - entPhysicalUUID";
+ }
+
+ container state {
+ if-feature hardware-state;
+ description
+ "State-related nodes";
+ reference
+ "RFC 4268: Entity State MIB";
+
+ leaf state-last-changed {
+ type yang:date-and-time;
+ config false;
+ description
+ "The date and time when the value of any of the
+ admin-state, oper-state, usage-state, alarm-state, or
+ standby-state changed for this component.
+ If there has been no change since the last
+ re-initialization of the local system, this node
+ contains the date and time of local system
+ initialization. If there has been no change since the
+ component was added to the local system, this node
+ contains the date and time of the insertion.";
+ reference
+ "RFC 4268: Entity State MIB - entStateLastChanged";
+ }
+
+ leaf admin-state {
+ type admin-state;
+ description
+ "The administrative state for this component.
+ This node refers to a component's administrative
+ permission to service both other components within its
+ containment hierarchy as well other users of its
+ services defined by means outside the scope of this
+ module.
+ Some components exhibit only a subset of the remaining
+ administrative state values. Some components cannot be
+ locked; hence, this node exhibits only the 'unlocked'
+ state. Other components cannot be shut down gracefully;
+ hence, this node does not exhibit the 'shutting-down'
+ state.";
+ reference
+ "RFC 4268: Entity State MIB - entStateAdmin";
+ }
+
+ leaf oper-state {
+ type oper-state;
+ config false;
+ description
+ "The operational state for this component.
+ Note that this node does not follow the administrative
+ state. An administrative state of 'down' does not
+ predict an operational state of 'disabled'.
+ Note that some implementations may not be able to
+ accurately report oper-state while the admin-state node
+ has a value other than 'unlocked'. In these cases, this
+ node MUST have a value of 'unknown'.";
+ reference
+ "RFC 4268: Entity State MIB - entStateOper";
+ }
+
+ leaf usage-state {
+ type usage-state;
+ config false;
+ description
+ "The usage state for this component.
+ This node refers to a component's ability to service
+ more components in a containment hierarchy.
+ Some components will exhibit only a subset of the usage
+ state values. Components that are unable to ever
+ service any components within a containment hierarchy
+ will always have a usage state of 'busy'. In some
+ cases, a component will be able to support only one
+ other component within its containment hierarchy and
+ will therefore only exhibit values of 'idle' and
+ 'busy'.";
+ reference
+ "RFC 4268: Entity State MIB - entStateUsage";
+ }
+
+ leaf alarm-state {
+ type alarm-state;
+ config false;
+ description
+ "The alarm state for this component. It does not
+ include the alarms raised on child components within its
+ containment hierarchy.";
+ reference
+ "RFC 4268: Entity State MIB - entStateAlarm";
+ }
+
+ leaf standby-state {
+ type standby-state;
+ config false;
+ description
+ "The standby state for this component.
+ Some components will exhibit only a subset of the
+ remaining standby state values. If this component
+ cannot operate in a standby role, the value of this node
+ will always be 'providing-service'.";
+ reference
+ "RFC 4268: Entity State MIB - entStateStandby";
+ }
+ }
+
+ container sensor-data {
+ when 'derived-from-or-self(../class,
+ "ianahw:sensor")' {
+ description
+ "Sensor data nodes present for any component of type
+ 'sensor'";
+ }
+ if-feature hardware-sensor;
+ config false;
+
+ description
+ "Sensor-related nodes.";
+ reference
+ "RFC 3433: Entity Sensor Management Information Base";
+
+ leaf value {
+ type sensor-value;
+ description
+ "The most recent measurement obtained by the server
+ for this sensor.
+ A client that periodically fetches this node should also
+ fetch the nodes 'value-type', 'value-scale', and
+ 'value-precision', since they may change when the value
+ is changed.";
+ reference
+ "RFC 3433: Entity Sensor Management Information Base -
+ entPhySensorValue";
+ }
+
+ leaf value-type {
+ type sensor-value-type;
+ description
+ "The type of data units associated with the
+ sensor value";
+ reference
+ "RFC 3433: Entity Sensor Management Information Base -
+ entPhySensorType";
+ }
+ leaf value-scale {
+ type sensor-value-scale;
+ description
+ "The (power of 10) scaling factor associated
+ with the sensor value";
+ reference
+ "RFC 3433: Entity Sensor Management Information Base -
+ entPhySensorScale";
+ }
+
+ leaf value-precision {
+ type sensor-value-precision;
+ description
+ "The number of decimal places of precision
+ associated with the sensor value";
+ reference
+ "RFC 3433: Entity Sensor Management Information Base -
+ entPhySensorPrecision";
+ }
+
+ leaf oper-status {
+ type sensor-status;
+ description
+ "The operational status of the sensor.";
+ reference
+ "RFC 3433: Entity Sensor Management Information Base -
+ entPhySensorOperStatus";
+ }
+
+ leaf units-display {
+ type string;
+ description
+ "A textual description of the data units that should be
+ used in the display of the sensor value.";
+ reference
+ "RFC 3433: Entity Sensor Management Information Base -
+ entPhySensorUnitsDisplay";
+ }
+
+ leaf value-timestamp {
+ type yang:date-and-time;
+ description
+ "The time the status and/or value of this sensor was last
+ obtained by the server.";
+ reference
+ "RFC 3433: Entity Sensor Management Information Base -
+ entPhySensorValueTimeStamp";
+ }
+ leaf value-update-rate {
+ type uint32;
+ units "milliseconds";
+ description
+ "An indication of the frequency that the server updates
+ the associated 'value' node, represented in
+ milliseconds. The value zero indicates:
+ - the sensor value is updated on demand (e.g.,
+ when polled by the server for a get-request),
+ - the sensor value is updated when the sensor
+ value changes (event-driven), or
+ - the server does not know the update rate.";
+ reference
+ "RFC 3433: Entity Sensor Management Information Base -
+ entPhySensorValueUpdateRate";
+ }
+ }
+ }
+}
+
+/*
+ * Notifications
+ */
+
+notification hardware-state-change {
+ description
+ "A hardware-state-change notification is generated when the
+ value of /hardware/last-change changes in the operational
+ state.";
+ reference
+ "RFC 6933: Entity MIB (Version 4) - entConfigChange";
+}
+
+notification hardware-state-oper-enabled {
+ if-feature hardware-state;
+ description
+ "A hardware-state-oper-enabled notification signifies that a
+ component has transitioned into the 'enabled' state.";
+
+ leaf name {
+ type leafref {
+ path "/hardware/component/name";
+ }
+
+ description
+ "The name of the component that has transitioned into the
+ 'enabled' state.";
+ }
+ leaf admin-state {
+ type leafref {
+ path "/hardware/component/state/admin-state";
+ }
+ description
+ "The administrative state for the component.";
+ }
+ leaf alarm-state {
+ type leafref {
+ path "/hardware/component/state/alarm-state";
+ }
+ description
+ "The alarm state for the component.";
+ }
+ reference
+ "RFC 4268: Entity State MIB - entStateOperEnabled";
+}
+
+notification hardware-state-oper-disabled {
+ if-feature hardware-state;
+ description
+ "A hardware-state-oper-disabled notification signifies that a
+ component has transitioned into the 'disabled' state.";
+
+ leaf name {
+ type leafref {
+ path "/hardware/component/name";
+ }
+ description
+ "The name of the component that has transitioned into the
+ 'disabled' state.";
+ }
+ leaf admin-state {
+ type leafref {
+ path "/hardware/component/state/admin-state";
+ }
+ description
+ "The administrative state for the component.";
+ }
+ leaf alarm-state {
+ type leafref {
+ path "/hardware/component/state/alarm-state";
+ }
+
+ description
+ "The alarm state for the component.";
+ }
+ reference
+ "RFC 4268: Entity State MIB - entStateOperDisabled";
+}
+
+}
diff --git a/radio/fhi_72/mplane/yang/models/ietf-interfaces.yang b/radio/fhi_72/mplane/yang/models/ietf-interfaces.yang
new file mode 100644
index 0000000000..8dae9d3e21
--- /dev/null
+++ b/radio/fhi_72/mplane/yang/models/ietf-interfaces.yang
@@ -0,0 +1,1073 @@
+module ietf-interfaces {
+ yang-version 1.1;
+ namespace "urn:ietf:params:xml:ns:yang:ietf-interfaces";
+ prefix if;
+
+ import ietf-yang-types {
+ prefix yang;
+ }
+
+ organization
+ "IETF NETMOD (Network Modeling) Working Group";
+
+ contact
+ "WG Web:
+ WG List:
+ Editor: Martin Bjorklund
+ ";
+
+ description
+ "This module contains a collection of YANG definitions for
+ managing network interfaces.
+ Copyright (c) 2018 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+ Redistribution and use in source and binary forms, with or
+ without modification, is permitted pursuant to, and subject
+ to the license terms contained in, the Simplified BSD License
+ set forth in Section 4.c of the IETF Trust's Legal Provisions
+ Relating to IETF Documents
+ (https://trustee.ietf.org/license-info).
+ This version of this YANG module is part of RFC 8343; see
+ the RFC itself for full legal notices.";
+
+ revision 2018-02-20 {
+ description
+ "Updated to support NMDA.";
+ reference
+ "RFC 8343: A YANG Data Model for Interface Management";
+ }
+
+ revision 2014-05-08 {
+ description
+ "Initial revision.";
+ reference
+ "RFC 7223: A YANG Data Model for Interface Management";
+ }
+
+ /*
+ * Typedefs
+ */
+
+ typedef interface-ref {
+ type leafref {
+ path "/if:interfaces/if:interface/if:name";
+ }
+ description
+ "This type is used by data models that need to reference
+ interfaces.";
+ }
+
+ /*
+ * Identities
+ */
+
+ identity interface-type {
+ description
+ "Base identity from which specific interface types are
+ derived.";
+ }
+
+ /*
+ * Features
+ */
+
+ feature arbitrary-names {
+ description
+ "This feature indicates that the device allows user-controlled
+ interfaces to be named arbitrarily.";
+ }
+ feature pre-provisioning {
+ description
+ "This feature indicates that the device supports
+ pre-provisioning of interface configuration, i.e., it is
+ possible to configure an interface whose physical interface
+ hardware is not present on the device.";
+ }
+ feature if-mib {
+ description
+ "This feature indicates that the device implements
+ the IF-MIB.";
+ reference
+ "RFC 2863: The Interfaces Group MIB";
+ }
+
+ /*
+ * Data nodes
+ */
+
+ container interfaces {
+ description
+ "Interface parameters.";
+
+ list interface {
+ key "name";
+
+ description
+ "The list of interfaces on the device.
+ The status of an interface is available in this list in the
+ operational state. If the configuration of a
+ system-controlled interface cannot be used by the system
+ (e.g., the interface hardware present does not match the
+ interface type), then the configuration is not applied to
+ the system-controlled interface shown in the operational
+ state. If the configuration of a user-controlled interface
+ cannot be used by the system, the configured interface is
+ not instantiated in the operational state.
+ System-controlled interfaces created by the system are
+ always present in this list in the operational state,
+ whether or not they are configured.";
+
+ leaf name {
+ type string;
+ description
+ "The name of the interface.
+ A device MAY restrict the allowed values for this leaf,
+ possibly depending on the type of the interface.
+ For system-controlled interfaces, this leaf is the
+ device-specific name of the interface.
+ If a client tries to create configuration for a
+ system-controlled interface that is not present in the
+ operational state, the server MAY reject the request if
+ the implementation does not support pre-provisioning of
+ interfaces or if the name refers to an interface that can
+ never exist in the system. A Network Configuration
+ Protocol (NETCONF) server MUST reply with an rpc-error
+ with the error-tag 'invalid-value' in this case.
+ If the device supports pre-provisioning of interface
+ configuration, the 'pre-provisioning' feature is
+ advertised.
+ If the device allows arbitrarily named user-controlled
+ interfaces, the 'arbitrary-names' feature is advertised.
+ When a configured user-controlled interface is created by
+ the system, it is instantiated with the same name in the
+ operational state.
+ A server implementation MAY map this leaf to the ifName
+ MIB object. Such an implementation needs to use some
+ mechanism to handle the differences in size and characters
+ allowed between this leaf and ifName. The definition of
+ such a mechanism is outside the scope of this document.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifName";
+ }
+
+ leaf description {
+ type string;
+ description
+ "A textual description of the interface.
+ A server implementation MAY map this leaf to the ifAlias
+ MIB object. Such an implementation needs to use some
+ mechanism to handle the differences in size and characters
+ allowed between this leaf and ifAlias. The definition of
+ such a mechanism is outside the scope of this document.
+ Since ifAlias is defined to be stored in non-volatile
+ storage, the MIB implementation MUST map ifAlias to the
+ value of 'description' in the persistently stored
+ configuration.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifAlias";
+ }
+
+ leaf type {
+ type identityref {
+ base interface-type;
+ }
+ mandatory true;
+ description
+ "The type of the interface.
+ When an interface entry is created, a server MAY
+ initialize the type leaf with a valid value, e.g., if it
+ is possible to derive the type from the name of the
+ interface.
+ If a client tries to set the type of an interface to a
+ value that can never be used by the system, e.g., if the
+ type is not supported or if the type does not match the
+ name of the interface, the server MUST reject the request.
+ A NETCONF server MUST reply with an rpc-error with the
+ error-tag 'invalid-value' in this case.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifType";
+ }
+
+ leaf enabled {
+ type boolean;
+ default "true";
+ description
+ "This leaf contains the configured, desired state of the
+ interface.
+ Systems that implement the IF-MIB use the value of this
+ leaf in the intended configuration to set
+ IF-MIB.ifAdminStatus to 'up' or 'down' after an ifEntry
+ has been initialized, as described in RFC 2863.
+ Changes in this leaf in the intended configuration are
+ reflected in ifAdminStatus.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifAdminStatus";
+ }
+
+ leaf link-up-down-trap-enable {
+ if-feature if-mib;
+ type enumeration {
+ enum enabled {
+ value 1;
+ description
+ "The device will generate linkUp/linkDown SNMP
+ notifications for this interface.";
+ }
+ enum disabled {
+ value 2;
+ description
+ "The device will not generate linkUp/linkDown SNMP
+ notifications for this interface.";
+ }
+ }
+ description
+ "Controls whether linkUp/linkDown SNMP notifications
+ should be generated for this interface.
+ If this node is not configured, the value 'enabled' is
+ operationally used by the server for interfaces that do
+ not operate on top of any other interface (i.e., there are
+ no 'lower-layer-if' entries), and 'disabled' otherwise.";
+ reference
+ "RFC 2863: The Interfaces Group MIB -
+ ifLinkUpDownTrapEnable";
+ }
+
+ leaf admin-status {
+ if-feature if-mib;
+ type enumeration {
+ enum up {
+ value 1;
+ description
+ "Ready to pass packets.";
+ }
+ enum down {
+ value 2;
+ description
+ "Not ready to pass packets and not in some test mode.";
+ }
+ enum testing {
+ value 3;
+ description
+ "In some test mode.";
+ }
+ }
+ config false;
+ mandatory true;
+ description
+ "The desired state of the interface.
+ This leaf has the same read semantics as ifAdminStatus.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifAdminStatus";
+ }
+
+ leaf oper-status {
+ type enumeration {
+ enum up {
+ value 1;
+ description
+ "Ready to pass packets.";
+ }
+ enum down {
+ value 2;
+
+ description
+ "The interface does not pass any packets.";
+ }
+ enum testing {
+ value 3;
+ description
+ "In some test mode. No operational packets can
+ be passed.";
+ }
+ enum unknown {
+ value 4;
+ description
+ "Status cannot be determined for some reason.";
+ }
+ enum dormant {
+ value 5;
+ description
+ "Waiting for some external event.";
+ }
+ enum not-present {
+ value 6;
+ description
+ "Some component (typically hardware) is missing.";
+ }
+ enum lower-layer-down {
+ value 7;
+ description
+ "Down due to state of lower-layer interface(s).";
+ }
+ }
+ config false;
+ mandatory true;
+ description
+ "The current operational state of the interface.
+ This leaf has the same semantics as ifOperStatus.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifOperStatus";
+ }
+
+ leaf last-change {
+ type yang:date-and-time;
+ config false;
+ description
+ "The time the interface entered its current operational
+ state. If the current state was entered prior to the
+ last re-initialization of the local network management
+ subsystem, then this node is not present.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifLastChange";
+ }
+
+ leaf if-index {
+ if-feature if-mib;
+ type int32 {
+ range "1..2147483647";
+ }
+ config false;
+ mandatory true;
+ description
+ "The ifIndex value for the ifEntry represented by this
+ interface.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifIndex";
+ }
+
+ leaf phys-address {
+ type yang:phys-address;
+ config false;
+ description
+ "The interface's address at its protocol sub-layer. For
+ example, for an 802.x interface, this object normally
+ contains a Media Access Control (MAC) address. The
+ interface's media-specific modules must define the bit
+ and byte ordering and the format of the value of this
+ object. For interfaces that do not have such an address
+ (e.g., a serial line), this node is not present.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifPhysAddress";
+ }
+
+ leaf-list higher-layer-if {
+ type interface-ref;
+ config false;
+ description
+ "A list of references to interfaces layered on top of this
+ interface.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifStackTable";
+ }
+
+ leaf-list lower-layer-if {
+ type interface-ref;
+ config false;
+
+ description
+ "A list of references to interfaces layered underneath this
+ interface.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifStackTable";
+ }
+
+ leaf speed {
+ type yang:gauge64;
+ units "bits/second";
+ config false;
+ description
+ "An estimate of the interface's current bandwidth in bits
+ per second. For interfaces that do not vary in
+ bandwidth or for those where no accurate estimation can
+ be made, this node should contain the nominal bandwidth.
+ For interfaces that have no concept of bandwidth, this
+ node is not present.";
+ reference
+ "RFC 2863: The Interfaces Group MIB -
+ ifSpeed, ifHighSpeed";
+ }
+
+ container statistics {
+ config false;
+ description
+ "A collection of interface-related statistics objects.";
+
+ leaf discontinuity-time {
+ type yang:date-and-time;
+ mandatory true;
+ description
+ "The time on the most recent occasion at which any one or
+ more of this interface's counters suffered a
+ discontinuity. If no such discontinuities have occurred
+ since the last re-initialization of the local management
+ subsystem, then this node contains the time the local
+ management subsystem re-initialized itself.";
+ }
+
+ leaf in-octets {
+ type yang:counter64;
+ description
+ "The total number of octets received on the interface,
+ including framing characters.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifHCInOctets";
+ }
+
+ leaf in-unicast-pkts {
+ type yang:counter64;
+ description
+ "The number of packets, delivered by this sub-layer to a
+ higher (sub-)layer, that were not addressed to a
+ multicast or broadcast address at this sub-layer.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifHCInUcastPkts";
+ }
+
+ leaf in-broadcast-pkts {
+ type yang:counter64;
+ description
+ "The number of packets, delivered by this sub-layer to a
+ higher (sub-)layer, that were addressed to a broadcast
+ address at this sub-layer.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB -
+ ifHCInBroadcastPkts";
+ }
+
+ leaf in-multicast-pkts {
+ type yang:counter64;
+ description
+ "The number of packets, delivered by this sub-layer to a
+ higher (sub-)layer, that were addressed to a multicast
+ address at this sub-layer. For a MAC-layer protocol,
+ this includes both Group and Functional addresses.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB -
+ ifHCInMulticastPkts";
+ }
+
+ leaf in-discards {
+ type yang:counter32;
+ description
+ "The number of inbound packets that were chosen to be
+ discarded even though no errors had been detected to
+ prevent their being deliverable to a higher-layer
+ protocol. One possible reason for discarding such a
+ packet could be to free up buffer space.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifInDiscards";
+ }
+
+ leaf in-errors {
+ type yang:counter32;
+ description
+ "For packet-oriented interfaces, the number of inbound
+ packets that contained errors preventing them from being
+ deliverable to a higher-layer protocol. For character-
+ oriented or fixed-length interfaces, the number of
+ inbound transmission units that contained errors
+ preventing them from being deliverable to a higher-layer
+ protocol.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifInErrors";
+ }
+
+ leaf in-unknown-protos {
+ type yang:counter32;
+
+ description
+ "For packet-oriented interfaces, the number of packets
+ received via the interface that were discarded because
+ of an unknown or unsupported protocol. For
+ character-oriented or fixed-length interfaces that
+ support protocol multiplexing, the number of
+ transmission units received via the interface that were
+ discarded because of an unknown or unsupported protocol.
+ For any interface that does not support protocol
+ multiplexing, this counter is not present.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifInUnknownProtos";
+ }
+
+ leaf out-octets {
+ type yang:counter64;
+ description
+ "The total number of octets transmitted out of the
+ interface, including framing characters.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifHCOutOctets";
+ }
+
+ leaf out-unicast-pkts {
+ type yang:counter64;
+ description
+ "The total number of packets that higher-level protocols
+ requested be transmitted and that were not addressed
+ to a multicast or broadcast address at this sub-layer,
+ including those that were discarded or not sent.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifHCOutUcastPkts";
+ }
+
+ leaf out-broadcast-pkts {
+ type yang:counter64;
+ description
+ "The total number of packets that higher-level protocols
+ requested be transmitted and that were addressed to a
+ broadcast address at this sub-layer, including those
+ that were discarded or not sent.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB -
+ ifHCOutBroadcastPkts";
+ }
+
+ leaf out-multicast-pkts {
+ type yang:counter64;
+ description
+ "The total number of packets that higher-level protocols
+ requested be transmitted and that were addressed to a
+ multicast address at this sub-layer, including those
+ that were discarded or not sent. For a MAC-layer
+ protocol, this includes both Group and Functional
+ addresses.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB -
+ ifHCOutMulticastPkts";
+ }
+
+ leaf out-discards {
+ type yang:counter32;
+ description
+ "The number of outbound packets that were chosen to be
+ discarded even though no errors had been detected to
+ prevent their being transmitted. One possible reason
+ for discarding such a packet could be to free up buffer
+ space.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifOutDiscards";
+ }
+
+ leaf out-errors {
+ type yang:counter32;
+ description
+ "For packet-oriented interfaces, the number of outbound
+ packets that could not be transmitted because of errors.
+ For character-oriented or fixed-length interfaces, the
+ number of outbound transmission units that could not be
+ transmitted because of errors.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifOutErrors";
+ }
+ }
+
+ }
+ }
+
+ /*
+ * Legacy typedefs
+ */
+
+ typedef interface-state-ref {
+ type leafref {
+ path "/if:interfaces-state/if:interface/if:name";
+ }
+ status deprecated;
+ description
+ "This type is used by data models that need to reference
+ the operationally present interfaces.";
+ }
+
+ /*
+ * Legacy operational state data nodes
+ */
+
+ container interfaces-state {
+ config false;
+ status deprecated;
+ description
+ "Data nodes for the operational state of interfaces.";
+
+ list interface {
+ key "name";
+ status deprecated;
+
+ description
+ "The list of interfaces on the device.
+ System-controlled interfaces created by the system are
+ always present in this list, whether or not they are
+ configured.";
+
+ leaf name {
+ type string;
+ status deprecated;
+ description
+ "The name of the interface.
+ A server implementation MAY map this leaf to the ifName
+ MIB object. Such an implementation needs to use some
+ mechanism to handle the differences in size and characters
+ allowed between this leaf and ifName. The definition of
+ such a mechanism is outside the scope of this document.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifName";
+ }
+
+ leaf type {
+ type identityref {
+ base interface-type;
+ }
+ mandatory true;
+ status deprecated;
+ description
+ "The type of the interface.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifType";
+ }
+
+ leaf admin-status {
+ if-feature if-mib;
+ type enumeration {
+ enum up {
+ value 1;
+ description
+ "Ready to pass packets.";
+ }
+ enum down {
+ value 2;
+ description
+ "Not ready to pass packets and not in some test mode.";
+ }
+ enum testing {
+ value 3;
+ description
+ "In some test mode.";
+ }
+ }
+ mandatory true;
+ status deprecated;
+ description
+ "The desired state of the interface.
+ This leaf has the same read semantics as ifAdminStatus.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifAdminStatus";
+ }
+
+ leaf oper-status {
+ type enumeration {
+ enum up {
+ value 1;
+ description
+ "Ready to pass packets.";
+ }
+ enum down {
+ value 2;
+ description
+ "The interface does not pass any packets.";
+ }
+ enum testing {
+ value 3;
+ description
+ "In some test mode. No operational packets can
+ be passed.";
+ }
+ enum unknown {
+ value 4;
+ description
+ "Status cannot be determined for some reason.";
+ }
+ enum dormant {
+ value 5;
+ description
+ "Waiting for some external event.";
+ }
+ enum not-present {
+ value 6;
+ description
+ "Some component (typically hardware) is missing.";
+ }
+ enum lower-layer-down {
+ value 7;
+ description
+ "Down due to state of lower-layer interface(s).";
+ }
+ }
+ mandatory true;
+ status deprecated;
+ description
+ "The current operational state of the interface.
+ This leaf has the same semantics as ifOperStatus.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifOperStatus";
+ }
+
+ leaf last-change {
+ type yang:date-and-time;
+ status deprecated;
+ description
+ "The time the interface entered its current operational
+ state. If the current state was entered prior to the
+ last re-initialization of the local network management
+ subsystem, then this node is not present.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifLastChange";
+ }
+
+ leaf if-index {
+ if-feature if-mib;
+ type int32 {
+ range "1..2147483647";
+ }
+ mandatory true;
+ status deprecated;
+ description
+ "The ifIndex value for the ifEntry represented by this
+ interface.";
+
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifIndex";
+ }
+
+ leaf phys-address {
+ type yang:phys-address;
+ status deprecated;
+ description
+ "The interface's address at its protocol sub-layer. For
+ example, for an 802.x interface, this object normally
+ contains a Media Access Control (MAC) address. The
+ interface's media-specific modules must define the bit
+ and byte ordering and the format of the value of this
+ object. For interfaces that do not have such an address
+ (e.g., a serial line), this node is not present.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifPhysAddress";
+ }
+
+ leaf-list higher-layer-if {
+ type interface-state-ref;
+ status deprecated;
+ description
+ "A list of references to interfaces layered on top of this
+ interface.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifStackTable";
+ }
+
+ leaf-list lower-layer-if {
+ type interface-state-ref;
+ status deprecated;
+ description
+ "A list of references to interfaces layered underneath this
+ interface.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifStackTable";
+ }
+
+ leaf speed {
+ type yang:gauge64;
+ units "bits/second";
+ status deprecated;
+ description
+ "An estimate of the interface's current bandwidth in bits
+ per second. For interfaces that do not vary in
+ bandwidth or for those where no accurate estimation can
+ be made, this node should contain the nominal bandwidth.
+ For interfaces that have no concept of bandwidth, this
+ node is not present.";
+ reference
+ "RFC 2863: The Interfaces Group MIB -
+ ifSpeed, ifHighSpeed";
+ }
+
+ container statistics {
+ status deprecated;
+ description
+ "A collection of interface-related statistics objects.";
+
+ leaf discontinuity-time {
+ type yang:date-and-time;
+ mandatory true;
+ status deprecated;
+ description
+ "The time on the most recent occasion at which any one or
+ more of this interface's counters suffered a
+ discontinuity. If no such discontinuities have occurred
+ since the last re-initialization of the local management
+ subsystem, then this node contains the time the local
+ management subsystem re-initialized itself.";
+ }
+
+ leaf in-octets {
+ type yang:counter64;
+ status deprecated;
+ description
+ "The total number of octets received on the interface,
+ including framing characters.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifHCInOctets";
+ }
+
+ leaf in-unicast-pkts {
+ type yang:counter64;
+ status deprecated;
+ description
+ "The number of packets, delivered by this sub-layer to a
+ higher (sub-)layer, that were not addressed to a
+ multicast or broadcast address at this sub-layer.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifHCInUcastPkts";
+ }
+
+ leaf in-broadcast-pkts {
+ type yang:counter64;
+ status deprecated;
+ description
+ "The number of packets, delivered by this sub-layer to a
+ higher (sub-)layer, that were addressed to a broadcast
+ address at this sub-layer.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB -
+ ifHCInBroadcastPkts";
+ }
+
+ leaf in-multicast-pkts {
+ type yang:counter64;
+ status deprecated;
+ description
+ "The number of packets, delivered by this sub-layer to a
+ higher (sub-)layer, that were addressed to a multicast
+ address at this sub-layer. For a MAC-layer protocol,
+ this includes both Group and Functional addresses.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB -
+ ifHCInMulticastPkts";
+ }
+
+ leaf in-discards {
+ type yang:counter32;
+ status deprecated;
+
+ description
+ "The number of inbound packets that were chosen to be
+ discarded even though no errors had been detected to
+ prevent their being deliverable to a higher-layer
+ protocol. One possible reason for discarding such a
+ packet could be to free up buffer space.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifInDiscards";
+ }
+
+ leaf in-errors {
+ type yang:counter32;
+ status deprecated;
+ description
+ "For packet-oriented interfaces, the number of inbound
+ packets that contained errors preventing them from being
+ deliverable to a higher-layer protocol. For character-
+ oriented or fixed-length interfaces, the number of
+ inbound transmission units that contained errors
+ preventing them from being deliverable to a higher-layer
+ protocol.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifInErrors";
+ }
+
+ leaf in-unknown-protos {
+ type yang:counter32;
+ status deprecated;
+ description
+ "For packet-oriented interfaces, the number of packets
+ received via the interface that were discarded because
+ of an unknown or unsupported protocol. For
+ character-oriented or fixed-length interfaces that
+ support protocol multiplexing, the number of
+ transmission units received via the interface that were
+ discarded because of an unknown or unsupported protocol.
+ For any interface that does not support protocol
+ multiplexing, this counter is not present.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifInUnknownProtos";
+ }
+
+ leaf out-octets {
+ type yang:counter64;
+ status deprecated;
+ description
+ "The total number of octets transmitted out of the
+ interface, including framing characters.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifHCOutOctets";
+ }
+
+ leaf out-unicast-pkts {
+ type yang:counter64;
+ status deprecated;
+ description
+ "The total number of packets that higher-level protocols
+ requested be transmitted and that were not addressed
+ to a multicast or broadcast address at this sub-layer,
+ including those that were discarded or not sent.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifHCOutUcastPkts";
+ }
+
+ leaf out-broadcast-pkts {
+ type yang:counter64;
+ status deprecated;
+
+ description
+ "The total number of packets that higher-level protocols
+ requested be transmitted and that were addressed to a
+ broadcast address at this sub-layer, including those
+ that were discarded or not sent.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB -
+ ifHCOutBroadcastPkts";
+ }
+
+ leaf out-multicast-pkts {
+ type yang:counter64;
+ status deprecated;
+ description
+ "The total number of packets that higher-level protocols
+ requested be transmitted and that were addressed to a
+ multicast address at this sub-layer, including those
+ that were discarded or not sent. For a MAC-layer
+ protocol, this includes both Group and Functional
+ addresses.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB -
+ ifHCOutMulticastPkts";
+ }
+
+ leaf out-discards {
+ type yang:counter32;
+ status deprecated;
+ description
+ "The number of outbound packets that were chosen to be
+ discarded even though no errors had been detected to
+ prevent their being transmitted. One possible reason
+ for discarding such a packet could be to free up buffer
+ space.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifOutDiscards";
+ }
+
+ leaf out-errors {
+ type yang:counter32;
+ status deprecated;
+ description
+ "For packet-oriented interfaces, the number of outbound
+ packets that could not be transmitted because of errors.
+ For character-oriented or fixed-length interfaces, the
+ number of outbound transmission units that could not be
+ transmitted because of errors.
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifOutErrors";
+ }
+ }
+ }
+ }
+}
diff --git a/radio/fhi_72/mplane/yang/models/ietf-ip.yang b/radio/fhi_72/mplane/yang/models/ietf-ip.yang
new file mode 100644
index 0000000000..449081b5c9
--- /dev/null
+++ b/radio/fhi_72/mplane/yang/models/ietf-ip.yang
@@ -0,0 +1,860 @@
+module ietf-ip {
+ yang-version 1.1;
+ namespace "urn:ietf:params:xml:ns:yang:ietf-ip";
+ prefix ip;
+
+ import ietf-interfaces {
+ prefix if;
+ }
+ import ietf-inet-types {
+ prefix inet;
+ }
+ import ietf-yang-types {
+ prefix yang;
+ }
+
+ organization
+ "IETF NETMOD (Network Modeling) Working Group";
+
+ contact
+ "WG Web:
+ WG List:
+ Editor: Martin Bjorklund
+ ";
+ description
+ "This module contains a collection of YANG definitions for
+ managing IP implementations.
+ Copyright (c) 2018 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+ Redistribution and use in source and binary forms, with or
+ without modification, is permitted pursuant to, and subject
+ to the license terms contained in, the Simplified BSD License
+ set forth in Section 4.c of the IETF Trust's Legal Provisions
+ Relating to IETF Documents
+ (https://trustee.ietf.org/license-info).
+ This version of this YANG module is part of RFC 8344; see
+ the RFC itself for full legal notices.";
+
+ revision 2018-02-22 {
+ description
+ "Updated to support NMDA.";
+ reference
+ "RFC 8344: A YANG Data Model for IP Management";
+ }
+
+ revision 2014-06-16 {
+ description
+ "Initial revision.";
+ reference
+ "RFC 7277: A YANG Data Model for IP Management";
+ }
+
+ /*
+ * Features
+ */
+
+ feature ipv4-non-contiguous-netmasks {
+ description
+ "Indicates support for configuring non-contiguous
+ subnet masks.";
+ }
+
+ feature ipv6-privacy-autoconf {
+ description
+ "Indicates support for privacy extensions for stateless address
+ autoconfiguration in IPv6.";
+ reference
+ "RFC 4941: Privacy Extensions for Stateless Address
+ Autoconfiguration in IPv6";
+ }
+
+ /*
+ * Typedefs
+ */
+
+ typedef ip-address-origin {
+ type enumeration {
+ enum other {
+ description
+ "None of the following.";
+ }
+
+ enum static {
+ description
+ "Indicates that the address has been statically
+ configured -- for example, using the Network Configuration
+ Protocol (NETCONF) or a command line interface.";
+ }
+ enum dhcp {
+ description
+ "Indicates an address that has been assigned to this
+ system by a DHCP server.";
+ }
+ enum link-layer {
+ description
+ "Indicates an address created by IPv6 stateless
+ autoconfiguration that embeds a link-layer address in its
+ interface identifier.";
+ }
+ enum random {
+ description
+ "Indicates an address chosen by the system at
+ random, e.g., an IPv4 address within 169.254/16, a
+ temporary address as described in RFC 4941, or a
+ semantically opaque address as described in RFC 7217.";
+ reference
+ "RFC 4941: Privacy Extensions for Stateless Address
+ Autoconfiguration in IPv6
+ RFC 7217: A Method for Generating Semantically Opaque
+ Interface Identifiers with IPv6 Stateless
+ Address Autoconfiguration (SLAAC)";
+ }
+ }
+ description
+ "The origin of an address.";
+ }
+
+ typedef neighbor-origin {
+ type enumeration {
+ enum other {
+ description
+ "None of the following.";
+ }
+ enum static {
+ description
+ "Indicates that the mapping has been statically
+ configured -- for example, using NETCONF or a command line
+ interface.";
+ }
+
+ enum dynamic {
+ description
+ "Indicates that the mapping has been dynamically resolved
+ using, for example, IPv4 ARP or the IPv6 Neighbor
+ Discovery protocol.";
+ }
+ }
+ description
+ "The origin of a neighbor entry.";
+ }
+
+ /*
+ * Data nodes
+ */
+
+ augment "/if:interfaces/if:interface" {
+ description
+ "IP parameters on interfaces.
+ If an interface is not capable of running IP, the server
+ must not allow the client to configure these parameters.";
+
+ container ipv4 {
+ presence
+ "Enables IPv4 unless the 'enabled' leaf
+ (which defaults to 'true') is set to 'false'";
+ description
+ "Parameters for the IPv4 address family.";
+
+ leaf enabled {
+ type boolean;
+ default true;
+ description
+ "Controls whether IPv4 is enabled or disabled on this
+ interface. When IPv4 is enabled, this interface is
+ connected to an IPv4 stack, and the interface can send
+ and receive IPv4 packets.";
+ }
+ leaf forwarding {
+ type boolean;
+ default false;
+ description
+ "Controls IPv4 packet forwarding of datagrams received by,
+ but not addressed to, this interface. IPv4 routers
+ forward datagrams. IPv4 hosts do not (except those
+ source-routed via the host).";
+ }
+
+ leaf mtu {
+ type uint16 {
+ range "68..max";
+ }
+ units "octets";
+ description
+ "The size, in octets, of the largest IPv4 packet that the
+ interface will send and receive.
+ The server may restrict the allowed values for this leaf,
+ depending on the interface's type.
+ If this leaf is not configured, the operationally used MTU
+ depends on the interface's type.";
+ reference
+ "RFC 791: Internet Protocol";
+ }
+ list address {
+ key "ip";
+ description
+ "The list of IPv4 addresses on the interface.";
+
+ leaf ip {
+ type inet:ipv4-address-no-zone;
+ description
+ "The IPv4 address on the interface.";
+ }
+ choice subnet {
+ mandatory true;
+ description
+ "The subnet can be specified as a prefix length or,
+ if the server supports non-contiguous netmasks, as
+ a netmask.";
+ leaf prefix-length {
+ type uint8 {
+ range "0..32";
+ }
+ description
+ "The length of the subnet prefix.";
+ }
+ leaf netmask {
+ if-feature ipv4-non-contiguous-netmasks;
+ type yang:dotted-quad;
+ description
+ "The subnet specified as a netmask.";
+ }
+ }
+
+ leaf origin {
+ type ip-address-origin;
+ config false;
+ description
+ "The origin of this address.";
+ }
+ }
+ list neighbor {
+ key "ip";
+ description
+ "A list of mappings from IPv4 addresses to
+ link-layer addresses.
+ Entries in this list in the intended configuration are
+ used as static entries in the ARP Cache.
+ In the operational state, this list represents the ARP
+ Cache.";
+ reference
+ "RFC 826: An Ethernet Address Resolution Protocol";
+
+ leaf ip {
+ type inet:ipv4-address-no-zone;
+ description
+ "The IPv4 address of the neighbor node.";
+ }
+ leaf link-layer-address {
+ type yang:phys-address;
+ mandatory true;
+ description
+ "The link-layer address of the neighbor node.";
+ }
+ leaf origin {
+ type neighbor-origin;
+ config false;
+ description
+ "The origin of this neighbor entry.";
+ }
+ }
+ }
+
+ container ipv6 {
+ presence
+ "Enables IPv6 unless the 'enabled' leaf
+ (which defaults to 'true') is set to 'false'";
+ description
+ "Parameters for the IPv6 address family.";
+
+ leaf enabled {
+ type boolean;
+ default true;
+ description
+ "Controls whether IPv6 is enabled or disabled on this
+ interface. When IPv6 is enabled, this interface is
+ connected to an IPv6 stack, and the interface can send
+ and receive IPv6 packets.";
+ }
+ leaf forwarding {
+ type boolean;
+ default false;
+ description
+ "Controls IPv6 packet forwarding of datagrams received by,
+ but not addressed to, this interface. IPv6 routers
+ forward datagrams. IPv6 hosts do not (except those
+ source-routed via the host).";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)
+ Section 6.2.1, IsRouter";
+ }
+ leaf mtu {
+ type uint32 {
+ range "1280..max";
+ }
+ units "octets";
+ description
+ "The size, in octets, of the largest IPv6 packet that the
+ interface will send and receive.
+ The server may restrict the allowed values for this leaf,
+ depending on the interface's type.
+ If this leaf is not configured, the operationally used MTU
+ depends on the interface's type.";
+ reference
+ "RFC 8200: Internet Protocol, Version 6 (IPv6)
+ Specification
+ Section 5";
+ }
+
+ list address {
+ key "ip";
+ description
+ "The list of IPv6 addresses on the interface.";
+
+ leaf ip {
+ type inet:ipv6-address-no-zone;
+ description
+ "The IPv6 address on the interface.";
+ }
+ leaf prefix-length {
+ type uint8 {
+ range "0..128";
+ }
+ mandatory true;
+ description
+ "The length of the subnet prefix.";
+ }
+ leaf origin {
+ type ip-address-origin;
+ config false;
+ description
+ "The origin of this address.";
+ }
+ leaf status {
+ type enumeration {
+ enum preferred {
+ description
+ "This is a valid address that can appear as the
+ destination or source address of a packet.";
+ }
+ enum deprecated {
+ description
+ "This is a valid but deprecated address that should
+ no longer be used as a source address in new
+ communications, but packets addressed to such an
+ address are processed as expected.";
+ }
+ enum invalid {
+ description
+ "This isn't a valid address, and it shouldn't appear
+ as the destination or source address of a packet.";
+ }
+
+ enum inaccessible {
+ description
+ "The address is not accessible because the interface
+ to which this address is assigned is not
+ operational.";
+ }
+ enum unknown {
+ description
+ "The status cannot be determined for some reason.";
+ }
+ enum tentative {
+ description
+ "The uniqueness of the address on the link is being
+ verified. Addresses in this state should not be
+ used for general communication and should only be
+ used to determine the uniqueness of the address.";
+ }
+ enum duplicate {
+ description
+ "The address has been determined to be non-unique on
+ the link and so must not be used.";
+ }
+ enum optimistic {
+ description
+ "The address is available for use, subject to
+ restrictions, while its uniqueness on a link is
+ being verified.";
+ }
+ }
+ config false;
+ description
+ "The status of an address. Most of the states correspond
+ to states from the IPv6 Stateless Address
+ Autoconfiguration protocol.";
+ reference
+ "RFC 4293: Management Information Base for the
+ Internet Protocol (IP)
+ - IpAddressStatusTC
+ RFC 4862: IPv6 Stateless Address Autoconfiguration";
+ }
+ }
+
+ list neighbor {
+ key "ip";
+ description
+ "A list of mappings from IPv6 addresses to
+ link-layer addresses.
+ Entries in this list in the intended configuration are
+ used as static entries in the Neighbor Cache.
+ In the operational state, this list represents the
+ Neighbor Cache.";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)";
+
+ leaf ip {
+ type inet:ipv6-address-no-zone;
+ description
+ "The IPv6 address of the neighbor node.";
+ }
+ leaf link-layer-address {
+ type yang:phys-address;
+ mandatory true;
+ description
+ "The link-layer address of the neighbor node.
+ In the operational state, if the neighbor's 'state' leaf
+ is 'incomplete', this leaf is not instantiated.";
+ }
+ leaf origin {
+ type neighbor-origin;
+ config false;
+ description
+ "The origin of this neighbor entry.";
+ }
+ leaf is-router {
+ type empty;
+ config false;
+ description
+ "Indicates that the neighbor node acts as a router.";
+ }
+
+ leaf state {
+ type enumeration {
+ enum incomplete {
+ description
+ "Address resolution is in progress, and the
+ link-layer address of the neighbor has not yet been
+ determined.";
+ }
+ enum reachable {
+ description
+ "Roughly speaking, the neighbor is known to have been
+ reachable recently (within tens of seconds ago).";
+ }
+ enum stale {
+ description
+ "The neighbor is no longer known to be reachable, but
+ until traffic is sent to the neighbor no attempt
+ should be made to verify its reachability.";
+ }
+ enum delay {
+ description
+ "The neighbor is no longer known to be reachable, and
+ traffic has recently been sent to the neighbor.
+ Rather than probe the neighbor immediately, however,
+ delay sending probes for a short while in order to
+ give upper-layer protocols a chance to provide
+ reachability confirmation.";
+ }
+ enum probe {
+ description
+ "The neighbor is no longer known to be reachable, and
+ unicast Neighbor Solicitation probes are being sent
+ to verify reachability.";
+ }
+ }
+ config false;
+ description
+ "The Neighbor Unreachability Detection state of this
+ entry.";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)
+ Section 7.3.2";
+ }
+ }
+
+ leaf dup-addr-detect-transmits {
+ type uint32;
+ default 1;
+ description
+ "The number of consecutive Neighbor Solicitation messages
+ sent while performing Duplicate Address Detection on a
+ tentative address. A value of zero indicates that
+ Duplicate Address Detection is not performed on
+ tentative addresses. A value of one indicates a single
+ transmission with no follow-up retransmissions.";
+ reference
+ "RFC 4862: IPv6 Stateless Address Autoconfiguration";
+ }
+ container autoconf {
+ description
+ "Parameters to control the autoconfiguration of IPv6
+ addresses, as described in RFC 4862.";
+ reference
+ "RFC 4862: IPv6 Stateless Address Autoconfiguration";
+
+ leaf create-global-addresses {
+ type boolean;
+ default true;
+ description
+ "If enabled, the host creates global addresses as
+ described in RFC 4862.";
+ reference
+ "RFC 4862: IPv6 Stateless Address Autoconfiguration
+ Section 5.5";
+ }
+ leaf create-temporary-addresses {
+ if-feature ipv6-privacy-autoconf;
+ type boolean;
+ default false;
+ description
+ "If enabled, the host creates temporary addresses as
+ described in RFC 4941.";
+ reference
+ "RFC 4941: Privacy Extensions for Stateless Address
+ Autoconfiguration in IPv6";
+ }
+
+ leaf temporary-valid-lifetime {
+ if-feature ipv6-privacy-autoconf;
+ type uint32;
+ units "seconds";
+ default 604800;
+ description
+ "The time period during which the temporary address
+ is valid.";
+ reference
+ "RFC 4941: Privacy Extensions for Stateless Address
+ Autoconfiguration in IPv6
+ - TEMP_VALID_LIFETIME";
+ }
+ leaf temporary-preferred-lifetime {
+ if-feature ipv6-privacy-autoconf;
+ type uint32;
+ units "seconds";
+ default 86400;
+ description
+ "The time period during which the temporary address is
+ preferred.";
+ reference
+ "RFC 4941: Privacy Extensions for Stateless Address
+ Autoconfiguration in IPv6
+ - TEMP_PREFERRED_LIFETIME";
+ }
+ }
+ }
+ }
+
+ /*
+ * Legacy operational state data nodes
+ */
+
+ augment "/if:interfaces-state/if:interface" {
+ status deprecated;
+ description
+ "Data nodes for the operational state of IP on interfaces.";
+
+ container ipv4 {
+ presence
+ "Present if IPv4 is enabled on this interface";
+ config false;
+ status deprecated;
+ description
+ "Interface-specific parameters for the IPv4 address family.";
+
+ leaf forwarding {
+ type boolean;
+ status deprecated;
+ description
+ "Indicates whether IPv4 packet forwarding is enabled or
+ disabled on this interface.";
+ }
+ leaf mtu {
+ type uint16 {
+ range "68..max";
+ }
+ units "octets";
+ status deprecated;
+ description
+ "The size, in octets, of the largest IPv4 packet that the
+ interface will send and receive.";
+ reference
+ "RFC 791: Internet Protocol";
+ }
+ list address {
+ key "ip";
+ status deprecated;
+ description
+ "The list of IPv4 addresses on the interface.";
+
+ leaf ip {
+ type inet:ipv4-address-no-zone;
+ status deprecated;
+ description
+ "The IPv4 address on the interface.";
+ }
+ choice subnet {
+ status deprecated;
+ description
+ "The subnet can be specified as a prefix length or,
+ if the server supports non-contiguous netmasks, as
+ a netmask.";
+ leaf prefix-length {
+ type uint8 {
+ range "0..32";
+ }
+ status deprecated;
+ description
+ "The length of the subnet prefix.";
+ }
+ leaf netmask {
+ if-feature ipv4-non-contiguous-netmasks;
+ type yang:dotted-quad;
+ status deprecated;
+ description
+ "The subnet specified as a netmask.";
+ }
+ }
+ leaf origin {
+ type ip-address-origin;
+ status deprecated;
+ description
+ "The origin of this address.";
+ }
+ }
+ list neighbor {
+ key "ip";
+ status deprecated;
+ description
+ "A list of mappings from IPv4 addresses to
+ link-layer addresses.
+ This list represents the ARP Cache.";
+ reference
+ "RFC 826: An Ethernet Address Resolution Protocol";
+
+ leaf ip {
+ type inet:ipv4-address-no-zone;
+ status deprecated;
+ description
+ "The IPv4 address of the neighbor node.";
+ }
+
+ leaf link-layer-address {
+ type yang:phys-address;
+ status deprecated;
+ description
+ "The link-layer address of the neighbor node.";
+ }
+ leaf origin {
+ type neighbor-origin;
+ status deprecated;
+ description
+ "The origin of this neighbor entry.";
+ }
+ }
+ }
+
+ container ipv6 {
+ presence
+ "Present if IPv6 is enabled on this interface";
+ config false;
+ status deprecated;
+ description
+ "Parameters for the IPv6 address family.";
+
+ leaf forwarding {
+ type boolean;
+ default false;
+ status deprecated;
+ description
+ "Indicates whether IPv6 packet forwarding is enabled or
+ disabled on this interface.";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)
+ Section 6.2.1, IsRouter";
+ }
+ leaf mtu {
+ type uint32 {
+ range "1280..max";
+ }
+ units "octets";
+ status deprecated;
+ description
+ "The size, in octets, of the largest IPv6 packet that the
+ interface will send and receive.";
+ reference
+ "RFC 8200: Internet Protocol, Version 6 (IPv6)
+ Specification
+ Section 5";
+ }
+ list address {
+ key "ip";
+ status deprecated;
+ description
+ "The list of IPv6 addresses on the interface.";
+
+ leaf ip {
+ type inet:ipv6-address-no-zone;
+ status deprecated;
+ description
+ "The IPv6 address on the interface.";
+ }
+ leaf prefix-length {
+ type uint8 {
+ range "0..128";
+ }
+ mandatory true;
+ status deprecated;
+ description
+ "The length of the subnet prefix.";
+ }
+ leaf origin {
+ type ip-address-origin;
+ status deprecated;
+ description
+ "The origin of this address.";
+ }
+ leaf status {
+ type enumeration {
+ enum preferred {
+ description
+ "This is a valid address that can appear as the
+ destination or source address of a packet.";
+ }
+ enum deprecated {
+ description
+ "This is a valid but deprecated address that should
+ no longer be used as a source address in new
+ communications, but packets addressed to such an
+ address are processed as expected.";
+ }
+ enum invalid {
+ description
+ "This isn't a valid address, and it shouldn't appear
+ as the destination or source address of a packet.";
+ }
+
+ enum inaccessible {
+ description
+ "The address is not accessible because the interface
+ to which this address is assigned is not
+ operational.";
+ }
+ enum unknown {
+ description
+ "The status cannot be determined for some reason.";
+ }
+ enum tentative {
+ description
+ "The uniqueness of the address on the link is being
+ verified. Addresses in this state should not be
+ used for general communication and should only be
+ used to determine the uniqueness of the address.";
+ }
+ enum duplicate {
+ description
+ "The address has been determined to be non-unique on
+ the link and so must not be used.";
+ }
+ enum optimistic {
+ description
+ "The address is available for use, subject to
+ restrictions, while its uniqueness on a link is
+ being verified.";
+ }
+ }
+ status deprecated;
+ description
+ "The status of an address. Most of the states correspond
+ to states from the IPv6 Stateless Address
+ Autoconfiguration protocol.";
+ reference
+ "RFC 4293: Management Information Base for the
+ Internet Protocol (IP)
+ - IpAddressStatusTC
+ RFC 4862: IPv6 Stateless Address Autoconfiguration";
+ }
+ }
+
+ list neighbor {
+ key "ip";
+ status deprecated;
+ description
+ "A list of mappings from IPv6 addresses to
+ link-layer addresses.
+ This list represents the Neighbor Cache.";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)";
+
+ leaf ip {
+ type inet:ipv6-address-no-zone;
+ status deprecated;
+ description
+ "The IPv6 address of the neighbor node.";
+ }
+ leaf link-layer-address {
+ type yang:phys-address;
+ status deprecated;
+ description
+ "The link-layer address of the neighbor node.";
+ }
+ leaf origin {
+ type neighbor-origin;
+ status deprecated;
+ description
+ "The origin of this neighbor entry.";
+ }
+ leaf is-router {
+ type empty;
+ status deprecated;
+ description
+ "Indicates that the neighbor node acts as a router.";
+ }
+ leaf state {
+ type enumeration {
+ enum incomplete {
+ description
+ "Address resolution is in progress, and the
+ link-layer address of the neighbor has not yet been
+ determined.";
+ }
+ enum reachable {
+ description
+ "Roughly speaking, the neighbor is known to have been
+ reachable recently (within tens of seconds ago).";
+ }
+ enum stale {
+ description
+ "The neighbor is no longer known to be reachable, but
+ until traffic is sent to the neighbor no attempt
+ should be made to verify its reachability.";
+ }
+ enum delay {
+ description
+ "The neighbor is no longer known to be reachable, and
+ traffic has recently been sent to the neighbor.
+ Rather than probe the neighbor immediately, however,
+ delay sending probes for a short while in order to
+ give upper-layer protocols a chance to provide
+ reachability confirmation.";
+ }
+ enum probe {
+ description
+ "The neighbor is no longer known to be reachable, and
+ unicast Neighbor Solicitation probes are being sent
+ to verify reachability.";
+ }
+ }
+ status deprecated;
+ description
+ "The Neighbor Unreachability Detection state of this
+ entry.";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)
+ Section 7.3.2";
+ }
+ }
+ }
+ }
+}
diff --git a/radio/fhi_72/mplane/yang/models/o-ran-compression-factors.yang b/radio/fhi_72/mplane/yang/models/o-ran-compression-factors.yang
new file mode 100644
index 0000000000..5816b5ed63
--- /dev/null
+++ b/radio/fhi_72/mplane/yang/models/o-ran-compression-factors.yang
@@ -0,0 +1,368 @@
+module o-ran-compression-factors {
+ yang-version 1.1;
+ namespace "urn:o-ran:compression-factors:1.0";
+ prefix "o-ran-compression-factors";
+
+
+ organization "O-RAN Alliance";
+
+ contact
+ "www.o-ran.org";
+
+ description
+ "This module defines the module capabilities for
+ the O-RAN Radio Unit U-Plane configuration.
+
+ Copyright 2020 the O-RAN Alliance.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the above disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the above disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the Members of the O-RAN Alliance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.";
+
+ revision "2020-08-10" {
+ description
+ "version 4.0.0
+
+ 1) supporting compression types per endpoint
+ 2) adding feature for configurable fs-offset for compression";
+
+ reference "ORAN-WG4.M.0-v04.00";
+ }
+
+ revision "2020-04-17" {
+ description
+ "version 3.0.0
+
+ 1) adding selective RE sending compression types";
+
+ reference "ORAN-WG4.M.0-v03.00";
+ }
+
+ revision "2019-07-03" {
+ description
+ "version 1.1.0
+
+ 1) changes related to compression bitwidth presentation";
+
+ reference "ORAN-WG4.M.0-v01.00";
+ }
+
+ revision "2019-02-04" {
+ description
+ "version 1.0.0
+
+ 1) imported model from xRAN
+ 2) changed namespace and reference from xran to o-ran";
+
+ reference "ORAN-WG4.M.0-v01.00";
+ }
+
+ feature CONFIGURABLE-FS-OFFSET {
+ description
+ "Presence of this feature means that O-RU supports configurable fs-offset for compression.";
+ }
+
+ grouping compression-method-grouping {
+ description
+ "Grouping for compression method.";
+
+ leaf iq-bitwidth {
+ type uint8;
+ description
+ "Bitwidth to be used in compression";
+ }
+
+ leaf compression-method {
+ type enumeration {
+ enum NO_COMPRESSION {
+ description
+ "No compression will be used";
+ }
+ enum BLOCK_FLOATING_POINT {
+ description
+ "Block floating point compression and decompression will be used";
+ }
+
+ enum BLOCK_SCALING {
+ description
+ "Block scaling compression and decompresion will be used";
+ }
+
+ enum U_LAW {
+ description
+ "u-Law compression and decompresion method will be used";
+ }
+
+ enum BEAMSPACE {
+ description
+ "Beamspace compression and decompression will be used";
+ }
+
+ enum MODULATION {
+ description
+ "Modulation compression and decompression will be used";
+ }
+ enum BLOCK-FLOATING-POINT-SELECTIVE-RE-SENDING {
+ description
+ "block floating point with selective re sending
+ compression and decompression will be used";
+ }
+ enum MODULATION-COMPRESSION-SELECTIVE-RE-SENDING {
+ description
+ "modulation compression with selective re sending
+ compression and decompression will be used";
+ }
+ }
+ description
+ "Compresion method which can be supported by the O-RU";
+ }
+ }
+
+ grouping compression-formats {
+ description
+ "Grouping deicated to list compression formats as choice";
+
+ choice compression-format {
+ description
+ "Choice of compression format for particular element";
+
+ case no-compresison {
+ description "Compression for beam weights is not supported.";
+ }
+ case block-floating-point {
+ description "Block floating point compression and decompression is supported.";
+
+ leaf exponent {
+ type uint8 {
+ range "4";
+ }
+ description "Exponent bit width size in number of bits used when encoding in udCompParam.";
+ }
+ }
+
+ case block-floating-point-selective-re-sending {
+ description
+ "Block floating point with selective re sending compression and decompression is supported.";
+
+ leaf sres-exponent {
+ type uint8 {
+ range "4";
+ }
+ description "Exponent bit width size in number of bits used when encoding in udCompParam.";
+ }
+ }
+
+ case block-scaling {
+ description "Block scaling compression and decompresion is supported.";
+ leaf block-scalar {
+ type uint8;
+ description
+ "Common scaler for compressed PRB";
+ }
+ }
+
+ case u-law {
+ description "u-Law compression and decompresion method is supported.";
+ leaf comp-bit-width {
+ type uint8 {
+ range "0..15";
+ }
+ description "Bit with for u-law compression";
+ }
+ leaf comp-shift {
+ type uint8 {
+ range "0..15";
+ }
+ description
+ "the shift applied to the entire PRB";
+ }
+ }
+
+ case beam-space-compression {
+ description "Beamspace compression and decompression is supported. Applies to beamforming weights only.";
+ leaf-list active-beam-space-coeficient-mask {
+ type uint8;
+ description
+ "active beamspace coefficient indices associated with the compressed beamforming vector";
+ }
+ leaf block-scaler {
+ type uint8;
+ description
+ "Common scaler for compressed beamforming coefficients";
+ }
+ }
+
+ case modulation-compression {
+ description "Modulation compression and decompression is supported.";
+ leaf csf {
+ type uint8 {
+ range "0..1";
+ }
+ description "Constallation shift flag";
+ }
+
+ leaf mod-comp-scaler {
+ type uint16 {
+ range "0..32767";
+ }
+ description "Modulation compression scaler value.";
+ }
+ }
+
+ case modulation-compression-selective-re-sending {
+ description "Modulation compression with selective re sending and decompression is supported.";
+ leaf sres-csf {
+ type uint8 {
+ range "0..1";
+ }
+ description "Constallation shift flag";
+ }
+
+ leaf sres-mod-comp-scaler {
+ type uint16 {
+ range "0..32767";
+ }
+ description "Modulation compression scaler value.";
+ }
+ }
+
+ }
+ }
+
+ grouping compression-params {
+ description
+ "Parameters to define compression";
+
+ leaf compression-type {
+ type enumeration {
+ enum STATIC {
+ description
+ "Indicates that static compression method will be used (both compression and IQ bitwidth)";
+ }
+ enum DYNAMIC {
+ description
+ "Indicates that dynamic compression method will be used";
+ }
+ }
+ mandatory true;
+ description
+ "Compression type that O-DU wants to be supported";
+ }
+
+// *********** TO BE REMOVED ***********
+ leaf bitwidth {
+ when "../compression-type = 'STATIC'";
+ type uint8;
+ status deprecated;
+ description
+ "Bitwidth to be used in compression.
+ This has since been replaced in M-Plane version
+ 2.0.0 with the iq-bitwidth schema node";
+ }
+// *************************************
+
+ uses compression-formats;
+ }
+
+ grouping compression-parameters {
+ description
+ "Parameters used to define description type";
+
+ leaf iq-bitwidth {
+ type uint8;
+ description
+ "Bitwidth to be used in compression";
+ }
+
+ uses compression-formats;
+ }
+
+ grouping format-of-iq-sample {
+ description
+ "Indicates module capabilities about IQ samples";
+
+ leaf dynamic-compression-supported {
+ type boolean;
+
+ description
+ "Informs if radio supports dynamic compression method";
+ }
+
+ leaf realtime-variable-bit-width-supported {
+ type boolean;
+
+ description
+ "Informs if O-RU supports realtime variable bit with";
+ }
+
+ list compression-method-supported {
+ uses compression-parameters;
+
+ description
+ "List of supported compression methods by O-RU
+ Note: if O-RU supports different compression methods per endpoint
+ then please refer do endpoints to have information what
+ exactly is supported on a paticular endpoint";
+ }
+
+ leaf syminc-supported {
+ type boolean;
+
+ description
+ "Informs if symbol number increment command in a C-Plane is
+ supported or not";
+ }
+
+ leaf regularization-factor-se-supported {
+ type boolean;
+
+ description
+ "Informs if regularizationFactor in section type 5 is
+ supported(true) or not(false)";
+ }
+
+ leaf little-endian-supported {
+ type boolean;
+ default false;
+
+ description
+ "All O-RUs support bigendian byte order. This node informs if module supports the
+ the optional capability for little endian byte order for C/U plane data flows.
+
+ Note - little endian support does not invalidate bigendian support.";
+ }
+ }
+
+
+ grouping compression-details {
+ description "";
+
+ leaf iq-bitwidth {
+ type uint8;
+ description
+ "Bitwidth to be used in compression";
+ }
+
+ uses compression-params;
+ }
+}
diff --git a/radio/fhi_72/mplane/yang/models/o-ran-interfaces.yang b/radio/fhi_72/mplane/yang/models/o-ran-interfaces.yang
new file mode 100644
index 0000000000..92587ce40c
--- /dev/null
+++ b/radio/fhi_72/mplane/yang/models/o-ran-interfaces.yang
@@ -0,0 +1,414 @@
+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-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;
+ }
+
+// 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
+
+
+ rpc reset-interface-counters {
+ description
+ "Management plane triggered restart of the interface counters.";
+ }
+}
diff --git a/radio/fhi_72/mplane/yang/models/o-ran-module-cap.yang b/radio/fhi_72/mplane/yang/models/o-ran-module-cap.yang
new file mode 100644
index 0000000000..e726d57e72
--- /dev/null
+++ b/radio/fhi_72/mplane/yang/models/o-ran-module-cap.yang
@@ -0,0 +1,840 @@
+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-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 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/radio/fhi_72/mplane/yang/models/o-ran-processing-element.yang b/radio/fhi_72/mplane/yang/models/o-ran-processing-element.yang
new file mode 100644
index 0000000000..fc930a0a81
--- /dev/null
+++ b/radio/fhi_72/mplane/yang/models/o-ran-processing-element.yang
@@ -0,0 +1,362 @@
+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 {
+ if-feature o-ran-int:UDPIP-BASED-CU-PLANE;
+ 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 {
+ if-feature o-ran-int:UDPIP-BASED-CU-PLANE;
+ 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/radio/fhi_72/mplane/yang/models/o-ran-uplane-conf.yang b/radio/fhi_72/mplane/yang/models/o-ran-uplane-conf.yang
new file mode 100644
index 0000000000..16fbaf3335
--- /dev/null
+++ b/radio/fhi_72/mplane/yang/models/o-ran-uplane-conf.yang
@@ -0,0 +1,2706 @@
+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-08-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-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";
+ }
+ }
+ 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";
+ }
+ }
+
+ 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.";
+ }
+
+ 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;
+ mandatory true;
+ description
+ "Absolute Radio Frequency Channel Number - indirectly indicates RF center carrier frequency of signal.
+ Reflected in arfcn.";
+ }
+
+ leaf center-of-channel-bandwidth {
+ type uint64;
+ units Hz;
+ mandatory true;
+ description
+ "Center frequency of channel bandwidth in Hz. Common for all numerologies.";
+ }
+
+ 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;
+ mandatory true;
+ description
+ "Absolute Radio Frequency Channel Number - indirectly indicates RF center carrier frequency of signal.
+ Reflected in arfcn.";
+ }
+
+ leaf center-of-channel-bandwidth {
+ type uint64;
+ units Hz;
+ mandatory true;
+ description
+ "Center frequency of channel bandwidth in Hz. Common for all numerologies.";
+ }
+
+ 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-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 {
+ 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 {
+ type leafref {
+ 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 {
+ when "(/user-plane-configuration/low-level-rx-endpoints[name=current()/../name]/static-config-supported = 'PRACH')";
+ if-feature mcap:PRACH-STATIC-CONFIGURATION-SUPPORTED;
+ type leafref {
+ 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 {
+ 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 {
+ 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 Hz and accuracy is 1/4 Tc. 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 Hz and accuracy is 1/4 Tc. 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 Hz and accuracy is 1/4 Tc.";
+ }
+ }
+ }
+
+ 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/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c
index 16dd2d85de..cbc530a785 100644
--- a/radio/fhi_72/oaioran.c
+++ b/radio/fhi_72/oaioran.c
@@ -90,7 +90,7 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status)
rx_sym = callback_tag->symbol & 0xFF;
uint32_t ru_id = callback_tag->oXuId;
- LOG_D(NR_PHY,
+ LOG_D(HW,
"rx_callback frame %d, subframe %d, slot %d, second %lld, rx_sym %d ru_id %d\n",
frame,
subframe,
@@ -127,7 +127,7 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status)
rx_RU[ru_id][slot2] = 1;
if (last_frame > 0 && frame > 0
&& ((slot2 > 0 && last_frame != frame) || (slot2 == 0 && last_frame != ((1024 + frame - 1) & 1023))))
- LOG_E(PHY, "Jump in frame counter last_frame %d => %d, slot %d\n", last_frame, frame, slot2);
+ LOG_E(HW, "Jump in frame counter last_frame %d => %d, slot %d\n", last_frame, frame, slot2);
for (int i = 0; i < num_ports; i++) {
if (rx_RU[i][slot2] == 0)
return;
@@ -142,16 +142,16 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status)
info->tti = tti;
info->sl = slot2;
info->f = frame;
- LOG_D(PHY, "Push %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, info->sl, slot, ru_id, subframe, last_slot);
+ LOG_D(HW, "Push %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, info->sl, slot, ru_id, subframe, last_slot);
pushNotifiedFIFO(&oran_sync_fifo, req);
#else
- LOG_D(PHY, "Writing %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, slot2, ru_id, slot, subframe, last_slot);
+ LOG_D(HW, "Writing %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, slot2, ru_id, slot, subframe, last_slot);
oran_sync_info.tti = tti;
oran_sync_info.sl = slot2;
oran_sync_info.f = frame;
#endif
} else
- LOG_E(PHY, "Cannot Push %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, slot2, ru_id, slot, subframe, last_slot);
+ LOG_E(HW, "Cannot Push %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, slot2, ru_id, slot, subframe, last_slot);
last_slot = slot2;
last_frame = frame;
} // rx_sym == 7
@@ -289,7 +289,7 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
while ((f = pollNotifiedFIFO(&oran_sync_fifo)) != NULL) {
oran_sync_info_t *old_info = NotifiedFifoData(res);
oran_sync_info_t *new_info = NotifiedFifoData(f);
- LOG_E(PHY, "Detected double sync message %d.%d => %d.%d\n", old_info->f, old_info->sl, new_info->f, new_info->sl);
+ LOG_E(HW, "Detected double sync message %d.%d => %d.%d\n", old_info->f, old_info->sl, new_info->f, new_info->sl);
delNotifiedFIFO_elt(res);
res = f;
}
@@ -305,14 +305,14 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
uint32_t tti_in = oran_sync_info.tti;
static int last_slot = -1;
- LOG_D(PHY, "oran slot %d, last_slot %d\n", *slot, last_slot);
+ LOG_D(HW, "oran slot %d, last_slot %d\n", *slot, last_slot);
int cnt = 0;
// while (*slot == last_slot) {
while (tti_in == oran_sync_info.tti) {
//*slot = oran_sync_info.sl;
cnt++;
}
- LOG_D(PHY, "cnt %d, Reading %d.%d\n", cnt, *frame, *slot);
+ LOG_D(HW, "cnt %d, Reading %d.%d\n", cnt, *frame, *slot);
last_slot = *slot;
#endif
// return(0);
@@ -380,9 +380,9 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
int16_t payload_len = 0;
- LOG_D(PHY, "pRbMap->nPrbElm %d\n", pRbMap->nPrbElm);
+ LOG_D(HW, "pRbMap->nPrbElm %d\n", pRbMap->nPrbElm);
for (idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) {
- LOG_D(PHY,
+ LOG_D(HW,
"prbMap[%d] : PRBstart %d nPRBs %d\n",
idxElm,
pRbMap->prbMap[idxElm].nRBStart,
@@ -436,7 +436,7 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
} // vv_inf
if ((*frame & 0x7f) == 0 && *slot == 0 && xran_get_common_counters(gxran_handle, &x_counters[0]) == XRAN_STATUS_SUCCESS) {
for (int o_xu_id = 0; o_xu_id < fh_init->xran_ports; o_xu_id++) {
- LOG_I(NR_PHY,
+ LOG_I(HW,
"[%s%d][rx %7ld pps %7ld kbps %7ld][tx %7ld pps %7ld kbps %7ld][Total Msgs_Rcvd %ld]\n",
"o-du ",
o_xu_id,
@@ -448,7 +448,7 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
x_counters[o_xu_id].tx_bytes_per_sec * 8 / 1000L,
x_counters[o_xu_id].Total_msgs_rcvd);
for (int rxant = 0; rxant < ru->nb_rx / fh_init->xran_ports; rxant++)
- LOG_I(NR_PHY,
+ LOG_I(HW,
"[%s%d][pusch%d %7ld prach%d %7ld]\n",
"o_du",
o_xu_id,
diff --git a/radio/fhi_72/oran-config.c b/radio/fhi_72/oran-config.c
index 2f2032c30a..71804c5298 100644
--- a/radio/fhi_72/oran-config.c
+++ b/radio/fhi_72/oran-config.c
@@ -32,6 +32,10 @@
#include "stdio.h"
#include "string.h"
+#ifdef OAI_MPLANE
+#include "mplane/ru-mplane-api.h"
+#endif
+
static void print_fh_eowd_cmn(unsigned index, const struct xran_ecpri_del_meas_cmn *eowd_cmn)
{
printf("\
@@ -522,6 +526,38 @@ static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, in
return true;
}
+#ifdef OAI_MPLANE
+static bool set_fh_eaxcid_conf_mplane(struct xran_eaxcid_config *eaxcid_conf, enum xran_category cat, const ru_session_list_t *ru_session_list)
+{
+ xran_mplane_t *xran_mplane = &ru_session_list->ru_session[0].xran_mplane;
+ switch (cat) {
+ case XRAN_CATEGORY_A:
+ eaxcid_conf->mask_cuPortId = xran_mplane->du_port_bitmask;
+ eaxcid_conf->mask_bandSectorId = xran_mplane->band_sector_bitmask;
+ eaxcid_conf->mask_ccId = xran_mplane->ccid_bitmask;
+ eaxcid_conf->mask_ruPortId = xran_mplane->ru_port_bitmask;
+ eaxcid_conf->bit_cuPortId = xran_mplane->du_port;
+ eaxcid_conf->bit_bandSectorId = xran_mplane->band_sector; // total number of band sectors supported by O-RU should be retrieved by M-plane - &&
+ eaxcid_conf->bit_ccId = xran_mplane->ccid; // total number of CC supported by O-RU should be retrieved by M-plane -
+ eaxcid_conf->bit_ruPortId = xran_mplane->ru_port;
+ break;
+ case XRAN_CATEGORY_B:
+ eaxcid_conf->mask_cuPortId = 0xf000;
+ eaxcid_conf->mask_bandSectorId = 0x0c00;
+ eaxcid_conf->mask_ccId = 0x0300;
+ eaxcid_conf->mask_ruPortId = 0x000f;
+ eaxcid_conf->bit_cuPortId = 12;
+ eaxcid_conf->bit_bandSectorId = 10;
+ eaxcid_conf->bit_ccId = 8;
+ eaxcid_conf->bit_ruPortId = 0;
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+#else
static bool set_fh_eaxcid_conf(struct xran_eaxcid_config *eaxcid_conf, enum xran_category cat)
{
/* CUS specification, section 3.1.3.1.6
@@ -540,8 +576,8 @@ static bool set_fh_eaxcid_conf(struct xran_eaxcid_config *eaxcid_conf, enum xran
eaxcid_conf->mask_ccId = 0x00f0;
eaxcid_conf->mask_ruPortId = 0x000f;
eaxcid_conf->bit_cuPortId = 0;
- eaxcid_conf->bit_bandSectorId = 0; // total number of band sectors supported by O-RU should be retreived by M-plane - &&
- eaxcid_conf->bit_ccId = 0; // total number of CC supported by O-RU should be retreived by M-plane -
+ eaxcid_conf->bit_bandSectorId = 0; // total number of band sectors supported by O-RU should be retrieved by M-plane - &&
+ eaxcid_conf->bit_ccId = 0; // total number of CC supported by O-RU should be retrieved by M-plane -
eaxcid_conf->bit_ruPortId = 0;
break;
case XRAN_CATEGORY_B:
@@ -560,6 +596,7 @@ static bool set_fh_eaxcid_conf(struct xran_eaxcid_config *eaxcid_conf, enum xran
return true;
}
+#endif
uint8_t *get_ether_addr(const char *addr, struct rte_ether_addr *ether_addr)
{
@@ -573,7 +610,7 @@ uint8_t *get_ether_addr(const char *addr, struct rte_ether_addr *ether_addr)
return NULL;
}
-static bool set_fh_init(struct xran_fh_init *fh_init, enum xran_category xran_cat)
+static bool set_fh_init(void *mplane_api, struct xran_fh_init *fh_init, enum xran_category xran_cat)
{
memset(fh_init, 0, sizeof(*fh_init));
@@ -606,30 +643,46 @@ static bool set_fh_init(struct xran_fh_init *fh_init, enum xran_category xran_ca
const int nfh = sizeofArray(FHconfigs);
config_getlist(config_get_if(), &FH_ConfigList, FHconfigs, nfh, aprefix);
- int num_rus = FH_ConfigList.numelt; // based on the number of fh_config sections -> number of RUs
+#ifdef OAI_MPLANE
+ ru_session_list_t *ru_session_list = (ru_session_list_t *)mplane_api;
+ int num_rus = ru_session_list->num_rus;
+ fh_init->xran_ports = num_rus; // since we use xran as O-DU, xran_ports is set to the number of RUs
+ if (!set_fh_io_cfg(&fh_init->io_cfg, fhip, nump, num_rus))
+ return false;
+ if (!set_fh_eaxcid_conf_mplane(&fh_init->eAxCId_conf, xran_cat, ru_session_list))
+ return false;
+ /* maximum transmission unit (MTU) is the size of the largest protocol data unit (PDU) that can be
+ communicated in a single xRAN network layer transaction. Supported 1500 bytes and 9600 bytes (Jumbo Frame);
+ xran only checks if (MTU <= 1500), therefore setting any value > 1500, xran assumes 9600 value is used */
+ fh_init->mtu = ru_session_list->ru_session[0].xran_mplane.mtu; // we suppose that each RU supports the same MTU size
+ int num_ru_addr = (fh_init->io_cfg.one_vf_cu_plane) ? num_rus : 2*num_rus;
+ fh_init->p_o_ru_addr = calloc(num_ru_addr, sizeof(struct rte_ether_addr));
+ AssertFatal(fh_init->p_o_ru_addr != NULL, "out of memory\n");
+ for (int i = 0; i < num_rus; i++) {
+ struct rte_ether_addr *ea = (struct rte_ether_addr *)fh_init->p_o_ru_addr;
+ for (int j = 0; j < num_ru_addr/num_rus; j++) {
+ if (get_ether_addr(ru_session_list->ru_session[i].xran_mplane.ru_mac_addr, &ea[i+j]) == NULL) {
+ printf("could not read ethernet address '%s' for RU!\n", ru_session_list->ru_session[i].xran_mplane.ru_mac_addr);
+ return false;
+ }
+ }
+ }
+#else
+ int num_rus = FH_ConfigList.numelt; // based on the number of fh_config sections -> number of RUs
+ fh_init->xran_ports = num_rus; // since we use xran as O-DU, xran_ports is set to the number of RUs
if (!set_fh_io_cfg(&fh_init->io_cfg, fhip, nump, num_rus))
return false;
if (!set_fh_eaxcid_conf(&fh_init->eAxCId_conf, xran_cat))
return false;
-
- fh_init->xran_ports = num_rus; // since we use xran as O-DU, xran_ports is set to the number of RUs
- fh_init->dpdkBasebandFecMode = 0; // DPDK Baseband FEC device mode (0-SW, 1-HW); not used in xran
- fh_init->dpdkBasebandDevice = NULL; // DPDK Baseband device address; not used in xran
- /* used to specify a unique prefix for shared memory, and files created by multiple DPDK processes;
- it is necessary */
- fh_init->filePrefix = strdup(*gpd(fhip, nump, ORAN_CONFIG_FILE_PREFIX)->strptr);
/* maximum transmission unit (MTU) is the size of the largest protocol data unit (PDU) that can be
communicated in a single xRAN network layer transaction. Supported 1500 bytes and 9600 bytes (Jumbo Frame);
xran only checks if (MTU <= 1500), therefore setting any value > 1500, xran assumes 9600 value is used */
fh_init->mtu = *gpd(fhip, nump, ORAN_CONFIG_MTU)->uptr;
-
- fh_init->p_o_du_addr = NULL; // DPDK retreives DU MAC address within the xran library with rte_eth_macaddr_get() function
-
int num_ru_addr = gpd(fhip, nump, ORAN_CONFIG_RU_ADDR)->numelt;
fh_init->p_o_ru_addr = calloc(num_ru_addr, sizeof(struct rte_ether_addr));
- char **ru_addrs = gpd(fhip, nump, ORAN_CONFIG_RU_ADDR)->strlistptr;
AssertFatal(fh_init->p_o_ru_addr != NULL, "out of memory\n");
+ char **ru_addrs = gpd(fhip, nump, ORAN_CONFIG_RU_ADDR)->strlistptr;
for (int i = 0; i < num_ru_addr; ++i) {
struct rte_ether_addr *ea = (struct rte_ether_addr *)fh_init->p_o_ru_addr;
if (get_ether_addr(ru_addrs[i], &ea[i]) == NULL) {
@@ -637,7 +690,14 @@ static bool set_fh_init(struct xran_fh_init *fh_init, enum xran_category xran_ca
return false;
}
}
+#endif
+ fh_init->dpdkBasebandFecMode = 0; // DPDK Baseband FEC device mode (0-SW, 1-HW); not used in xran
+ fh_init->dpdkBasebandDevice = NULL; // DPDK Baseband device address; not used in xran
+ /* used to specify a unique prefix for shared memory, and files created by multiple DPDK processes;
+ it is necessary */
+ fh_init->filePrefix = strdup(*gpd(fhip, nump, ORAN_CONFIG_FILE_PREFIX)->strptr);
+ fh_init->p_o_du_addr = NULL; // DPDK retreives DU MAC address within the xran library with rte_eth_macaddr_get() function
fh_init->totalBfWeights = 0; // only used if id = O_RU (for emulation); C-plane extension types; section 5.4.6 of CUS spec
#ifdef F_RELEASE
@@ -656,7 +716,8 @@ static bool set_fh_init(struct xran_fh_init *fh_init, enum xran_category xran_ca
// this is a hack
int g_kbar;
-static bool set_fh_prach_config(const openair0_config_t *oai0,
+static bool set_fh_prach_config(void *mplane_api,
+ const openair0_config_t *oai0,
const uint32_t max_num_ant,
const paramdef_t *prachp,
int nprach,
@@ -692,8 +753,13 @@ static bool set_fh_prach_config(const openair0_config_t *oai0,
xran assumes PRACH offset >= max(Ntx, Nrx). However, we made a workaround that xran supports PRACH eAxC IDs same as PUSCH eAxC IDs.
This is achieved with is_prach and filter_id parameters in the patch.
Please note that this approach only applies to the RUs that support this functionality, e.g. LITEON RU. */
+#ifdef OAI_MPLANE
+ xran_mplane_t *xran_mplane = (xran_mplane_t *)mplane_api;
+ prach_config->eAxC_offset = xran_mplane->prach_offset;
+#else
uint8_t offset = *gpd(prachp, nprach, ORAN_PRACH_CONFIG_EAXC_OFFSET)->u8ptr;
prach_config->eAxC_offset = (offset != 0) ? offset : max_num_ant;
+#endif
g_kbar = *gpd(prachp, nprach, ORAN_PRACH_CONFIG_KBAR)->uptr;
@@ -722,17 +788,24 @@ static bool set_fh_frame_config(const openair0_config_t *oai0, struct xran_frame
return true;
}
-static bool set_fh_ru_config(const paramdef_t *rup, uint16_t fftSize, int nru, enum xran_category xran_cat, struct xran_ru_config *ru_config)
+static bool set_fh_ru_config(void *mplane_api, const paramdef_t *rup, uint16_t fftSize, int nru, enum xran_category xran_cat, struct xran_ru_config *ru_config)
{
ru_config->xranTech = XRAN_RAN_5GNR; // 5GNR or LTE
ru_config->xranCat = xran_cat; // mode: Catergory A or Category B
ru_config->xranCompHdrType = XRAN_COMP_HDR_TYPE_STATIC; // dynamic or static udCompHdr handling
+#ifdef OAI_MPLANE
+ xran_mplane_t *xran_mplane = (xran_mplane_t *)mplane_api;
+ ru_config->iqWidth = xran_mplane->iq_width;
+ ru_config->iqWidth_PRACH = xran_mplane->iq_width;
+#else
ru_config->iqWidth = *gpd(rup, nru, ORAN_RU_CONFIG_IQWIDTH)->uptr; // IQ bit width
AssertFatal(ru_config->iqWidth <= 16, "IQ Width cannot be > 16!\n");
- ru_config->compMeth = ru_config->iqWidth < 16 ? XRAN_COMPMETHOD_BLKFLOAT : XRAN_COMPMETHOD_NONE; // compression method
ru_config->iqWidth_PRACH = *gpd(rup, nru, ORAN_RU_CONFIG_IQWIDTH_PRACH)->uptr; // IQ bit width for PRACH
AssertFatal(ru_config->iqWidth_PRACH <= 16, "IQ Width for PRACH cannot be > 16!\n");
+#endif
+ ru_config->compMeth = ru_config->iqWidth < 16 ? XRAN_COMPMETHOD_BLKFLOAT : XRAN_COMPMETHOD_NONE; // compression method
ru_config->compMeth_PRACH = ru_config->iqWidth_PRACH < 16 ? XRAN_COMPMETHOD_BLKFLOAT : XRAN_COMPMETHOD_NONE; // compression method for PRACH
+
AssertFatal(fftSize > 0, "FFT size cannot be 0\n");
ru_config->fftSize = fftSize; // FFT Size
ru_config->byteOrder = XRAN_NE_BE_BYTE_ORDER; // order of bytes in int16_t in buffer; big or little endian
@@ -757,7 +830,7 @@ static bool set_maxmin_pd(const paramdef_t *pd, int num, const char *name, uint1
return true;
}
-static bool set_fh_config(int ru_idx, int num_rus, enum xran_category xran_cat, const openair0_config_t *oai0, struct xran_fh_config *fh_config)
+static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_category xran_cat, const openair0_config_t *oai0, struct xran_fh_config *fh_config)
{
AssertFatal(num_rus == 1 || num_rus == 2, "only support 1 or 2 RUs as of now\n");
AssertFatal(ru_idx < num_rus, "illegal ru_idx %d: must be < %d\n", ru_idx, num_rus);
@@ -839,22 +912,22 @@ static bool set_fh_config(int ru_idx, int num_rus, enum xran_category xran_cat,
#endif
fh_config->puschMaskEnable = 0; // enable PUSCH mask; only used if id = O_RU
fh_config->puschMaskSlot = 0; // specific which slot PUSCH channel masked; only used if id = O_RU
- fh_config->cp_vlan_tag = *gpd(fhp, nfh, ORAN_FH_CONFIG_CP_VLAN_TAG)->uptr; // C-plane VLAN tag; not used in xran; needed for M-plane
- fh_config->up_vlan_tag = *gpd(fhp, nfh, ORAN_FH_CONFIG_UP_VLAN_TAG)->uptr; // U-plane VLAN tag; not used in xran; needed for M-plane
+ fh_config->cp_vlan_tag = 0; // C-plane VLAN tag; not used in xran; needed for M-plane
+ fh_config->up_vlan_tag = 0; // U-plane VLAN tag; not used in xran; needed for M-plane
fh_config->debugStop = 0; // enable auto stop; only used if id = O_RU
fh_config->debugStopCount = 0; // enable auto stop after number of Tx packets; not used in xran
fh_config->DynamicSectionEna = 0; // enable dynamic C-Plane section allocation
fh_config->GPS_Alpha = 0; // refers to alpha as defined in section 9.7.2 of ORAN spec. this value should be alpha*(1/1.2288ns), range 0 - 1e7 (ns); offset_nsec = (pConf->GPS_Beta - offset_sec * 100) * 1e7 + pConf->GPS_Alpha
fh_config->GPS_Beta = 0; // beta value as defined in section 9.7.2 of ORAN spec. range -32767 ~ +32767; offset_sec = pConf->GPS_Beta / 100
- if (!set_fh_prach_config(oai0, fh_config->neAxc, prachp, nprach, &fh_config->prach_conf))
+ if (!set_fh_prach_config(mplane_api, oai0, fh_config->neAxc, prachp, nprach, &fh_config->prach_conf))
return false;
/* SRS only used if XRAN_CATEGORY_B
Note: srs_config->eAxC_offset >= prach_config->eAxC_offset + PRACH */
// fh_config->srs_conf = {0};
if (!set_fh_frame_config(oai0, &fh_config->frame_conf))
return false;
- if (!set_fh_ru_config(rup, oai0->split7.fftSize, nru, xran_cat, &fh_config->ru_conf))
+ if (!set_fh_ru_config(mplane_api, rup, oai0->split7.fftSize, nru, xran_cat, &fh_config->ru_conf))
return false;
fh_config->bbdev_enc = NULL; // call back to poll BBDev encoder
@@ -889,24 +962,35 @@ static bool set_fh_config(int ru_idx, int num_rus, enum xran_category xran_cat,
return true;
}
-bool get_xran_config(const openair0_config_t *openair0_cfg, struct xran_fh_init *fh_init, struct xran_fh_config *fh_config)
+bool get_xran_config(void *mplane_api, const struct openair0_config *openair0_cfg, struct xran_fh_init *fh_init, struct xran_fh_config *fh_config)
{
/* This xran integration release is only valid for O-RU CAT A.
Therefore, each FH parameter is hardcoded to CAT A.
If you are interested in CAT B, please be aware that parameters of fh_init and fh_config structs must be modified accordingly. */
enum xran_category xran_cat = XRAN_CATEGORY_A;
- if (!set_fh_init(fh_init, xran_cat)) {
+ if (!set_fh_init(mplane_api, fh_init, xran_cat)) {
printf("could not read FHI 7.2/ORAN config\n");
return false;
}
+#ifdef OAI_MPLANE
+ ru_session_list_t *ru_session_list = (ru_session_list_t *)mplane_api;
for (int32_t o_xu_id = 0; o_xu_id < fh_init->xran_ports; o_xu_id++) {
- if (!set_fh_config(o_xu_id, fh_init->xran_ports, xran_cat, openair0_cfg, &fh_config[o_xu_id])) {
+ xran_mplane_t *xran_mplane = &ru_session_list->ru_session[o_xu_id].xran_mplane;
+ if (!set_fh_config(xran_mplane, o_xu_id, fh_init->xran_ports, xran_cat, openair0_cfg, &fh_config[o_xu_id])) {
+ MP_LOG_I("could not read FHI 7.2/RU-specific config\n");
+ return false;
+ }
+ }
+#else
+ for (int32_t o_xu_id = 0; o_xu_id < fh_init->xran_ports; o_xu_id++) {
+ if (!set_fh_config(NULL, o_xu_id, fh_init->xran_ports, xran_cat, openair0_cfg, &fh_config[o_xu_id])) {
printf("could not read FHI 7.2/RU-specific config\n");
return false;
}
}
+#endif
return true;
}
diff --git a/radio/fhi_72/oran-config.h b/radio/fhi_72/oran-config.h
index c5a086638f..bbe934e757 100644
--- a/radio/fhi_72/oran-config.h
+++ b/radio/fhi_72/oran-config.h
@@ -29,7 +29,7 @@ struct xran_fh_init;
struct xran_fh_config;
struct openair0_config;
-bool get_xran_config(const struct openair0_config *openair0_cfg, struct xran_fh_init *fh_init, struct xran_fh_config *fh_config);
+bool get_xran_config(void *mplane_api, const struct openair0_config *openair0_cfg, struct xran_fh_init *fh_init, struct xran_fh_config *fh_config);
void print_fh_init(const struct xran_fh_init *fh_init);
void print_fh_config(const struct xran_fh_config *fh_config);
diff --git a/radio/fhi_72/oran-init.c b/radio/fhi_72/oran-init.c
index 97930a172b..fd3fdaa5bf 100644
--- a/radio/fhi_72/oran-init.c
+++ b/radio/fhi_72/oran-init.c
@@ -443,7 +443,7 @@ int *oai_oran_initialize(struct xran_fh_init *xran_fh_init, struct xran_fh_confi
pi->prach_tag = tag;
pi->pusch_tag = tag;
#ifdef E_RELEASE
- LOG_W(PHY, "Please be aware that E release support will be removed in the future. Consider switching to F release.\n");
+ LOG_W(HW, "Please be aware that E release support will be removed in the future. Consider switching to F release.\n");
oran_allocate_buffers(gxran_handle, o_xu_id, 1, pi, &xran_fh_config[o_xu_id]);
#elif defined F_RELEASE
oran_allocate_buffers(gxran_handle, o_xu_id, 1, pi, xran_fh_init->mtu, &xran_fh_config[o_xu_id]);
diff --git a/radio/fhi_72/oran-params.h b/radio/fhi_72/oran-params.h
index 20c3d71634..42aabd99bb 100644
--- a/radio/fhi_72/oran-params.h
+++ b/radio/fhi_72/oran-params.h
@@ -31,8 +31,12 @@
#define ORAN_CONFIG_SYSTEM_CORE "system_core"
#define ORAN_CONFIG_IO_CORE "io_core"
#define ORAN_CONFIG_WORKER_CORES "worker_cores"
-#define ORAN_CONFIG_RU_ADDR "ru_addr"
-#define ORAN_CONFIG_MTU "mtu"
+#define ORAN_CONFIG_DU_KEYPAIR "du_key_pair" // only needed for M-plane
+#define ORAN_CONFIG_DU_ADDR "du_addr" // only needed for M-plane
+#define ORAN_CONFIG_VLAN_TAG "vlan_tag" // only needed for M-plane
+#define ORAN_CONFIG_RU_ADDR "ru_addr" // not needed if M-plane used
+#define ORAN_CONFIG_RU_IP_ADDR "ru_ip_addr" // only needed for M-plane
+#define ORAN_CONFIG_MTU "mtu" // not needed if M-plane used
#define ORAN_CONFIG_FILE_PREFIX "file_prefix"
#define ORAN_CONFIG_NETHPERPORT "eth_lines"
#define ORAN_CONFIG_NETHSPEED "eth_speed"
@@ -48,7 +52,11 @@
{ORAN_CONFIG_SYSTEM_CORE, "DPDK control threads core\n", PARAMFLAG_MANDATORY, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
{ORAN_CONFIG_IO_CORE, "DPDK Core used for IO\n", PARAMFLAG_MANDATORY, .iptr=NULL, .defintval=4, TYPE_INT, 0}, \
{ORAN_CONFIG_WORKER_CORES, "CPU Cores to use for workers\n", PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=NULL,TYPE_UINTARRAY, 0}, \
+ {ORAN_CONFIG_DU_KEYPAIR, "DU keypair for RU authentication\n", PARAMFLAG_MANDATORY, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \
+ {ORAN_CONFIG_DU_ADDR, "Ether addr of DU\n", PARAMFLAG_MANDATORY, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \
+ {ORAN_CONFIG_VLAN_TAG, "VLAN tag\n", PARAMFLAG_MANDATORY, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \
{ORAN_CONFIG_RU_ADDR, "Ether addr of RU\n", PARAMFLAG_MANDATORY, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \
+ {ORAN_CONFIG_RU_IP_ADDR, "IP addr of RU\n", PARAMFLAG_MANDATORY, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \
{ORAN_CONFIG_MTU, "MTU of Eth interface\n", 0, .uptr=NULL, .defuintval=1500, TYPE_UINT, 0}, \
{ORAN_CONFIG_FILE_PREFIX, "DPDK file-prefix\n", 0, .strptr=NULL, .defstrval="wls_0", TYPE_STRING, 0}, \
{ORAN_CONFIG_NETHPERPORT, "number of links per port\n", 0, .uptr=NULL, .defuintval=1, TYPE_UINT, 0}, \
@@ -70,6 +78,10 @@
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
+ { .s5 = { NULL } }, \
+ { .s5 = { NULL } }, \
+ { .s5 = { NULL } }, \
+ { .s5 = { NULL } }, \
{ .s3a = { config_checkstr_assign_integer, \
{"PA", "VA"}, {0, 1}, 2} }, \
{ .s5 = { NULL } }, \
@@ -84,8 +96,6 @@
#define ORAN_FH_CONFIG_T1A_CP_UL "T1a_cp_ul"
#define ORAN_FH_CONFIG_T1A_UP "T1a_up"
#define ORAN_FH_CONFIG_TA4 "Ta4"
-#define ORAN_FH_CONFIG_CP_VLAN_TAG "cp_vlan_tag"
-#define ORAN_FH_CONFIG_UP_VLAN_TAG "up_vlan_tag"
#define ORAN_FH_HLP_CPLT " parameter of RU in list form (Min&Max, length 2!)\n"
@@ -95,15 +105,13 @@
{ORAN_FH_CONFIG_T1A_CP_UL, "T1a_cp_ul" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \
{ORAN_FH_CONFIG_T1A_UP, "T1a_up" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \
{ORAN_FH_CONFIG_TA4, "Ta4" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \
- {ORAN_FH_CONFIG_CP_VLAN_TAG, "not used by xran", 0, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \
- {ORAN_FH_CONFIG_UP_VLAN_TAG, "not used by xran", 0, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \
}
// clang-format on
#define CONFIG_STRING_ORAN_RU "ru_config"
-#define ORAN_RU_CONFIG_IQWIDTH "iq_width"
-#define ORAN_RU_CONFIG_IQWIDTH_PRACH "iq_width_prach"
+#define ORAN_RU_CONFIG_IQWIDTH "iq_width" // not needed if M-plane used
+#define ORAN_RU_CONFIG_IQWIDTH_PRACH "iq_width_prach" // not needed if M-plane used
// clang-format off
#define ORAN_RU_DESC {\
@@ -114,7 +122,7 @@
#define CONFIG_STRING_ORAN_PRACH "prach_config"
-#define ORAN_PRACH_CONFIG_EAXC_OFFSET "eAxC_offset"
+#define ORAN_PRACH_CONFIG_EAXC_OFFSET "eAxC_offset" // not needed if M-plane used
#define ORAN_PRACH_CONFIG_KBAR "kbar"
// clang-format off
diff --git a/radio/fhi_72/oran_isolate.c b/radio/fhi_72/oran_isolate.c
index d3f4fa1796..0a200a39a0 100644
--- a/radio/fhi_72/oran_isolate.c
+++ b/radio/fhi_72/oran_isolate.c
@@ -39,11 +39,17 @@
// line and the use of VERSIONX further below. It is relative to phy/fhi_lib/lib/api
#include "../../app/src/common.h"
+#ifdef OAI_MPLANE
+#include "mplane/init-mplane.h"
+#include "mplane/connect-mplane.h"
+#endif
+
typedef struct {
eth_state_t e;
rru_config_msg_type_t last_msg;
int capabilities_sent;
void *oran_priv;
+ void *mplane_priv;
} oran_eth_state_t;
notifiedFIFO_t oran_sync_fifo;
@@ -76,6 +82,10 @@ int trx_oran_stop(openair0_device *device)
printf("ORAN: %s\n", __FUNCTION__);
oran_eth_state_t *s = device->priv;
xran_stop(s->oran_priv);
+#ifdef OAI_MPLANE
+ printf("[MPLANE] Stopping M-plane.\n");
+ disconnect_mplane(s->mplane_priv);
+#endif
return (0);
}
@@ -204,11 +214,11 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
RU_proc_t *proc = &ru->proc;
int f, sl;
- LOG_D(PHY, "Read rxdataF %p,%p\n", ru_info.rxdataF[0], ru_info.rxdataF[1]);
+ LOG_D(HW, "Read rxdataF %p,%p\n", ru_info.rxdataF[0], ru_info.rxdataF[1]);
start_meas(&ru->rx_fhaul);
int ret = xran_fh_rx_read_slot(&ru_info, &f, &sl);
stop_meas(&ru->rx_fhaul);
- LOG_D(PHY, "Read %d.%d rxdataF %p,%p\n", f, sl, ru_info.rxdataF[0], ru_info.rxdataF[1]);
+ LOG_D(HW, "Read %d.%d rxdataF %p,%p\n", f, sl, ru_info.rxdataF[0], ru_info.rxdataF[1]);
if (ret != 0) {
printf("ORAN: %d.%d ORAN_fh_if4p5_south_in ERROR in RX function \n", f, sl);
}
@@ -221,7 +231,7 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
if (proc->first_rx == 0) {
if (proc->tti_rx != *slot) {
- LOG_E(PHY,
+ LOG_E(HW,
"Received Time doesn't correspond to the time we think it is (slot mismatch, received %d.%d, expected %d.%d)\n",
proc->frame_rx,
proc->tti_rx,
@@ -231,7 +241,7 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
}
if (proc->frame_rx != *frame) {
- LOG_E(PHY,
+ LOG_E(HW,
"Received Time doesn't correspond to the time we think it is (frame mismatch, %d.%d , expected %d.%d)\n",
proc->frame_rx,
proc->tti_rx,
@@ -241,10 +251,10 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
}
} else {
proc->first_rx = 0;
- LOG_I(PHY, "before adjusting, OAI: frame=%d slot=%d, XRAN: frame=%d slot=%d\n", *frame, *slot, proc->frame_rx, proc->tti_rx);
+ LOG_I(HW, "before adjusting, OAI: frame=%d slot=%d, XRAN: frame=%d slot=%d\n", *frame, *slot, proc->frame_rx, proc->tti_rx);
*frame = proc->frame_rx;
*slot = proc->tti_rx;
- LOG_I(PHY, "After adjusting, OAI: frame=%d slot=%d, XRAN: frame=%d slot=%d\n", *frame, *slot, proc->frame_rx, proc->tti_rx);
+ LOG_I(HW, "After adjusting, OAI: frame=%d slot=%d, XRAN: frame=%d slot=%d\n", *frame, *slot, proc->frame_rx, proc->tti_rx);
}
}
@@ -279,7 +289,80 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device *d
openair0_config_t *openair0_cfg,
eth_params_t *eth_params)
{
- oran_eth_state_t *eth;
+ oran_eth_state_t *eth = calloc_or_fail(1, sizeof(*eth));
+
+ struct xran_fh_init fh_init = {0};
+ struct xran_fh_config fh_config[XRAN_PORTS_NUM] = {0};
+
+ bool success = false;
+#ifdef OAI_MPLANE
+ ru_session_list_t ru_session_list = {0};
+ success = init_mplane(&ru_session_list);
+ AssertFatal(success, "[MPLANE] Cannot initialize M-plane.\n");
+
+ bool ru_configured[ru_session_list.num_rus];
+ for (size_t i = 0; i < ru_session_list.num_rus; i++) {
+ ru_session_t *ru_session = &ru_session_list.ru_session[i];
+ ru_configured[i] = connect_mplane(ru_session);
+ if (!ru_configured[i]) {
+ continue;
+ }
+ ru_configured[i] = manage_ru(ru_session, openair0_cfg, ru_session_list.num_rus);
+ }
+
+ bool all_ok = true;
+ bool ru_ready[ru_session_list.num_rus];
+ for (size_t i = 0; i < ru_session_list.num_rus; i++) {
+ if (!ru_configured[i]) {
+ MP_LOG_I("RU with IP %s couldn't be configured.\n", ru_session_list.ru_session[i].ru_ip_add);
+ all_ok = false;
+ }
+ ru_ready[i] = false;
+ }
+
+ if (!all_ok) {
+ disconnect_mplane((void *)&ru_session_list);
+ AssertFatal(false, "[MPLANE] Stopping M-plane.\n");
+ }
+
+ while (true) {
+ sleep(1);
+ bool all_rus_ready = true;
+ for (int i = 0; i < ru_session_list.num_rus; i++) {
+ ru_session_t *ru_session = &ru_session_list.ru_session[i];
+ if (!ru_ready[i] && ru_session->ru_notif.config_change && ru_session->ru_notif.rx_carrier_state && ru_session->ru_notif.tx_carrier_state) {
+ MP_LOG_I("RU \"%s\" is now ready.\n", ru_session->ru_ip_add);
+ ru_ready[i] = true;
+ } else {
+ all_rus_ready = false;
+ break;
+ }
+ }
+ if (all_rus_ready) {
+ break;
+ }
+ }
+
+ eth->mplane_priv = (void *)&ru_session_list;
+
+ success = get_xran_config((void *)&ru_session_list, openair0_cfg, &fh_init, fh_config);
+ AssertFatal(success, "[MPLANE] Cannot configure xran with M-plane info.\n");
+#else
+ success = get_xran_config(NULL, openair0_cfg, &fh_init, fh_config);
+ AssertFatal(success, "cannot get configuration for xran\n");
+#endif
+
+ LOG_I(HW, "Initializing O-RAN 7.2 FH interface through xran library (compiled against headers of %s)\n", VERSIONX);
+ eth->oran_priv = oai_oran_initialize(&fh_init, fh_config);
+ AssertFatal(eth->oran_priv != NULL, "can not initialize fronthaul");
+ // create message queues for ORAN sync
+
+ initNotifiedFIFO(&oran_sync_fifo);
+
+ eth->e.flags = ETH_RAW_IF4p5_MODE;
+ eth->e.compression = NO_COMPRESS;
+ eth->e.if_name = eth_params->local_if_name;
+ eth->last_msg = (rru_config_msg_type_t)-1;
device->Mod_id = 0;
device->transp_type = ETHERNET_TP;
@@ -290,43 +373,13 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device *d
device->trx_stop_func = trx_oran_stop;
device->trx_set_freq_func = trx_oran_set_freq;
device->trx_set_gains_func = trx_oran_set_gains;
-
device->trx_write_func = trx_oran_write_raw;
device->trx_read_func = trx_oran_read_raw;
-
device->trx_ctlsend_func = trx_oran_ctlsend;
device->trx_ctlrecv_func = trx_oran_ctlrecv;
-
device->get_internal_parameter = get_internal_parameter;
-
- eth = (oran_eth_state_t *)calloc(1, sizeof(oran_eth_state_t));
- if (eth == NULL) {
- AssertFatal(0 == 1, "out of memory\n");
- }
-
- eth->e.flags = ETH_RAW_IF4p5_MODE;
- eth->e.compression = NO_COMPRESS;
- eth->e.if_name = eth_params->local_if_name;
- eth->oran_priv = NULL; // define_oran_pointer();
device->priv = eth;
device->openair0_cfg = &openair0_cfg[0];
- eth->last_msg = (rru_config_msg_type_t)-1;
-
- LOG_I(HW, "Initializing O-RAN 7.2 FH interface through xran library (compiled against headers of %s)\n", VERSIONX);
-
- initNotifiedFIFO(&oran_sync_fifo);
-
- struct xran_fh_init fh_init = {0};
- struct xran_fh_config fh_config[XRAN_PORTS_NUM] = {0};
-#ifndef OAI_MPLANE_SUPPORT
- bool success = get_xran_config(openair0_cfg, &fh_init, fh_config);
- AssertFatal(success, "cannot get configuration for xran\n");
-#else
- /* TODO: M-plane integration */
-#endif
- eth->oran_priv = oai_oran_initialize(&fh_init, fh_config);
- AssertFatal(eth->oran_priv != NULL, "can not initialize fronthaul");
- // create message queues for ORAN sync
return 0;
}
diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c
index b11f4034ca..ca01a1768c 100644
--- a/radio/rfsimulator/simulator.c
+++ b/radio/rfsimulator/simulator.c
@@ -1004,7 +1004,7 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest
t->nextRxTstamp + nsamps);
flushInput(t, 3, nsamps);
}
- if (t->hanging_workaround && loops++ > 10 && t->role == SIMU_ROLE_SERVER) {
+ if (t->hanging_workaround && loops++ > 10 && t->role == SIMU_ROLE_SERVER && nb_ue > 1) {
// Just start producing samples. The clients will catch up.
have_to_wait = false;
LOG_W(HW,
diff --git a/radio/vrtsim/CMakeLists.txt b/radio/vrtsim/CMakeLists.txt
new file mode 100644
index 0000000000..79eb4d88da
--- /dev/null
+++ b/radio/vrtsim/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_library(vrtsim MODULE vrtsim.c noise_device.c)
+set_target_properties(vrtsim PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
+target_link_libraries(vrtsim PRIVATE SIMU shm_td_iq_channel actor)
+add_dependencies(vrtsim generate_T)
diff --git a/radio/vrtsim/README.md b/radio/vrtsim/README.md
new file mode 100644
index 0000000000..71455175c3
--- /dev/null
+++ b/radio/vrtsim/README.md
@@ -0,0 +1,25 @@
+# Overview
+
+This implements a shared memory realtime and near-realtime radio interface.
+This is performed using `shm_td_iq_channel` which handles the shared memory
+interface.
+
+# Limitations
+
+ - Only 1gNB to 1nrUE: gNB as a server, UE as a client.
+ - Server only accepts connections during device bringup. This means that
+ restarting the client will not make it reconnect, the server has to be
+ restarted as well.
+
+# Usage
+
+On the UE and gNB: use `device.name vrtsim` command line argument.
+
+Additionally on gNB use `vrtsim.role server` and optionally
+`vrtsim.timescale ` to set the timescale. Timescale 1.0
+is the default and means realtime.
+
+Channel modelling can be enabled by adding `vrtsim.chanmod 1` to the
+command line and should work the same as channel modelling in rfsimulator,
+see rfsimulator [documentation](../rfsimulator/README.md), provided that your
+CPU is fast enough.
diff --git a/radio/vrtsim/noise_device.c b/radio/vrtsim/noise_device.c
new file mode 100644
index 0000000000..2e15944d4a
--- /dev/null
+++ b/radio/vrtsim/noise_device.c
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+#include
+#include
+#include "noise_device.h"
+
+// Use block size equal to cache size
+#define BLOCK_SIZE (64 / sizeof(float)) // 4 bytes per float
+// Use a power of 2 for block size length
+#define NUM_BLOCKS (8192)
+#define NOISE_VECTOR_LENGTH (BLOCK_SIZE * NUM_BLOCKS)
+
+static struct {
+ pthread_t noise_device_thread;
+ float noise[NOISE_VECTOR_LENGTH] __attribute__((aligned(64)));
+ float noise_power;
+ bool running;
+} state;
+
+static uint32_t jz, jsr = 123456789;
+static uint32_t random_uint(void)
+{
+ return SHR3;
+}
+
+static void generate_one_block_noise(int write_block_index, float noise_power)
+{
+ // Generate noise vector
+ float block[BLOCK_SIZE];
+ for (int i = 0; i < BLOCK_SIZE; i++) {
+ block[i] = noise_power * gaussZiggurat(0, 1);
+ }
+ // Write block to noise vector
+ memcpy(state.noise + write_block_index * BLOCK_SIZE, block, sizeof(block));
+}
+
+void *noise_device_thread_function(void *arg)
+{
+ while (state.running) {
+ // Generate noise vector
+ generate_one_block_noise(random_uint() % NUM_BLOCKS, state.noise_power);
+ usleep(10000);
+ }
+ return NULL;
+}
+
+void init_noise_device(float noise_power)
+{
+ for (int i = 0; i < NUM_BLOCKS; i++) {
+ generate_one_block_noise(i, noise_power);
+ }
+ int ret = pthread_create(&state.noise_device_thread, NULL, noise_device_thread_function, NULL);
+ AssertFatal(ret == 0, "pthread_create failed: %d, errno %d (%s)\n", ret, errno, strerror(errno));
+}
+
+void free_noise_device(void)
+{
+ state.running = false;
+ pthread_join(state.noise_device_thread, NULL);
+}
+
+void get_noise_vector(float *noise_vector, int length)
+{
+ int start_block = random_uint() % NUM_BLOCKS;
+ while (length > 0) {
+ int copy_size = min(length, (NUM_BLOCKS - start_block) * BLOCK_SIZE);
+ memcpy(noise_vector, &state.noise[start_block * BLOCK_SIZE], copy_size * sizeof(float));
+ start_block = 0;
+ length -= copy_size;
+ noise_vector += copy_size;
+ }
+}
diff --git a/radio/vrtsim/noise_device.h b/radio/vrtsim/noise_device.h
new file mode 100644
index 0000000000..421723891a
--- /dev/null
+++ b/radio/vrtsim/noise_device.h
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#ifndef NOISE_DEVICE_H
+#define NOISE_DEVICE_H
+
+#include "SIMULATION/TOOLS/sim.h"
+
+void init_noise_device(float noise_power);
+void free_noise_device(void);
+void get_noise_vector(float *noise_vector, int length);
+
+#endif
diff --git a/radio/vrtsim/vrtsim.c b/radio/vrtsim/vrtsim.c
new file mode 100644
index 0000000000..f0e0151aa6
--- /dev/null
+++ b/radio/vrtsim/vrtsim.c
@@ -0,0 +1,598 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include "common_lib.h"
+#include "shm_td_iq_channel.h"
+#include "SIMULATION/TOOLS/sim.h"
+#include "actor.h"
+#include "noise_device.h"
+#include "simde/x86/avx512.h"
+
+// Simulator role
+typedef enum { ROLE_SERVER = 1, ROLE_CLIENT } role;
+
+#define NUM_CHANMOD_THREADS 1
+
+#define ROLE_CLIENT_STRING "client"
+#define ROLE_SERVER_STRING "server"
+
+#define VRTSIM_SECTION "vrtsim"
+#define TIME_SCALE_HLP \
+ "sample time scale. 1.0 means realtime. Values > 1 mean faster than realtime. Values < 1 mean slower than realtime\n"
+
+// clang-format off
+#define VRTSIM_PARAMS_DESC \
+ { \
+ {"channel_name", "shared memory channel name\n", 0, .strptr = &channel_name, .defstrval = "vrtsim_channel", TYPE_STRING, 0}, \
+ {"role", "either client or server\n", 0, .strptr = &role, .defstrval = ROLE_CLIENT_STRING, TYPE_STRING, 0}, \
+ {"timescale", TIME_SCALE_HLP, 0, .dblptr = &vrtsim_state->timescale, .defdblval = 1.0, TYPE_DOUBLE, 0}, \
+ {"chanmod", "Enable channel modelling", 0, .iptr = &vrtsim_state->chanmod, .defintval = 0, TYPE_INT, 0}, \
+ };
+// clang-format on
+
+typedef struct histogram_s {
+ uint64_t diff[30];
+ int num_samples;
+ int min_samples;
+ double range;
+} histogram_t;
+
+// Information about the peer
+typedef struct peer_info_s {
+ int num_rx_antennas;
+} peer_info_t;
+
+typedef struct tx_timing_s {
+ uint64_t tx_samples_late;
+ uint64_t tx_early;
+ uint64_t tx_samples_total;
+ double average_tx_budget;
+ histogram_t tx_histogram;
+} tx_timing_t;
+
+typedef struct {
+ int role;
+ char channel_name[40];
+ ShmTDIQChannel *channel;
+ uint64_t last_received_sample;
+ pthread_t timing_thread;
+ bool run_timing_thread;
+ double timescale;
+ double sample_rate;
+ uint64_t rx_samples_late;
+ uint64_t rx_early;
+ uint64_t rx_samples_total;
+ tx_timing_t *tx_timing;
+ peer_info_t peer_info;
+ int chanmod;
+ double rx_freq;
+ double tx_bw;
+ int tx_num_channels;
+ int rx_num_channels;
+ channel_desc_t *channel_desc;
+ Actor_t *channel_modelling_actors;
+} vrtsim_state_t;
+
+static void histogram_add(histogram_t *histogram, double diff)
+{
+ histogram->num_samples++;
+ if (histogram->num_samples >= histogram->min_samples) {
+ int bin = min(sizeofArray(histogram->diff) - 1, max(0, (int)(diff / histogram->range * sizeofArray(histogram->diff))));
+ histogram->diff[bin]++;
+ }
+}
+
+static void histogram_print(histogram_t *histogram)
+{
+ LOG_I(HW, "VRTSIM: TX budget histogram: %d samples\n", histogram->num_samples);
+ float bin_size = histogram->range / sizeofArray(histogram->diff);
+ float bin_start = 0;
+ for (int i = 0; i < sizeofArray(histogram->diff); i++) {
+ LOG_I(HW, "Bin %d\t[%.1f - %.1fuS]:\t\t%lu\n", i, bin_start, bin_start + bin_size, histogram->diff[i]);
+ bin_start += bin_size;
+ }
+}
+
+static void histogram_merge(histogram_t *dest, histogram_t *src)
+{
+ for (int i = 0; i < sizeofArray(dest->diff); i++) {
+ dest->diff[i] += src->diff[i];
+ }
+ dest->num_samples += src->num_samples;
+}
+
+static void load_channel_model(vrtsim_state_t *vrtsim_state)
+{
+ load_channellist(vrtsim_state->tx_num_channels,
+ vrtsim_state->peer_info.num_rx_antennas,
+ vrtsim_state->sample_rate,
+ vrtsim_state->rx_freq,
+ vrtsim_state->tx_bw);
+ char *model_name = vrtsim_state->role == ROLE_CLIENT ? "client_tx_channel_model" : "server_tx_channel_model";
+ vrtsim_state->channel_desc = find_channel_desc_fromname(model_name);
+ random_channel(vrtsim_state->channel_desc, 0);
+ AssertFatal(vrtsim_state->channel_desc != NULL, "Could not find channel model %s\n", model_name);
+}
+
+static void vrtsim_readconfig(vrtsim_state_t *vrtsim_state)
+{
+ char *channel_name = NULL;
+ char *role = NULL;
+ paramdef_t vrtsim_params[] = VRTSIM_PARAMS_DESC;
+ int ret = config_get(config_get_if(), vrtsim_params, sizeofArray(vrtsim_params), VRTSIM_SECTION);
+ AssertFatal(ret >= 0, "configuration couldn't be performed\n");
+ strncpy(vrtsim_state->channel_name, channel_name, sizeof(vrtsim_state->channel_name) - 1);
+ if (strncmp(role, ROLE_CLIENT_STRING, strlen(ROLE_CLIENT_STRING)) == 0) {
+ vrtsim_state->role = ROLE_CLIENT;
+ } else if (strncmp(role, ROLE_SERVER_STRING, strlen(ROLE_SERVER_STRING)) == 0) {
+ vrtsim_state->role = ROLE_SERVER;
+ } else {
+ AssertFatal(false, "Invalid role configuration\n");
+ }
+}
+
+static void *vrtsim_timing_job(void *arg)
+{
+ vrtsim_state_t *vrtsim_state = arg;
+ struct timespec timestamp;
+ if (clock_gettime(CLOCK_REALTIME, ×tamp)) {
+ LOG_E(UTIL, "clock_gettime failed\n");
+ exit(1);
+ }
+ double leftover_samples = 0;
+ while (vrtsim_state->run_timing_thread) {
+ struct timespec current_time;
+ if (clock_gettime(CLOCK_REALTIME, ¤t_time)) {
+ LOG_E(UTIL, "clock_gettime failed\n");
+ exit(1);
+ }
+ uint64_t diff = (current_time.tv_sec - timestamp.tv_sec) * 1000000000 + (current_time.tv_nsec - timestamp.tv_nsec);
+ timestamp = current_time;
+ double samples_to_produce = vrtsim_state->sample_rate * vrtsim_state->timescale * diff / 1e9;
+
+ // Attempt to correct compounding rounding error
+ leftover_samples += samples_to_produce - (uint64_t)samples_to_produce;
+ if (leftover_samples > 1.0f) {
+ samples_to_produce += 1;
+ leftover_samples -= 1;
+ }
+ shm_td_iq_channel_produce_samples(vrtsim_state->channel, samples_to_produce);
+ usleep(1);
+ }
+ return 0;
+}
+
+/**
+ * @brief Exchanges peer information between the server and the client.
+ *
+ * This function sets up a Unix domain socket server, waits for a client to connect,
+ * and exchanges peer information (number of RX antennas) with the client.
+ *
+ * @param peer_info The peer information to send to the client.
+ * @return The peer information received from the client.
+ *
+ * @note This function will block until a client connects and the information is exchanged.
+ */
+static peer_info_t server_exchange_peer_info(peer_info_t peer_info)
+{
+ int server_fd, client_fd;
+
+ // Create a Unix domain socket
+ server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ AssertFatal(server_fd >= 0, "socket() failed: errno: %d, %s\n", errno, strerror(errno));
+
+ // Bind the socket to a file path
+ struct sockaddr_un addr = {.sun_family = AF_UNIX};
+ strncpy(addr.sun_path, "/tmp/vrtsim_socket", sizeof(addr.sun_path) - 1);
+ unlink(addr.sun_path); // Ensure the path does not already exist
+ int ret = bind(server_fd, (struct sockaddr *)&addr, sizeof(addr));
+ AssertFatal(ret == 0, "bind() failed: errno: %d, %s\n", errno, strerror(errno));
+
+ // Listen for incoming connections
+ ret = listen(server_fd, 1);
+ AssertFatal(ret == 0, "listen() failed: errno: %d, %s\n", errno, strerror(errno));
+
+ // Accept a connection from a client
+ socklen_t addr_len = sizeof(addr);
+ client_fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
+ AssertFatal(client_fd >= 0, "accept() failed: errno: %d, %s\n", errno, strerror(errno));
+
+ // Send the antenna info to the server
+ ssize_t bytes_sent = send(client_fd, &peer_info, sizeof(peer_info), 0);
+ AssertFatal(bytes_sent == sizeof(peer_info), "send() failed: errno: %d, %s\n", errno, strerror(errno));
+
+ ssize_t bytes_received = recv(client_fd, &peer_info, sizeof(peer_info), 0);
+ AssertFatal(bytes_received == sizeof(peer_info), "recv() failed: errno: %d, %s\n", errno, strerror(errno));
+
+ LOG_I(HW, "Received client info: RX %d\n", peer_info.num_rx_antennas);
+
+ // Close the client and server sockets
+ close(client_fd);
+ close(server_fd);
+ return peer_info;
+}
+
+/**
+ * @brief Exchanges peer information between the client and the server.
+ *
+ * This function connects to a Unix domain socket server, exchanges peer information
+ * (number of RX antennas) with the server, and returns the peer information received
+ * from the server.
+ *
+ * @param peer_info The peer information to send to the server.
+ * @return The peer information received from the server.
+ *
+ * @note This function will block until the information is exchanged.
+ */
+static peer_info_t client_exchange_peer_info(peer_info_t peer_info)
+{
+ int client_fd;
+
+ // Create a Unix domain socket
+ client_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ AssertFatal(client_fd >= 0, "socket() failed: errno: %d, %s\n", errno, strerror(errno));
+
+ // Connect to the server
+ struct sockaddr_un addr = {.sun_family = AF_UNIX};
+ strncpy(addr.sun_path, "/tmp/vrtsim_socket", sizeof(addr.sun_path) - 1);
+ int ret = -1;
+ int tries = 0;
+ while (ret != 0 && tries < 10) {
+ ret = connect(client_fd, (struct sockaddr *)&addr, sizeof(addr));
+ tries++;
+ sleep(1);
+ }
+ AssertFatal(ret == 0, "connect() failed: errno: %d, %s\n", errno, strerror(errno));
+
+ peer_info_t peer_info_received;
+ ssize_t bytes_received = recv(client_fd, &peer_info_received, sizeof(peer_info_received), 0);
+ AssertFatal(bytes_received == sizeof(peer_info_received), "recv() failed: errno: %d, %s\n", errno, strerror(errno));
+
+ // Send the antenna info to the server
+ ssize_t bytes_sent = send(client_fd, &peer_info, sizeof(peer_info), 0);
+ AssertFatal(bytes_sent == sizeof(peer_info), "send() failed: errno: %d, %s\n", errno, strerror(errno));
+
+ LOG_I(HW, "Received peer info: RX %d\n", peer_info_received.num_rx_antennas);
+
+ // Close the client socket
+ close(client_fd);
+ return peer_info_received;
+}
+
+static int vrtsim_connect(openair0_device *device)
+{
+ vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv;
+ // Exchange peer info
+ peer_info_t peer_info = {.num_rx_antennas = device->openair0_cfg[0].rx_num_channels};
+ if (vrtsim_state->role == ROLE_SERVER) {
+ vrtsim_state->peer_info = server_exchange_peer_info(peer_info);
+ } else {
+ vrtsim_state->peer_info = client_exchange_peer_info(peer_info);
+ }
+
+ // Handle channel modelling after number of RX antennas are known
+ int num_tx_stats = 1;
+ if (vrtsim_state->chanmod) {
+ vrtsim_state->channel_modelling_actors = calloc_or_fail(vrtsim_state->peer_info.num_rx_antennas, sizeof(Actor_t));
+ for (int i = 0; i < vrtsim_state->peer_info.num_rx_antennas; i++) {
+ init_actor(&vrtsim_state->channel_modelling_actors[i], "chanmod", -1);
+ }
+ load_channel_model(vrtsim_state);
+ num_tx_stats = vrtsim_state->peer_info.num_rx_antennas;
+ }
+ vrtsim_state->tx_timing = calloc_or_fail(num_tx_stats, sizeof(tx_timing_t));
+ for (int i = 0; i < num_tx_stats; i++) {
+ vrtsim_state->tx_timing[i].tx_histogram.min_samples = 100;
+ // Set the histogram range to 3000uS. Anything above that is not interesting
+ vrtsim_state->tx_timing[i].tx_histogram.range = 3000.0;
+ }
+
+ // Setup a shared memory channel
+ if (vrtsim_state->role == ROLE_SERVER) {
+ vrtsim_state->channel = shm_td_iq_channel_create(vrtsim_state->channel_name,
+ vrtsim_state->peer_info.num_rx_antennas,
+ device->openair0_cfg[0].rx_num_channels);
+ vrtsim_state->run_timing_thread = true;
+ while (!shm_td_iq_channel_is_connected(vrtsim_state->channel)) {
+ LOG_I(HW, "Waiting for client\n");
+ sleep(1);
+ }
+ int ret = pthread_create(&vrtsim_state->timing_thread, NULL, vrtsim_timing_job, vrtsim_state);
+ AssertFatal(ret == 0, "pthread_create() failed: errno: %d, %s\n", errno, strerror(errno));
+ } else {
+ vrtsim_state->channel = shm_td_iq_channel_connect(vrtsim_state->channel_name, 10);
+ }
+
+ return 0;
+}
+
+static int vrtsim_write_internal(vrtsim_state_t *vrtsim_state,
+ openair0_timestamp timestamp,
+ c16_t *samples,
+ int nsamps,
+ int aarx,
+ int flags,
+ int stats_index)
+{
+ tx_timing_t *tx_timing = &vrtsim_state->tx_timing[stats_index];
+
+ uint64_t sample = shm_td_iq_channel_get_current_sample(vrtsim_state->channel);
+ int64_t diff = timestamp - sample;
+ double budget = diff / (vrtsim_state->sample_rate / 1e6);
+ tx_timing->average_tx_budget = .05 * budget + .95 * tx_timing->average_tx_budget;
+ histogram_add(&tx_timing->tx_histogram, budget);
+
+ int ret = shm_td_iq_channel_tx(vrtsim_state->channel, timestamp, nsamps, aarx, (sample_t *)samples);
+
+ if (ret == CHANNEL_ERROR_TOO_LATE) {
+ tx_timing->tx_samples_late += nsamps;
+ } else if (ret == CHANNEL_ERROR_TOO_EARLY) {
+ tx_timing->tx_early += 1;
+ }
+ tx_timing->tx_samples_total += nsamps;
+
+ return nsamps;
+}
+
+typedef struct {
+ vrtsim_state_t *vrtsim_state;
+ openair0_timestamp timestamp;
+ c16_t *samples[4];
+ int nsamps;
+ int nbAnt;
+ int flags;
+ int aarx;
+} channel_modelling_args_t;
+
+static void perform_channel_modelling(void *arg)
+{
+ channel_modelling_args_t *channel_modelling_args = arg;
+ int nsamps = channel_modelling_args->nsamps;
+ int aarx = channel_modelling_args->aarx;
+ int nb_tx_ant = channel_modelling_args->nbAnt;
+ c16_t **input_samples = (c16_t **)channel_modelling_args->samples;
+
+ int aligned_nsamps = ceil_mod(nsamps, (512 / 8) / sizeof(cf_t));
+ cf_t samples[aligned_nsamps] __attribute__((aligned(64)));
+ // Apply noise from global settings
+ get_noise_vector((float *)samples, nsamps * 2);
+
+ channel_desc_t *channel_desc = channel_modelling_args->vrtsim_state->channel_desc;
+ const float pathloss_linear = powf(10, channel_desc->path_loss_dB / 20.0);
+
+ // Convert channel impulse response to float + apply pathloss
+ cf_t channel_impulse_response[nb_tx_ant][channel_desc->channel_length];
+ for (int aatx = 0; aatx < nb_tx_ant; aatx++) {
+ const struct complexd *channelModel = channel_desc->ch[aarx + (aatx * channel_desc->nb_rx)];
+ for (int i = 0; i < channel_desc->channel_length; i++) {
+ channel_impulse_response[aatx][i].r = channelModel[i].r * pathloss_linear;
+ channel_impulse_response[aatx][i].i = channelModel[i].i * pathloss_linear;
+ }
+ }
+
+ for (int aatx = 0; aatx < nb_tx_ant; aatx++) {
+ for (int i = 0; i < nsamps; i++) {
+ cf_t *impulse_response = channel_impulse_response[aatx];
+ for (int l = 0; l < channel_desc->channel_length; l++) {
+ int idx = i - l;
+ // TODO: Use AVX512 for this
+ // TODO: What are the previously sent samples (for impulse response)
+ if (idx >= 0) {
+ c16_t tx_input = input_samples[aatx][idx];
+ samples[i].r += tx_input.r * impulse_response[l].r - tx_input.i * impulse_response[l].i;
+ samples[i].i += tx_input.i * impulse_response[l].r + tx_input.r * impulse_response[l].i;
+ }
+ }
+ }
+ }
+
+ // Convert to c16_t
+ c16_t samples_out[aligned_nsamps] __attribute__((aligned(64)));
+#if defined(__AVX512F__)
+ for (int i = 0; i < aligned_nsamps / 8; i++) {
+ simde__m512 *in = (simde__m512 *)&samples[i * 8];
+ simde__m256i *out = (simde__m256i *)&samples_out[i * 8];
+ *out = simde_mm512_cvtsepi32_epi16(simde_mm512_cvtps_epi32(*in));
+ }
+#elif defined(__AVX2__)
+ for (int i = 0; i < aligned_nsamps / 4; i++) {
+ simde__m256 *in = (simde__m256 *)&samples[i * 4];
+ simde__m128i *out = (simde__m128i *)&samples_out[i * 4];
+ *out = simde_mm256_cvtsepi32_epi16(simde_mm256_cvtps_epi32(*in));
+ }
+#else
+ for (int i = 0; i < nsamps; i++) {
+ samples_out[i].r = lroundf(samples[i].r);
+ samples_out[i].i = lroundf(samples[i].i);
+ }
+#endif
+
+ vrtsim_write_internal(channel_modelling_args->vrtsim_state,
+ channel_modelling_args->timestamp,
+ samples_out,
+ channel_modelling_args->nsamps,
+ aarx,
+ channel_modelling_args->flags,
+ aarx);
+}
+
+static int vrtsim_write_with_chanmod(vrtsim_state_t *vrtsim_state,
+ openair0_timestamp timestamp,
+ void **samplesVoid,
+ int nsamps,
+ int nbAnt,
+ int flags)
+{
+ for (int aarx = 0; aarx < vrtsim_state->peer_info.num_rx_antennas; aarx++) {
+ notifiedFIFO_elt_t *task = newNotifiedFIFO_elt(sizeof(channel_modelling_args_t), 0, NULL, perform_channel_modelling);
+ channel_modelling_args_t *args = (channel_modelling_args_t *)NotifiedFifoData(task);
+ args->vrtsim_state = vrtsim_state;
+ args->timestamp = timestamp;
+ args->nsamps = nsamps;
+ args->nbAnt = nbAnt;
+ args->flags = flags;
+ args->aarx = aarx;
+ for (int i = 0; i < nbAnt; i++) {
+ args->samples[i] = samplesVoid[i];
+ }
+ pushNotifiedFIFO(&vrtsim_state->channel_modelling_actors[aarx].fifo, task);
+ }
+ return nsamps;
+}
+
+static int vrtsim_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags)
+{
+ timestamp -= device->openair0_cfg->command_line_sample_advance;
+ vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv;
+ return vrtsim_state->chanmod ? vrtsim_write_with_chanmod(vrtsim_state, timestamp, samplesVoid, nsamps, nbAnt, flags)
+ : vrtsim_write_internal(vrtsim_state, timestamp, (c16_t *)samplesVoid[0], nsamps, 0, flags, 0);
+}
+
+static int vrtsim_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt)
+{
+ vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv;
+ shm_td_iq_channel_wait(vrtsim_state->channel, vrtsim_state->last_received_sample + nsamps);
+ int ret = shm_td_iq_channel_rx(vrtsim_state->channel, vrtsim_state->last_received_sample, nsamps, 0, samplesVoid[0]);
+ if (ret == CHANNEL_ERROR_TOO_LATE) {
+ vrtsim_state->rx_samples_late += nsamps;
+ } else if (ret == CHANNEL_ERROR_TOO_EARLY) {
+ vrtsim_state->rx_early += 1;
+ }
+ vrtsim_state->rx_samples_total += nsamps;
+ *ptimestamp = vrtsim_state->last_received_sample;
+ vrtsim_state->last_received_sample += nsamps;
+ return nsamps;
+}
+
+static void vrtsim_end(openair0_device *device)
+{
+ vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv;
+ if (vrtsim_state->role == ROLE_SERVER) {
+ vrtsim_state->run_timing_thread = false;
+ int ret = pthread_join(vrtsim_state->timing_thread, NULL);
+ AssertFatal(ret == 0, "pthread_join() failed: errno: %d, %s\n", errno, strerror(errno));
+ }
+
+ tx_timing_t *tx_timing = vrtsim_state->tx_timing;
+ if (vrtsim_state->chanmod) {
+ for (int i = 0; i < vrtsim_state->peer_info.num_rx_antennas; i++) {
+ shutdown_actor(&vrtsim_state->channel_modelling_actors[i]);
+ }
+ free(vrtsim_state->channel_modelling_actors);
+ for (int i = 1; i < vrtsim_state->peer_info.num_rx_antennas; i++) {
+ histogram_merge(&tx_timing->tx_histogram, &tx_timing[i].tx_histogram);
+ tx_timing->tx_early += tx_timing[i].tx_early;
+ tx_timing->tx_samples_late += tx_timing[i].tx_samples_late;
+ tx_timing->average_tx_budget += tx_timing[i].average_tx_budget;
+ tx_timing->tx_samples_total += tx_timing[i].tx_samples_total;
+ }
+ tx_timing->average_tx_budget /= vrtsim_state->peer_info.num_rx_antennas;
+ }
+ // produce 1 second of extra samples so threads can finish
+ shm_td_iq_channel_produce_samples(vrtsim_state->channel, vrtsim_state->sample_rate);
+ sleep(1);
+ shm_td_iq_channel_destroy(vrtsim_state->channel);
+
+ LOG_I(HW,
+ "VRTSIM: Realtime issues: TX %.2f%%, RX %.2f%%\n",
+ tx_timing->tx_samples_late / (float)tx_timing->tx_samples_total * 100,
+ vrtsim_state->rx_samples_late / (float)vrtsim_state->rx_samples_total * 100);
+ LOG_I(HW,
+ "VRTSIM: Read/write too early (suspected radio implementaton error) TX: %lu, RX: %lu\n",
+ tx_timing->tx_early,
+ vrtsim_state->rx_early);
+ LOG_I(HW, "VRTSIM: Average TX budget %.3lf uS\n", tx_timing->average_tx_budget);
+ histogram_print(&tx_timing->tx_histogram);
+ free(vrtsim_state->tx_timing);
+}
+
+static int vrtsim_stub(openair0_device *device)
+{
+ return 0;
+}
+static int vrtsim_stub2(openair0_device *device, openair0_config_t *openair0_cfg)
+{
+ return 0;
+}
+
+static int vrtsim_set_freq(openair0_device *device, openair0_config_t *openair0_cfg)
+{
+ vrtsim_state_t *s = device->priv;
+ s->rx_freq = openair0_cfg->rx_freq[0];
+ return 0;
+}
+
+__attribute__((__visibility__("default"))) int device_init(openair0_device *device, openair0_config_t *openair0_cfg)
+{
+ vrtsim_state_t *vrtsim_state = calloc_or_fail(1, sizeof(vrtsim_state_t));
+ vrtsim_readconfig(vrtsim_state);
+ LOG_I(HW,
+ "Running as %s\n",
+ vrtsim_state->role == ROLE_SERVER ? "server: waiting for client to connect" : "client: will connect to a vrtsim server");
+ device->trx_start_func = vrtsim_connect;
+ device->trx_reset_stats_func = vrtsim_stub;
+ device->trx_end_func = vrtsim_end;
+ device->trx_stop_func = vrtsim_stub;
+ device->trx_set_freq_func = vrtsim_set_freq;
+ device->trx_set_gains_func = vrtsim_stub2;
+ device->trx_write_func = vrtsim_write;
+ device->trx_read_func = vrtsim_read;
+
+ device->type = RFSIMULATOR;
+ device->openair0_cfg = &openair0_cfg[0];
+ device->priv = vrtsim_state;
+ device->trx_write_init = vrtsim_stub;
+ vrtsim_state->last_received_sample = 0;
+ vrtsim_state->sample_rate = openair0_cfg->sample_rate;
+ vrtsim_state->rx_freq = openair0_cfg->rx_freq[0];
+ vrtsim_state->tx_bw = openair0_cfg->tx_bw;
+ vrtsim_state->tx_num_channels = openair0_cfg->tx_num_channels;
+ vrtsim_state->rx_num_channels = openair0_cfg->rx_num_channels;
+
+ if (vrtsim_state->chanmod) {
+ init_channelmod();
+ int noise_power_dBFS = get_noise_power_dBFS();
+ int16_t noise_power = noise_power_dBFS == INVALID_DBFS_VALUE ? 0 : (int16_t)(32767.0 / powf(10.0, .05 * -noise_power_dBFS));
+ init_noise_device(noise_power);
+ }
+ return 0;
+}
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf
new file mode 100644
index 0000000000..28f9baf6f8
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf
@@ -0,0 +1,265 @@
+Active_gNBs = ( "gNB-OAI-DU");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+gNBs =
+(
+ {
+ ////////// Identification parameters:
+ gNB_ID = 0xe00;
+ gNB_DU_ID = 0xe00;
+ gNB_name = "gNB-OAI-DU";
+
+ // Tracking area code, 0x0000 and 0xfffe are reserved values
+ tracking_area_code = 1;
+ plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ( { sst = 1; }); });
+
+ nr_cellid = 1;
+
+ ////////// Physical parameters:
+
+ pdsch_AntennaPorts_XP = 2;
+ pdsch_AntennaPorts_N1 = 2;
+ pusch_AntennaPorts = 8;
+ do_CSIRS = 1;
+ do_SRS = 0;
+ sib1_tda = 15;
+ force_UL256qam_off = 1;
+ maxMIMO_layers = 2;
+
+ servingCellConfigCommon = (
+ {
+ #spCellConfigCommon
+
+ physCellId = 0;
+ # n_TimingAdvanceOffset = 0;
+# downlinkConfigCommon
+ #frequencyInfoDL
+ # center frequency = 3950.4 MHz
+ # selected SSB frequency = 3950.4 MHz
+ absoluteFrequencySSB = 663360;
+ dl_frequencyBand = 77;
+ # frequency point A = 3901.26 MHz
+ dl_absoluteFrequencyPointA = 660084;
+ #scs-SpecificCarrierList
+ dl_offstToCarrier = 0;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ dl_subcarrierSpacing = 1;
+ dl_carrierBandwidth = 273;
+ #initialDownlinkBWP
+ #genericParameters
+ initialDLBWPlocationAndBandwidth = 1099; #38.101-1 Table 5.3.2-1
+ #
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ initialDLBWPsubcarrierSpacing = 1;
+ #pdcch-ConfigCommon
+ initialDLBWPcontrolResourceSetZero = 11;
+ initialDLBWPsearchSpaceZero = 0;
+
+ #uplinkConfigCommon
+ #frequencyInfoUL
+ ul_frequencyBand = 77;
+ #scs-SpecificCarrierList
+ ul_offstToCarrier = 0;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ ul_subcarrierSpacing = 1;
+ ul_carrierBandwidth = 273;
+ pMax = 23;
+ #initialUplinkBWP
+ #genericParameters
+ initialULBWPlocationAndBandwidth = 1099;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ initialULBWPsubcarrierSpacing = 1;
+ #rach-ConfigCommon
+ #rach-ConfigGeneric
+ prach_ConfigurationIndex = 152;
+#prach_msg1_FDM
+#0 = one, 1=two, 2=four, 3=eight
+ prach_msg1_FDM = 0;
+ prach_msg1_FrequencyStart = 0;
+ zeroCorrelationZoneConfig = 0;
+ preambleReceivedTargetPower = -100;
+#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
+ preambleTransMax = 8;
+#powerRampingStep
+# 0=dB0,1=dB2,2=dB4,3=dB6
+ powerRampingStep = 3;
+#ra_ReponseWindow
+#1,2,4,8,10,20,40,80
+ ra_ResponseWindow = 5;
+#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
+#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
+ ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4;
+#one (0..15) 4,8,12,16,...60,64
+ ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15;
+#ra_ContentionResolutionTimer
+#(0..7) 8,16,24,32,40,48,56,64
+ ra_ContentionResolutionTimer = 7;
+ rsrp_ThresholdSSB = 19;
+#prach-RootSequenceIndex_PR
+#1 = 839, 2 = 139
+ prach_RootSequenceIndex_PR = 2;
+ prach_RootSequenceIndex = 1;
+ # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
+ #
+ msg1_SubcarrierSpacing = 1,
+# restrictedSetConfig
+# 0=unrestricted, 1=restricted type A, 2=restricted type B
+ restrictedSetConfig = 0,
+
+# this is the offset between the last PRACH preamble power and the Msg3 PUSCH, 2 times the field value in dB
+ msg3_DeltaPreamble = 2;
+ p0_NominalWithGrant = -96;
+
+# pucch-ConfigCommon setup :
+# pucchGroupHopping
+# 0 = neither, 1= group hopping, 2=sequence hopping
+ pucchGroupHopping = 0;
+ hoppingId = 0;
+ p0_nominal = -96;
+
+ ssb_PositionsInBurst_Bitmap = 0x1;
+
+# ssb_periodicityServingCell
+# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
+ ssb_periodicityServingCell = 2;
+
+# dmrs_TypeA_position
+# 0 = pos2, 1 = pos3
+ dmrs_TypeA_Position = 0;
+
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ subcarrierSpacing = 1;
+
+
+ #tdd-UL-DL-ConfigurationCommon
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ referenceSubcarrierSpacing = 1;
+ # pattern1
+ # dl_UL_TransmissionPeriodicity
+ # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
+ dl_UL_TransmissionPeriodicity = 5;
+ nrofDownlinkSlots = 3;
+ nrofDownlinkSymbols = 6;
+ nrofUplinkSlots = 1;
+ nrofUplinkSymbols = 4;
+
+ ssPBCH_BlockPower = 10;
+ }
+
+ );
+
+
+ # ------- SCTP definitions
+ SCTP :
+ {
+ # Number of streams to use in input/output
+ SCTP_INSTREAMS = 2;
+ SCTP_OUTSTREAMS = 2;
+ };
+ }
+);
+
+
+MACRLCs = (
+{
+ num_cc = 1;
+ tr_s_preference = "local_L1";
+ tr_n_preference = "f1";
+ local_n_if_name = "enp193s0f0";
+ local_n_address = "172.21.16.51";
+ remote_n_address = "172.21.6.90";
+ local_n_portc = 500;
+ local_n_portd = 2153;
+ remote_n_portc = 501;
+ remote_n_portd = 2153;
+ pusch_TargetSNRx10 = 120;
+ pucch_TargetSNRx10 = 200;
+ dl_bler_target_upper = .35;
+ dl_bler_target_lower = .15;
+ ul_bler_target_upper = .35;
+ ul_bler_target_lower = .15;
+ pusch_FailureThres = 100;
+ ul_max_mcs = 28;
+ min_grant_prb = 1;
+}
+);
+
+L1s = (
+{
+ num_cc = 1;
+ tr_n_preference = "local_mac";
+ prach_dtx_threshold = 100;
+ pucch0_dtx_threshold = 80;
+ pusch_dtx_threshold = 10;
+ max_ldpc_iterations = 10;
+ tx_amp_backoff_dB = 12; # needs to match O-RU configuration
+ L1_rx_thread_core = 8;
+ L1_tx_thread_core = 10; # relevant after merge of l1_tx_thread
+ phase_compensation = 0; # needs to match O-RU configuration
+}
+);
+
+RUs = (
+{
+ local_rf = "no";
+ nb_tx = 8;
+ nb_rx = 8;
+ att_tx = 0;
+ att_rx = 0;
+ bands = [77];
+ max_pdschReferenceSignalPower = -27;
+ max_rxgain = 75;
+ sf_extension = 0;
+ eNB_instances = [0];
+ ru_thread_core = 9;
+ sl_ahead = 10;
+ tr_preference = "raw_if4p5"; # important: activate FHI7.2
+ do_precoding = 0; # needs to match O-RU configuration
+}
+);
+
+log_config :
+{
+ global_log_level = "info";
+ hw_log_level = "info";
+ phy_log_level = "info";
+ mac_log_level = "info";
+ rlc_log_level = "info";
+ pdcp_log_level = "info";
+ rrc_log_level = "info";
+ ngap_log_level = "info";
+ f1ap_log_level = "info";
+};
+
+fhi_72 = {
+ dpdk_devices = ("0000:01:01.0", "0000:01:01.1", "0000:01:01.2", "0000:01:01.3"); # two VFs can be used as well
+ system_core = 0;
+ io_core = 1;
+ worker_cores = (2);
+ du_key_pair = ("/home/eurecom/.ssh/id_rsa.pub", "/home/eurecom/.ssh/id_rsa");
+ du_addr = ("00:11:22:33:44:66", "00:11:22:33:44:67", "00:11:22:33:44:68", "00:11:22:33:44:69");
+ vlan_tag = (5, 5, 6, 6);
+ ru_ip_addr = ("192.168.80.5", "192.168.80.6");
+ fh_config = (
+# RAN650 #1
+ {
+ T1a_cp_dl = (419, 470);
+ T1a_cp_ul = (285, 336);
+ T1a_up = (294, 345);
+ Ta4 = (0, 200);
+ },
+# RAN650 #2
+ {
+ T1a_cp_dl = (419, 470);
+ T1a_cp_ul = (285, 336);
+ T1a_up = (294, 345);
+ Ta4 = (0, 200);
+ });
+};
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf
new file mode 100644
index 0000000000..6fa4c200dc
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf
@@ -0,0 +1,273 @@
+Active_gNBs = ( "gNB-OAI");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+gNBs =
+(
+ {
+ ////////// Identification parameters:
+ gNB_ID = 0xe00;
+ gNB_name = "gNB-OAI";
+
+ // Tracking area code, 0x0000 and 0xfffe are reserved values
+ tracking_area_code = 1;
+ plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ( { sst = 1; }); });
+
+ nr_cellid = 1;
+
+ ////////// Physical parameters:
+
+ pdsch_AntennaPorts_XP = 2;
+ pdsch_AntennaPorts_N1 = 2;
+ maxMIMO_layers = 2;
+ pusch_AntennaPorts = 4;
+ do_CSIRS = 1;
+ do_SRS = 0;
+ sib1_tda = 15;
+ # force_UL256qam_off = 1;
+
+ servingCellConfigCommon = (
+ {
+ #spCellConfigCommon
+
+ physCellId = 0;
+ # n_TimingAdvanceOffset = 0;
+# downlinkConfigCommon
+ #frequencyInfoDL
+ # center frequency = 3350.01 MHz
+ # selected SSB frequency = 3349.92 MHz
+ absoluteFrequencySSB = 623328;
+ dl_frequencyBand = 78;
+ # frequency point A = 3300.87 MHz
+ dl_absoluteFrequencyPointA = 620058;
+ #scs-SpecificCarrierList
+ dl_offstToCarrier = 0;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ dl_subcarrierSpacing = 1;
+ dl_carrierBandwidth = 273;
+ #initialDownlinkBWP
+ #genericParameters
+ initialDLBWPlocationAndBandwidth = 1099; #38.101-1 Table 5.3.2-1
+ #
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ initialDLBWPsubcarrierSpacing = 1;
+ #pdcch-ConfigCommon
+ initialDLBWPcontrolResourceSetZero = 11;
+ initialDLBWPsearchSpaceZero = 0;
+
+ #uplinkConfigCommon
+ #frequencyInfoUL
+ ul_frequencyBand = 78;
+ #scs-SpecificCarrierList
+ ul_offstToCarrier = 0;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ ul_subcarrierSpacing = 1;
+ ul_carrierBandwidth = 273;
+ pMax = 23;
+ #initialUplinkBWP
+ #genericParameters
+ initialULBWPlocationAndBandwidth = 1099;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ initialULBWPsubcarrierSpacing = 1;
+ #rach-ConfigCommon
+ #rach-ConfigGeneric
+ prach_ConfigurationIndex = 152;
+#prach_msg1_FDM
+#0 = one, 1=two, 2=four, 3=eight
+ prach_msg1_FDM = 0;
+ prach_msg1_FrequencyStart = 0;
+ zeroCorrelationZoneConfig = 0;
+ preambleReceivedTargetPower = -100;
+#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
+ preambleTransMax = 8;
+#powerRampingStep
+# 0=dB0,1=dB2,2=dB4,3=dB6
+ powerRampingStep = 3;
+#ra_ReponseWindow
+#1,2,4,8,10,20,40,80
+ ra_ResponseWindow = 5;
+#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
+#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
+ ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4;
+#one (0..15) 4,8,12,16,...60,64
+ ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15;
+#ra_ContentionResolutionTimer
+#(0..7) 8,16,24,32,40,48,56,64
+ ra_ContentionResolutionTimer = 7;
+ rsrp_ThresholdSSB = 19;
+#prach-RootSequenceIndex_PR
+#1 = 839, 2 = 139
+ prach_RootSequenceIndex_PR = 2;
+ prach_RootSequenceIndex = 1;
+ # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
+ #
+ msg1_SubcarrierSpacing = 1,
+# restrictedSetConfig
+# 0=unrestricted, 1=restricted type A, 2=restricted type B
+ restrictedSetConfig = 0,
+
+# this is the offset between the last PRACH preamble power and the Msg3 PUSCH, 2 times the field value in dB
+ msg3_DeltaPreamble = 2;
+ p0_NominalWithGrant = -96;
+
+# pucch-ConfigCommon setup :
+# pucchGroupHopping
+# 0 = neither, 1= group hopping, 2=sequence hopping
+ pucchGroupHopping = 0;
+ hoppingId = 0;
+ p0_nominal = -96;
+
+ ssb_PositionsInBurst_Bitmap = 0x1;
+
+# ssb_periodicityServingCell
+# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
+ ssb_periodicityServingCell = 2;
+
+# dmrs_TypeA_position
+# 0 = pos2, 1 = pos3
+ dmrs_TypeA_Position = 0;
+
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ subcarrierSpacing = 1;
+
+
+ #tdd-UL-DL-ConfigurationCommon
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ referenceSubcarrierSpacing = 1;
+ # pattern1
+ # dl_UL_TransmissionPeriodicity
+ # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
+ dl_UL_TransmissionPeriodicity = 6;
+ nrofDownlinkSlots = 7;
+ nrofDownlinkSymbols = 6;
+ nrofUplinkSlots = 2;
+ nrofUplinkSymbols = 4;
+
+ ssPBCH_BlockPower = 0;
+ }
+ );
+
+
+ # ------- SCTP definitions
+ SCTP :
+ {
+ # Number of streams to use in input/output
+ SCTP_INSTREAMS = 2;
+ SCTP_OUTSTREAMS = 2;
+ };
+
+
+ ////////// AMF parameters:
+ amf_ip_address = ({ ipv4 = "172.21.6.5"; });
+
+ NETWORK_INTERFACES :
+ {
+ GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.51";
+ GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.51";
+ GNB_PORT_FOR_S1U = 2152; # Spec 2152
+ };
+ }
+);
+
+MACRLCs = (
+{
+ num_cc = 1;
+ tr_s_preference = "local_L1";
+ tr_n_preference = "local_RRC";
+ pusch_TargetSNRx10 = 180;
+ pucch_TargetSNRx10 = 220;
+ dl_bler_target_upper = .35;
+ dl_bler_target_lower = .15;
+ ul_bler_target_upper = .35;
+ ul_bler_target_lower = .15;
+ pusch_FailureThres = 1000;
+ ul_max_mcs = 28;
+}
+);
+
+L1s = (
+{
+ num_cc = 1;
+ tr_n_preference = "local_mac";
+ prach_dtx_threshold = 100;
+ pucch0_dtx_threshold = 80;
+ pusch_dtx_threshold = 10;
+ max_ldpc_iterations = 15;
+ tx_amp_backoff_dB = 12; # needs to match O-RU configuration
+ L1_rx_thread_core = 8;
+ L1_tx_thread_core = 10;
+ phase_compensation = 0; # needs to match O-RU configuration
+}
+);
+
+RUs = (
+{
+ local_rf = "no";
+ nb_tx = 4;
+ nb_rx = 4;
+ att_tx = 0;
+ att_rx = 0;
+ bands = [78];
+ max_pdschReferenceSignalPower = -27;
+ max_rxgain = 75;
+ sf_extension = 0;
+ eNB_instances = [0];
+ ru_thread_core = 9;
+ sl_ahead = 10;
+ tr_preference = "raw_if4p5"; # important: activate FHI7.2
+ do_precoding = 0; # needs to match O-RU configuration
+}
+);
+
+security = {
+ # preferred ciphering algorithms
+ # the first one of the list that an UE supports in chosen
+ # valid values: nea0, nea1, nea2, nea3
+ ciphering_algorithms = ( "nea0" );
+
+ # preferred integrity algorithms
+ # the first one of the list that an UE supports in chosen
+ # valid values: nia0, nia1, nia2, nia3
+ integrity_algorithms = ( "nia2", "nia0" );
+
+ # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
+ # what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
+ drb_ciphering = "yes";
+ drb_integrity = "no";
+};
+
+log_config :
+{
+ global_log_level = "info";
+ hw_log_level = "info";
+ phy_log_level = "info";
+ mac_log_level = "info";
+ rlc_log_level = "info";
+ pdcp_log_level = "info";
+ rrc_log_level = "info";
+ ngap_log_level = "info";
+ f1ap_log_level = "info";
+};
+
+fhi_72 = {
+ dpdk_devices = ("0000:c1:11.0", "0000:c1:11.1"); # one VF can be used as well
+ system_core = 0;
+ io_core = 1;
+ worker_cores = (2);
+ du_key_pair = ("/home/eurecom/.ssh/id_rsa.pub", "/home/eurecom/.ssh/id_rsa");
+ du_addr = ("00:11:22:33:44:68","00:11:22:33:44:69");
+ vlan_tag = (11, 11);
+ ru_ip_addr = ("192.168.80.10");
+ fh_config = ({
+ T1a_cp_dl = (419, 470);
+ T1a_cp_ul = (285, 336);
+ T1a_up = (294, 345);
+ Ta4 = (0, 200);
+ });
+};
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-foxconn.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-foxconn.conf
new file mode 100644
index 0000000000..97fd75bda8
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-foxconn.conf
@@ -0,0 +1,271 @@
+Active_gNBs = ( "oai-du");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+gNBs =
+(
+ {
+ ////////// Identification parameters:
+ gNB_ID = 0xe00;
+ gNB_name = "oai-du";
+
+ // Tracking area code, 0x0000 and 0xfffe are reserved values
+ tracking_area_code = 1;
+ plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ( { sst = 1; }); });
+
+ nr_cellid = 1;
+
+ ////////// Physical parameters:
+
+ pdsch_AntennaPorts_XP = 2;
+ pdsch_AntennaPorts_N1 = 2;
+ maxMIMO_layers = 2;
+ pusch_AntennaPorts = 4;
+ do_CSIRS = 1;
+ do_SRS = 0;
+
+
+ servingCellConfigCommon = (
+ {
+ #spCellConfigCommon
+
+ physCellId = 0;
+# downlinkConfigCommon
+ #frequencyInfoDL
+ # selected SSB frequency = 3748.80 MHz
+ absoluteFrequencySSB = 649920;
+ dl_frequencyBand = 78;
+ # frequency point A = 3700.86 MHz
+ dl_absoluteFrequencyPointA = 646724;
+ #scs-SpecificCarrierList
+ dl_offstToCarrier = 0;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ dl_subcarrierSpacing = 1;
+ dl_carrierBandwidth = 273;
+ #initialDownlinkBWP
+ #genericParameters
+ #this is RBstart=0,L=162 (275*(275-L+1))+(274-RBstart))
+ initialDLBWPlocationAndBandwidth = 1099;
+ #
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ initialDLBWPsubcarrierSpacing = 1;
+ #pdcch-ConfigCommon
+ initialDLBWPcontrolResourceSetZero = 12;
+ initialDLBWPsearchSpaceZero = 0;
+
+ #uplinkConfigCommon
+ #frequencyInfoUL
+ ul_frequencyBand = 78;
+ #scs-SpecificCarrierList
+ ul_offstToCarrier = 0;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ ul_subcarrierSpacing = 1;
+ ul_carrierBandwidth = 273;
+ pMax = 20;
+ #initialUplinkBWP
+ #genericParameters
+ initialULBWPlocationAndBandwidth = 1099;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ initialULBWPsubcarrierSpacing = 1;
+ #rach-ConfigCommon
+ #rach-ConfigGeneric
+ prach_ConfigurationIndex = 151;# testMAC 158; OAI gNB 98
+#prach_msg1_FDM
+#0 = one, 1=two, 2=four, 3=eight
+ prach_msg1_FDM = 0;
+ prach_msg1_FrequencyStart = 0;
+ zeroCorrelationZoneConfig = 12;
+ preambleReceivedTargetPower = -96;
+#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
+ preambleTransMax = 6;
+#powerRampingStep
+# 0=dB0,1=dB2,2=dB4,3=dB6
+ powerRampingStep = 1;
+#ra_ReponseWindow
+#1,2,4,8,10,20,40,80
+ ra_ResponseWindow = 5;
+#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
+#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
+ ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3;
+#oneHalf (0..15) 4,8,12,16,...60,64
+ ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15;
+#ra_ContentionResolutionTimer
+#(0..7) 8,16,24,32,40,48,56,64
+ ra_ContentionResolutionTimer = 7;
+ rsrp_ThresholdSSB = 19;
+#prach-RootSequenceIndex_PR
+#1 = 839, 2 = 139
+ prach_RootSequenceIndex_PR = 2;
+ prach_RootSequenceIndex = 1;
+ # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
+ #
+ msg1_SubcarrierSpacing = 1,
+# restrictedSetConfig
+# 0=unrestricted, 1=restricted type A, 2=restricted type B
+ restrictedSetConfig = 0,
+
+# this is the offset between the last PRACH preamble power and the Msg3 PUSCH, 2 times the field value in dB
+ msg3_DeltaPreamble = 1;
+ p0_NominalWithGrant = -90;
+
+# pucch-ConfigCommon setup :
+# pucchGroupHopping
+# 0 = neither, 1= group hopping, 2=sequence hopping
+ pucchGroupHopping = 0;
+ hoppingId = 40;
+ p0_nominal = -90;
+
+ ssb_PositionsInBurst_Bitmap = 1;
+
+# ssb_periodicityServingCell
+# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
+ ssb_periodicityServingCell = 2;
+
+# dmrs_TypeA_position
+# 0 = pos2, 1 = pos3
+ dmrs_TypeA_Position = 0;
+
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ subcarrierSpacing = 1;
+
+
+ #tdd-UL-DL-ConfigurationCommon
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ referenceSubcarrierSpacing = 1;
+ # pattern1
+ # dl_UL_TransmissionPeriodicity
+ # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
+ dl_UL_TransmissionPeriodicity = 5; #6;
+ nrofDownlinkSlots = 3; #7;
+ nrofDownlinkSymbols = 6;
+ nrofUplinkSlots = 1; #2;
+ nrofUplinkSymbols = 4;
+
+ ssPBCH_BlockPower = 0;
+ }
+ );
+
+
+ # ------- SCTP definitions
+ SCTP :
+ {
+ # Number of streams to use in input/output
+ SCTP_INSTREAMS = 2;
+ SCTP_OUTSTREAMS = 2;
+ };
+
+
+ ////////// AMF parameters:
+ amf_ip_address = ({ ipv4 = "172.21.6.5"; });
+
+ NETWORK_INTERFACES :
+ {
+ GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.51";
+ GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.51";
+ GNB_PORT_FOR_S1U = 2152; # Spec 2152
+ };
+ }
+);
+
+MACRLCs = (
+{
+ num_cc = 1;
+ tr_s_preference = "local_L1";
+ tr_n_preference = "local_RRC";
+ pusch_TargetSNRx10 = 120;
+ pucch_TargetSNRx10 = 260;
+ ul_bler_target_upper = .35;
+ ul_bler_target_lower = .15;
+ pusch_FailureThres = 100;
+ ul_max_mcs = 28;
+}
+);
+
+L1s = (
+{
+ num_cc = 1;
+ tr_n_preference = "local_mac";
+ prach_dtx_threshold = 130;
+ pucch0_dtx_threshold = 80;
+ pusch_dtx_threshold = 10;
+ max_ldpc_iterations = 15;
+ tx_amp_backoff_dB = 24; # needs to match O-RU configuration
+ L1_rx_thread_core = 8;
+ L1_tx_thread_core = 10;
+ phase_compensation = 0; # needs to match O-RU configuration
+}
+);
+
+RUs = (
+{
+ local_rf = "no";
+ nb_tx = 4;
+ nb_rx = 4;
+ att_tx = 0
+ att_rx = 0;
+ bands = [78];
+ max_pdschReferenceSignalPower = -27;
+ max_rxgain = 75;
+ sf_extension = 0;
+ eNB_instances = [0];
+ ru_thread_core = 9;
+ sl_ahead = 5;
+ tr_preference = "raw_if4p5"; # important: activate FHI7.2
+ do_precoding = 0; # needs to match O-RU configuration
+}
+);
+
+security = {
+ # preferred ciphering algorithms
+ # the first one of the list that an UE supports in chosen
+ # valid values: nea0, nea1, nea2, nea3
+ ciphering_algorithms = ( "nea0" );
+
+ # preferred integrity algorithms
+ # the first one of the list that an UE supports in chosen
+ # valid values: nia0, nia1, nia2, nia3
+ integrity_algorithms = ( "nia2", "nia0" );
+
+ # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
+ # what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
+ drb_ciphering = "yes";
+ drb_integrity = "no";
+};
+
+log_config :
+{
+ global_log_level = "info";
+ hw_log_level = "info";
+ phy_log_level = "info";
+ mac_log_level = "info";
+ rlc_log_level = "info";
+ pdcp_log_level = "info";
+ rrc_log_level = "info";
+ ngap_log_level = "info";
+ f1ap_log_level = "info";
+};
+
+fhi_72 = {
+ dpdk_devices = ("0000:c1:11.0", "0000:c1:11.1");
+ system_core = 0;
+ io_core = 1;
+ worker_cores = (2);
+ ru_addr = ("6c:ad:ad:00:04:dc", "6c:ad:ad:00:04:dc");
+ mtu = 8000;
+ fh_config = ({
+ T1a_cp_dl = (285, 470);
+ T1a_cp_ul = (285, 429);
+ T1a_up = (96, 196);
+ Ta4 = (0, 75);
+ ru_config = {
+ iq_width = 9;
+ iq_width_prach = 9;
+ };
+ });
+};