M-plane integration - initial commit

This commit is contained in:
Teodora
2025-03-29 12:51:07 +01:00
parent 0be72c1917
commit da63bf9f9f
7 changed files with 363 additions and 36 deletions
+5 -1
View File
@@ -99,7 +99,7 @@ Options:
USRP, BLADERF, LMSSDR, IRIS, SIMU, AW2SORI, AERIAL, None (Default) USRP, BLADERF, LMSSDR, IRIS, SIMU, AW2SORI, AERIAL, None (Default)
Adds this RF board support (in external packages installation and in compilation) Adds this RF board support (in external packages installation and in compilation)
-t | --transport -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 -P | --phy_simulators
Makes the unitary tests Layer 1 simulators Makes the unitary tests Layer 1 simulators
-s | --check -s | --check
@@ -304,6 +304,10 @@ function main() {
TARGET_LIST="$TARGET_LIST $2" TARGET_LIST="$TARGET_LIST $2"
CMAKE_CMD="$CMAKE_CMD -DOAI_FHI72=ON" 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") "None")
;; ;;
*) *)
+8 -4
View File
@@ -30,15 +30,19 @@ endif()
add_compile_options(-Wno-packed-not-aligned) add_compile_options(-Wno-packed-not-aligned)
set_target_properties(oran_fhlib_5g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -march=native") 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 xran::xran ${dpdk_LINK_LIBRARIES} ${T_LIB} pthread dl rt m numa)
target_link_libraries(oran_fhlib_5g PRIVATE ${dpdk_LINK_LIBRARIES})
target_include_directories(oran_fhlib_5g PRIVATE ${dpdk_INCLUDE_DIRS}) 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})
add_boolean_option(OAI_FHI72_USE_POLLING OFF "Enable polling in FHI72 driver" ON) 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}) set_target_properties(oran_fhlib_5g PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
add_custom_command(TARGET oran_fhlib_5g POST_BUILD add_custom_command(TARGET oran_fhlib_5g POST_BUILD
COMMAND ${CMAKE_COMMAND} -E create_symlink liboran_fhlib_5g.so liboai_transpro.so COMMAND ${CMAKE_COMMAND} -E create_symlink liboran_fhlib_5g.so liboai_transpro.so
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) 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()
+64
View File
@@ -0,0 +1,64 @@
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
)
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})
+131
View File
@@ -0,0 +1,131 @@
/*
* 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 <libyang/libyang.h>
#include <nc_client.h>
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;
}
+30
View File
@@ -0,0 +1,30 @@
/*
* 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);
#endif /* OAI_MPLANE_H */
+95
View File
@@ -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
*/
#ifndef RU_MPLANE_API_H
#define RU_MPLANE_API_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#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;
// 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;
#endif /* RU_MPLANE_API_H */
+30 -31
View File
@@ -39,6 +39,10 @@
// line and the use of VERSIONX further below. It is relative to phy/fhi_lib/lib/api // line and the use of VERSIONX further below. It is relative to phy/fhi_lib/lib/api
#include "../../app/src/common.h" #include "../../app/src/common.h"
#ifdef OAI_MPLANE
#include "mplane/init-mplane.h"
#endif
typedef struct { typedef struct {
eth_state_t e; eth_state_t e;
rru_config_msg_type_t last_msg; rru_config_msg_type_t last_msg;
@@ -279,7 +283,32 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device *d
openair0_config_t *openair0_cfg, openair0_config_t *openair0_cfg,
eth_params_t *eth_params) 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");
#else
success = get_xran_config(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->Mod_id = 0;
device->transp_type = ETHERNET_TP; device->transp_type = ETHERNET_TP;
@@ -290,43 +319,13 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device *d
device->trx_stop_func = trx_oran_stop; device->trx_stop_func = trx_oran_stop;
device->trx_set_freq_func = trx_oran_set_freq; device->trx_set_freq_func = trx_oran_set_freq;
device->trx_set_gains_func = trx_oran_set_gains; device->trx_set_gains_func = trx_oran_set_gains;
device->trx_write_func = trx_oran_write_raw; device->trx_write_func = trx_oran_write_raw;
device->trx_read_func = trx_oran_read_raw; device->trx_read_func = trx_oran_read_raw;
device->trx_ctlsend_func = trx_oran_ctlsend; device->trx_ctlsend_func = trx_oran_ctlsend;
device->trx_ctlrecv_func = trx_oran_ctlrecv; device->trx_ctlrecv_func = trx_oran_ctlrecv;
device->get_internal_parameter = get_internal_parameter; 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->priv = eth;
device->openair0_cfg = &openair0_cfg[0]; 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; return 0;
} }