mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-16 22:20:31 +00:00
Compare commits
10 Commits
pre-commit
...
IISc_XnSet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03906410cc | ||
|
|
848490aa71 | ||
|
|
3cc763e993 | ||
|
|
d6f735ef71 | ||
|
|
7dc8075f4b | ||
|
|
0b950a6dbd | ||
|
|
a74235456e | ||
|
|
15e51783e8 | ||
|
|
8eb29950fd | ||
|
|
495d8eb446 |
@@ -1380,6 +1380,7 @@ set (ENB_APP_SRC
|
||||
set (GNB_APP_SRC
|
||||
${OPENAIR2_DIR}/GNB_APP/gnb_app.c
|
||||
${OPENAIR2_DIR}/E1AP/e1ap_setup.c
|
||||
${OPENAIR2_DIR}/XNAP/xnap_gNB_task.c
|
||||
${OPENAIR2_DIR}/GNB_APP/gnb_config.c
|
||||
)
|
||||
|
||||
@@ -1438,7 +1439,7 @@ add_library(e1_pdcp_if
|
||||
|
||||
target_link_libraries(e1_pdcp_if PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
|
||||
|
||||
target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc e1ap nr_rlc)
|
||||
target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc e1ap nr_rlc xnap)
|
||||
if(E2_AGENT)
|
||||
target_link_libraries(L2_NR PUBLIC e2_agent e2_ran_func)
|
||||
target_compile_definitions(L2_NR PRIVATE E2_AGENT)
|
||||
@@ -2053,12 +2054,12 @@ target_link_libraries(nr-softmodem PRIVATE
|
||||
UTIL HASHTABLE SCTP_CLIENT SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU GTPV1U SECURITY
|
||||
ITTI ${NAS_UE_LIB} lte_rrc nr_rrc
|
||||
ngap s1ap L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB SIMU SIMU_ETH
|
||||
x2ap f1ap m2ap m3ap e1ap shlib_loader
|
||||
x2ap xnap f1ap m2ap m3ap e1ap shlib_loader
|
||||
-Wl,--end-group z dl)
|
||||
|
||||
target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt sctp)
|
||||
target_link_libraries(nr-softmodem PRIVATE ${T_LIB})
|
||||
target_link_libraries(nr-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
|
||||
target_link_libraries(nr-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs )
|
||||
|
||||
add_dependencies(nr-softmodem ldpc_orig ldpc_optim ldpc_optim8seg ldpc)
|
||||
|
||||
|
||||
@@ -232,6 +232,7 @@ typedef enum {
|
||||
LOCALIZE,
|
||||
F1U,
|
||||
X2AP,
|
||||
XNAP,
|
||||
M2AP,
|
||||
M3AP,
|
||||
NGAP,
|
||||
|
||||
@@ -465,6 +465,29 @@ ID = LEGACY_X2AP_TRACE
|
||||
DESC = X2AP legacy logs - trace level
|
||||
GROUP = ALL:LEGACY_X2AP:LEGACY_GROUP_TRACE:LEGACY
|
||||
FORMAT = string,log
|
||||
|
||||
|
||||
ID = LEGACY_XNAP_INFO
|
||||
DESC = XNAP legacy logs - info level
|
||||
GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_INFO:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_XNAP_ERROR
|
||||
DESC = XNAP legacy logs - error level
|
||||
GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_ERROR:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_XNAP_WARNING
|
||||
DESC = XNAP legacy logs - warning level
|
||||
GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_WARNING:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_XNAP_DEBUG
|
||||
DESC = XNAP legacy logs - debug level
|
||||
GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_DEBUG:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_XNAP_TRACE
|
||||
DESC = XNAP legacy logs - trace level
|
||||
GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_TRACE:LEGACY
|
||||
FORMAT = string,log
|
||||
|
||||
|
||||
ID = LEGACY_M2AP_INFO
|
||||
DESC = M2AP legacy logs - info level
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#endif
|
||||
#include "openair2/COMMON/s1ap_messages_def.h"
|
||||
#include "openair2/COMMON/x2ap_messages_def.h"
|
||||
#include "openair2/COMMON/xnap_messages_def.h"
|
||||
#include "openair2/COMMON/m2ap_messages_def.h"
|
||||
#include "openair2/COMMON/m3ap_messages_def.h"
|
||||
#include "openair2/COMMON/sctp_messages_def.h"
|
||||
|
||||
@@ -229,6 +229,7 @@ typedef struct IttiMsgText_s {
|
||||
#endif
|
||||
#include <openair2/COMMON/s1ap_messages_types.h>
|
||||
#include <openair2/COMMON/x2ap_messages_types.h>
|
||||
#include <openair2/COMMON/xnap_messages_types.h>
|
||||
#include <openair2/COMMON/m2ap_messages_types.h>
|
||||
#include <openair2/COMMON/m3ap_messages_types.h>
|
||||
#include <openair2/COMMON/sctp_messages_types.h>
|
||||
@@ -318,6 +319,7 @@ void *rrc_enb_process_msg(void *);
|
||||
TASK_DEF(TASK_S1AP, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_NGAP, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_X2AP, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_XNAP, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_M2AP_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_M2AP_MCE, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_M3AP, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
|
||||
@@ -74,6 +74,7 @@ unsigned short config_frames[4] = {2,9,11,13};
|
||||
#include "executables/thread-common.h"
|
||||
#include "NB_IoT_interface.h"
|
||||
#include "x2ap_eNB.h"
|
||||
#include "openair2/XNAP/xnap_gNB_task.h"
|
||||
#include "ngap_gNB.h"
|
||||
#include "gnb_paramdef.h"
|
||||
#include <openair3/ocp-gtpu/gtp_itf.h>
|
||||
@@ -356,6 +357,19 @@ static int create_gNB_tasks(ngran_node_t node_type)
|
||||
} else {
|
||||
LOG_I(X2AP, "X2AP is disabled.\n");
|
||||
}
|
||||
|
||||
if (is_xnap_enabled()) {
|
||||
if (itti_create_task(TASK_XNAP, xnap_task, NULL) < 0) {
|
||||
LOG_E(XNAP, "Create task for XNAP failed\n");
|
||||
}
|
||||
} else {
|
||||
LOG_I(XNAP, "XNAP is disabled.\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (is_xnap_enabled()) {
|
||||
LOG_I(XNAP, "XNAP enabled \n");
|
||||
gNB_app_register_xn(gnb_nb);
|
||||
}
|
||||
|
||||
if (get_softmodem_params()->sa &&
|
||||
|
||||
36
openair2/COMMON/xnap_messages_def.h
Normal file
36
openair2/COMMON/xnap_messages_def.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file xnap_messages_def.h
|
||||
* \author Sreeshma Shiv <sreeshmau@iisc.ac.in>
|
||||
* \date August 2023
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
/* gNB application layer -> XNAP messages */
|
||||
MESSAGE_DEF(XNAP_REGISTER_GNB_REQ, MESSAGE_PRIORITY_MED, xnap_register_gnb_req_t, xnap_register_gnb_req)
|
||||
/* XNAP -> gNB application layer messages */
|
||||
MESSAGE_DEF(XNAP_REGISTER_GNB_CNF, MESSAGE_PRIORITY_MED, xnap_register_gnb_cnf_t, xnap_register_gnb_cnf)
|
||||
MESSAGE_DEF(XNAP_DEREGISTERED_GNB_IND, MESSAGE_PRIORITY_MED, xnap_deregistered_gnb_ind_t, xnap_deregistered_gnb_ind)
|
||||
|
||||
/* handover messages XNAP <-> RRC */
|
||||
MESSAGE_DEF(XNAP_SETUP_REQ, MESSAGE_PRIORITY_MED, xnap_setup_req_t, xnap_setup_req)
|
||||
MESSAGE_DEF(XNAP_SETUP_RESP, MESSAGE_PRIORITY_MED, xnap_setup_resp_t, xnap_setup_resp)
|
||||
137
openair2/COMMON/xnap_messages_types.h
Normal file
137
openair2/COMMON/xnap_messages_types.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file xnap_messages_types.h
|
||||
* \author Sreeshma Shiv <sreeshmau@iisc.ac.in>
|
||||
* \date August 2023
|
||||
* \version 1.0
|
||||
*/
|
||||
#ifndef XNAP_MESSAGES_TYPES_H_
|
||||
#define XNAP_MESSAGES_TYPES_H_
|
||||
|
||||
// Defines to access message fields.
|
||||
|
||||
#define XNAP_REGISTER_GNB_REQ(mSGpTR) (mSGpTR)->ittiMsg.xnap_register_gnb_req
|
||||
#define XNAP_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.xnap_setup_req
|
||||
#define XNAP_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.xnap_setup_resp
|
||||
#define XNAP_REGISTER_GNB_CNF(mSGpTR) (mSGpTR)->ittiMsg.xnap_register_gnb_cnf
|
||||
#define XNAP_DEREGISTERED_GNB_IND(mSGpTR) (mSGpTR)->ittiMsg.xnap_deregistered_gnb_ind
|
||||
|
||||
#define XNAP_MAX_NB_GNB_IP_ADDRESS 6
|
||||
|
||||
// gNB application layer -> XNAP messages
|
||||
|
||||
typedef struct xnap_setup_req_s {
|
||||
uint32_t Nid_cell;
|
||||
} xnap_setup_req_t;
|
||||
|
||||
typedef struct xnap_setup_resp_s {
|
||||
uint32_t Nid_cell;
|
||||
} xnap_setup_resp_t;
|
||||
|
||||
typedef struct gnb_ip_address_s {
|
||||
unsigned ipv4: 1;
|
||||
unsigned ipv6: 1;
|
||||
char ipv4_address[16];
|
||||
char ipv6_address[46];
|
||||
} gnb_ip_address_t;
|
||||
|
||||
typedef struct xnap_register_gnb_req_s {
|
||||
uint32_t gNB_id;
|
||||
/* Optional name for the cell
|
||||
* NOTE: the name can be NULL (i.e no name) and will be cropped to 150
|
||||
* characters.
|
||||
*/
|
||||
char *gNB_name;
|
||||
|
||||
/* Tracking area code */
|
||||
uint16_t tac;
|
||||
|
||||
/* Mobile Country Code
|
||||
* Mobile Network Code
|
||||
*/
|
||||
uint16_t mcc;
|
||||
uint16_t mnc;
|
||||
uint8_t mnc_digit_length;
|
||||
|
||||
/*
|
||||
* CC Params
|
||||
*/
|
||||
int16_t eutra_band;
|
||||
int32_t nr_band;
|
||||
int32_t nrARFCN;
|
||||
uint32_t downlink_frequency;
|
||||
int32_t uplink_frequency_offset;
|
||||
uint32_t Nid_cell;
|
||||
int16_t N_RB_DL;
|
||||
frame_type_t frame_type;
|
||||
uint32_t fdd_earfcn_DL;
|
||||
uint32_t fdd_earfcn_UL;
|
||||
uint32_t subframeAssignment;
|
||||
uint32_t specialSubframe;
|
||||
uint16_t tdd_nRARFCN;
|
||||
uint16_t tdd_Transmission_Bandwidth;
|
||||
|
||||
/* The local gNB IP address to bind */
|
||||
gnb_ip_address_t gnb_xn_ip_address;
|
||||
|
||||
/* Nb of GNB to connect to */
|
||||
uint8_t nb_xn;
|
||||
|
||||
/* List of target gNB to connect to for Xn*/
|
||||
gnb_ip_address_t target_gnb_xn_ip_address[XNAP_MAX_NB_GNB_IP_ADDRESS];
|
||||
|
||||
/* Number of SCTP streams used for associations */
|
||||
uint16_t sctp_in_streams;
|
||||
uint16_t sctp_out_streams;
|
||||
|
||||
/*gNB port for XNC*/
|
||||
uint32_t gnb_port_for_XNC;
|
||||
|
||||
/* timers (unit: millisecond) */
|
||||
int t_reloc_prep;
|
||||
int txn_reloc_overall;
|
||||
int t_dc_prep;
|
||||
int t_dc_overall;
|
||||
} xnap_register_gnb_req_t;
|
||||
|
||||
// XNAP -> gNB application layer messages
|
||||
typedef struct xnap_register_gnb_cnf_s {
|
||||
/* Nb of connected gNBs*/
|
||||
uint8_t nb_xn;
|
||||
} xnap_register_gnb_cnf_t;
|
||||
|
||||
typedef struct xnap_deregistered_gnb_ind_s {
|
||||
/* Nb of connected gNBs */
|
||||
uint8_t nb_xn;
|
||||
} xnap_deregistered_gnb_ind_t;
|
||||
|
||||
// XNAP <-> RRC
|
||||
typedef struct xnap_guami_s {
|
||||
uint16_t mcc;
|
||||
uint16_t mnc;
|
||||
uint8_t mnc_len;
|
||||
uint8_t amf_region_id;
|
||||
uint16_t amf_set_id;
|
||||
uint8_t amf_pointer;
|
||||
} xnap_guami_t;
|
||||
|
||||
#endif /* XNAP_MESSAGES_TYPES_H_ */
|
||||
@@ -38,7 +38,7 @@
|
||||
#include "common/ran_context.h"
|
||||
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
#include "openair2/XNAP/xnap_gNB_task.h"
|
||||
#include "x2ap_eNB.h"
|
||||
#include "intertask_interface.h"
|
||||
#include "ngap_gNB.h"
|
||||
@@ -59,6 +59,7 @@ extern unsigned char NB_gNB_INST;
|
||||
extern RAN_CONTEXT_t RC;
|
||||
|
||||
#define GNB_REGISTER_RETRY_DELAY 10
|
||||
#define XNAP_GNB_REGISTER_RETRY_DELAY 10
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
|
||||
@@ -116,6 +117,22 @@ uint32_t gNB_app_register_x2(uint32_t gnb_id_start, uint32_t gnb_id_end) {
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
|
||||
void gNB_app_register_xn(uint32_t gnb_id_num) {
|
||||
uint32_t gnb_id;
|
||||
MessageDef *msg_p;
|
||||
|
||||
for (gnb_id = 0; (gnb_id < gnb_id_num) ; gnb_id++) {
|
||||
{
|
||||
msg_p = itti_alloc_new_message (TASK_GNB_APP, 0, XNAP_REGISTER_GNB_REQ);
|
||||
LOG_I(XNAP, "GNB_ID: %d \n", gnb_id);
|
||||
RCconfig_NR_Xn(msg_p, gnb_id);
|
||||
itti_send_msg_to_task (TASK_XNAP, GNB_MODULE_ID_TO_INSTANCE(gnb_id), msg_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* added -------------------------------------------------------------------------------------*/
|
||||
|
||||
void *gNB_app_task(void *args_p)
|
||||
{
|
||||
@@ -128,6 +145,11 @@ void *gNB_app_task(void *args_p)
|
||||
(void)instance;
|
||||
|
||||
int cell_to_activate = 0;
|
||||
|
||||
if (is_xnap_enabled()) {
|
||||
gNB_app_register_xn (RC.nb_nr_inst);
|
||||
}
|
||||
|
||||
itti_mark_task_ready (TASK_GNB_APP);
|
||||
ngran_node_t node_type = get_node_type();
|
||||
|
||||
@@ -252,7 +274,19 @@ void *gNB_app_task(void *args_p)
|
||||
|
||||
/* TODO handle recovering of registration */
|
||||
break;
|
||||
|
||||
case XNAP_DEREGISTERED_GNB_IND:
|
||||
LOG_W(GNB_APP, "[gNB %ld] Received %s: associated gNB %d\n", instance, ITTI_MSG_NAME (msg_p),
|
||||
XNAP_DEREGISTERED_GNB_IND(msg_p).nb_xn);
|
||||
/* TODO handle recovering of registration */
|
||||
break;
|
||||
|
||||
case XNAP_REGISTER_GNB_CNF:
|
||||
LOG_I(GNB_APP, "[gNB %ld] Received %s: associated gNB %d\n", instance, ITTI_MSG_NAME (msg_p),
|
||||
XNAP_REGISTER_GNB_CNF(msg_p).nb_xn);
|
||||
/*TODO Retries if no cnf recieved*/
|
||||
break;
|
||||
|
||||
case TIMER_HAS_EXPIRED:
|
||||
LOG_I(GNB_APP, " Received %s: timer_id %ld\n", msg_name, TIMER_HAS_EXPIRED(msg_p).timer_id);
|
||||
|
||||
|
||||
@@ -35,4 +35,5 @@
|
||||
void *gNB_app_task(void *args_p);
|
||||
uint32_t gNB_app_register(uint32_t gnb_id_start, uint32_t gnb_id_end);
|
||||
uint32_t gNB_app_register_x2(uint32_t gnb_id_start, uint32_t gnb_id_end);
|
||||
void gNB_app_register_xn(uint32_t gnb_id_num);
|
||||
#endif /* GNB_APP_H_ */
|
||||
|
||||
@@ -2191,6 +2191,171 @@ int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_up
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int RCconfig_NR_Xn(MessageDef *msg_p, uint32_t i)
|
||||
{
|
||||
int l = 0;
|
||||
char *address = NULL;
|
||||
char *cidr = NULL;
|
||||
int j, k = 0;
|
||||
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
|
||||
paramdef_t GNBParams[] = GNBPARAMS_DESC;
|
||||
paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST, NULL, 0};
|
||||
config_get(GNBSParams, sizeof(GNBSParams) / sizeof(paramdef_t), NULL);
|
||||
NR_ServingCellConfigCommon_t *scc = calloc(1, sizeof(NR_ServingCellConfigCommon_t));
|
||||
uint64_t ssb_bitmap = 0xff;
|
||||
memset((void *)scc, 0, sizeof(NR_ServingCellConfigCommon_t));
|
||||
prepare_scc(scc);
|
||||
paramdef_t SCCsParams[] = SCCPARAMS_DESC(scc);
|
||||
paramlist_def_t SCCsParamList = {GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, NULL, 0};
|
||||
|
||||
AssertFatal(i < GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt,
|
||||
"Failed to parse config file %s, %uth attribute %s \n",
|
||||
RC.config_file_name,
|
||||
i,
|
||||
GNB_CONFIG_STRING_ACTIVE_GNBS);
|
||||
|
||||
if (GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt > 0) {
|
||||
// Output a list of all gNBs.
|
||||
config_getlist(&GNBParamList, GNBParams, sizeof(GNBParams) / sizeof(paramdef_t), NULL);
|
||||
AssertFatal(GNBParamList.paramarray[k][GNB_GNB_ID_IDX].uptr != NULL, "gNB id not defined in configuration file: %u \n", i);
|
||||
xnap_register_gnb_req_t *xnap_reg_gnb = &XNAP_REGISTER_GNB_REQ(msg_p);
|
||||
// search if in active list
|
||||
for (j = 0; j < GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; j++) {
|
||||
if (strcmp(GNBSParams[GNB_ACTIVE_GNBS_IDX].strlistptr[j], *(GNBParamList.paramarray[k][GNB_GNB_NAME_IDX].strptr)) == 0) {
|
||||
paramdef_t PLMNParams[] = GNBPLMNPARAMS_DESC;
|
||||
paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0};
|
||||
checkedparam_t config_check_PLMNParams[] = PLMNPARAMS_CHECK;
|
||||
for (int I = 0; I < sizeof(PLMNParams) / sizeof(paramdef_t); ++I)
|
||||
PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
|
||||
paramdef_t XnParams[] = XnPARAMS_DESC;
|
||||
paramlist_def_t XnParamList = {GNB_CONFIG_STRING_TARGET_GNB_Xn_IP_ADDRESS, NULL, 0};
|
||||
paramdef_t SCTPParams[] = GNBSCTPPARAMS_DESC;
|
||||
char *gnb_ipv4_address_for_NGU = NULL;
|
||||
uint32_t gnb_port_for_NGU = 0;
|
||||
char *gnb_ipv4_address_for_S1U = NULL;
|
||||
uint32_t gnb_port_for_S1U = 0;
|
||||
paramdef_t NETParams[] = GNBNETPARAMS_DESC;
|
||||
char aprefix[MAX_OPTNAME_SIZE * 80 + 8];
|
||||
sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, k);
|
||||
/* Some default/random parameters */
|
||||
xnap_reg_gnb->gNB_id = *(GNBParamList.paramarray[0][GNB_GNB_ID_IDX].uptr);
|
||||
xnap_reg_gnb->gNB_name = strdup(*(GNBParamList.paramarray[k][GNB_GNB_NAME_IDX].strptr));
|
||||
xnap_reg_gnb->tac = *GNBParamList.paramarray[k][GNB_TRACKING_AREA_CODE_IDX].uptr;
|
||||
config_getlist(&PLMNParamList, PLMNParams, sizeof(PLMNParams) / sizeof(paramdef_t), aprefix);
|
||||
|
||||
if (PLMNParamList.numelt < 1 || PLMNParamList.numelt > 6)
|
||||
AssertFatal(0, "The number of PLMN IDs must be in [1,6], but is %d\n", PLMNParamList.numelt);
|
||||
|
||||
if (PLMNParamList.numelt > 1)
|
||||
LOG_W(XNAP, "XNAP currently handles only one PLMN, ignoring the others!\n");
|
||||
|
||||
xnap_reg_gnb->mcc = *PLMNParamList.paramarray[0][GNB_MOBILE_COUNTRY_CODE_IDX].uptr;
|
||||
xnap_reg_gnb->mnc = *PLMNParamList.paramarray[0][GNB_MOBILE_NETWORK_CODE_IDX].uptr;
|
||||
xnap_reg_gnb->mnc_digit_length = *PLMNParamList.paramarray[0][GNB_MNC_DIGIT_LENGTH].u8ptr;
|
||||
AssertFatal(xnap_reg_gnb->mnc_digit_length == 3 || xnap_reg_gnb->mnc < 100,
|
||||
"MNC %d cannot be encoded in two digits as requested (change mnc_digit_length to 3)\n",
|
||||
xnap_reg_gnb->mnc);
|
||||
sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0);
|
||||
config_getlist(&SCCsParamList, NULL, 0, aprefix);
|
||||
if (SCCsParamList.numelt > 0) {
|
||||
sprintf(aprefix, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0, GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, 0);
|
||||
config_get(SCCsParams, sizeof(SCCsParams) / sizeof(paramdef_t), aprefix);
|
||||
fix_scc(scc, ssb_bitmap);
|
||||
}
|
||||
xnap_reg_gnb->nr_band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; // nr_band; //78
|
||||
xnap_reg_gnb->nrARFCN = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA;
|
||||
xnap_reg_gnb->uplink_frequency_offset =
|
||||
scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier; // 0
|
||||
xnap_reg_gnb->Nid_cell = *scc->physCellId; // 0
|
||||
xnap_reg_gnb->N_RB_DL =
|
||||
scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; // 106
|
||||
xnap_reg_gnb->frame_type = TDD;
|
||||
LOG_I(XNAP,
|
||||
"gNB configuration parameters: nr_band: %d, nr_ARFCN: %d, DL_RBs: %d \n",
|
||||
xnap_reg_gnb->nr_band,
|
||||
xnap_reg_gnb->nrARFCN,
|
||||
xnap_reg_gnb->N_RB_DL);
|
||||
sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, k);
|
||||
config_getlist(&XnParamList, XnParams, sizeof(XnParams) / sizeof(paramdef_t), aprefix);
|
||||
AssertFatal(XnParamList.numelt <= XNAP_MAX_NB_GNB_IP_ADDRESS,
|
||||
"value of XnParamList.numelt %d must be lower than XnAP_MAX_NB_GNB_IP_ADDRESS %d value: reconsider to increase "
|
||||
"XNAP_MAX_NB_GNB_IP_ADDRESS\n",
|
||||
XnParamList.numelt,
|
||||
XNAP_MAX_NB_GNB_IP_ADDRESS);
|
||||
xnap_reg_gnb->nb_xn = 0;
|
||||
|
||||
for (l = 0; l < XnParamList.numelt; l++) {
|
||||
xnap_reg_gnb->nb_xn += 1;
|
||||
strcpy(xnap_reg_gnb->target_gnb_xn_ip_address[l].ipv4_address,
|
||||
*(XnParamList.paramarray[l][GNB_Xn_IPV4_ADDRESS_IDX].strptr));
|
||||
strcpy(xnap_reg_gnb->target_gnb_xn_ip_address[l].ipv6_address,
|
||||
*(XnParamList.paramarray[l][GNB_Xn_IPV6_ADDRESS_IDX].strptr));
|
||||
|
||||
if (strcmp(*(XnParamList.paramarray[l][GNB_Xn_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv4") == 0) {
|
||||
xnap_reg_gnb->target_gnb_xn_ip_address[l].ipv4 = 1;
|
||||
xnap_reg_gnb->target_gnb_xn_ip_address[l].ipv6 = 0;
|
||||
} else if (strcmp(*(XnParamList.paramarray[l][GNB_Xn_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv6") == 0) {
|
||||
xnap_reg_gnb->target_gnb_xn_ip_address[l].ipv4 = 0;
|
||||
xnap_reg_gnb->target_gnb_xn_ip_address[l].ipv6 = 1;
|
||||
} else if (strcmp(*(XnParamList.paramarray[l][GNB_Xn_IP_ADDRESS_PREFERENCE_IDX].strptr), "no") == 0) {
|
||||
xnap_reg_gnb->target_gnb_xn_ip_address[l].ipv4 = 1;
|
||||
xnap_reg_gnb->target_gnb_xn_ip_address[l].ipv6 = 1;
|
||||
}
|
||||
}
|
||||
// timers
|
||||
{
|
||||
int t_reloc_prep = 0;
|
||||
int txn_reloc_overall = 0;
|
||||
int t_dc_prep = 0;
|
||||
int t_dc_overall = 0;
|
||||
paramdef_t p[] = {{"t_reloc_prep", "t_reloc_prep", 0, .iptr = &t_reloc_prep, .defintval = 0, TYPE_INT, 0},
|
||||
{"txn_reloc_overall", "txn_reloc_overall", 0, .iptr = &txn_reloc_overall, .defintval = 0, TYPE_INT, 0},
|
||||
{"t_dc_prep", "t_dc_prep", 0, .iptr = &t_dc_prep, .defintval = 0, TYPE_INT, 0},
|
||||
{"t_dc_overall", "t_dc_overall", 0, .iptr = &t_dc_overall, .defintval = 0, TYPE_INT, 0}};
|
||||
config_get(p, sizeof(p) / sizeof(paramdef_t), aprefix);
|
||||
if (t_reloc_prep <= 0 || t_reloc_prep > 10000 || txn_reloc_overall <= 0 || txn_reloc_overall > 20000 || t_dc_prep <= 0
|
||||
|| t_dc_prep > 10000 || t_dc_overall <= 0 || t_dc_overall > 20000) {
|
||||
LOG_E(XNAP,
|
||||
"timers in configuration file have wrong values. We must have [0 < t_reloc_prep <= 10000] and [0 < "
|
||||
"txn_reloc_overall <= 20000] and [0 < t_dc_prep <= 10000] and [0 < t_dc_overall <= 20000]\n");
|
||||
exit(1);
|
||||
}
|
||||
xnap_reg_gnb->t_reloc_prep = t_reloc_prep;
|
||||
xnap_reg_gnb->txn_reloc_overall = txn_reloc_overall;
|
||||
xnap_reg_gnb->t_dc_prep = t_dc_prep;
|
||||
xnap_reg_gnb->t_dc_overall = t_dc_overall;
|
||||
}
|
||||
// SCTP SETTING
|
||||
xnap_reg_gnb->sctp_out_streams = SCTP_OUT_STREAMS;
|
||||
xnap_reg_gnb->sctp_in_streams = SCTP_IN_STREAMS;
|
||||
|
||||
if (get_softmodem_params()->sa) {
|
||||
sprintf(aprefix, "%s.[%i].%s", GNB_CONFIG_STRING_GNB_LIST, k, GNB_CONFIG_STRING_SCTP_CONFIG);
|
||||
config_get(SCTPParams, sizeof(SCTPParams) / sizeof(paramdef_t), aprefix);
|
||||
xnap_reg_gnb->sctp_in_streams = (uint16_t) * (SCTPParams[GNB_SCTP_INSTREAMS_IDX].uptr);
|
||||
xnap_reg_gnb->sctp_out_streams = (uint16_t) * (SCTPParams[GNB_SCTP_OUTSTREAMS_IDX].uptr);
|
||||
}
|
||||
sprintf(aprefix, "%s.[%i].%s", GNB_CONFIG_STRING_GNB_LIST, k, GNB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
|
||||
// NETWORK_INTERFACES
|
||||
config_get(NETParams, sizeof(NETParams) / sizeof(paramdef_t), aprefix);
|
||||
xnap_reg_gnb->gnb_port_for_XNC = (uint32_t) * (NETParams[GNB_PORT_FOR_XNC_IDX].uptr);
|
||||
// temp out
|
||||
if ((NETParams[GNB_IPV4_ADDR_FOR_XNC_IDX].strptr == NULL) || (xnap_reg_gnb->gnb_port_for_XNC == 0)) {
|
||||
LOG_E(RRC, "Add gNB IPv4 address and/or port for XNC in the CONF file!\n");
|
||||
exit(1);
|
||||
}
|
||||
cidr = *(NETParams[GNB_IPV4_ADDR_FOR_XNC_IDX].strptr);
|
||||
char *save = NULL;
|
||||
address = strtok_r(cidr, "/", &save);
|
||||
xnap_reg_gnb->gnb_xn_ip_address.ipv6 = 0;
|
||||
xnap_reg_gnb->gnb_xn_ip_address.ipv4 = 1;
|
||||
strcpy(xnap_reg_gnb->gnb_xn_ip_address.ipv4_address, address);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ngran_node_t get_node_type(void)
|
||||
{
|
||||
paramdef_t MacRLC_Params[] = MACRLCPARAMS_DESC;
|
||||
|
||||
@@ -107,6 +107,7 @@ int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i);
|
||||
int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i);
|
||||
void wait_f1_setup_response(void);
|
||||
int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_update_t *gnb_cu_cfg_update);
|
||||
int RCconfig_NR_Xn(MessageDef *msg_p, uint32_t i);
|
||||
MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process);
|
||||
ngran_node_t get_node_type(void);
|
||||
|
||||
|
||||
@@ -127,6 +127,7 @@ typedef enum {
|
||||
#define GNB_CONFIG_STRING_UMONDEFAULTDRB "um_on_default_drb"
|
||||
#define GNB_CONFIG_STRING_FORCE256QAMOFF "force_256qam_off"
|
||||
#define GNB_CONFIG_STRING_ENABLE_SDAP "enable_sdap"
|
||||
#define ENB_CONFIG_STRING_XN "enable_xn"
|
||||
#define GNB_CONFIG_HLP_STRING_ENABLE_SDAP "enable the SDAP layer\n"
|
||||
#define GNB_CONFIG_HLP_FORCE256QAMOFF "suppress activation of 256 QAM despite UE support"
|
||||
#define GNB_CONFIG_STRING_DRBS "drbs"
|
||||
@@ -333,6 +334,8 @@ typedef enum {
|
||||
#define GNB_PORT_FOR_NGU_IDX 4
|
||||
#define GNB_IPV4_ADDR_FOR_X2C_IDX 5
|
||||
#define GNB_PORT_FOR_X2C_IDX 6
|
||||
#define GNB_IPV4_ADDR_FOR_XNC_IDX 7
|
||||
#define GNB_PORT_FOR_XNC_IDX 8
|
||||
|
||||
/* S1 interface configuration parameters names */
|
||||
#define GNB_CONFIG_STRING_GNB_INTERFACE_NAME_FOR_S1_MME "GNB_INTERFACE_NAME_FOR_S1_MME"
|
||||
@@ -351,6 +354,10 @@ typedef enum {
|
||||
#define GNB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2C "GNB_IPV4_ADDRESS_FOR_X2C"
|
||||
#define GNB_CONFIG_STRING_ENB_PORT_FOR_X2C "GNB_PORT_FOR_X2C"
|
||||
|
||||
/* Xn interface configuration parameters names */
|
||||
#define GNB_CONFIG_STRING_GNB_IPV4_ADDR_FOR_XNC "GNB_IPV4_ADDRESS_FOR_XNC"
|
||||
#define GNB_CONFIG_STRING_GNB_PORT_FOR_XNC "GNB_PORT_FOR_XNC"
|
||||
|
||||
/*--------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* S1 interface configuration parameters */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
@@ -363,6 +370,8 @@ typedef enum {
|
||||
{GNB_CONFIG_STRING_GNB_PORT_FOR_NGU, NULL, 0, .uptr=&gnb_port_for_NGU, .defintval=2152L, TYPE_UINT, 0}, \
|
||||
{GNB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2C, NULL, 0, .strptr=NULL, .defstrval=NULL, TYPE_STRING, 0}, \
|
||||
{GNB_CONFIG_STRING_ENB_PORT_FOR_X2C, NULL, 0, .uptr=NULL, .defintval=0L, TYPE_UINT, 0}, \
|
||||
{GNB_CONFIG_STRING_GNB_IPV4_ADDR_FOR_XNC, NULL, 0, .strptr=NULL, .defstrval=NULL, TYPE_STRING, 0}, \
|
||||
{GNB_CONFIG_STRING_GNB_PORT_FOR_XNC, NULL, 0, .uptr=NULL, .defintval=0L, TYPE_UINT, 0}, \
|
||||
{GNB_CONFIG_STRING_GNB_INTERFACE_NAME_FOR_S1U, NULL, 0, .strptr=NULL, .defstrval=NULL, TYPE_STRING, 0}, \
|
||||
{GNB_CONFIG_STRING_GNB_IPV4_ADDRESS_FOR_S1U, NULL, 0, .strptr=&gnb_ipv4_address_for_S1U, .defstrval="127.0.0.1",TYPE_STRING, 0}, \
|
||||
{GNB_CONFIG_STRING_GNB_PORT_FOR_S1U, NULL, 0, .uptr=&gnb_port_for_S1U, .defintval=2152L, TYPE_UINT, 0} \
|
||||
@@ -370,6 +379,40 @@ typedef enum {
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
/* Xn configuration parameters section name */
|
||||
#define GNB_CONFIG_STRING_TARGET_GNB_Xn_IP_ADDRESS "target_gnb_xn_ip_address"
|
||||
|
||||
/* Xn configuration parameters names */
|
||||
|
||||
|
||||
#define GNB_CONFIG_STRING_TARGET_GNB_Xn_IPV4_ADDRESS "ipv4"
|
||||
#define GNB_CONFIG_STRING_TARGET_GNB_Xn_IPV6_ADDRESS "ipv6"
|
||||
#define GNB_CONFIG_STRING_TARGET_GNB_Xn_IP_ADDRESS_PREFERENCE "preference"
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* Xn configuration parameters */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
// clang-format off
|
||||
#define XnPARAMS_DESC { \
|
||||
{GNB_CONFIG_STRING_TARGET_GNB_Xn_IPV4_ADDRESS, NULL, 0, .uptr=NULL, .defstrval=NULL, TYPE_STRING, 0}, \
|
||||
{GNB_CONFIG_STRING_TARGET_GNB_Xn_IPV6_ADDRESS, NULL, 0, .uptr=NULL, .defstrval=NULL, TYPE_STRING, 0}, \
|
||||
{GNB_CONFIG_STRING_TARGET_GNB_Xn_IP_ADDRESS_PREFERENCE, NULL, 0, .uptr=NULL, .defstrval=NULL, TYPE_STRING, 0}, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
#define GNB_Xn_IPV4_ADDRESS_IDX 0
|
||||
#define GNB_Xn_IPV6_ADDRESS_IDX 1
|
||||
#define GNB_Xn_IP_ADDRESS_PREFERENCE_IDX 2
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
/* E1 configuration section */
|
||||
#define GNB_CONFIG_STRING_E1_PARAMETERS "E1_INTERFACE"
|
||||
|
||||
|
||||
@@ -96,6 +96,8 @@
|
||||
#define NR_UE_MODULE_INVALID ((module_id_t) ~0) // FIXME attention! depends on type uint8_t!!!
|
||||
#define NR_UE_INDEX_INVALID ((module_id_t) ~0) // FIXME attention! depends on type uint8_t!!! used to be -1
|
||||
|
||||
#define MAX_NUM_NR_NEIGH_CELLs 6 /* maximum neighbouring cells number */
|
||||
|
||||
typedef enum {
|
||||
NR_RRC_OK=0,
|
||||
NR_RRC_ConnSetup_failed,
|
||||
@@ -414,6 +416,12 @@ typedef struct gNB_RRC_INST_s {
|
||||
int srs_enable[MAX_NUM_CCs];
|
||||
|
||||
char *uecap_file;
|
||||
|
||||
// XN handover controlled by network
|
||||
|
||||
// Neighborouring cells id
|
||||
int num_nr_neigh_cells;
|
||||
uint32_t nr_neigh_cells_id[MAX_NUM_NR_NEIGH_CELLs];
|
||||
|
||||
// security configuration (preferred algorithms)
|
||||
nr_security_configuration_t security;
|
||||
|
||||
@@ -56,6 +56,8 @@
|
||||
#include "NR_RejectWaitTime.h"
|
||||
#include "NR_RRCSetup.h"
|
||||
|
||||
//#include "xnap_gNB_task.h"
|
||||
|
||||
#include "NR_CellGroupConfig.h"
|
||||
#include "NR_MeasResults.h"
|
||||
#include "NR_UL-CCCH-Message.h"
|
||||
@@ -1922,6 +1924,27 @@ static void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t ass
|
||||
*/
|
||||
}
|
||||
|
||||
void rrc_gNB_process_xn_setup_request(int mod_id, xnap_setup_req_t *m)
|
||||
{
|
||||
if (RC.nrrrc[mod_id]->num_nr_neigh_cells > MAX_NUM_NR_NEIGH_CELLs) {
|
||||
LOG_E(NR_RRC, "Error: number of neighbouring cells is exceeded \n");
|
||||
return;
|
||||
}
|
||||
|
||||
RC.nrrrc[mod_id]->num_nr_neigh_cells++;
|
||||
RC.nrrrc[mod_id]->nr_neigh_cells_id[RC.nrrrc[mod_id]->num_nr_neigh_cells - 1] = m->Nid_cell;
|
||||
}
|
||||
|
||||
void rrc_gNB_process_xn_setup_response(int mod_id, xnap_setup_resp_t *m)
|
||||
{
|
||||
if (RC.nrrrc[mod_id]->num_nr_neigh_cells > MAX_NUM_NR_NEIGH_CELLs) {
|
||||
LOG_E(RRC, "Error: number of neighbouring cells is exceeded \n");
|
||||
return;
|
||||
}
|
||||
RC.nrrrc[mod_id]->num_nr_neigh_cells++;
|
||||
RC.nrrrc[mod_id]->nr_neigh_cells_id[RC.nrrrc[mod_id]->num_nr_neigh_cells - 1] = m->Nid_cell;
|
||||
}
|
||||
|
||||
void rrc_gNB_process_initial_ul_rrc_message(const f1ap_initial_ul_rrc_message_t *ul_rrc)
|
||||
{
|
||||
// first get RRC instance (note, no the ITTI instance)
|
||||
@@ -2334,6 +2357,9 @@ int rrc_gNB_process_e1_setup_req(e1ap_setup_req_t *req, instance_t instance) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p, e1ap_bearer_setup_resp_t *e1ap_resp)
|
||||
{
|
||||
/* Generate a UE context modification request message towards the DU to
|
||||
@@ -2663,6 +2689,16 @@ void *rrc_gnb_task(void *args_p) {
|
||||
rrc_CU_process_f1_lost_connection(RC.nrrrc[0], &F1AP_LOST_CONNECTION(msg_p), msg_p->ittiMsgHeader.originInstance);
|
||||
break;
|
||||
|
||||
/*Messages from XNAP*/
|
||||
case XNAP_SETUP_RESP:
|
||||
rrc_gNB_process_xn_setup_response(instance, &XNAP_SETUP_RESP(msg_p));
|
||||
break;
|
||||
|
||||
case XNAP_SETUP_REQ:
|
||||
printf("reached here");
|
||||
rrc_gNB_process_xn_setup_request(instance, &XNAP_SETUP_REQ(msg_p));
|
||||
break;
|
||||
|
||||
/* Messages from X2AP */
|
||||
case X2AP_ENDC_SGNB_ADDITION_REQ:
|
||||
LOG_I(NR_RRC, "Received ENDC sgNB addition request from X2AP \n");
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "X2AP_ProtocolExtensionContainer.h"
|
||||
#include "X2AP_asn_constant.h"
|
||||
#include "intertask_interface.h"
|
||||
//#include "X2AP_ServedCells-NR-Item.h"
|
||||
|
||||
/** @defgroup _x2ap_impl_ X2AP Layer Reference Implementation
|
||||
* @ingroup _ref_implementation_
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
add_subdirectory(MESSAGES)
|
||||
add_library(xnap xnap_common.c)
|
||||
add_library(xnap
|
||||
xnap_gNB_decoder.c
|
||||
xnap_gNB_encoder.c
|
||||
xnap_gNB_task.c
|
||||
xnap_gNB_management_procedures.c
|
||||
xnap_gNB_itti_messaging.c
|
||||
xnap_gNB_handler.c
|
||||
xnap_gNB_generate_messages)
|
||||
target_link_libraries(xnap
|
||||
PUBLIC asn1_xnap
|
||||
PRIVATE nr_rrc)
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
/* 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
|
||||
* 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
|
||||
*
|
||||
* Author and copyright: Laurent Thomas, open-cells.com
|
||||
*
|
||||
* 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.
|
||||
@@ -23,22 +20,26 @@
|
||||
|
||||
#ifndef XNAP_COMMON_H_
|
||||
#define XNAP_COMMON_H_
|
||||
|
||||
#include "XNAP_XnAP-PDU.h"
|
||||
#include "intertask_interface.h"
|
||||
#include "common/openairinterface5g_limits.h"
|
||||
#include "oai_asn1.h"
|
||||
#include "XNAP_ProtocolIE-Field.h"
|
||||
#include "XNAP_InitiatingMessage.h"
|
||||
#include "XNAP_ProtocolIE-ContainerPair.h"
|
||||
#include "XNAP_ProtocolExtensionField.h"
|
||||
#include "XNAP_ProtocolExtensionContainer.h"
|
||||
#include "XNAP_ProtocolExtensionField.h"
|
||||
#include "XNAP_ProtocolIE-ContainerPair.h"
|
||||
#include "XNAP_ProtocolIE-Field.h"
|
||||
#include "XNAP_ProtocolIE-FieldPair.h"
|
||||
#include "XNAP_SuccessfulOutcome.h"
|
||||
#include "XNAP_UnsuccessfulOutcome.h"
|
||||
#include "XNAP_XnAP-PDU.h"
|
||||
#include "XNAP_asn_constant.h"
|
||||
#include "common/openairinterface5g_limits.h"
|
||||
#include "intertask_interface.h"
|
||||
#include "oai_asn1.h"
|
||||
|
||||
#ifndef XNAP_PORT
|
||||
#define XNAP_PORT 38422
|
||||
#define XNAP_PORT 38423
|
||||
#endif
|
||||
|
||||
extern int asn1_xer_print;
|
||||
|
||||
#define XNAP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \
|
||||
do { \
|
||||
IE_TYPE **ptr; \
|
||||
@@ -54,11 +55,5 @@
|
||||
DevAssert(ie != NULL); \
|
||||
} while (0)
|
||||
|
||||
ssize_t xnap_generate_initiating_message(uint8_t **buffer,
|
||||
uint32_t *length,
|
||||
XNAP_ProcedureCode_t procedureCode,
|
||||
XNAP_Criticality_t criticality,
|
||||
asn_TYPE_descriptor_t *td,
|
||||
void *sptr);
|
||||
|
||||
typedef int (*xnap_message_decoded_callback)(instance_t instance, uint32_t assocId, uint32_t stream, XNAP_XnAP_PDU_t *pdu);
|
||||
#endif /* XNAP_COMMON_H_ */
|
||||
|
||||
61
openair2/XNAP/xnap_gNB_decoder.c
Normal file
61
openair2/XNAP/xnap_gNB_decoder.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file xnap_gNB_decoder.c
|
||||
* \date July 2023
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "assertions.h"
|
||||
#include "intertask_interface.h"
|
||||
#include "xnap_common.h"
|
||||
#include "xnap_gNB_decoder.h"
|
||||
|
||||
int xnap_gNB_decode_pdu(XNAP_XnAP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length)
|
||||
{
|
||||
asn_dec_rval_t dec_ret;
|
||||
|
||||
DevAssert(buffer != NULL);
|
||||
|
||||
dec_ret = aper_decode(NULL, &asn_DEF_XNAP_XnAP_PDU, (void **)&pdu, buffer, length, 0, 0);
|
||||
xer_fprint(stdout, &asn_DEF_XNAP_XnAP_PDU, pdu);
|
||||
if (dec_ret.code != RC_OK) {
|
||||
LOG_E(XNAP, "Failed to decode PDU\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (pdu->present) {
|
||||
case XNAP_XnAP_PDU_PR_initiatingMessage:
|
||||
LOG_I(XNAP, "xnap_gNB_decode_initiating_message!\n");
|
||||
break;
|
||||
case XNAP_XnAP_PDU_PR_successfulOutcome:
|
||||
LOG_I(XNAP, "xnap_gNB_decode_successfuloutcome_message!\n");
|
||||
break;
|
||||
case XNAP_XnAP_PDU_PR_unsuccessfulOutcome:
|
||||
LOG_I(XNAP, "xnap_gNB_decode_unsuccessfuloutcome_message!\n");
|
||||
break;
|
||||
default:
|
||||
LOG_D(XNAP, "Unknown presence (%d) or not implemented\n", (int)pdu->present);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
32
openair2/XNAP/xnap_gNB_decoder.h
Normal file
32
openair2/XNAP/xnap_gNB_decoder.h
Normal file
@@ -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
|
||||
*/
|
||||
|
||||
/*! \file xnap_gNB_decoder.h
|
||||
* \date July 2023
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#ifndef XNAP_GNB_DECODER_H_
|
||||
#define XNAP_GNB_DECODER_H_
|
||||
|
||||
int xnap_gNB_decode_pdu(XNAP_XnAP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length) __attribute__((warn_unused_result));
|
||||
|
||||
#endif /* XNAP_GNB_DECODER_H_ */
|
||||
186
openair2/XNAP/xnap_gNB_defs.h
Normal file
186
openair2/XNAP/xnap_gNB_defs.h
Normal file
@@ -0,0 +1,186 @@
|
||||
/* 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 <stdint.h>
|
||||
#include "queue.h"
|
||||
#include "tree.h"
|
||||
#include "sctp_eNB_defs.h"
|
||||
#include "xnap_messages_types.h"
|
||||
|
||||
#ifndef XNAP_GNB_DEFS_H_
|
||||
#define XNAP_GNB_DEFS_H_
|
||||
|
||||
#define XNAP_GNB_NAME_LENGTH_MAX (150)
|
||||
|
||||
typedef enum {
|
||||
/* Disconnected state: initial state for any association. */
|
||||
XNAP_GNB_STATE_DISCONNECTED = 0x0,
|
||||
|
||||
/* State waiting for xn Setup response message if the target gNB accepts or
|
||||
* Xn Setup failure if rejects the gNB.
|
||||
*/
|
||||
XNAP_GNB_STATE_WAITING = 0x1,
|
||||
|
||||
/* The gNB is successfully connected to another gNB. */
|
||||
XNAP_GNB_STATE_CONNECTED = 0x2,
|
||||
|
||||
/* XnAP is ready, and the gNB is successfully connected to another gNB. */
|
||||
XNAP_GNB_STATE_READY = 0x3,
|
||||
|
||||
XNAP_GNB_STATE_OVERLOAD = 0x4,
|
||||
|
||||
XNAP_GNB_STATE_RESETTING = 0x5,
|
||||
|
||||
/* Max number of states available */
|
||||
XNAP_GNB_STATE_MAX,
|
||||
} xnap_gNB_state_t;
|
||||
|
||||
/* Served PLMN identity element */
|
||||
/*struct plmn_identity_s {
|
||||
uint16_t mcc;
|
||||
uint16_t mnc;
|
||||
uint8_t mnc_digit_length;
|
||||
STAILQ_ENTRY(plmn_identity_s) next;
|
||||
};*/
|
||||
|
||||
struct gnb_code_s {
|
||||
uint8_t gnb_code;
|
||||
STAILQ_ENTRY(gnb_code_s) next;
|
||||
};
|
||||
|
||||
struct xnap_gNB_instance_s;
|
||||
|
||||
/* This structure describes association of a eNB to another eNB */
|
||||
typedef struct xnap_gNB_data_s {
|
||||
/* eNB descriptors tree, ordered by sctp assoc id */
|
||||
RB_ENTRY(xnap_gNB_data_s) entry;
|
||||
|
||||
/* This is the optional name provided by the MME */
|
||||
char *gNB_name;
|
||||
|
||||
/* target eNB ID */
|
||||
uint32_t gNB_id;
|
||||
|
||||
/* Current gNB load information (if any). */
|
||||
// xnap_load_state_t overload_state;
|
||||
|
||||
/* Current gNB->gNB XnAP association state */
|
||||
xnap_gNB_state_t state;
|
||||
|
||||
/* Next usable stream for UE signalling */
|
||||
int32_t nextstream;
|
||||
|
||||
/* Number of input/ouput streams */
|
||||
uint16_t in_streams;
|
||||
uint16_t out_streams;
|
||||
|
||||
/* Connexion id used between SCTP/X2AP */
|
||||
uint16_t cnx_id;
|
||||
|
||||
/* SCTP association id */
|
||||
int32_t assoc_id;
|
||||
|
||||
/* Nid cells */
|
||||
uint32_t Nid_cell;
|
||||
int num_cc;
|
||||
/*Frequency band of NR neighbor cell supporting ENDC NSA */
|
||||
uint32_t servedNrCell_band;
|
||||
|
||||
/* Only meaningfull in virtual mode */
|
||||
struct xnap_gNB_instance_s *xnap_gNB_instance;
|
||||
} xnap_gNB_data_t;
|
||||
|
||||
typedef struct xnap_gNB_instance_s {
|
||||
/* used in simulation to store multiple gNB instances*/
|
||||
STAILQ_ENTRY(xnap_gNB_instance_s) xnap_gNB_entries;
|
||||
|
||||
/* Number of target gNBs requested by gNB (tree size) */
|
||||
uint32_t xn_target_gnb_nb;
|
||||
/* Number of target gNBs for which association is pending */
|
||||
uint32_t xn_target_gnb_pending_nb;
|
||||
/* Number of target gNB successfully associated to gNB */
|
||||
uint32_t xn_target_gnb_associated_nb;
|
||||
/* Tree of XNAP gNB associations ordered by association ID */
|
||||
RB_HEAD(xnap_gnb_map, xnap_gNB_data_s) xnap_gnb_head;
|
||||
|
||||
instance_t instance;
|
||||
|
||||
/* Displayable name of gNB */
|
||||
char *gNB_name;
|
||||
|
||||
/* Unique gNB_id to identify the gNB within core.
|
||||
* In our case the gNB id will be 28 bits long.
|
||||
*/
|
||||
uint32_t gNB_id;
|
||||
|
||||
/* Tracking area code */
|
||||
uint16_t tac; // octet string of size 3
|
||||
|
||||
/* Mobile Country Code
|
||||
* Mobile Network Code
|
||||
*/
|
||||
uint16_t mcc;
|
||||
uint16_t mnc;
|
||||
uint8_t mnc_digit_length;
|
||||
|
||||
/* CC params */
|
||||
uint32_t downlink_frequency;
|
||||
int32_t uplink_frequency_offset;
|
||||
uint32_t Nid_cell;
|
||||
int16_t N_RB_DL;
|
||||
int16_t N_RB_UL;
|
||||
frame_type_t frame_type;
|
||||
uint32_t fdd_earfcn_DL;
|
||||
uint32_t fdd_earfcn_UL;
|
||||
uint32_t subframeAssignment;
|
||||
uint32_t specialSubframe;
|
||||
uint32_t nr_band;
|
||||
uint32_t tdd_nRARFCN;
|
||||
uint32_t nrARFCN;
|
||||
int16_t nr_SCS;
|
||||
int16_t eutra_band;
|
||||
int num_cc;
|
||||
gnb_ip_address_t target_gnb_xn_ip_address[XNAP_MAX_NB_GNB_IP_ADDRESS];
|
||||
uint8_t nb_xn;
|
||||
gnb_ip_address_t gnb_xn_ip_address;
|
||||
uint16_t sctp_in_streams;
|
||||
uint16_t sctp_out_streams;
|
||||
uint32_t gnb_port_for_XNC;
|
||||
int multi_sd;
|
||||
} xnap_gNB_instance_t;
|
||||
|
||||
typedef struct {
|
||||
/* List of served gNBs*/
|
||||
STAILQ_HEAD(xnap_gNB_instances_head_s, xnap_gNB_instance_s) xnap_gNB_instances_head;
|
||||
/* Nb of registered gNBs */
|
||||
uint8_t nb_registered_gNBs;
|
||||
|
||||
/* Generate a unique connexion id used between XnAP and SCTP */
|
||||
uint16_t global_cnx_id;
|
||||
} xnap_gNB_internal_data_t;
|
||||
|
||||
int xnap_gNB_compare_assoc_id(struct xnap_gNB_data_s *p1, struct xnap_gNB_data_s *p2);
|
||||
|
||||
/* Generate the tree management functions */
|
||||
struct xnap_gNB_map;
|
||||
struct xnap_gNB_data_s;
|
||||
RB_PROTOTYPE(xnap_gNB_map, xnap_gNB_data_s, entry, xnap_gNB_compare_assoc_id);
|
||||
|
||||
#endif /* XNAP_GNB_DEFS_H_ */
|
||||
@@ -19,30 +19,42 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file x2ap_eNB_encoder.c
|
||||
* \brief x2ap encoder procedures for eNB
|
||||
* \author Sreeshma Shiv <sreeshmau@iisc.ac.in>
|
||||
* \date August 2023
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "assertions.h"
|
||||
#include "conversions.h"
|
||||
#include "intertask_interface.h"
|
||||
#include "xnap_common.h"
|
||||
#include "XNAP_XnAP-PDU.h"
|
||||
#include "xnap_gNB_encoder.h"
|
||||
|
||||
ssize_t XNAP_generate_initiating_message(uint8_t **buffer,
|
||||
uint32_t *length,
|
||||
XNAP_ProcedureCode_t procedureCode,
|
||||
XNAP_Criticality_t criticality,
|
||||
asn_TYPE_descriptor_t *td,
|
||||
void *sptr)
|
||||
int xnap_gNB_encode_pdu(XNAP_XnAP_PDU_t *pdu, uint8_t **buffer, uint32_t *len)
|
||||
{
|
||||
XNAP_XnAP_PDU_t pdu;
|
||||
ssize_t encoded;
|
||||
memset(&pdu, 0, sizeof(XNAP_XnAP_PDU_t));
|
||||
pdu.present = XNAP_XnAP_PDU_PR_initiatingMessage;
|
||||
pdu.choice.initiatingMessage->procedureCode = procedureCode;
|
||||
pdu.choice.initiatingMessage->criticality = criticality;
|
||||
ANY_fromType_aper((ANY_t *)&pdu.choice.initiatingMessage->value, td, sptr);
|
||||
|
||||
if ((encoded = aper_encode_to_new_buffer(&asn_DEF_XNAP_XnAP_PDU, 0, &pdu, (void **)buffer)) < 0) {
|
||||
DevAssert(pdu != NULL);
|
||||
DevAssert(buffer != NULL);
|
||||
DevAssert(len != NULL);
|
||||
|
||||
// Can remove later
|
||||
xer_fprint(stdout, &asn_DEF_XNAP_XnAP_PDU, (void *)pdu);
|
||||
|
||||
encoded = aper_encode_to_new_buffer(&asn_DEF_XNAP_XnAP_PDU, 0, pdu, (void **)buffer);
|
||||
|
||||
if (encoded < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*length = encoded;
|
||||
*len = encoded;
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_XNAP_XnAP_PDU, pdu);
|
||||
return encoded;
|
||||
}
|
||||
|
||||
33
openair2/XNAP/xnap_gNB_encoder.h
Normal file
33
openair2/XNAP/xnap_gNB_encoder.h
Normal file
@@ -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
|
||||
*/
|
||||
|
||||
/*! \file xnap_gNB_encoder.h
|
||||
* \brief xnap encoder procedures for gNB
|
||||
* \date July 2023
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#ifndef XNAP_GNB_ENCODER_H_
|
||||
#define XNAP_GNB_ENCODER_H_
|
||||
|
||||
int xnap_gNB_encode_pdu(XNAP_XnAP_PDU_t *pdu, uint8_t **buffer, uint32_t *len) __attribute__((warn_unused_result));
|
||||
|
||||
#endif /* XNAP_GNB_ENCODER_H_ */
|
||||
793
openair2/XNAP/xnap_gNB_generate_messages.c
Normal file
793
openair2/XNAP/xnap_gNB_generate_messages.c
Normal file
@@ -0,0 +1,793 @@
|
||||
/* 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 "intertask_interface.h"
|
||||
#include "xnap_common.h"
|
||||
#include "xnap_gNB_task.h"
|
||||
#include "xnap_gNB_generate_messages.h"
|
||||
#include "xnap_gNB_encoder.h"
|
||||
#include "xnap_gNB_decoder.h"
|
||||
#include "XNAP_GlobalgNB-ID.h"
|
||||
#include "XNAP_ServedCells-NR-Item.h"
|
||||
#include "XNAP_ServedCellInformation-NR.h"
|
||||
#include "XNAP_NRFrequencyBandItem.h"
|
||||
#include "xnap_gNB_itti_messaging.h"
|
||||
#include "XNAP_ServedCells-NR.h"
|
||||
#include "assertions.h"
|
||||
#include "conversions.h"
|
||||
#include "XNAP_BroadcastPLMNinTAISupport-Item.h"
|
||||
#include "XNAP_TAISupport-Item.h"
|
||||
#include "XNAP_GlobalAMF-Region-Information.h"
|
||||
#include "XNAP_NRModeInfoFDD.h"
|
||||
#include "XNAP_NRModeInfoTDD.h"
|
||||
|
||||
int xnap_gNB_generate_xn_setup_request(xnap_gNB_instance_t *instance_p, xnap_gNB_data_t *xnap_gNB_data_p)
|
||||
{
|
||||
XNAP_XnAP_PDU_t pdu;
|
||||
XNAP_XnSetupRequest_t *out;
|
||||
XNAP_XnSetupRequest_IEs_t *ie;
|
||||
XNAP_BroadcastPLMNinTAISupport_Item_t *e_BroadcastPLMNinTAISupport_ItemIE;
|
||||
XNAP_TAISupport_Item_t *TAISupport_ItemIEs;
|
||||
XNAP_S_NSSAI_t *e_S_NSSAI_ItemIE;
|
||||
XNAP_GlobalAMF_Region_Information_t *e_GlobalAMF_Region_Information_ItemIEs;
|
||||
XNAP_ServedCells_NR_Item_t *servedCellMember;
|
||||
// XNAP_ServedCells_NR_t *ServedCells_NR;
|
||||
XNAP_NRFrequencyBandItem_t *nrfreqbanditemul;
|
||||
XNAP_NRFrequencyBandItem_t *nrfreqbanditemdl;
|
||||
XNAP_NRFrequencyBandItem_t *nrfreqbanditem;
|
||||
XNAP_PLMN_Identity_t *plmn;
|
||||
|
||||
uint8_t *buffer;
|
||||
uint32_t len;
|
||||
int ret = 0;
|
||||
|
||||
DevAssert(instance_p != NULL);
|
||||
DevAssert(xnap_gNB_data_p != NULL);
|
||||
|
||||
xnap_gNB_data_p->state = XNAP_GNB_STATE_WAITING;
|
||||
|
||||
/* Prepare the XnAP message to encode */
|
||||
memset(&pdu, 0, sizeof(pdu));
|
||||
|
||||
pdu.present = XNAP_XnAP_PDU_PR_initiatingMessage;
|
||||
// pdu.choice.initiatingMessage = &initiating_msg;
|
||||
pdu.choice.initiatingMessage = (XNAP_InitiatingMessage_t *)calloc(1, sizeof(XNAP_InitiatingMessage_t));
|
||||
pdu.choice.initiatingMessage->procedureCode = XNAP_ProcedureCode_id_xnSetup;
|
||||
pdu.choice.initiatingMessage->criticality = XNAP_Criticality_reject;
|
||||
pdu.choice.initiatingMessage->value.present = XNAP_InitiatingMessage__value_PR_XnSetupRequest;
|
||||
|
||||
out = &pdu.choice.initiatingMessage->value.choice.XnSetupRequest;
|
||||
|
||||
/* mandatory */
|
||||
ie = (XNAP_XnSetupRequest_IEs_t *)calloc(1, sizeof(XNAP_XnSetupRequest_IEs_t));
|
||||
ie->id = XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID;
|
||||
ie->criticality = XNAP_Criticality_reject;
|
||||
ie->value.present = XNAP_XnSetupRequest_IEs__value_PR_GlobalNG_RANNode_ID;
|
||||
ie->value.choice.GlobalNG_RANNode_ID.present = XNAP_GlobalNG_RANNode_ID_PR_gNB;
|
||||
ie->value.choice.GlobalNG_RANNode_ID.choice.gNB = (XNAP_GlobalgNB_ID_t *)calloc(1, sizeof(XNAP_GlobalgNB_ID_t));
|
||||
MCC_MNC_TO_PLMNID(instance_p->mcc,
|
||||
instance_p->mnc,
|
||||
instance_p->mnc_digit_length,
|
||||
&ie->value.choice.GlobalNG_RANNode_ID.choice.gNB->plmn_id);
|
||||
|
||||
ie->value.choice.GlobalNG_RANNode_ID.choice.gNB->gnb_id.present = XNAP_GNB_ID_Choice_PR_gnb_ID;
|
||||
|
||||
MACRO_GNB_ID_TO_BIT_STRING(instance_p->gNB_id, &ie->value.choice.GlobalNG_RANNode_ID.choice.gNB->gnb_id.choice.gnb_ID); // 28 bits
|
||||
LOG_I(XNAP,
|
||||
"%d -> %02x%02x%02x\n",
|
||||
instance_p->gNB_id,
|
||||
ie->value.choice.GlobalNG_RANNode_ID.choice.gNB->gnb_id.choice.gnb_ID.buf[0],
|
||||
ie->value.choice.GlobalNG_RANNode_ID.choice.gNB->gnb_id.choice.gnb_ID.buf[1],
|
||||
ie->value.choice.GlobalNG_RANNode_ID.choice.gNB->gnb_id.choice.gnb_ID.buf[2]);
|
||||
|
||||
asn1cSeqAdd(&out->protocolIEs.list, ie);
|
||||
|
||||
/* mandatory */ // TAI Support list
|
||||
ie = (XNAP_XnSetupRequest_IEs_t *)calloc(1, sizeof(XNAP_XnSetupRequest_IEs_t));
|
||||
ie->id = XNAP_ProtocolIE_ID_id_TAISupport_list;
|
||||
ie->criticality = XNAP_Criticality_reject;
|
||||
ie->value.present = XNAP_XnSetupRequest_IEs__value_PR_TAISupport_List;
|
||||
|
||||
//{
|
||||
// for (int i=0;i<1;i++)
|
||||
{
|
||||
TAISupport_ItemIEs = (XNAP_TAISupport_Item_t *)calloc(1, sizeof(XNAP_TAISupport_Item_t));
|
||||
INT24_TO_OCTET_STRING(instance_p->tac, &TAISupport_ItemIEs->tac);
|
||||
{
|
||||
for (int j = 0; j < 1; j++) {
|
||||
e_BroadcastPLMNinTAISupport_ItemIE =
|
||||
(XNAP_BroadcastPLMNinTAISupport_Item_t *)calloc(1, sizeof(XNAP_BroadcastPLMNinTAISupport_Item_t));
|
||||
|
||||
MCC_MNC_TO_PLMNID(instance_p->mcc,
|
||||
instance_p->mnc,
|
||||
instance_p->mnc_digit_length,
|
||||
&e_BroadcastPLMNinTAISupport_ItemIE->plmn_id);
|
||||
|
||||
{
|
||||
for (int k = 0; k < 1; k++) {
|
||||
e_S_NSSAI_ItemIE = (XNAP_S_NSSAI_t *)calloc(1, sizeof(XNAP_S_NSSAI_t));
|
||||
e_S_NSSAI_ItemIE->sst.size = 1; // OCTET STRING(SIZE(1))
|
||||
e_S_NSSAI_ItemIE->sst.buf = calloc(e_S_NSSAI_ItemIE->sst.size, sizeof(OCTET_STRING_t));
|
||||
e_S_NSSAI_ItemIE->sst.buf[0] = 1;
|
||||
|
||||
asn1cSeqAdd(&e_BroadcastPLMNinTAISupport_ItemIE->tAISliceSupport_List.list, e_S_NSSAI_ItemIE);
|
||||
}
|
||||
}
|
||||
asn1cSeqAdd(&TAISupport_ItemIEs->broadcastPLMNs.list, e_BroadcastPLMNinTAISupport_ItemIE);
|
||||
}
|
||||
}
|
||||
asn1cSeqAdd(&ie->value.choice.TAISupport_List.list, TAISupport_ItemIEs);
|
||||
}
|
||||
//}
|
||||
|
||||
asn1cSeqAdd(&out->protocolIEs.list, ie);
|
||||
|
||||
/* mandatory */
|
||||
ie = (XNAP_XnSetupRequest_IEs_t *)calloc(1, sizeof(XNAP_XnSetupRequest_IEs_t));
|
||||
ie->id = XNAP_ProtocolIE_ID_id_List_of_served_cells_NR;
|
||||
ie->criticality = XNAP_Criticality_reject;
|
||||
ie->value.present = XNAP_XnSetupRequest_IEs__value_PR_ServedCells_NR;
|
||||
{
|
||||
servedCellMember = (XNAP_ServedCells_NR_Item_t *)calloc(1, sizeof(XNAP_ServedCells_NR_Item_t));
|
||||
{
|
||||
servedCellMember->served_cell_info_NR.nrPCI = instance_p->Nid_cell; // long
|
||||
|
||||
MCC_MNC_TO_PLMNID(instance_p->mcc,
|
||||
instance_p->mnc,
|
||||
instance_p->mnc_digit_length,
|
||||
&servedCellMember->served_cell_info_NR.cellID.plmn_id); // octet string
|
||||
NR_CELL_ID_TO_BIT_STRING(instance_p->gNB_id,
|
||||
&servedCellMember->served_cell_info_NR.cellID.nr_CI); // bit string
|
||||
|
||||
INT24_TO_OCTET_STRING(instance_p->tac, &servedCellMember->served_cell_info_NR.tac); // octet string
|
||||
for (int k = 0; k < 1; k++) {
|
||||
plmn = (XNAP_PLMN_Identity_t *)calloc(1, sizeof(XNAP_PLMN_Identity_t));
|
||||
{
|
||||
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, plmn);
|
||||
asn1cSeqAdd(&servedCellMember->served_cell_info_NR.broadcastPLMN.list, plmn);
|
||||
}
|
||||
}
|
||||
if (instance_p->frame_type == FDD) {
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.present = XNAP_NRModeInfo_PR_fdd;
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd =
|
||||
(XNAP_NRModeInfoFDD_t *)calloc(1, sizeof(XNAP_NRModeInfoFDD_t));
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRFrequencyInfo.nrARFCN = instance_p->fdd_earfcn_UL;
|
||||
for (int j = 0; j < 1; j++) {
|
||||
nrfreqbanditemul = (XNAP_NRFrequencyBandItem_t *)calloc(1, sizeof(XNAP_NRFrequencyBandItem_t));
|
||||
nrfreqbanditemul->nr_frequency_band = 78; // how to fill ?
|
||||
asn1cSeqAdd(&servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRFrequencyInfo.frequencyBand_List.list,
|
||||
nrfreqbanditemul);
|
||||
}
|
||||
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRFrequencyInfo.nrARFCN = instance_p->fdd_earfcn_DL;
|
||||
for (int j = 0; j < 1; j++) {
|
||||
nrfreqbanditemdl = (XNAP_NRFrequencyBandItem_t *)calloc(1, sizeof(XNAP_NRFrequencyBandItem_t));
|
||||
nrfreqbanditemdl->nr_frequency_band = 78; // how to fill ?
|
||||
asn1cSeqAdd(&servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRFrequencyInfo.frequencyBand_List.list,
|
||||
nrfreqbanditemdl);
|
||||
}
|
||||
|
||||
switch (instance_p->nr_SCS) {
|
||||
case 15:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs15;
|
||||
break;
|
||||
|
||||
case 30:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs30;
|
||||
break;
|
||||
|
||||
case 60:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs60;
|
||||
break;
|
||||
|
||||
case 120:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs120;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (instance_p->N_RB_UL) {
|
||||
case 11:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb11;
|
||||
break;
|
||||
|
||||
case 18:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb18;
|
||||
break;
|
||||
|
||||
case 24:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb24;
|
||||
break;
|
||||
|
||||
case 78:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb78;
|
||||
break;
|
||||
|
||||
case 106:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb106;
|
||||
break;
|
||||
|
||||
case 162:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb162;
|
||||
break;
|
||||
case 217:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb217;
|
||||
break;
|
||||
case 273:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb273;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(0, "Failed: Check value for N_RB_DL/N_RB_UL");
|
||||
break;
|
||||
}
|
||||
switch (instance_p->nr_SCS) {
|
||||
case 15:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs15;
|
||||
break;
|
||||
|
||||
case 30:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs30;
|
||||
break;
|
||||
|
||||
case 60:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs60;
|
||||
break;
|
||||
|
||||
case 120:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs120;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (instance_p->N_RB_DL) {
|
||||
case 11:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb11;
|
||||
break;
|
||||
|
||||
case 18:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb18;
|
||||
break;
|
||||
|
||||
case 24:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb24;
|
||||
break;
|
||||
|
||||
case 78:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb78;
|
||||
break;
|
||||
|
||||
case 106:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb106;
|
||||
break;
|
||||
|
||||
case 162:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb162;
|
||||
break;
|
||||
case 217:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb217;
|
||||
break;
|
||||
case 273:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb273;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(0, "Failed: Check value for N_RB_DL/N_RB_UL");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.present = XNAP_NRModeInfo_PR_tdd;
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd =
|
||||
(XNAP_NRModeInfoTDD_t *)calloc(1, sizeof(XNAP_NRModeInfoTDD_t));
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrFrequencyInfo.nrARFCN = 640008; // instance_p->nrARFCN[i];
|
||||
for (int j = 0; j < 1; j++) {
|
||||
nrfreqbanditem = (XNAP_NRFrequencyBandItem_t *)calloc(1, sizeof(XNAP_NRFrequencyBandItem_t));
|
||||
nrfreqbanditem->nr_frequency_band = 106; // instance_p->nr_band; //how to fill ?
|
||||
asn1cSeqAdd(&servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrFrequencyInfo.frequencyBand_List.list,
|
||||
nrfreqbanditem);
|
||||
}
|
||||
switch (instance_p->nr_SCS) {
|
||||
case 15:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs15;
|
||||
break;
|
||||
|
||||
case 30:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs30;
|
||||
break;
|
||||
|
||||
case 60:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs60;
|
||||
break;
|
||||
|
||||
case 120:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs120;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (instance_p->N_RB_DL) {
|
||||
case 11:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb11;
|
||||
break;
|
||||
|
||||
case 18:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb18;
|
||||
break;
|
||||
|
||||
case 24:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb24;
|
||||
break;
|
||||
|
||||
case 78:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb78;
|
||||
break;
|
||||
|
||||
case 106:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb106;
|
||||
break;
|
||||
|
||||
case 162:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb162;
|
||||
break;
|
||||
case 217:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb217;
|
||||
break;
|
||||
case 273:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb273;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(0, "Failed: Check value for N_RB_DL/N_RB_UL");
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Setting MTC to 0 now. Will be handled later.
|
||||
INT8_TO_OCTET_STRING(0, &servedCellMember->served_cell_info_NR.measurementTimingConfiguration);
|
||||
servedCellMember->served_cell_info_NR.connectivitySupport.eNDC_Support = 1;
|
||||
}
|
||||
asn1cSeqAdd(&ie->value.choice.ServedCells_NR.list, servedCellMember);
|
||||
}
|
||||
asn1cSeqAdd(&out->protocolIEs.list, ie);
|
||||
|
||||
/* mandatory */ // AMFRegion
|
||||
ie = (XNAP_XnSetupRequest_IEs_t *)calloc(1, sizeof(XNAP_XnSetupRequest_IEs_t));
|
||||
ie->id = XNAP_ProtocolIE_ID_id_AMF_Region_Information;
|
||||
ie->criticality = XNAP_Criticality_reject;
|
||||
ie->value.present = XNAP_XnSetupRequest_IEs__value_PR_AMF_Region_Information;
|
||||
//{
|
||||
// for (int i=0;i<1;i++)
|
||||
{
|
||||
e_GlobalAMF_Region_Information_ItemIEs =
|
||||
(XNAP_GlobalAMF_Region_Information_t *)calloc(1, sizeof(XNAP_GlobalAMF_Region_Information_t));
|
||||
|
||||
MCC_MNC_TO_PLMNID(instance_p->mcc,
|
||||
instance_p->mnc,
|
||||
instance_p->mnc_digit_length,
|
||||
&e_GlobalAMF_Region_Information_ItemIEs->plmn_ID);
|
||||
e_GlobalAMF_Region_Information_ItemIEs->amf_region_id.size = 1;
|
||||
e_GlobalAMF_Region_Information_ItemIEs->amf_region_id.buf =
|
||||
calloc(1, e_GlobalAMF_Region_Information_ItemIEs->amf_region_id.size);
|
||||
e_GlobalAMF_Region_Information_ItemIEs->amf_region_id.buf[0] = 80;
|
||||
e_GlobalAMF_Region_Information_ItemIEs->amf_region_id.bits_unused = 0;
|
||||
|
||||
asn1cSeqAdd(&ie->value.choice.AMF_Region_Information.list, e_GlobalAMF_Region_Information_ItemIEs);
|
||||
}
|
||||
//}
|
||||
asn1cSeqAdd(&out->protocolIEs.list, ie);
|
||||
|
||||
if (xnap_gNB_encode_pdu(&pdu, &buffer, &len) < 0) {
|
||||
LOG_E(XNAP, "Failed to encode Xn setup request\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
xnap_gNB_itti_send_sctp_data_req(instance_p->instance, xnap_gNB_data_p->assoc_id, buffer, len, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int xnap_gNB_generate_xn_setup_failure(instance_t instance,
|
||||
uint32_t assoc_id,
|
||||
XNAP_Cause_PR cause_type,
|
||||
long cause_value,
|
||||
long time_to_wait)
|
||||
{
|
||||
XNAP_XnAP_PDU_t pdu;
|
||||
XNAP_XnSetupFailure_t *out;
|
||||
XNAP_XnSetupFailure_IEs_t *ie;
|
||||
|
||||
uint8_t *buffer;
|
||||
uint32_t len;
|
||||
int ret = 0;
|
||||
|
||||
/* Prepare the XnAP message to encode */
|
||||
memset(&pdu, 0, sizeof(pdu));
|
||||
pdu.present = XNAP_XnAP_PDU_PR_unsuccessfulOutcome;
|
||||
pdu.choice.unsuccessfulOutcome = (XNAP_UnsuccessfulOutcome_t *)calloc(1, sizeof(XNAP_UnsuccessfulOutcome_t));
|
||||
pdu.choice.unsuccessfulOutcome->procedureCode = XNAP_ProcedureCode_id_xnSetup;
|
||||
pdu.choice.unsuccessfulOutcome->criticality = XNAP_Criticality_reject;
|
||||
pdu.choice.unsuccessfulOutcome->value.present = XNAP_UnsuccessfulOutcome__value_PR_XnSetupFailure;
|
||||
out = &pdu.choice.unsuccessfulOutcome->value.choice.XnSetupFailure;
|
||||
|
||||
/* mandatory */
|
||||
ie = (XNAP_XnSetupFailure_IEs_t *)calloc(1, sizeof(XNAP_XnSetupFailure_IEs_t));
|
||||
ie->id = XNAP_ProtocolIE_ID_id_Cause;
|
||||
ie->criticality = XNAP_Criticality_ignore;
|
||||
ie->value.present = XNAP_XnSetupFailure_IEs__value_PR_Cause;
|
||||
|
||||
xnap_gNB_set_cause(&ie->value.choice.Cause, cause_type, cause_value);
|
||||
|
||||
asn1cSeqAdd(&out->protocolIEs.list, ie);
|
||||
|
||||
if (xnap_gNB_encode_pdu(&pdu, &buffer, &len) < 0) {
|
||||
LOG_E(XNAP, "Failed to encode Xn setup failure\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
xnap_gNB_itti_send_sctp_data_req(instance, assoc_id, buffer, len, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int xnap_gNB_set_cause(XNAP_Cause_t *cause_p, XNAP_Cause_PR cause_type, long cause_value)
|
||||
{
|
||||
DevAssert(cause_p != NULL);
|
||||
cause_p->present = cause_type;
|
||||
|
||||
switch (cause_type) {
|
||||
case XNAP_Cause_PR_radioNetwork:
|
||||
cause_p->choice.misc = cause_value;
|
||||
break;
|
||||
|
||||
case XNAP_Cause_PR_transport:
|
||||
cause_p->choice.misc = cause_value;
|
||||
break;
|
||||
|
||||
case XNAP_Cause_PR_protocol:
|
||||
cause_p->choice.misc = cause_value;
|
||||
break;
|
||||
|
||||
case XNAP_Cause_PR_misc:
|
||||
cause_p->choice.misc = cause_value;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xnap_gNB_generate_xn_setup_response(xnap_gNB_instance_t *instance_p, xnap_gNB_data_t *xnap_gNB_data_p)
|
||||
{
|
||||
XNAP_XnAP_PDU_t pdu;
|
||||
XNAP_XnSetupResponse_t *out;
|
||||
XNAP_XnSetupResponse_IEs_t *ie;
|
||||
XNAP_PLMN_Identity_t *plmn;
|
||||
XNAP_BroadcastPLMNinTAISupport_Item_t *e_BroadcastPLMNinTAISupport_ItemIE;
|
||||
XNAP_TAISupport_Item_t *TAISupport_ItemIEs;
|
||||
XNAP_S_NSSAI_t *e_S_NSSAI_ItemIE;
|
||||
// XNAP_GlobalAMF_Region_Information_t *e_GlobalAMF_Region_Information_ItemIEs;
|
||||
XNAP_ServedCells_NR_Item_t *servedCellMember;
|
||||
// XNAP_ServedCells_NR_t *ServedCells_NR;
|
||||
XNAP_NRFrequencyBandItem_t *nrfreqbanditemul;
|
||||
XNAP_NRFrequencyBandItem_t *nrfreqbanditemdl;
|
||||
XNAP_NRFrequencyBandItem_t *nrfreqbanditem;
|
||||
|
||||
uint8_t *buffer;
|
||||
uint32_t len;
|
||||
int ret = 0;
|
||||
|
||||
DevAssert(instance_p != NULL);
|
||||
DevAssert(xnap_gNB_data_p != NULL);
|
||||
|
||||
/* Prepare the XNAP message to encode */
|
||||
memset(&pdu, 0, sizeof(pdu));
|
||||
pdu.present = XNAP_XnAP_PDU_PR_successfulOutcome;
|
||||
pdu.choice.successfulOutcome = (XNAP_SuccessfulOutcome_t *)calloc(1, sizeof(XNAP_SuccessfulOutcome_t));
|
||||
pdu.choice.successfulOutcome->procedureCode = XNAP_ProcedureCode_id_xnSetup;
|
||||
pdu.choice.successfulOutcome->criticality = XNAP_Criticality_reject;
|
||||
pdu.choice.successfulOutcome->value.present = XNAP_SuccessfulOutcome__value_PR_XnSetupResponse;
|
||||
out = &pdu.choice.successfulOutcome->value.choice.XnSetupResponse;
|
||||
|
||||
/* mandatory */
|
||||
ie = (XNAP_XnSetupResponse_IEs_t *)calloc(1, sizeof(XNAP_XnSetupResponse_IEs_t));
|
||||
ie->id = XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID;
|
||||
ie->criticality = XNAP_Criticality_reject;
|
||||
ie->value.present = XNAP_XnSetupResponse_IEs__value_PR_GlobalNG_RANNode_ID;
|
||||
ie->value.choice.GlobalNG_RANNode_ID.present = XNAP_GlobalNG_RANNode_ID_PR_gNB;
|
||||
ie->value.choice.GlobalNG_RANNode_ID.choice.gNB = (XNAP_GlobalgNB_ID_t *)calloc(1, sizeof(XNAP_GlobalgNB_ID_t));
|
||||
MCC_MNC_TO_PLMNID(instance_p->mcc,
|
||||
instance_p->mnc,
|
||||
instance_p->mnc_digit_length,
|
||||
&ie->value.choice.GlobalNG_RANNode_ID.choice.gNB->plmn_id);
|
||||
ie->value.choice.GlobalNG_RANNode_ID.choice.gNB->gnb_id.present = XNAP_GNB_ID_Choice_PR_gnb_ID;
|
||||
MACRO_GNB_ID_TO_BIT_STRING(instance_p->gNB_id, &ie->value.choice.GlobalNG_RANNode_ID.choice.gNB->gnb_id.choice.gnb_ID);
|
||||
LOG_I(XNAP,
|
||||
"%d -> %02x%02x%02x\n",
|
||||
instance_p->gNB_id,
|
||||
ie->value.choice.GlobalNG_RANNode_ID.choice.gNB->gnb_id.choice.gnb_ID.buf[0],
|
||||
ie->value.choice.GlobalNG_RANNode_ID.choice.gNB->gnb_id.choice.gnb_ID.buf[1],
|
||||
ie->value.choice.GlobalNG_RANNode_ID.choice.gNB->gnb_id.choice.gnb_ID.buf[2]);
|
||||
asn1cSeqAdd(&out->protocolIEs.list, ie);
|
||||
|
||||
/* mandatory */ // TAI Support list
|
||||
ie = (XNAP_XnSetupResponse_IEs_t *)calloc(1, sizeof(XNAP_XnSetupResponse_IEs_t));
|
||||
ie->id = XNAP_ProtocolIE_ID_id_TAISupport_list;
|
||||
ie->criticality = XNAP_Criticality_reject;
|
||||
ie->value.present = XNAP_XnSetupResponse_IEs__value_PR_TAISupport_List;
|
||||
|
||||
//{
|
||||
// for (int i=0;i<1;i++)
|
||||
{
|
||||
TAISupport_ItemIEs = (XNAP_TAISupport_Item_t *)calloc(1, sizeof(XNAP_TAISupport_Item_t));
|
||||
INT24_TO_OCTET_STRING(instance_p->tac, &TAISupport_ItemIEs->tac);
|
||||
{
|
||||
for (int j = 0; j < 1; j++) {
|
||||
e_BroadcastPLMNinTAISupport_ItemIE =
|
||||
(XNAP_BroadcastPLMNinTAISupport_Item_t *)calloc(1, sizeof(XNAP_BroadcastPLMNinTAISupport_Item_t));
|
||||
|
||||
MCC_MNC_TO_PLMNID(instance_p->mcc,
|
||||
instance_p->mnc,
|
||||
instance_p->mnc_digit_length,
|
||||
&e_BroadcastPLMNinTAISupport_ItemIE->plmn_id);
|
||||
|
||||
{
|
||||
for (int k = 0; k < 1; k++) {
|
||||
e_S_NSSAI_ItemIE = (XNAP_S_NSSAI_t *)calloc(1, sizeof(XNAP_S_NSSAI_t));
|
||||
e_S_NSSAI_ItemIE->sst.size = 1; // OCTET STRING(SIZE(1))
|
||||
e_S_NSSAI_ItemIE->sst.buf = calloc(e_S_NSSAI_ItemIE->sst.size, sizeof(OCTET_STRING_t));
|
||||
e_S_NSSAI_ItemIE->sst.buf[0] = 1;
|
||||
|
||||
asn1cSeqAdd(&e_BroadcastPLMNinTAISupport_ItemIE->tAISliceSupport_List.list, e_S_NSSAI_ItemIE);
|
||||
}
|
||||
}
|
||||
asn1cSeqAdd(&TAISupport_ItemIEs->broadcastPLMNs.list, e_BroadcastPLMNinTAISupport_ItemIE);
|
||||
}
|
||||
}
|
||||
asn1cSeqAdd(&ie->value.choice.TAISupport_List.list, TAISupport_ItemIEs);
|
||||
}
|
||||
//}
|
||||
|
||||
asn1cSeqAdd(&out->protocolIEs.list, ie);
|
||||
|
||||
/* mandatory */
|
||||
ie = (XNAP_XnSetupResponse_IEs_t *)calloc(1, sizeof(XNAP_XnSetupResponse_IEs_t));
|
||||
ie->id = XNAP_ProtocolIE_ID_id_List_of_served_cells_NR;
|
||||
ie->criticality = XNAP_Criticality_reject;
|
||||
ie->value.present = XNAP_XnSetupResponse_IEs__value_PR_ServedCells_NR;
|
||||
{
|
||||
servedCellMember = (XNAP_ServedCells_NR_Item_t *)calloc(1, sizeof(XNAP_ServedCells_NR_Item_t));
|
||||
{
|
||||
servedCellMember->served_cell_info_NR.nrPCI = instance_p->Nid_cell; // long
|
||||
|
||||
MCC_MNC_TO_PLMNID(instance_p->mcc,
|
||||
instance_p->mnc,
|
||||
instance_p->mnc_digit_length,
|
||||
&servedCellMember->served_cell_info_NR.cellID.plmn_id); // octet string
|
||||
NR_CELL_ID_TO_BIT_STRING(instance_p->gNB_id,
|
||||
&servedCellMember->served_cell_info_NR.cellID.nr_CI); // bit string
|
||||
|
||||
INT24_TO_OCTET_STRING(instance_p->tac, &servedCellMember->served_cell_info_NR.tac); // octet string
|
||||
for (int k = 0; k < 1; k++) {
|
||||
plmn = (XNAP_PLMN_Identity_t *)calloc(1, sizeof(XNAP_PLMN_Identity_t));
|
||||
{
|
||||
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, plmn);
|
||||
asn1cSeqAdd(&servedCellMember->served_cell_info_NR.broadcastPLMN.list, plmn);
|
||||
}
|
||||
}
|
||||
if (instance_p->frame_type == FDD) {
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.present = XNAP_NRModeInfo_PR_fdd;
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd =
|
||||
(XNAP_NRModeInfoFDD_t *)calloc(1, sizeof(XNAP_NRModeInfoFDD_t));
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRFrequencyInfo.nrARFCN = instance_p->fdd_earfcn_UL;
|
||||
for (int j = 0; j < 1; j++) {
|
||||
nrfreqbanditemul = (XNAP_NRFrequencyBandItem_t *)calloc(1, sizeof(XNAP_NRFrequencyBandItem_t));
|
||||
nrfreqbanditemul->nr_frequency_band = 78; // how to fill ?
|
||||
asn1cSeqAdd(&servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRFrequencyInfo.frequencyBand_List.list,
|
||||
nrfreqbanditemul);
|
||||
}
|
||||
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRFrequencyInfo.nrARFCN = instance_p->fdd_earfcn_DL;
|
||||
for (int j = 0; j < 1; j++) {
|
||||
nrfreqbanditemdl = (XNAP_NRFrequencyBandItem_t *)calloc(1, sizeof(XNAP_NRFrequencyBandItem_t));
|
||||
nrfreqbanditemdl->nr_frequency_band = 78; // how to fill ?
|
||||
asn1cSeqAdd(&servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRFrequencyInfo.frequencyBand_List.list,
|
||||
nrfreqbanditemdl);
|
||||
}
|
||||
|
||||
switch (instance_p->nr_SCS) {
|
||||
case 15:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs15;
|
||||
break;
|
||||
|
||||
case 30:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs30;
|
||||
break;
|
||||
|
||||
case 60:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs60;
|
||||
break;
|
||||
|
||||
case 120:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs120;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (instance_p->N_RB_UL) {
|
||||
case 11:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb11;
|
||||
break;
|
||||
|
||||
case 18:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb18;
|
||||
break;
|
||||
|
||||
case 24:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb24;
|
||||
break;
|
||||
|
||||
case 78:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb78;
|
||||
break;
|
||||
|
||||
case 106:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb106;
|
||||
break;
|
||||
|
||||
case 162:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb162;
|
||||
break;
|
||||
case 217:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb217;
|
||||
break;
|
||||
case 273:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->ulNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb273;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(0, "Failed: Check value for N_RB_DL/N_RB_UL");
|
||||
break;
|
||||
}
|
||||
switch (instance_p->nr_SCS) {
|
||||
case 15:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs15;
|
||||
break;
|
||||
|
||||
case 30:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs30;
|
||||
break;
|
||||
|
||||
case 60:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs60;
|
||||
break;
|
||||
|
||||
case 120:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs120;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (instance_p->N_RB_DL) {
|
||||
case 11:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb11;
|
||||
break;
|
||||
|
||||
case 18:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb18;
|
||||
break;
|
||||
|
||||
case 24:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb24;
|
||||
break;
|
||||
|
||||
case 78:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb78;
|
||||
break;
|
||||
|
||||
case 106:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb106;
|
||||
break;
|
||||
|
||||
case 162:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb162;
|
||||
break;
|
||||
case 217:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb217;
|
||||
break;
|
||||
case 273:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.fdd->dlNRTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb273;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(0, "Failed: Check value for N_RB_DL/N_RB_UL");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.present = XNAP_NRModeInfo_PR_tdd;
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd =
|
||||
(XNAP_NRModeInfoTDD_t *)calloc(1, sizeof(XNAP_NRModeInfoTDD_t));
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrFrequencyInfo.nrARFCN = 640008; // instance_p->nrARFCN[i];
|
||||
for (int j = 0; j < 1; j++) {
|
||||
nrfreqbanditem = (XNAP_NRFrequencyBandItem_t *)calloc(1, sizeof(XNAP_NRFrequencyBandItem_t));
|
||||
nrfreqbanditem->nr_frequency_band = 106; // instance_p->nr_band; //how to fill ?
|
||||
asn1cSeqAdd(&servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrFrequencyInfo.frequencyBand_List.list,
|
||||
nrfreqbanditem);
|
||||
}
|
||||
switch (instance_p->nr_SCS) {
|
||||
case 15:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs15;
|
||||
break;
|
||||
|
||||
case 30:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs30;
|
||||
break;
|
||||
|
||||
case 60:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs60;
|
||||
break;
|
||||
|
||||
case 120:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRSCS = XNAP_NRSCS_scs120;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (instance_p->N_RB_DL) {
|
||||
case 11:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb11;
|
||||
break;
|
||||
|
||||
case 18:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb18;
|
||||
break;
|
||||
|
||||
case 24:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb24;
|
||||
break;
|
||||
|
||||
case 78:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb78;
|
||||
break;
|
||||
|
||||
case 106:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb106;
|
||||
break;
|
||||
|
||||
case 162:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb162;
|
||||
break;
|
||||
case 217:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb217;
|
||||
break;
|
||||
case 273:
|
||||
servedCellMember->served_cell_info_NR.nrModeInfo.choice.tdd->nrTransmissonBandwidth.nRNRB = XNAP_NRNRB_nrb273;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(0, "Failed: Check value for N_RB_DL/N_RB_UL");
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Setting MTC to 0 now. Will be handled later.
|
||||
INT8_TO_OCTET_STRING(0, &servedCellMember->served_cell_info_NR.measurementTimingConfiguration);
|
||||
servedCellMember->served_cell_info_NR.connectivitySupport.eNDC_Support = 1;
|
||||
}
|
||||
asn1cSeqAdd(&ie->value.choice.ServedCells_NR.list, servedCellMember);
|
||||
}
|
||||
asn1cSeqAdd(&out->protocolIEs.list, ie);
|
||||
|
||||
if (xnap_gNB_encode_pdu(&pdu, &buffer, &len) < 0) {
|
||||
LOG_E(XNAP, "Failed to encode Xn setup response\n");
|
||||
return -1;
|
||||
}
|
||||
xnap_gNB_data_p->state = XNAP_GNB_STATE_READY;
|
||||
xnap_gNB_itti_send_sctp_data_req(instance_p->instance, xnap_gNB_data_p->assoc_id, buffer, len, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
46
openair2/XNAP/xnap_gNB_generate_messages.h
Normal file
46
openair2/XNAP/xnap_gNB_generate_messages.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file xnap_gNB_generate_messages.h
|
||||
* \brief xnap procedures for gNB
|
||||
* \date 2023 July
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#ifndef XNAP_GNB_GENERATE_MESSAGES_H_
|
||||
#define XNAP_GNB_GENERATE_MESSAGES_H_
|
||||
|
||||
#include "xnap_gNB_defs.h"
|
||||
#include "xnap_common.h"
|
||||
|
||||
int xnap_gNB_generate_xn_setup_request(xnap_gNB_instance_t *instance_p, xnap_gNB_data_t *xnap_gNB_data_p);
|
||||
|
||||
int xnap_gNB_generate_xn_setup_response(xnap_gNB_instance_t *instance_p, xnap_gNB_data_t *xnap_gNB_data_p);
|
||||
|
||||
int xnap_gNB_generate_xn_setup_failure(instance_t instance,
|
||||
uint32_t assoc_id,
|
||||
XNAP_Cause_PR cause_type,
|
||||
long cause_value,
|
||||
long time_to_wait);
|
||||
|
||||
int xnap_gNB_set_cause(XNAP_Cause_t *cause_p, XNAP_Cause_PR cause_type, long cause_value);
|
||||
|
||||
#endif /* XNAP_GNB_GENERATE_MESSAGES_H_ */
|
||||
507
openair2/XNAP/xnap_gNB_handler.c
Normal file
507
openair2/XNAP/xnap_gNB_handler.c
Normal file
@@ -0,0 +1,507 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file xnap_gNB_handler.c
|
||||
* \brief xnap handler procedures for gNB
|
||||
* \author Sreeshma Shiv <sreeshmau@iisc.ac.in>
|
||||
* \date August 2023
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "intertask_interface.h"
|
||||
#include "xnap_common.h"
|
||||
#include "xnap_gNB_defs.h"
|
||||
#include "xnap_gNB_handler.h"
|
||||
#include "xnap_gNB_decoder.h"
|
||||
#include "XNAP_GlobalgNB-ID.h"
|
||||
#include "xnap_gNB_management_procedures.h"
|
||||
#include "xnap_gNB_generate_messages.h"
|
||||
#include "XNAP_ServedCells-NR-Item.h"
|
||||
#include "assertions.h"
|
||||
#include "conversions.h"
|
||||
#include "XNAP_NRFrequencyBandItem.h"
|
||||
#include "XNAP_GlobalNG-RANNode-ID.h"
|
||||
|
||||
static int xnap_gNB_handle_xn_setup_request(instance_t instance, uint32_t assoc_id, uint32_t stream, XNAP_XnAP_PDU_t *pdu);
|
||||
static int xnap_gNB_handle_xn_setup_response(instance_t instance, uint32_t assoc_id, uint32_t stream, XNAP_XnAP_PDU_t *pdu);
|
||||
static int xnap_gNB_handle_xn_setup_failure(instance_t instance, uint32_t assoc_id, uint32_t stream, XNAP_XnAP_PDU_t *pdu);
|
||||
|
||||
/* Placement of callback functions according to XNAP_ProcedureCode.h */
|
||||
static const xnap_message_decoded_callback xnap_messages_callback[][3] = {
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{xnap_gNB_handle_xn_setup_request, xnap_gNB_handle_xn_setup_response, xnap_gNB_handle_xn_setup_failure}, /* xnSetup */
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0}};
|
||||
|
||||
static const char *const xnap_direction_String[] = {
|
||||
"", /* Nothing */
|
||||
"Originating message", /* originating message */
|
||||
"Successfull outcome", /* successfull outcome */
|
||||
"UnSuccessfull outcome", /* successfull outcome */
|
||||
};
|
||||
const char *xnap_direction2String(int xnap_dir)
|
||||
{
|
||||
return (xnap_direction_String[xnap_dir]);
|
||||
}
|
||||
void xnap_handle_xn_setup_message(xnap_gNB_instance_t *instance_p, xnap_gNB_data_t *gnb_desc_p, int sctp_shutdown)
|
||||
{
|
||||
if (sctp_shutdown) {
|
||||
/* A previously connected gNB has been shutdown */
|
||||
|
||||
/* TODO check if it was used by some gNB and send a message to inform these gNB if there is no more associated gNB */
|
||||
if (gnb_desc_p->state == XNAP_GNB_STATE_CONNECTED) {
|
||||
gnb_desc_p->state = XNAP_GNB_STATE_DISCONNECTED;
|
||||
|
||||
if (instance_p->xn_target_gnb_associated_nb > 0) {
|
||||
/* Decrease associated gNB number */
|
||||
instance_p->xn_target_gnb_associated_nb--;
|
||||
}
|
||||
|
||||
/* If there are no more associated gNB, inform gNB app */
|
||||
if (instance_p->xn_target_gnb_associated_nb == 0) {
|
||||
MessageDef *message_p;
|
||||
|
||||
message_p = itti_alloc_new_message(TASK_XNAP, 0, XNAP_DEREGISTERED_GNB_IND);
|
||||
XNAP_DEREGISTERED_GNB_IND(message_p).nb_xn = 0;
|
||||
itti_send_msg_to_task(TASK_GNB_APP, instance_p->instance, message_p);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Check that at least one setup message is pending */
|
||||
DevCheck(instance_p->xn_target_gnb_pending_nb > 0, instance_p->instance, instance_p->xn_target_gnb_pending_nb, 0);
|
||||
|
||||
if (instance_p->xn_target_gnb_pending_nb > 0) {
|
||||
/* Decrease pending messages number */
|
||||
instance_p->xn_target_gnb_pending_nb--;
|
||||
}
|
||||
|
||||
/* If there are no more pending messages, inform gNB app */
|
||||
if (instance_p->xn_target_gnb_pending_nb == 0) {
|
||||
MessageDef *message_p;
|
||||
|
||||
message_p = itti_alloc_new_message(TASK_XNAP, 0, XNAP_REGISTER_GNB_CNF);
|
||||
XNAP_REGISTER_GNB_CNF(message_p).nb_xn = instance_p->xn_target_gnb_associated_nb;
|
||||
itti_send_msg_to_task(TASK_GNB_APP, instance_p->instance, message_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int xnap_gNB_handle_message(instance_t instance,
|
||||
uint32_t assoc_id,
|
||||
int32_t stream,
|
||||
const uint8_t *const data,
|
||||
const uint32_t data_length)
|
||||
{
|
||||
XNAP_XnAP_PDU_t pdu;
|
||||
int ret = 0;
|
||||
|
||||
DevAssert(data != NULL);
|
||||
|
||||
memset(&pdu, 0, sizeof(pdu));
|
||||
|
||||
// printf("Data length received: %d\n", data_length);
|
||||
|
||||
if (xnap_gNB_decode_pdu(&pdu, data, data_length) < 0) {
|
||||
LOG_E(XNAP, "Failed to decode PDU\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (pdu.present) {
|
||||
case XNAP_XnAP_PDU_PR_initiatingMessage:
|
||||
/* Checking procedure Code and direction of message */
|
||||
if (pdu.choice.initiatingMessage->procedureCode
|
||||
>= sizeof(xnap_messages_callback) / (3 * sizeof(xnap_message_decoded_callback))) {
|
||||
//|| (pdu.present > XNAP_XnAP_PDU_PR_unsuccessfulOutcome)) {
|
||||
LOG_E(XNAP, "[SCTP %d] Either procedureCode %ld exceed expected\n", assoc_id, pdu.choice.initiatingMessage->procedureCode);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_XNAP_XnAP_PDU, &pdu);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* No handler present */
|
||||
if (xnap_messages_callback[pdu.choice.initiatingMessage->procedureCode][pdu.present - 1] == NULL) {
|
||||
LOG_E(XNAP,
|
||||
"[SCTP %d] No handler for procedureCode %ld in %s\n",
|
||||
assoc_id,
|
||||
pdu.choice.initiatingMessage->procedureCode,
|
||||
xnap_direction2String(pdu.present - 1));
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_XNAP_XnAP_PDU, &pdu);
|
||||
return -1;
|
||||
}
|
||||
/* Calling the right handler */
|
||||
ret =
|
||||
(*xnap_messages_callback[pdu.choice.initiatingMessage->procedureCode][pdu.present - 1])(instance, assoc_id, stream, &pdu);
|
||||
break;
|
||||
|
||||
case XNAP_XnAP_PDU_PR_successfulOutcome:
|
||||
/* Checking procedure Code and direction of message */
|
||||
if (pdu.choice.successfulOutcome->procedureCode
|
||||
>= sizeof(xnap_messages_callback) / (3 * sizeof(xnap_message_decoded_callback))) {
|
||||
//|| (pdu.present > XNAP_XnAP_PDU_PR_unsuccessfulOutcome)) {
|
||||
LOG_E(XNAP, "[SCTP %d] Either procedureCode %ld exceed expected\n", assoc_id, pdu.choice.successfulOutcome->procedureCode);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_XNAP_XnAP_PDU, &pdu);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* No handler present.*/
|
||||
if (xnap_messages_callback[pdu.choice.successfulOutcome->procedureCode][pdu.present - 1] == NULL) {
|
||||
LOG_E(XNAP,
|
||||
"[SCTP %d] No handler for procedureCode %ld in %s\n",
|
||||
assoc_id,
|
||||
pdu.choice.successfulOutcome->procedureCode,
|
||||
xnap_direction2String(pdu.present - 1));
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_XNAP_XnAP_PDU, &pdu);
|
||||
return -1;
|
||||
}
|
||||
/* Calling the right handler */
|
||||
ret =
|
||||
(*xnap_messages_callback[pdu.choice.successfulOutcome->procedureCode][pdu.present - 1])(instance, assoc_id, stream, &pdu);
|
||||
break;
|
||||
|
||||
case XNAP_XnAP_PDU_PR_unsuccessfulOutcome:
|
||||
/* Checking procedure Code and direction of message */
|
||||
if (pdu.choice.unsuccessfulOutcome->procedureCode
|
||||
>= sizeof(xnap_messages_callback) / (3 * sizeof(xnap_message_decoded_callback))) {
|
||||
//|| (pdu.present > XNAP_XnAP_PDU_PR_unsuccessfulOutcome)) {
|
||||
LOG_E(XNAP,
|
||||
"[SCTP %d] Either procedureCode %ld exceed expected\n",
|
||||
assoc_id,
|
||||
pdu.choice.unsuccessfulOutcome->procedureCode);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_XNAP_XnAP_PDU, &pdu);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* No handler present */
|
||||
if (xnap_messages_callback[pdu.choice.unsuccessfulOutcome->procedureCode][pdu.present - 1] == NULL) {
|
||||
LOG_E(XNAP,
|
||||
"[SCTP %d] No handler for procedureCode %ld in %s\n",
|
||||
assoc_id,
|
||||
pdu.choice.unsuccessfulOutcome->procedureCode,
|
||||
xnap_direction2String(pdu.present - 1));
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_XNAP_XnAP_PDU, &pdu);
|
||||
return -1;
|
||||
}
|
||||
/* Calling the right handler */
|
||||
ret = (*xnap_messages_callback[pdu.choice.unsuccessfulOutcome->procedureCode][pdu.present - 1])(instance,
|
||||
assoc_id,
|
||||
stream,
|
||||
&pdu);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(XNAP, "[SCTP %d] Direction %d exceed expected\n", assoc_id, pdu.present);
|
||||
break;
|
||||
}
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_XNAP_XnAP_PDU, &pdu);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int xnap_gNB_handle_xn_setup_request(instance_t instance, uint32_t assoc_id, uint32_t stream, XNAP_XnAP_PDU_t *pdu)
|
||||
{
|
||||
XNAP_XnSetupRequest_t *xnSetupRequest;
|
||||
XNAP_XnSetupRequest_IEs_t *ie;
|
||||
xnap_gNB_instance_t *instance_p;
|
||||
xnap_gNB_data_t *xnap_gNB_data;
|
||||
MessageDef *msg;
|
||||
uint32_t gNB_id = 0;
|
||||
XNAP_ServedCells_NR_Item_t *servedCellMember;
|
||||
|
||||
DevAssert(pdu != NULL);
|
||||
xnSetupRequest = &pdu->choice.initiatingMessage->value.choice.XnSetupRequest;
|
||||
if (stream != 0) {
|
||||
LOG_E(XNAP, "Received new xn setup request on stream != 0\n");
|
||||
/* Send a xn setup failure with protocol cause unspecified */
|
||||
return xnap_gNB_generate_xn_setup_failure(instance, assoc_id, XNAP_Cause_PR_protocol, XNAP_CauseProtocol_unspecified, -1);
|
||||
}
|
||||
LOG_D(XNAP, "Received a new XN setup request\n");
|
||||
|
||||
XNAP_FIND_PROTOCOLIE_BY_ID(XNAP_XnSetupRequest_IEs_t, ie, xnSetupRequest, XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID, true);
|
||||
if (ie == NULL) {
|
||||
LOG_E(XNAP, "%s %d: ie is a NULL pointer \n", __FILE__, __LINE__);
|
||||
return -1;
|
||||
} else {
|
||||
if (ie->value.choice.GlobalNG_RANNode_ID.choice.gNB->gnb_id.present == XNAP_GNB_ID_Choice_PR_gnb_ID) {
|
||||
// gNB ID = 28 bits
|
||||
uint8_t *gNB_id_buf = ie->value.choice.GlobalNG_RANNode_ID.choice.gNB->gnb_id.choice.gnb_ID.buf;
|
||||
if (ie->value.choice.GlobalNG_RANNode_ID.choice.gNB->gnb_id.choice.gnb_ID.size != 28) {
|
||||
// TODO: handle case were size != 28 -> notify ? reject ?
|
||||
}
|
||||
gNB_id = (gNB_id_buf[0] << 20) + (gNB_id_buf[1] << 12) + (gNB_id_buf[2] << 4) + ((gNB_id_buf[3] & 0xf0) >> 4);
|
||||
LOG_D(XNAP, "gNB id: %07x\n", gNB_id);
|
||||
} else {
|
||||
// TODO if NSA setup
|
||||
}
|
||||
}
|
||||
LOG_D(XNAP, "Adding gNB to the list of associated gNBs\n");
|
||||
|
||||
if ((xnap_gNB_data = xnap_is_gNB_id_in_list(gNB_id)) == NULL) {
|
||||
/*
|
||||
* gNB has not been found in list of associated gNB,
|
||||
* * * * Add it to the tail of list and initialize data
|
||||
*/
|
||||
if ((xnap_gNB_data = xnap_is_gNB_assoc_id_in_list(assoc_id)) == NULL) {
|
||||
return -1;
|
||||
} else {
|
||||
xnap_gNB_data->state = XNAP_GNB_STATE_RESETTING;
|
||||
xnap_gNB_data->gNB_id = gNB_id;
|
||||
}
|
||||
} else {
|
||||
xnap_gNB_data->state = XNAP_GNB_STATE_RESETTING;
|
||||
/*
|
||||
* gNB has been found in list, consider the xn setup request as a reset connection,
|
||||
* reseting any previous UE state if sctp association is != than the previous one
|
||||
*/
|
||||
if (xnap_gNB_data->assoc_id != assoc_id) {
|
||||
/*
|
||||
* ??: Send an overload cause...
|
||||
*/
|
||||
LOG_E(XNAP,
|
||||
"Rejecting xn setup request as gNB id %d is already associated to an active sctp association"
|
||||
"Previous known: %d, new one: %d\n",
|
||||
gNB_id,
|
||||
xnap_gNB_data->assoc_id,
|
||||
assoc_id);
|
||||
|
||||
xnap_gNB_generate_xn_setup_failure(instance, assoc_id, XNAP_Cause_PR_protocol, XNAP_CauseProtocol_unspecified, -1);
|
||||
return -1;
|
||||
}
|
||||
/* TODO: call the reset procedure*/
|
||||
}
|
||||
|
||||
/* Set proper pci */
|
||||
XNAP_FIND_PROTOCOLIE_BY_ID(XNAP_XnSetupRequest_IEs_t, ie, xnSetupRequest, XNAP_ProtocolIE_ID_id_List_of_served_cells_NR, true);
|
||||
if (ie == NULL) {
|
||||
LOG_E(XNAP, "%s %d: ie is a NULL pointer \n", __FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
msg = itti_alloc_new_message(TASK_XNAP, 0, XNAP_SETUP_REQ);
|
||||
servedCellMember = (XNAP_ServedCells_NR_Item_t *)ie->value.choice.ServedCells_NR.list.array[0];
|
||||
xnap_gNB_data->Nid_cell = servedCellMember->served_cell_info_NR.nrPCI;
|
||||
XNAP_SETUP_REQ(msg).Nid_cell = xnap_gNB_data->Nid_cell;
|
||||
instance_p = xnap_gNB_get_instance(instance);
|
||||
DevAssert(instance_p != NULL);
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, instance_p->instance, msg);
|
||||
return xnap_gNB_generate_xn_setup_response(instance_p, xnap_gNB_data);
|
||||
}
|
||||
|
||||
int xnap_gNB_handle_xn_reset_response(instance_t instance, uint32_t assoc_id, uint32_t stream, XNAP_XnAP_PDU_t *pdu)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int xnap_gNB_handle_xn_setup_response(instance_t instance, uint32_t assoc_id, uint32_t stream, XNAP_XnAP_PDU_t *pdu)
|
||||
{
|
||||
XNAP_XnSetupResponse_t *xnSetupResponse;
|
||||
XNAP_XnSetupResponse_IEs_t *ie;
|
||||
|
||||
xnap_gNB_instance_t *instance_p;
|
||||
xnap_gNB_data_t *xnap_gNB_data;
|
||||
MessageDef *msg;
|
||||
uint32_t gNB_id = 0;
|
||||
XNAP_ServedCells_NR_Item_t *servedCellMember;
|
||||
|
||||
DevAssert(pdu != NULL);
|
||||
xnSetupResponse = &pdu->choice.successfulOutcome->value.choice.XnSetupResponse;
|
||||
|
||||
/* We received a new valid XN Setup Response on a stream != 0.
|
||||
* Reject gNB xn setup response.*/
|
||||
|
||||
if (stream != 0) {
|
||||
LOG_E(XNAP, "Received new xn setup response on stream != 0\n");
|
||||
}
|
||||
|
||||
if ((xnap_gNB_data = xnap_get_gNB(NULL, assoc_id, 0)) == NULL) {
|
||||
LOG_E(XNAP,
|
||||
"[SCTP %d] Received XN setup response for non existing "
|
||||
"gNB context\n",
|
||||
assoc_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((xnap_gNB_data->state == XNAP_GNB_STATE_CONNECTED) || (xnap_gNB_data->state == XNAP_GNB_STATE_READY))
|
||||
|
||||
{
|
||||
LOG_E(XNAP, "Received Unexpexted XN Setup Response Message\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG_D(XNAP, "Received a new XN setup response\n");
|
||||
|
||||
XNAP_FIND_PROTOCOLIE_BY_ID(XNAP_XnSetupResponse_IEs_t, ie, xnSetupResponse, XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID, true);
|
||||
|
||||
if (ie == NULL) {
|
||||
LOG_E(XNAP, "%s %d: ie is a NULL pointer \n", __FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
uint8_t *gNB_id_buf = ie->value.choice.GlobalNG_RANNode_ID.choice.gNB->gnb_id.choice.gnb_ID.buf;
|
||||
gNB_id = (gNB_id_buf[0] << 20) + (gNB_id_buf[1] << 12) + (gNB_id_buf[2] << 4) + ((gNB_id_buf[3] & 0xf0) >> 4);
|
||||
LOG_D(XNAP, "Home gNB id: %07x\n", gNB_id);
|
||||
LOG_D(XNAP, "Adding gNB to the list of associated gNBs\n");
|
||||
|
||||
if ((xnap_gNB_data = xnap_is_gNB_id_in_list(gNB_id)) == NULL) {
|
||||
/*
|
||||
* gNB has not been found in list of associated gNB,
|
||||
* Add it to the tail of list and initialize data
|
||||
*/
|
||||
if ((xnap_gNB_data = xnap_is_gNB_assoc_id_in_list(assoc_id)) == NULL) {
|
||||
/*
|
||||
* ??: Send an overload cause...
|
||||
*/
|
||||
return -1;
|
||||
} else {
|
||||
xnap_gNB_data->state = XNAP_GNB_STATE_RESETTING;
|
||||
xnap_gNB_data->gNB_id = gNB_id;
|
||||
}
|
||||
} else {
|
||||
xnap_gNB_data->state = XNAP_GNB_STATE_RESETTING;
|
||||
/* TODO: call the reset procedure*/
|
||||
}
|
||||
|
||||
/* Set proper pci */
|
||||
XNAP_FIND_PROTOCOLIE_BY_ID(XNAP_XnSetupResponse_IEs_t, ie, xnSetupResponse, XNAP_ProtocolIE_ID_id_List_of_served_cells_NR, true);
|
||||
if (ie == NULL) {
|
||||
LOG_E(XNAP, "%s %d: ie is a NULL pointer \n", __FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
msg = itti_alloc_new_message(TASK_XNAP, 0, XNAP_SETUP_RESP);
|
||||
|
||||
if (ie->value.choice.ServedCells_NR.list.count > 0) {
|
||||
servedCellMember = (XNAP_ServedCells_NR_Item_t *)ie->value.choice.ServedCells_NR.list.array[0];
|
||||
xnap_gNB_data->Nid_cell = servedCellMember->served_cell_info_NR.nrPCI;
|
||||
XNAP_SETUP_RESP(msg).Nid_cell = xnap_gNB_data->Nid_cell;
|
||||
}
|
||||
|
||||
/* The association is now ready as source and target gNBs know parameters of each other.
|
||||
* Mark the association as connected */
|
||||
xnap_gNB_data->state = XNAP_GNB_STATE_READY;
|
||||
|
||||
instance_p = xnap_gNB_get_instance(instance);
|
||||
DevAssert(instance_p != NULL);
|
||||
|
||||
instance_p->xn_target_gnb_associated_nb++;
|
||||
xnap_handle_xn_setup_message(instance_p, xnap_gNB_data, 0);
|
||||
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, instance_p->instance, msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xnap_gNB_handle_xn_setup_failure(instance_t instance, uint32_t assoc_id, uint32_t stream, XNAP_XnAP_PDU_t *pdu)
|
||||
{
|
||||
XNAP_XnSetupFailure_t *xnSetupFailure;
|
||||
XNAP_XnSetupFailure_IEs_t *ie;
|
||||
|
||||
xnap_gNB_instance_t *instance_p;
|
||||
xnap_gNB_data_t *xnap_gNB_data;
|
||||
|
||||
DevAssert(pdu != NULL);
|
||||
|
||||
xnSetupFailure = &pdu->choice.unsuccessfulOutcome->value.choice.XnSetupFailure;
|
||||
|
||||
/*
|
||||
* We received a new valid XN Setup Failure on a stream != 0.
|
||||
* * * * This should not happen -> reject gNB xn setup failure.
|
||||
*/
|
||||
|
||||
if (stream != 0) {
|
||||
LOG_W(XNAP, "[SCTP %d] Received xn setup failure on stream != 0 (%d)\n", assoc_id, stream);
|
||||
}
|
||||
|
||||
if ((xnap_gNB_data = xnap_get_gNB(NULL, assoc_id, 0)) == NULL) {
|
||||
LOG_E(XNAP,
|
||||
"[SCTP %d] Received XN setup failure for non existing "
|
||||
"gNB context\n",
|
||||
assoc_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((xnap_gNB_data->state == XNAP_GNB_STATE_CONNECTED) || (xnap_gNB_data->state == XNAP_GNB_STATE_READY))
|
||||
|
||||
{
|
||||
LOG_E(XNAP, "Received Unexpexted XN Setup Failure Message\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG_D(XNAP, "Received a new XN setup failure\n");
|
||||
|
||||
XNAP_FIND_PROTOCOLIE_BY_ID(XNAP_XnSetupFailure_IEs_t, ie, xnSetupFailure, XNAP_ProtocolIE_ID_id_Cause, true);
|
||||
|
||||
if (ie == NULL) {
|
||||
LOG_E(XNAP, "%s %d: ie is a NULL pointer \n", __FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((ie->value.choice.Cause.present == XNAP_Cause_PR_misc)
|
||||
&& (ie->value.choice.Cause.choice.misc == XNAP_CauseMisc_unspecified)) {
|
||||
LOG_E(XNAP, "Received XN setup failure for gNB ... gNB is not ready\n");
|
||||
exit(1);
|
||||
} else {
|
||||
LOG_E(XNAP, "Received xn setup failure for gNB... please check your parameters\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
xnap_gNB_data->state = XNAP_GNB_STATE_WAITING;
|
||||
|
||||
instance_p = xnap_gNB_get_instance(instance);
|
||||
DevAssert(instance_p != NULL);
|
||||
|
||||
xnap_handle_xn_setup_message(instance_p, xnap_gNB_data, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
41
openair2/XNAP/xnap_gNB_handler.h
Normal file
41
openair2/XNAP/xnap_gNB_handler.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file xnap_gNB_handler.h
|
||||
* \brief xnap handler procedures for gNB
|
||||
* \date 2023 July
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#ifndef XNAP_GNB_HANDLERS_H_
|
||||
#define XNAP_GNB_HANDLERS_H_
|
||||
|
||||
#include "xnap_gNB_defs.h"
|
||||
|
||||
void xnap_handle_xn_setup_message(xnap_gNB_instance_t *instance_p, xnap_gNB_data_t *gNB_desc_p, int sctp_shutdown);
|
||||
|
||||
int xnap_gNB_handle_message(instance_t instance,
|
||||
uint32_t assoc_id,
|
||||
int32_t stream,
|
||||
const uint8_t *const data,
|
||||
const uint32_t data_length);
|
||||
|
||||
#endif /* XNAP_GNB_HANDLERS_H_ */
|
||||
54
openair2/XNAP/xnap_gNB_itti_messaging.c
Normal file
54
openair2/XNAP/xnap_gNB_itti_messaging.c
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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 "intertask_interface.h"
|
||||
#include "xnap_gNB_itti_messaging.h"
|
||||
|
||||
void xnap_gNB_itti_send_sctp_data_req(instance_t instance,
|
||||
int32_t assoc_id,
|
||||
uint8_t *buffer,
|
||||
uint32_t buffer_length,
|
||||
uint16_t stream)
|
||||
{
|
||||
MessageDef *message_p;
|
||||
sctp_data_req_t *sctp_data_req;
|
||||
|
||||
message_p = itti_alloc_new_message(TASK_XNAP, 0, SCTP_DATA_REQ);
|
||||
sctp_data_req = &message_p->ittiMsg.sctp_data_req;
|
||||
|
||||
sctp_data_req->assoc_id = assoc_id;
|
||||
sctp_data_req->buffer = buffer;
|
||||
sctp_data_req->buffer_length = buffer_length;
|
||||
sctp_data_req->stream = stream;
|
||||
itti_send_msg_to_task(TASK_SCTP, instance, message_p);
|
||||
}
|
||||
|
||||
void xnap_gNB_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id)
|
||||
{
|
||||
MessageDef *message_p = NULL;
|
||||
sctp_close_association_t *sctp_close_association_p = NULL;
|
||||
|
||||
message_p = itti_alloc_new_message(TASK_XNAP, 0, SCTP_CLOSE_ASSOCIATION);
|
||||
sctp_close_association_p = &message_p->ittiMsg.sctp_close_association;
|
||||
sctp_close_association_p->assoc_id = assoc_id;
|
||||
|
||||
itti_send_msg_to_task(TASK_SCTP, instance, message_p);
|
||||
}
|
||||
39
openair2/XNAP/xnap_gNB_itti_messaging.h
Normal file
39
openair2/XNAP/xnap_gNB_itti_messaging.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file xnap_gNB_itti_messaging.h
|
||||
* \brief xnap tasks for gNB
|
||||
* \date 2023 July
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#ifndef XNAP_GNB_ITTI_MESSAGING_H_
|
||||
#define XNAP_GNB_ITTI_MESSAGING_H_
|
||||
|
||||
void xnap_gNB_itti_send_sctp_data_req(instance_t instance,
|
||||
int32_t assoc_id,
|
||||
uint8_t *buffer,
|
||||
uint32_t buffer_length,
|
||||
uint16_t stream);
|
||||
|
||||
void xnap_gNB_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id);
|
||||
|
||||
#endif /* XNAP_GNB_ITTI_MESSAGING_H_ */
|
||||
240
openair2/XNAP/xnap_gNB_management_procedures.c
Normal file
240
openair2/XNAP/xnap_gNB_management_procedures.c
Normal file
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "intertask_interface.h"
|
||||
#include "assertions.h"
|
||||
#include "conversions.h"
|
||||
#include "xnap_common.h"
|
||||
#include "xnap_gNB_defs.h"
|
||||
#include "xnap_gNB_task.h"
|
||||
|
||||
#define XNAP_DEBUG_LIST
|
||||
#ifdef XNAP_DEBUG_LIST
|
||||
#define XNAP_gNB_LIST_OUT(x, args...) LOG_I(XNAP, "[gNB]%*s" x "\n", 4 * indent, "", ##args)
|
||||
#else
|
||||
#define XNAP_gNB_LIST_OUT(x, args...)
|
||||
#endif
|
||||
|
||||
static int indent = 0;
|
||||
|
||||
xnap_gNB_internal_data_t xnap_gNB_internal_data;
|
||||
|
||||
RB_GENERATE(xnap_gnb_map, xnap_gNB_data_s, entry, xnap_gNB_compare_assoc_id);
|
||||
|
||||
int xnap_gNB_compare_assoc_id(struct xnap_gNB_data_s *p1, struct xnap_gNB_data_s *p2)
|
||||
{
|
||||
if (p1->assoc_id == -1) {
|
||||
if (p1->cnx_id < p2->cnx_id) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (p1->cnx_id > p2->cnx_id) {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (p1->assoc_id < p2->assoc_id) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (p1->assoc_id > p2->assoc_id) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Matching reference */
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t xnap_gNB_fetch_add_global_cnx_id(void)
|
||||
{
|
||||
return ++xnap_gNB_internal_data.global_cnx_id;
|
||||
}
|
||||
|
||||
void xnap_gNB_prepare_internal_data(void)
|
||||
{
|
||||
memset(&xnap_gNB_internal_data, 0, sizeof(xnap_gNB_internal_data));
|
||||
STAILQ_INIT(&xnap_gNB_internal_data.xnap_gNB_instances_head);
|
||||
}
|
||||
|
||||
void xnap_gNB_insert_new_instance(xnap_gNB_instance_t *new_instance_p)
|
||||
{
|
||||
DevAssert(new_instance_p != NULL);
|
||||
|
||||
STAILQ_INSERT_TAIL(&xnap_gNB_internal_data.xnap_gNB_instances_head, new_instance_p, xnap_gNB_entries);
|
||||
}
|
||||
|
||||
void xnap_dump_tree(xnap_gNB_data_t *t)
|
||||
{
|
||||
if (t == NULL)
|
||||
return;
|
||||
printf("-----------------------\n");
|
||||
printf("gNB id %d %s\n", t->gNB_id, t->gNB_name);
|
||||
printf("state %d\n", t->state);
|
||||
printf("nextstream %d\n", t->nextstream);
|
||||
printf("in_streams %d out_streams %d\n", t->in_streams, t->out_streams);
|
||||
printf("cnx_id %d assoc_id %d\n", t->cnx_id, t->assoc_id);
|
||||
xnap_dump_tree(t->entry.rbe_left);
|
||||
xnap_dump_tree(t->entry.rbe_right);
|
||||
}
|
||||
|
||||
void xnap_dump_trees(void)
|
||||
{
|
||||
xnap_gNB_instance_t *zz;
|
||||
STAILQ_FOREACH(zz, &xnap_gNB_internal_data.xnap_gNB_instances_head, xnap_gNB_entries)
|
||||
{
|
||||
printf("here comes the tree (instance %ld):\n---------------------------------------------\n", zz->instance);
|
||||
xnap_dump_tree(zz->xnap_gnb_head.rbh_root);
|
||||
printf("---------------------------------------------\n");
|
||||
}
|
||||
}
|
||||
|
||||
struct xnap_gNB_data_s *xnap_get_gNB(xnap_gNB_instance_t *instance_p, int32_t assoc_id, uint16_t cnx_id)
|
||||
{
|
||||
struct xnap_gNB_data_s temp;
|
||||
struct xnap_gNB_data_s *found;
|
||||
|
||||
memset(&temp, 0, sizeof(struct xnap_gNB_data_s));
|
||||
temp.assoc_id = assoc_id;
|
||||
temp.cnx_id = cnx_id;
|
||||
|
||||
if (instance_p == NULL) {
|
||||
STAILQ_FOREACH(instance_p, &xnap_gNB_internal_data.xnap_gNB_instances_head, xnap_gNB_entries)
|
||||
{
|
||||
found = RB_FIND(xnap_gnb_map, &instance_p->xnap_gnb_head, &temp);
|
||||
|
||||
if (found != NULL) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return RB_FIND(xnap_gnb_map, &instance_p->xnap_gnb_head, &temp);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xnap_gNB_instance_t *xnap_gNB_get_instance(instance_t instance)
|
||||
{
|
||||
xnap_gNB_instance_t *temp = NULL;
|
||||
|
||||
STAILQ_FOREACH(temp, &xnap_gNB_internal_data.xnap_gNB_instances_head, xnap_gNB_entries)
|
||||
{
|
||||
if (temp->instance == instance) {
|
||||
/* Matching occurence */
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// utility functions
|
||||
|
||||
void xnap_dump_gNB(xnap_gNB_data_t *gNB_ref);
|
||||
|
||||
void xnap_dump_gNB_list(void)
|
||||
{
|
||||
xnap_gNB_instance_t *inst = NULL;
|
||||
struct xnap_gNB_data_s *found = NULL;
|
||||
struct xnap_gNB_data_s temp;
|
||||
|
||||
memset(&temp, 0, sizeof(struct xnap_gNB_data_s));
|
||||
|
||||
STAILQ_FOREACH(inst, &xnap_gNB_internal_data.xnap_gNB_instances_head, xnap_gNB_entries)
|
||||
{
|
||||
found = RB_FIND(xnap_gnb_map, &inst->xnap_gnb_head, &temp);
|
||||
xnap_dump_gNB(found);
|
||||
}
|
||||
}
|
||||
|
||||
void xnap_dump_gNB(xnap_gNB_data_t *gNB_ref)
|
||||
{
|
||||
if (gNB_ref == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
XNAP_gNB_LIST_OUT("");
|
||||
XNAP_gNB_LIST_OUT("gNB name: %s", gNB_ref->gNB_name == NULL ? "not present" : gNB_ref->gNB_name);
|
||||
XNAP_gNB_LIST_OUT("gNB STATE: %07x", gNB_ref->state);
|
||||
XNAP_gNB_LIST_OUT("gNB ID: %07x", gNB_ref->gNB_id);
|
||||
indent++;
|
||||
XNAP_gNB_LIST_OUT("SCTP cnx id: %d", gNB_ref->cnx_id);
|
||||
XNAP_gNB_LIST_OUT("SCTP assoc id: %d", gNB_ref->assoc_id);
|
||||
XNAP_gNB_LIST_OUT("SCTP instreams: %d", gNB_ref->in_streams);
|
||||
XNAP_gNB_LIST_OUT("SCTP outstreams: %d", gNB_ref->out_streams);
|
||||
indent--;
|
||||
}
|
||||
|
||||
xnap_gNB_data_t *xnap_is_gNB_pci_in_list(const uint32_t pci)
|
||||
{
|
||||
xnap_gNB_instance_t *inst;
|
||||
struct xnap_gNB_data_s *elm;
|
||||
|
||||
STAILQ_FOREACH(inst, &xnap_gNB_internal_data.xnap_gNB_instances_head, xnap_gNB_entries)
|
||||
{
|
||||
RB_FOREACH(elm, xnap_gnb_map, &inst->xnap_gnb_head)
|
||||
{
|
||||
if (elm->Nid_cell == pci) {
|
||||
return elm;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xnap_gNB_data_t *xnap_is_gNB_id_in_list(const uint32_t gNB_id)
|
||||
{
|
||||
xnap_gNB_instance_t *inst;
|
||||
struct xnap_gNB_data_s *elm;
|
||||
|
||||
STAILQ_FOREACH(inst, &xnap_gNB_internal_data.xnap_gNB_instances_head, xnap_gNB_entries)
|
||||
{
|
||||
RB_FOREACH(elm, xnap_gnb_map, &inst->xnap_gnb_head)
|
||||
{
|
||||
if (elm->gNB_id == gNB_id)
|
||||
return elm;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xnap_gNB_data_t *xnap_is_gNB_assoc_id_in_list(const uint32_t sctp_assoc_id)
|
||||
{
|
||||
xnap_gNB_instance_t *inst;
|
||||
struct xnap_gNB_data_s *found;
|
||||
struct xnap_gNB_data_s temp;
|
||||
|
||||
temp.assoc_id = sctp_assoc_id;
|
||||
temp.cnx_id = -1;
|
||||
|
||||
STAILQ_FOREACH(inst, &xnap_gNB_internal_data.xnap_gNB_instances_head, xnap_gNB_entries)
|
||||
{
|
||||
found = RB_FIND(xnap_gnb_map, &inst->xnap_gnb_head, &temp);
|
||||
if (found != NULL) {
|
||||
if (found->assoc_id == sctp_assoc_id) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
45
openair2/XNAP/xnap_gNB_management_procedures.h
Normal file
45
openair2/XNAP/xnap_gNB_management_procedures.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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 __XNAP_GNB_MANAGEMENT_PROCEDURES__H__
|
||||
#define __XNAP_GNB_MANAGEMENT_PROCEDURES__H__
|
||||
|
||||
void xnap_gNB_prepare_internal_data(void);
|
||||
|
||||
void xnap_dump_trees(void);
|
||||
|
||||
void xnap_gNB_insert_new_instance(xnap_gNB_instance_t *new_instance_p);
|
||||
|
||||
xnap_gNB_instance_t *xnap_gNB_get_instance(uint8_t mod_id);
|
||||
|
||||
uint16_t xnap_gNB_fetch_add_global_cnx_id(void);
|
||||
|
||||
void xnap_gNB_prepare_internal_data(void);
|
||||
|
||||
xnap_gNB_data_t *xnap_is_gNB_id_in_list(uint32_t gNB_id);
|
||||
|
||||
xnap_gNB_data_t *xnap_is_gNB_assoc_id_in_list(uint32_t sctp_assoc_id);
|
||||
|
||||
xnap_gNB_data_t *xnap_is_gNB_pci_in_list(const uint32_t pci);
|
||||
|
||||
struct xnap_gNB_data_s *xnap_get_gNB(xnap_gNB_instance_t *instance_p, int32_t assoc_id, uint16_t cnx_id);
|
||||
|
||||
#endif /* __XNAP_GNB_MANAGEMENT_PROCEDURES__H__ */
|
||||
444
openair2/XNAP/xnap_gNB_task.c
Normal file
444
openair2/XNAP/xnap_gNB_task.c
Normal file
@@ -0,0 +1,444 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
/*! \file XNAP/xnap_gNB_task.c
|
||||
* \brief XNAP tasks and functions definitions
|
||||
* \author Sreeshma Shiv
|
||||
* \date Aug 2023
|
||||
* \version 1.0
|
||||
* \email: sreeshmau@iisc.ac.in
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "intertask_interface.h"
|
||||
#include <openair3/ocp-gtpu/gtp_itf.h>
|
||||
#include "xnap_gNB_task.h"
|
||||
#include "xnap_gNB_defs.h"
|
||||
#include "xnap_gNB_management_procedures.h"
|
||||
#include "xnap_gNB_handler.h"
|
||||
#include "xnap_gNB_generate_messages.h"
|
||||
#include "queue.h"
|
||||
#include "assertions.h"
|
||||
#include "conversions.h"
|
||||
|
||||
struct xnap_gnb_map;
|
||||
struct xnap_gNB_data_s;
|
||||
|
||||
RB_PROTOTYPE(xnap_gnb_map, xnap_gNB_data_s, entry, xnap_gNB_compare_assoc_id);
|
||||
|
||||
static void xnap_gNB_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind);
|
||||
|
||||
static void xnap_gNB_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind);
|
||||
|
||||
static void xnap_gNB_handle_register_gNB(instance_t instance, xnap_register_gnb_req_t *xnap_register_gNB);
|
||||
|
||||
static void xnap_gNB_register_gNB(xnap_gNB_instance_t *instance_p,
|
||||
gnb_ip_address_t *target_gNB_ip_addr,
|
||||
gnb_ip_address_t *local_ip_addr,
|
||||
uint16_t in_streams,
|
||||
uint16_t out_streams,
|
||||
uint32_t gnb_port_for_XNC);
|
||||
static void xnap_gNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp);
|
||||
|
||||
static void xnap_gNB_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind)
|
||||
{
|
||||
int result;
|
||||
DevAssert(sctp_data_ind != NULL);
|
||||
xnap_gNB_handle_message(instance,
|
||||
sctp_data_ind->assoc_id,
|
||||
sctp_data_ind->stream,
|
||||
sctp_data_ind->buffer,
|
||||
sctp_data_ind->buffer_length);
|
||||
result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer);
|
||||
AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||
}
|
||||
|
||||
static void xnap_gNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp)
|
||||
{
|
||||
xnap_gNB_instance_t *instance_p;
|
||||
xnap_gNB_data_t *xnap_gnb_data_p;
|
||||
DevAssert(sctp_new_association_resp != NULL);
|
||||
xnap_dump_trees();
|
||||
instance_p = xnap_gNB_get_instance(instance); // managementproc
|
||||
DevAssert(instance_p != NULL);
|
||||
// printf("handle response");
|
||||
|
||||
/* if the assoc_id is already known, it is certainly because an IND was received
|
||||
* before. In this case, just update streams and return
|
||||
*/
|
||||
if (sctp_new_association_resp->assoc_id != -1) {
|
||||
xnap_gnb_data_p = xnap_get_gNB(instance_p, sctp_new_association_resp->assoc_id, sctp_new_association_resp->ulp_cnx_id);
|
||||
|
||||
if (xnap_gnb_data_p != NULL) {
|
||||
/* some sanity check - to be refined at some point */
|
||||
if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
|
||||
LOG_E(XNAP, "xnap_gnb_data_p not NULL and sctp state not SCTP_STATE_ESTABLISHED?\n");
|
||||
if (sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN) {
|
||||
RB_REMOVE(xnap_gnb_map, &instance_p->xnap_gnb_head, xnap_gnb_data_p);
|
||||
return;
|
||||
}
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
xnap_gnb_data_p->in_streams = sctp_new_association_resp->in_streams;
|
||||
xnap_gnb_data_p->out_streams = sctp_new_association_resp->out_streams;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
xnap_gnb_data_p = xnap_get_gNB(instance_p, -1, sctp_new_association_resp->ulp_cnx_id);
|
||||
DevAssert(xnap_gnb_data_p != NULL);
|
||||
xnap_dump_trees();
|
||||
|
||||
/* gNB: return if connection to gNB failed - to be modified if needed.
|
||||
* We may want to try to connect over and over again until we succeed
|
||||
* but the modifications to the code to get this behavior are complex.
|
||||
* Exit on error is done in XnAP implementation */
|
||||
|
||||
if (sctp_new_association_resp->sctp_state == SCTP_STATE_UNREACHABLE) {
|
||||
LOG_E(XNAP,
|
||||
"association with gNB failed, is it running? If no, run it first. If yes, check IP addresses in your configuration "
|
||||
"file.\n");
|
||||
RB_REMOVE(xnap_gnb_map, &instance_p->xnap_gnb_head, xnap_gnb_data_p);
|
||||
return;
|
||||
}
|
||||
// cell_macro_gnb already using in xnap,ngap,f1
|
||||
|
||||
if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
|
||||
LOG_W(XNAP,
|
||||
"Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n",
|
||||
sctp_new_association_resp->sctp_state,
|
||||
instance,
|
||||
sctp_new_association_resp->ulp_cnx_id);
|
||||
xnap_handle_xn_setup_message(instance_p, xnap_gnb_data_p, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
|
||||
return;
|
||||
}
|
||||
|
||||
xnap_dump_trees();
|
||||
/* Update parameters */
|
||||
xnap_gnb_data_p->assoc_id = sctp_new_association_resp->assoc_id;
|
||||
xnap_gnb_data_p->in_streams = sctp_new_association_resp->in_streams;
|
||||
xnap_gnb_data_p->out_streams = sctp_new_association_resp->out_streams;
|
||||
xnap_dump_trees();
|
||||
/* Prepare new xn Setup Request */
|
||||
xnap_gNB_generate_xn_setup_request(instance_p, xnap_gnb_data_p);
|
||||
}
|
||||
|
||||
static void xnap_gNB_handle_register_gNB(instance_t instance, xnap_register_gnb_req_t *xnap_register_gNB)
|
||||
{
|
||||
xnap_gNB_instance_t *new_instance;
|
||||
DevAssert(xnap_register_gNB != NULL);
|
||||
/* Look if the provided instance already exists */
|
||||
new_instance = xnap_gNB_get_instance(instance);
|
||||
|
||||
if (new_instance != NULL) {
|
||||
/* Checks if it is a retry on the same gNB */
|
||||
DevCheck(new_instance->gNB_id == xnap_register_gNB->gNB_id, new_instance->gNB_id, xnap_register_gNB->gNB_id, 0);
|
||||
DevCheck(new_instance->tac == xnap_register_gNB->tac, new_instance->tac, xnap_register_gNB->tac, 0);
|
||||
DevCheck(new_instance->mcc == xnap_register_gNB->mcc, new_instance->mcc, xnap_register_gNB->mcc, 0);
|
||||
DevCheck(new_instance->mnc == xnap_register_gNB->mnc, new_instance->mnc, xnap_register_gNB->mnc, 0);
|
||||
LOG_W(XNAP, "gNB[%ld] already registered\n", instance);
|
||||
} else {
|
||||
new_instance = calloc(1, sizeof(xnap_gNB_instance_t));
|
||||
DevAssert(new_instance != NULL);
|
||||
RB_INIT(&new_instance->xnap_gnb_head);
|
||||
/* Copy usefull parameters */
|
||||
new_instance->instance = instance;
|
||||
new_instance->gNB_name = xnap_register_gNB->gNB_name;
|
||||
new_instance->gNB_id = xnap_register_gNB->gNB_id;
|
||||
new_instance->tac = xnap_register_gNB->tac;
|
||||
new_instance->mcc = xnap_register_gNB->mcc;
|
||||
new_instance->mnc = xnap_register_gNB->mnc;
|
||||
new_instance->mnc_digit_length = xnap_register_gNB->mnc_digit_length;
|
||||
new_instance->nr_band = xnap_register_gNB->nr_band;
|
||||
new_instance->tdd_nRARFCN = xnap_register_gNB->nrARFCN;
|
||||
new_instance->uplink_frequency_offset = xnap_register_gNB->uplink_frequency_offset;
|
||||
new_instance->Nid_cell = xnap_register_gNB->Nid_cell;
|
||||
new_instance->N_RB_DL = xnap_register_gNB->N_RB_DL;
|
||||
new_instance->frame_type = xnap_register_gNB->frame_type;
|
||||
|
||||
DevCheck(xnap_register_gNB->nb_xn <= XNAP_MAX_NB_GNB_IP_ADDRESS, XNAP_MAX_NB_GNB_IP_ADDRESS, xnap_register_gNB->nb_xn, 0);
|
||||
memcpy(new_instance->target_gnb_xn_ip_address,
|
||||
xnap_register_gNB->target_gnb_xn_ip_address,
|
||||
xnap_register_gNB->nb_xn * sizeof(gnb_ip_address_t));
|
||||
new_instance->nb_xn = xnap_register_gNB->nb_xn;
|
||||
new_instance->gnb_xn_ip_address = xnap_register_gNB->gnb_xn_ip_address;
|
||||
new_instance->sctp_in_streams = xnap_register_gNB->sctp_in_streams;
|
||||
new_instance->sctp_out_streams = xnap_register_gNB->sctp_out_streams;
|
||||
new_instance->gnb_port_for_XNC = xnap_register_gNB->gnb_port_for_XNC;
|
||||
/* Add the new instance to the list of gNB (meaningfull in virtual mode) */
|
||||
xnap_gNB_insert_new_instance(new_instance);
|
||||
LOG_I(XNAP, "Registered new gNB[%ld] gNB id %u\n", instance, xnap_register_gNB->gNB_id);
|
||||
|
||||
/* initiate the SCTP listener */
|
||||
if (xnap_gNB_init_sctp(new_instance, &xnap_register_gNB->gnb_xn_ip_address, xnap_register_gNB->gnb_port_for_XNC) < 0) {
|
||||
LOG_E(XNAP, "Error while sending SCTP_INIT_MSG to SCTP \n");
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_I(XNAP, "gNB[%ld] gNB id %u acting as a listner (server)\n", instance, xnap_register_gNB->gNB_id);
|
||||
}
|
||||
}
|
||||
|
||||
int xnap_gNB_init_sctp(xnap_gNB_instance_t *instance_p, gnb_ip_address_t *local_ip_addr, uint32_t gnb_port_for_XNC)
|
||||
{
|
||||
// Create and alloc new message
|
||||
MessageDef *message;
|
||||
sctp_init_t *sctp_init = NULL;
|
||||
DevAssert(instance_p != NULL);
|
||||
DevAssert(local_ip_addr != NULL);
|
||||
LOG_I(XNAP, "entered function init sctp\n");
|
||||
message = itti_alloc_new_message(TASK_XNAP, 0, SCTP_INIT_MSG_MULTI_REQ);
|
||||
sctp_init = &message->ittiMsg.sctp_init_multi;
|
||||
sctp_init->port = gnb_port_for_XNC;
|
||||
sctp_init->ppid = XNAP_SCTP_PPID;
|
||||
sctp_init->ipv4 = 1;
|
||||
sctp_init->ipv6 = 0;
|
||||
sctp_init->nb_ipv4_addr = 1;
|
||||
#if 0
|
||||
memcpy(&sctp_init->ipv4_address,
|
||||
local_ip_addr,
|
||||
sizeof(*local_ip_addr));
|
||||
#endif
|
||||
sctp_init->ipv4_address[0] = inet_addr(local_ip_addr->ipv4_address);
|
||||
/*
|
||||
* SR WARNING: ipv6 multi-homing fails sometimes for localhost.
|
||||
* * * * Disable it for now.
|
||||
*/
|
||||
sctp_init->nb_ipv6_addr = 0;
|
||||
sctp_init->ipv6_address[0] = "0:0:0:0:0:0:0:1";
|
||||
return itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message);
|
||||
}
|
||||
|
||||
static void xnap_gNB_register_gNB(xnap_gNB_instance_t *instance_p,
|
||||
gnb_ip_address_t *target_gNB_ip_address,
|
||||
gnb_ip_address_t *local_ip_addr,
|
||||
uint16_t in_streams,
|
||||
uint16_t out_streams,
|
||||
uint32_t gnb_port_for_XNC)
|
||||
{
|
||||
MessageDef *message = NULL;
|
||||
xnap_gNB_data_t *xnap_gnb_data = NULL;
|
||||
DevAssert(instance_p != NULL);
|
||||
DevAssert(target_gNB_ip_address != NULL);
|
||||
message = itti_alloc_new_message(TASK_XNAP, 0, SCTP_NEW_ASSOCIATION_REQ);
|
||||
sctp_new_association_req_t *sctp_new_association_req = &message->ittiMsg.sctp_new_association_req;
|
||||
sctp_new_association_req->port = gnb_port_for_XNC;
|
||||
sctp_new_association_req->ppid = XNAP_SCTP_PPID;
|
||||
sctp_new_association_req->in_streams = in_streams;
|
||||
sctp_new_association_req->out_streams = out_streams;
|
||||
|
||||
memcpy(&sctp_new_association_req->remote_address, target_gNB_ip_address, sizeof(*target_gNB_ip_address));
|
||||
memcpy(&sctp_new_association_req->local_address, local_ip_addr, sizeof(*local_ip_addr));
|
||||
/* Create new gNB descriptor */
|
||||
xnap_gnb_data = calloc(1, sizeof(*xnap_gnb_data));
|
||||
DevAssert(xnap_gnb_data != NULL);
|
||||
xnap_gnb_data->cnx_id = xnap_gNB_fetch_add_global_cnx_id();
|
||||
sctp_new_association_req->ulp_cnx_id = xnap_gnb_data->cnx_id;
|
||||
xnap_gnb_data->assoc_id = -1;
|
||||
xnap_gnb_data->xnap_gNB_instance = instance_p;
|
||||
/* Insert the new descriptor in list of known gNB
|
||||
* but not yet associated.
|
||||
*/
|
||||
RB_INSERT(xnap_gnb_map, &instance_p->xnap_gnb_head, xnap_gnb_data);
|
||||
xnap_gnb_data->state = XNAP_GNB_STATE_WAITING;
|
||||
instance_p->xn_target_gnb_nb++;
|
||||
instance_p->xn_target_gnb_pending_nb++;
|
||||
itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message);
|
||||
LOG_I(XNAP, "entered function send to task sctp\n");
|
||||
}
|
||||
|
||||
static void xnap_gNB_handle_sctp_init_msg_multi_cnf(instance_t instance_id, sctp_init_msg_multi_cnf_t *m)
|
||||
{
|
||||
xnap_gNB_instance_t *instance;
|
||||
int index;
|
||||
DevAssert(m != NULL);
|
||||
instance = xnap_gNB_get_instance(instance_id);
|
||||
DevAssert(instance != NULL);
|
||||
instance->multi_sd = m->multi_sd;
|
||||
|
||||
/* Exit if CNF message reports failure.
|
||||
* Failure means multi_sd < 0.
|
||||
*/
|
||||
if (instance->multi_sd < 0) {
|
||||
LOG_E(XNAP, "Error: be sure to properly configure XN in your configuration file.\n");
|
||||
DevAssert(instance->multi_sd >= 0);
|
||||
}
|
||||
|
||||
/* Trying to connect to the provided list of gNB ip address */
|
||||
|
||||
for (index = 0; index < instance->nb_xn; index++) {
|
||||
LOG_I(XNAP, "gNB[%ld] gNB id %u acting as an initiator (client)\n", instance_id, instance->gNB_id);
|
||||
|
||||
xnap_gNB_register_gNB(instance,
|
||||
&instance->target_gnb_xn_ip_address[index],
|
||||
&instance->gnb_xn_ip_address,
|
||||
instance->sctp_in_streams,
|
||||
instance->sctp_out_streams,
|
||||
instance->gnb_port_for_XNC);
|
||||
}
|
||||
}
|
||||
|
||||
static void xnap_gNB_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind)
|
||||
{
|
||||
xnap_gNB_instance_t *instance_p;
|
||||
xnap_gNB_data_t *xnap_gnb_data_p;
|
||||
printf("xnap_gNB_handle_sctp_association_ind at 1 (called for instance %ld)\n", instance);
|
||||
xnap_dump_trees();
|
||||
DevAssert(sctp_new_association_ind != NULL);
|
||||
instance_p = xnap_gNB_get_instance(instance);
|
||||
DevAssert(instance_p != NULL);
|
||||
xnap_gnb_data_p = xnap_get_gNB(instance_p, sctp_new_association_ind->assoc_id, -1);
|
||||
|
||||
if (xnap_gnb_data_p != NULL)
|
||||
abort();
|
||||
|
||||
// DevAssert(xnap_gnb_data_p != NULL);
|
||||
if (xnap_gnb_data_p == NULL) {
|
||||
/* Create new gNB descriptor */
|
||||
xnap_gnb_data_p = calloc(1, sizeof(*xnap_gnb_data_p));
|
||||
DevAssert(xnap_gnb_data_p != NULL);
|
||||
xnap_gnb_data_p->cnx_id = xnap_gNB_fetch_add_global_cnx_id();
|
||||
xnap_gnb_data_p->xnap_gNB_instance = instance_p;
|
||||
/* insert the new descriptor in list of known gNB
|
||||
* but not yet associated.
|
||||
*/
|
||||
// RB_INSERT(xnap_gnb_map, &instance_p->xnap_gnb_head, xnap_gnb_data_p);
|
||||
xnap_gnb_data_p->state = XNAP_GNB_STATE_CONNECTED;
|
||||
instance_p->xn_target_gnb_nb++;
|
||||
|
||||
if (instance_p->xn_target_gnb_pending_nb > 0) {
|
||||
instance_p->xn_target_gnb_pending_nb--;
|
||||
}
|
||||
} else {
|
||||
LOG_W(XNAP, "xnap_gnb_data_p already exists\n");
|
||||
}
|
||||
|
||||
printf("xnap_gNB_handle_sctp_association_ind at 2\n");
|
||||
xnap_dump_trees();
|
||||
/* Update parameters */
|
||||
xnap_gnb_data_p->assoc_id = sctp_new_association_ind->assoc_id;
|
||||
xnap_gnb_data_p->in_streams = sctp_new_association_ind->in_streams;
|
||||
xnap_gnb_data_p->out_streams = sctp_new_association_ind->out_streams;
|
||||
RB_INSERT(xnap_gnb_map, &instance_p->xnap_gnb_head, xnap_gnb_data_p);
|
||||
printf("xnap_gNB_handle_sctp_association_ind at 3\n");
|
||||
xnap_dump_trees();
|
||||
}
|
||||
|
||||
void *xnap_task(void *arg)
|
||||
{
|
||||
MessageDef *received_msg = NULL;
|
||||
int result;
|
||||
LOG_D(XNAP, "Starting XNAP layer\n");
|
||||
xnap_gNB_prepare_internal_data(); // management procedures
|
||||
itti_mark_task_ready(TASK_XNAP);
|
||||
|
||||
while (1) {
|
||||
itti_receive_msg(TASK_XNAP, &received_msg);
|
||||
LOG_D(XNAP, "Received message %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
|
||||
switch (ITTI_MSG_ID(received_msg)) {
|
||||
case TERMINATE_MESSAGE:
|
||||
LOG_W(XNAP, "Exiting XNAP thread\n");
|
||||
itti_exit_task();
|
||||
break;
|
||||
|
||||
case XNAP_REGISTER_GNB_REQ:
|
||||
xnap_gNB_handle_register_gNB(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &XNAP_REGISTER_GNB_REQ(received_msg));
|
||||
break;
|
||||
|
||||
case SCTP_INIT_MSG_MULTI_CNF:
|
||||
xnap_gNB_handle_sctp_init_msg_multi_cnf(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
|
||||
&received_msg->ittiMsg.sctp_init_msg_multi_cnf);
|
||||
break;
|
||||
|
||||
case SCTP_NEW_ASSOCIATION_RESP:
|
||||
xnap_gNB_handle_sctp_association_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
|
||||
&received_msg->ittiMsg.sctp_new_association_resp);
|
||||
break;
|
||||
|
||||
case SCTP_NEW_ASSOCIATION_IND:
|
||||
xnap_gNB_handle_sctp_association_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
|
||||
&received_msg->ittiMsg.sctp_new_association_ind);
|
||||
break;
|
||||
|
||||
case SCTP_DATA_IND:
|
||||
xnap_gNB_handle_sctp_data_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_data_ind);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(XNAP, "Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
|
||||
break;
|
||||
}
|
||||
|
||||
result = itti_free(ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
|
||||
AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||
received_msg = NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#include "common/config/config_userapi.h"
|
||||
|
||||
int is_xnap_enabled(void)
|
||||
{
|
||||
static volatile int config_loaded = 0;
|
||||
static volatile int enabled = 0;
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
if (pthread_mutex_lock(&mutex))
|
||||
goto mutex_error;
|
||||
if (config_loaded) {
|
||||
if (pthread_mutex_unlock(&mutex))
|
||||
goto mutex_error;
|
||||
return enabled;
|
||||
}
|
||||
|
||||
char *enable_xn = NULL;
|
||||
paramdef_t p[] = {{"enable_xn", "yes/no", 0, .strptr = &enable_xn, .defstrval = "", TYPE_STRING, 0}};
|
||||
|
||||
/* TODO: do it per module - we check only first gNB */
|
||||
config_get(p, sizeof(p) / sizeof(paramdef_t), "gNBs.[0]");
|
||||
if (enable_xn != NULL && strcmp(enable_xn, "yes") == 0) {
|
||||
enabled = 1;
|
||||
}
|
||||
|
||||
/*Consider also the case of enabling XnAP for a gNB by parsing a gNB configuration file*/
|
||||
|
||||
config_get(p, sizeof(p) / sizeof(paramdef_t), "gNBs.[0]");
|
||||
if (enable_xn != NULL && strcmp(enable_xn, "yes") == 0) {
|
||||
enabled = 1;
|
||||
}
|
||||
|
||||
config_loaded = 1;
|
||||
|
||||
if (pthread_mutex_unlock(&mutex))
|
||||
goto mutex_error;
|
||||
return enabled;
|
||||
|
||||
mutex_error:
|
||||
LOG_E(XNAP, "mutex error\n");
|
||||
exit(1);
|
||||
}
|
||||
46
openair2/XNAP/xnap_gNB_task.h
Normal file
46
openair2/XNAP/xnap_gNB_task.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* 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 <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/** @defgroup _xnap_impl_ X2AP Layer Reference Implementation
|
||||
* @ingroup _ref_implementation_
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef XNAP_H_
|
||||
#define XNAP_H_
|
||||
|
||||
#define XNAP_SCTP_PPID (61) ///< XNAP SCTP Payload Protocol Identifier (PPID)
|
||||
#include "xnap_gNB_defs.h"
|
||||
|
||||
int xnap_gNB_init_sctp(xnap_gNB_instance_t *instance_p, gnb_ip_address_t *local_ip_addr, uint32_t gnb_port_for_XNC);
|
||||
|
||||
void *xnap_task(void *arg);
|
||||
|
||||
int is_xnap_enabled(void);
|
||||
void xnap_trigger(void);
|
||||
|
||||
#endif /* XNAP_H_ */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
292
targets/PROJECTS/GENERIC-NR-5GC/CONF/Xnsetup_test.conf
Normal file
292
targets/PROJECTS/GENERIC-NR-5GC/CONF/Xnsetup_test.conf
Normal file
@@ -0,0 +1,292 @@
|
||||
Active_gNBs = ( "gNB-OAI");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
gNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
gNB_ID = 0xe00; //change gNB_ID for second gNB(XNAP)
|
||||
gNB_name = "gNB-OAI";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 0xa000;
|
||||
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1; }) });
|
||||
|
||||
nr_cellid = 12345678L;
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 1;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
#spCellConfigCommon
|
||||
|
||||
physCellId = 0;
|
||||
|
||||
# downlinkConfigCommon
|
||||
#frequencyInfoDL
|
||||
# this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP)
|
||||
absoluteFrequencySSB = 641280;
|
||||
dl_frequencyBand = 78;
|
||||
# this is 3600 MHz
|
||||
dl_absoluteFrequencyPointA = 640008;
|
||||
#scs-SpecificCarrierList
|
||||
dl_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
dl_subcarrierSpacing = 1;
|
||||
dl_carrierBandwidth = 106;
|
||||
#initialDownlinkBWP
|
||||
#genericParameters
|
||||
# this is RBstart=27,L=48 (275*(L-1))+RBstart
|
||||
initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952
|
||||
# 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 = 106;
|
||||
pMax = 20;
|
||||
#initialUplinkBWP
|
||||
#genericParameters
|
||||
initialULBWPlocationAndBandwidth = 28875;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialULBWPsubcarrierSpacing = 1;
|
||||
#rach-ConfigCommon
|
||||
#rach-ConfigGeneric
|
||||
prach_ConfigurationIndex = 98;
|
||||
#prach_msg1_FDM
|
||||
#0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM = 0;
|
||||
prach_msg1_FrequencyStart = 0;
|
||||
zeroCorrelationZoneConfig = 13;
|
||||
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 = 4;
|
||||
#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;
|
||||
#oneHalf (0..15) 4,8,12,16,...60,64
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14;
|
||||
#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,
|
||||
|
||||
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_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
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 = 6;
|
||||
nrofDownlinkSlots = 7;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
ssPBCH_BlockPower = -25;
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
|
||||
|
||||
////////// AMF parameters:
|
||||
amf_ip_address = ( { ipv4 = "192.168.70.132";
|
||||
ipv6 = "192:168:30::17";
|
||||
active = "yes";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
///Xn
|
||||
enable_xn = "yes";
|
||||
t_reloc_prep = 1000; /* unit: millisecond */
|
||||
txn_reloc_overall = 2000; /* unit: millisecond */
|
||||
t_dc_prep = 1000; /* unit: millisecond */
|
||||
t_dc_overall = 2000; /* unit: millisecond */
|
||||
target_gnb_xn_ip_address = (
|
||||
{ ipv4 = "10.33.42.107";
|
||||
ipv6 = "192:168:30::17";
|
||||
preference = "ipv4";
|
||||
},
|
||||
{ ipv4 = "10.33.42.213";
|
||||
ipv6 = "192:168:30::16";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
GNB_INTERFACE_NAME_FOR_NG_AMF = "enp3s0";
|
||||
GNB_IPV4_ADDRESS_FOR_NG_AMF = "10.33.42.216";
|
||||
GNB_INTERFACE_NAME_FOR_NGU = "enp3s0";
|
||||
GNB_IPV4_ADDRESS_FOR_NGU = "10.33.42.216";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
GNB_IPV4_ADDRESS_FOR_XNC = "10.33.42.216";
|
||||
GNB_PORT_FOR_XNC = 38422; # Spec 36422
|
||||
};
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
MACRLCs = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
pusch_TargetSNRx10 = 150;
|
||||
pucch_TargetSNRx10 = 200;
|
||||
ulsch_max_frame_inactivity = 0;
|
||||
ul_max_mcs = 28;
|
||||
}
|
||||
);
|
||||
|
||||
L1s = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
prach_dtx_threshold = 120;
|
||||
pucch0_dtx_threshold = 100;
|
||||
ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0
|
||||
}
|
||||
);
|
||||
|
||||
RUs = (
|
||||
{
|
||||
local_rf = "yes"
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 12;
|
||||
att_rx = 12;
|
||||
bands = [78];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 114;
|
||||
eNB_instances = [0];
|
||||
#beamforming 1x4 matrix:
|
||||
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||
clock_src = "internal";
|
||||
}
|
||||
);
|
||||
|
||||
THREAD_STRUCT = (
|
||||
{
|
||||
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
|
||||
parallel_config = "PARALLEL_SINGLE_THREAD";
|
||||
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
|
||||
worker_config = "WORKER_ENABLE";
|
||||
}
|
||||
);
|
||||
|
||||
rfsimulator :
|
||||
{
|
||||
serveraddr = "server";
|
||||
serverport = "4043";
|
||||
options = (); #("saviq"); or/and "chanmod"
|
||||
modelname = "AWGN";
|
||||
IQfile = "/tmp/rfsimulator.iqs";
|
||||
};
|
||||
|
||||
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 ="debug";
|
||||
f1ap_log_level ="debug";
|
||||
};
|
||||
|
||||
e2_agent = {
|
||||
near_ric_ip_addr = "127.0.0.1";
|
||||
#sm_dir = "/path/where/the/SMs/are/located/"
|
||||
sm_dir = "/usr/local/lib/flexric/"
|
||||
};
|
||||
Reference in New Issue
Block a user