mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
Compare commits
19 Commits
liteon_dev
...
iisc_draft
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
442093069c | ||
|
|
8346517407 | ||
|
|
9567a316c8 | ||
|
|
7a33605d9e | ||
|
|
8e2d468be7 | ||
|
|
f8607ae6c0 | ||
|
|
a108c03160 | ||
|
|
2c9a57f0a7 | ||
|
|
09c37d7b1f | ||
|
|
a601306ad0 | ||
|
|
63f23425ac | ||
|
|
e6d4e96d96 | ||
|
|
3ef7977429 | ||
|
|
6ac9597fbb | ||
|
|
922f070206 | ||
|
|
74dcd3c9d6 | ||
|
|
dfde5dc349 | ||
|
|
8d1f92597a | ||
|
|
665e3e3888 |
@@ -1458,7 +1458,7 @@ add_library(e1_if
|
||||
|
||||
target_link_libraries(e1_if PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs asn1_f1ap SECURITY ${OPENSSL_LIBRARIES} e1ap GTPV1U)
|
||||
|
||||
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_agent_arg e2_ran_func_du_cucp_cuup)
|
||||
target_compile_definitions(L2_NR PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT)
|
||||
|
||||
@@ -56,4 +56,5 @@ typedef enum { CPtype = 0, UPtype } E1_t;
|
||||
#define GTPV1_U_PORT_NUMBER (2152)
|
||||
|
||||
typedef enum { non_dynamic, dynamic } fiveQI_type_t;
|
||||
#define maxSRBs 4
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
# define NUMBER_OF_SRS_MAX 16
|
||||
# define NUMBER_OF_SCH_STATS_MAX 16
|
||||
|
||||
#define NUMBER_OF_DU_PER_CU_MAX 2
|
||||
#define MAX_MANAGED_ENB_PER_MOBILE 2
|
||||
#define MAX_MANAGED_GNB_PER_MOBILE 2
|
||||
|
||||
|
||||
@@ -155,6 +155,7 @@ extern "C" {
|
||||
COMP_DEF(USIM, log) \
|
||||
COMP_DEF(F1U, ) \
|
||||
COMP_DEF(X2AP, ) \
|
||||
COMP_DEF(XNAP, ) \
|
||||
COMP_DEF(M2AP, ) \
|
||||
COMP_DEF(M3AP, ) \
|
||||
COMP_DEF(NGAP, ) \
|
||||
|
||||
@@ -1240,6 +1240,27 @@ ID = LEGACY_E1AP_ERROR
|
||||
GROUP = ALL:LEGACY_E1AP:LEGACY_GROUP_ERROR:LEGACY
|
||||
FORMAT = string,log
|
||||
|
||||
ID = LEGACY_XNAP_TRACE
|
||||
DESC = XNAP TRACE LEVEL
|
||||
GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_TRACE:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_XNAP_DEBUG
|
||||
DESC = XNAP DEBUG LEVEL
|
||||
GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_DEBUG:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_XNAP_INFO
|
||||
DESC = XNAP INFO LEVEL
|
||||
GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_INFO:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_XNAP_WARNING
|
||||
DESC = XNAP WARNING LEVEL
|
||||
GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_WARNING:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_XNAP_ERROR
|
||||
DESC = XNAP ERROR LEVEL
|
||||
GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_ERROR:LEGACY
|
||||
FORMAT = string,log
|
||||
|
||||
#################
|
||||
#### UE LOGS ####
|
||||
#################
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -81,6 +81,7 @@ typedef struct IttiMsgText_s {
|
||||
#include <openair2/RRC/LTE/rrc_types.h>
|
||||
#include <openair2/COMMON/rrc_messages_types.h>
|
||||
#include <openair2/COMMON/e1ap_messages_types.h>
|
||||
#include <openair2/COMMON/xnap_messages_types.h>
|
||||
|
||||
#include <openair3/NAS/COMMON/UTIL/OctetString.h>
|
||||
#include <openair3/NAS/COMMON/IES/AccessPointName.h>
|
||||
@@ -298,6 +299,7 @@ typedef struct {
|
||||
TASK_DEF(TASK_S1AP, 200) \
|
||||
TASK_DEF(TASK_NGAP, 200) \
|
||||
TASK_DEF(TASK_X2AP, 200) \
|
||||
TASK_DEF(TASK_XNAP, 200) \
|
||||
TASK_DEF(TASK_M2AP_ENB, 200) \
|
||||
TASK_DEF(TASK_M2AP_MCE, 200) \
|
||||
TASK_DEF(TASK_M3AP, 200) \
|
||||
|
||||
@@ -371,6 +371,9 @@ typedef struct cu_to_du_rrc_information_s {
|
||||
uint32_t uE_CapabilityRAT_ContainerList_length;
|
||||
uint8_t * measConfig;
|
||||
uint32_t measConfig_length;
|
||||
uint8_t *handoverPreparationInfo;
|
||||
uint32_t handoverPreparationInfo_length;
|
||||
|
||||
}cu_to_du_rrc_information_t;
|
||||
|
||||
typedef struct du_to_cu_rrc_information_s {
|
||||
@@ -393,6 +396,13 @@ typedef enum ReconfigurationCompl_e {
|
||||
RRCreconf_success = 2,
|
||||
} ReconfigurationCompl_t;
|
||||
|
||||
|
||||
typedef enum TransmActionInd_e {
|
||||
TransmActionInd_STOP,
|
||||
TransmActionInd_RESTART,
|
||||
} TransmActionInd_t;
|
||||
|
||||
|
||||
typedef struct f1ap_ue_context_setup_s {
|
||||
uint32_t gNB_CU_ue_id;
|
||||
uint32_t gNB_DU_ue_id;
|
||||
@@ -423,6 +433,12 @@ typedef struct f1ap_ue_context_setup_s {
|
||||
ReconfigurationCompl_t ReconfigComplOutcome;
|
||||
uint8_t *rrc_container;
|
||||
int rrc_container_length;
|
||||
uint16_t mcc;
|
||||
uint16_t mnc;
|
||||
uint8_t mnc_digit_length;
|
||||
uint16_t *crnti;
|
||||
uint8_t *transmission_action_indicator;
|
||||
TransmActionInd_t *transm_action_ind;
|
||||
} f1ap_ue_context_setup_t, f1ap_ue_context_modif_req_t, f1ap_ue_context_modif_resp_t;
|
||||
|
||||
typedef enum F1ap_Cause_e {
|
||||
@@ -439,6 +455,7 @@ typedef struct f1ap_ue_context_modif_required_t {
|
||||
du_to_cu_rrc_information_t *du_to_cu_rrc_information;
|
||||
f1ap_Cause_t cause;
|
||||
long cause_value;
|
||||
uint8_t *transmission_action_indicator; //not sure
|
||||
} f1ap_ue_context_modif_required_t;
|
||||
|
||||
typedef struct f1ap_ue_context_modif_confirm_t {
|
||||
|
||||
40
openair2/COMMON/xnap_messages_def.h
Normal file
40
openair2/COMMON/xnap_messages_def.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "openair2/COMMON/xnap_messages_types.h"
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* 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)
|
||||
MESSAGE_DEF(XNAP_SETUP_FAILURE, MESSAGE_PRIORITY_MED, xnap_setup_failure_t, xnap_setup_failure)
|
||||
MESSAGE_DEF(XNAP_HANDOVER_REQ, MESSAGE_PRIORITY_MED, xnap_handover_req_t, xnap_handover_req)
|
||||
MESSAGE_DEF(XNAP_HANDOVER_REQ_FAILURE, MESSAGE_PRIORITY_MED, xnap_handover_req_failure_t, xnap_handover_req_failure)
|
||||
MESSAGE_DEF(XNAP_HANDOVER_REQ_ACK, MESSAGE_PRIORITY_MED, xnap_handover_req_ack_t, xnap_handover_req_ack)
|
||||
302
openair2/COMMON/xnap_messages_types.h
Normal file
302
openair2/COMMON/xnap_messages_types.h
Normal file
@@ -0,0 +1,302 @@
|
||||
/*
|
||||
* 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_
|
||||
|
||||
#include "s1ap_messages_types.h"
|
||||
#include "f1ap_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_SETUP_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.xnap_setup_failure
|
||||
#define XNAP_HANDOVER_REQ(mSGpTR) (mSGpTR)->ittiMsg.xnap_handover_req
|
||||
#define XNAP_HANDOVER_REQ_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.xnap_handover_req_failure
|
||||
#define XNAP_HANDOVER_REQ_ACK(mSGpTR) (mSGpTR)->ittiMsg.xnap_handover_req_ack
|
||||
|
||||
|
||||
#define XNAP_MAX_NB_GNB_IP_ADDRESS 4
|
||||
|
||||
// gNB application layer -> XNAP messages
|
||||
|
||||
typedef struct xnap_net_ip_address_s {
|
||||
unsigned ipv4:1;
|
||||
unsigned ipv6:1;
|
||||
char ipv4_address[16];
|
||||
char ipv6_address[46];
|
||||
} xnap_net_ip_address_t;
|
||||
|
||||
typedef struct xnap_sctp_s {
|
||||
uint16_t sctp_in_streams;
|
||||
uint16_t sctp_out_streams;
|
||||
} xnap_sctp_t;
|
||||
|
||||
typedef struct xnap_net_config_t {
|
||||
uint8_t nb_xn;
|
||||
xnap_net_ip_address_t gnb_xn_ip_address;
|
||||
xnap_net_ip_address_t target_gnb_xn_ip_address[XNAP_MAX_NB_GNB_IP_ADDRESS];
|
||||
uint32_t gnb_port_for_XNC;
|
||||
xnap_sctp_t sctp_streams;
|
||||
} xnap_net_config_t;
|
||||
|
||||
typedef struct xnap_plmn_t {
|
||||
uint16_t mcc;
|
||||
uint16_t mnc;
|
||||
uint8_t mnc_digit_length;
|
||||
} xnap_plmn_t;
|
||||
|
||||
typedef struct xnap_amf_regioninfo_s {
|
||||
uint16_t mcc;
|
||||
uint16_t mnc;
|
||||
uint8_t mnc_len;
|
||||
uint8_t amf_region_id;
|
||||
} xnap_amf_regioninfo_t;
|
||||
|
||||
typedef enum xnap_mode_t { XNAP_MODE_TDD = 0, XNAP_MODE_FDD = 1 } xnap_mode_t;
|
||||
|
||||
typedef struct xnap_nr_frequency_info_t {
|
||||
uint32_t arfcn;
|
||||
int band;
|
||||
} xnap_nr_frequency_info_t;
|
||||
|
||||
typedef struct xnap_transmission_bandwidth_t {
|
||||
uint8_t scs;
|
||||
uint16_t nrb;
|
||||
} xnap_transmission_bandwidth_t;
|
||||
|
||||
typedef struct xnap_fdd_info_t {
|
||||
xnap_nr_frequency_info_t ul_freqinfo;
|
||||
xnap_nr_frequency_info_t dl_freqinfo;
|
||||
xnap_transmission_bandwidth_t ul_tbw;
|
||||
xnap_transmission_bandwidth_t dl_tbw;
|
||||
} xnap_fdd_info_t;
|
||||
|
||||
typedef struct xnap_tdd_info_t {
|
||||
xnap_nr_frequency_info_t freqinfo;
|
||||
xnap_transmission_bandwidth_t tbw;
|
||||
} xnap_tdd_info_t;
|
||||
|
||||
typedef struct xnap_snssai_s {
|
||||
uint8_t sst;
|
||||
uint8_t sd;
|
||||
} xnap_snssai_t;
|
||||
|
||||
typedef struct xnap_served_cell_info_t {
|
||||
// NR CGI
|
||||
xnap_plmn_t plmn;
|
||||
uint64_t nr_cellid; // NR Global Cell Id
|
||||
uint16_t nr_pci;// NR Physical Cell Ids
|
||||
|
||||
/* Tracking area code */
|
||||
uint32_t tac;
|
||||
|
||||
xnap_mode_t mode;
|
||||
union {
|
||||
xnap_fdd_info_t fdd;
|
||||
xnap_tdd_info_t tdd;
|
||||
};
|
||||
|
||||
char *measurement_timing_information;
|
||||
} xnap_served_cell_info_t;
|
||||
|
||||
typedef struct xnap_setup_req_s {
|
||||
uint64_t gNB_id;
|
||||
/* Tracking area code */
|
||||
uint16_t num_tai;
|
||||
uint32_t tai_support;
|
||||
xnap_plmn_t plmn_support;
|
||||
// Number of slide support items
|
||||
uint16_t num_snssai;
|
||||
xnap_snssai_t snssai[2];
|
||||
xnap_amf_regioninfo_t amf_region_info;
|
||||
uint8_t num_cells_available;
|
||||
xnap_served_cell_info_t info;
|
||||
} xnap_setup_req_t;
|
||||
|
||||
typedef struct xnap_setup_resp_s {
|
||||
int64_t gNB_id;
|
||||
/* Tracking area code */
|
||||
uint16_t num_tai;
|
||||
uint32_t tai_support;
|
||||
xnap_plmn_t plmn_support;
|
||||
// Number of slide support items
|
||||
uint16_t num_ssi;
|
||||
uint8_t sst;
|
||||
uint8_t sd;
|
||||
uint16_t nb_xn;//number of gNBs connected
|
||||
xnap_served_cell_info_t info;
|
||||
} xnap_setup_resp_t;
|
||||
|
||||
typedef struct xnap_register_gnb_req_s {
|
||||
xnap_setup_req_t setup_req;
|
||||
xnap_net_config_t net_config;
|
||||
char *gNB_name;
|
||||
} xnap_register_gnb_req_t;
|
||||
|
||||
typedef enum xnap_Cause_e {
|
||||
XNAP_CAUSE_NOTHING, /* No components present */
|
||||
XNAP_CAUSE_RADIO_NETWORK,
|
||||
XNAP_CAUSE_TRANSPORT,
|
||||
XNAP_CAUSE_PROTOCOL,
|
||||
XNAP_CAUSE_MISC,
|
||||
} xnap_Cause_t;
|
||||
|
||||
typedef struct xnap_setup_failure_s {
|
||||
long cause_value;
|
||||
xnap_Cause_t cause_type;
|
||||
uint16_t time_to_wait;
|
||||
uint16_t criticality_diagnostics;
|
||||
} xnap_setup_failure_t;
|
||||
|
||||
typedef struct xnap_guami_s {
|
||||
xnap_plmn_t plmn_id;
|
||||
uint8_t amf_region_id;
|
||||
uint8_t amf_set_id;
|
||||
uint8_t amf_pointer;
|
||||
} xnap_guami_t;
|
||||
|
||||
typedef struct xnap_allocation_retention_priority_s {
|
||||
uint16_t priority_level;
|
||||
preemption_capability_t preemption_capability;
|
||||
preemption_vulnerability_t preemption_vulnerability;
|
||||
} xnap_allocation_retention_priority_t;
|
||||
|
||||
typedef struct xnap_qos_characteristics_s {
|
||||
union {
|
||||
struct {
|
||||
long fiveqi;
|
||||
long qos_priority_level;
|
||||
} non_dynamic;
|
||||
struct {
|
||||
long fiveqi; // -1 -> optional
|
||||
long qos_priority_level;
|
||||
long packet_delay_budget;
|
||||
struct {
|
||||
long per_scalar;
|
||||
long per_exponent;
|
||||
} packet_error_rate;
|
||||
} dynamic;
|
||||
};
|
||||
fiveQI_type_t qos_type;
|
||||
} xnap_qos_characteristics_t;
|
||||
|
||||
typedef struct xnap_qos_tobe_setup_item_s {
|
||||
long qfi;
|
||||
xnap_qos_characteristics_t qos_params;
|
||||
xnap_allocation_retention_priority_t allocation_retention_priority;
|
||||
} xnap_qos_tobe_setup_item_t;
|
||||
|
||||
typedef struct xnap_qos_tobe_setup_list_s {
|
||||
uint8_t num_qos;
|
||||
xnap_qos_tobe_setup_item_t qos[QOSFLOW_MAX_VALUE]; //QOSFLOW_MAX_VALUE= 64 Put this?
|
||||
} xnap_qos_tobe_setup_list_t;
|
||||
|
||||
typedef struct xnap_pdusession_tobe_setup_item_s {
|
||||
long pdusession_id;
|
||||
xnap_snssai_t snssai;
|
||||
xnap_net_ip_address_t up_ngu_tnl_ip_upf;
|
||||
teid_t up_ngu_tnl_teid_upf;
|
||||
pdu_session_type_t pdu_session_type;
|
||||
xnap_qos_tobe_setup_list_t qos_list;
|
||||
} xnap_pdusession_tobe_setup_item_t;
|
||||
|
||||
typedef struct xnap_pdusession_tobe_setup_list_s {
|
||||
uint8_t num_pdu;
|
||||
xnap_pdusession_tobe_setup_item_t pdu[NGAP_MAX_PDUSESSION]; //Is the limit ok?
|
||||
} xnap_pdusession_tobe_setup_list_t;
|
||||
|
||||
typedef struct xnap_ngran_cgi_t {
|
||||
xnap_plmn_t plmn_id;
|
||||
uint32_t cgi;
|
||||
} xnap_ngran_cgi_t;
|
||||
|
||||
typedef struct xnap_security_capabilities_s {
|
||||
uint16_t encryption_algorithms;
|
||||
uint16_t integrity_algorithms;
|
||||
} xnap_security_capabilities_t;
|
||||
|
||||
typedef struct xnap_ambr_s {
|
||||
uint64_t br_ul;
|
||||
uint64_t br_dl;
|
||||
} xnap_ambr_t;
|
||||
|
||||
typedef struct xnap_uehistory_info_s {
|
||||
xnap_ngran_cgi_t last_visited_cgi;
|
||||
cell_type_t cell_type; //enumerated -s1ap_messages_types.h
|
||||
uint64_t time_UE_StayedInCell;
|
||||
} xnap_uehistory_info_t; //38.413- 9.3.1.97
|
||||
|
||||
typedef struct xnap_ue_context_info_s {
|
||||
uint64_t ngc_ue_sig_ref;// 0-2^40-1
|
||||
xnap_net_ip_address_t tnl_ip_source;
|
||||
uint32_t tnl_port_source;
|
||||
xnap_security_capabilities_t security_capabilities;
|
||||
//uint8_t kRRCenc[16];
|
||||
//uint8_t kRRCint[16];
|
||||
uint32_t as_security_key_ranstar;//bitstring 256, why array?
|
||||
long as_security_ncc;
|
||||
xnap_ambr_t ue_ambr;
|
||||
uint8_t rrc_buffer[8192 /* arbitrary, big enough */];
|
||||
xnap_pdusession_tobe_setup_list_t pdusession_tobe_setup_list;
|
||||
int rrc_buffer_size;//rrc msg type needed?
|
||||
int target_assoc_id;
|
||||
uint8_t nb_e_rabs_tobesetup;
|
||||
} xnap_ue_context_info_t;
|
||||
|
||||
typedef struct xnap_handover_req_s {
|
||||
int ue_id; /* used for RRC->XNAP in source */
|
||||
//int xn_id; /* used for XNAP->RRC in target*/
|
||||
uint32_t s_ng_node_ue_xnap_id;
|
||||
uint32_t t_ng_node_ue_xnap_id;
|
||||
xnap_plmn_t plmn_id;
|
||||
xnap_Cause_t cause_type;
|
||||
xnap_ngran_cgi_t target_cgi;
|
||||
xnap_guami_t guami;
|
||||
xnap_ue_context_info_t ue_context;
|
||||
} xnap_handover_req_t;
|
||||
|
||||
typedef struct xnap_handover_req_ack_s {
|
||||
int ue_id;
|
||||
uint32_t s_ng_node_ue_xnap_id;
|
||||
uint32_t t_ng_node_ue_xnap_id;
|
||||
xnap_ngran_cgi_t target_cgi;
|
||||
xnap_plmn_t plmn_id;
|
||||
xnap_guami_t guami;
|
||||
xnap_ue_context_info_t ue_context;
|
||||
xnap_uehistory_info_t uehistory_info;
|
||||
uint8_t rrc_buffer[8192];
|
||||
int rrc_buffer_size;
|
||||
} xnap_handover_req_ack_t;
|
||||
|
||||
typedef struct xnap_handover_req_failure_s{
|
||||
uint32_t ng_node_ue_xnap_id;
|
||||
long cause_value;
|
||||
xnap_Cause_t cause_type;
|
||||
xnap_ngran_cgi_t target_cgi;
|
||||
}xnap_handover_req_failure_t;
|
||||
#endif /* XNAP_MESSAGES_TYPES_H_ */
|
||||
@@ -124,7 +124,7 @@ int CU_handle_F1_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint3
|
||||
if (servedCellInformation->fiveGS_TAC) {
|
||||
req->cell[i].info.tac = malloc(sizeof(*req->cell[i].info.tac));
|
||||
AssertFatal(req->cell[i].info.tac != NULL, "out of memory\n");
|
||||
OCTET_STRING_TO_INT16(servedCellInformation->fiveGS_TAC, *req->cell[i].info.tac);
|
||||
OCTET_STRING_TO_INT24(servedCellInformation->fiveGS_TAC, *req->cell[i].info.tac); //OCTET_STRING_TO_INT16(servedCellInformation->fiveGS_TAC, *req->cell[i].info.tac); - OAI
|
||||
LOG_D(F1AP, "req->tac[%d] %d \n", i, *req->cell[i].info.tac);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "f1ap_cu_task.h"
|
||||
#include <openair3/ocp-gtpu/gtp_itf.h>
|
||||
|
||||
|
||||
//Fixme: Uniq dirty DU instance, by global var, datamodel need better management
|
||||
instance_t CUuniqInstance=0;
|
||||
|
||||
@@ -118,6 +119,54 @@ static void cu_task_send_sctp_init_req(instance_t instance, char *my_addr) {
|
||||
itti_send_msg_to_task(TASK_SCTP, instance, message_p);
|
||||
}
|
||||
|
||||
void cu_register_xn(uint32_t gnb_id_num,f1ap_served_cell_info_t *cell , xnap_net_config_t nc);
|
||||
|
||||
void cu_register_xn(uint32_t gnb_id_num,f1ap_served_cell_info_t *cell , xnap_net_config_t nc)
|
||||
{
|
||||
MessageDef *msg;
|
||||
|
||||
for (uint32_t gnb_id = 0; (gnb_id < gnb_id_num); gnb_id++) {
|
||||
msg = itti_alloc_new_message(TASK_CU_F1, 0, XNAP_REGISTER_GNB_REQ);
|
||||
// uint64_t id;
|
||||
xnap_register_gnb_req_t *req = &XNAP_REGISTER_GNB_REQ(msg);
|
||||
req->setup_req.info.tac =(*cell->tac);
|
||||
req->setup_req.info.plmn.mcc = cell->plmn.mcc;
|
||||
req->setup_req.info.plmn.mnc = cell->plmn.mnc;
|
||||
req->setup_req.info.plmn.mnc_digit_length = cell->plmn.mnc_digit_length;
|
||||
req->setup_req.info.nr_cellid = cell->nr_cellid;
|
||||
req->setup_req.info.nr_pci = cell->nr_pci;
|
||||
if (cell->mode == F1AP_MODE_TDD) {
|
||||
req->setup_req.info.mode = XNAP_MODE_TDD;
|
||||
req->setup_req.info.tdd.freqinfo.arfcn = cell->tdd.freqinfo.arfcn;
|
||||
req->setup_req.info.tdd.tbw.scs = cell->tdd.tbw.scs;
|
||||
req->setup_req.info.tdd.tbw.nrb = cell->tdd.tbw.nrb;
|
||||
req->setup_req.info.tdd.freqinfo.band = cell->tdd.freqinfo.band;
|
||||
} else {
|
||||
req->setup_req.info.mode = XNAP_MODE_FDD;
|
||||
req->setup_req.info.fdd.dl_freqinfo.arfcn = cell->fdd.dl_freqinfo.arfcn;
|
||||
req->setup_req.info.fdd.ul_freqinfo.arfcn = cell->fdd.ul_freqinfo.arfcn;
|
||||
req->setup_req.info.fdd.dl_tbw.scs = cell->fdd.ul_tbw.scs;
|
||||
req->setup_req.info.fdd.ul_tbw.scs = cell->fdd.ul_tbw.scs;
|
||||
req->setup_req.info.fdd.dl_tbw.nrb = cell->fdd.dl_tbw.nrb;
|
||||
req->setup_req.info.fdd.ul_tbw.nrb = cell->fdd.ul_tbw.nrb;
|
||||
req->setup_req.info.fdd.dl_freqinfo.band = cell->fdd.dl_freqinfo.band;
|
||||
req->setup_req.info.fdd.ul_freqinfo.band = cell->fdd.ul_freqinfo.band;
|
||||
}
|
||||
req->setup_req.info.measurement_timing_information = cell->measurement_timing_information;
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[0];
|
||||
req->setup_req.gNB_id = rrc->node_id;
|
||||
req->setup_req.tai_support = *cell->tac;
|
||||
req->setup_req.plmn_support.mcc = cell->plmn.mcc;
|
||||
req->setup_req.plmn_support.mnc = cell->plmn.mnc;
|
||||
req->setup_req.plmn_support.mnc_digit_length = cell->plmn.mnc_digit_length;
|
||||
req->net_config = nc;
|
||||
req->gNB_name = rrc->node_name;
|
||||
void updateXninst(instance_t instanceP, xnap_setup_req_t *req, xnap_net_config_t *nc,sctp_assoc_t assoc_id);
|
||||
updateXninst(0, &req->setup_req,NULL,0);
|
||||
itti_send_msg_to_task(TASK_XNAP, GNB_MODULE_ID_TO_INSTANCE(gnb_id), msg);
|
||||
}
|
||||
}
|
||||
|
||||
void *F1AP_CU_task(void *arg) {
|
||||
MessageDef *received_msg = NULL;
|
||||
int result;
|
||||
|
||||
@@ -190,6 +190,7 @@ static void f1ap_write_flows_mapped(const f1ap_flows_mapped_to_drb_t *flows_mapp
|
||||
|
||||
int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setup_t *f1ap_ue_context_setup_req)
|
||||
{
|
||||
LOG_I(F1AP,"CU sending UE Context request");
|
||||
F1AP_F1AP_PDU_t pdu= {0};
|
||||
/* Create */
|
||||
/* 0. Message Type */
|
||||
@@ -272,8 +273,25 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu
|
||||
OCTET_STRING_fromBuf(measConfig, (const char*)f1ap_ue_context_setup_req->cu_to_du_rrc_information->measConfig,
|
||||
f1ap_ue_context_setup_req->cu_to_du_rrc_information->measConfig_length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* optional */
|
||||
/* HandoverPreparationInformation */
|
||||
if (f1ap_ue_context_setup_req->cu_to_du_rrc_information->handoverPreparationInfo_length > 0) {
|
||||
DevAssert(f1ap_ue_context_setup_req->cu_to_du_rrc_information->handoverPreparationInfo != NULL);
|
||||
F1AP_ProtocolExtensionContainer_10696P60_t *p = calloc(1, sizeof(*p));
|
||||
ie6->value.choice.CUtoDURRCInformation.iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p;
|
||||
asn1cSequenceAdd(p->list, F1AP_CUtoDURRCInformation_ExtIEs_t, ie_ext);
|
||||
ie_ext->id = F1AP_ProtocolIE_ID_id_HandoverPreparationInformation;
|
||||
ie_ext->criticality = F1AP_Criticality_ignore;
|
||||
ie_ext->extensionValue.present = F1AP_CUtoDURRCInformation_ExtIEs__extensionValue_PR_HandoverPreparationInformation;
|
||||
OCTET_STRING_fromBuf(&ie_ext->extensionValue.choice.HandoverPreparationInformation,
|
||||
(const char *)f1ap_ue_context_setup_req->cu_to_du_rrc_information->handoverPreparationInfo,
|
||||
f1ap_ue_context_setup_req->cu_to_du_rrc_information->handoverPreparationInfo_length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* mandatory */
|
||||
/* c7. Candidate_SpCell_List */
|
||||
@@ -574,12 +592,14 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu
|
||||
// return -1;
|
||||
// }
|
||||
LOG_D(F1AP,"F1AP UEContextSetupRequest Encoded %u bits\n", len);
|
||||
LOG_I(F1AP,"F1AP UEContextSetupRequest Encoded %u bits\n", len);
|
||||
f1ap_itti_send_sctp_data_req(assoc_id, buffer, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu)
|
||||
{
|
||||
LOG_I(F1AP,"CU_handle_UE_CONTEXT_SETUP_RESPONSE ");
|
||||
MessageDef *msg_p;
|
||||
F1AP_UEContextSetupResponse_t *container;
|
||||
F1AP_UEContextSetupResponseIEs_t *ie;
|
||||
@@ -599,6 +619,12 @@ int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_
|
||||
F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true);
|
||||
f1ap_ue_context_setup_resp->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID;
|
||||
LOG_D(F1AP, "f1ap_ue_context_setup_resp->gNB_DU_ue_id is: %d \n", f1ap_ue_context_setup_resp->gNB_DU_ue_id);
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, F1AP_ProtocolIE_ID_id_C_RNTI, false);
|
||||
if (ie) {
|
||||
f1ap_ue_context_setup_resp->crnti = calloc(1, sizeof(uint16_t));
|
||||
*f1ap_ue_context_setup_resp->crnti = ie->value.choice.C_RNTI;
|
||||
}
|
||||
|
||||
// DUtoCURRCInformation
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container,
|
||||
F1AP_ProtocolIE_ID_id_DUtoCURRCInformation, true);
|
||||
|
||||
@@ -117,6 +117,7 @@ static void f1ap_read_drb_nssai(const F1AP_SNSSAI_t *asn1_nssai, nssai_t *nssai)
|
||||
|
||||
int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu)
|
||||
{
|
||||
LOG_I(F1AP,"DU handling UE Context request");
|
||||
F1AP_UEContextSetupRequest_t *container;
|
||||
int i;
|
||||
DevAssert(pdu);
|
||||
@@ -129,11 +130,19 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_i
|
||||
F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true);
|
||||
f1ap_ue_context_setup_req->gNB_CU_ue_id = ieCU->value.choice.GNB_CU_UE_F1AP_ID;
|
||||
/* optional */
|
||||
/* GNB_DU_UE_F1AP_ID */
|
||||
/* GNB_DU_UE_F1AP_ID
|
||||
F1AP_UEContextSetupRequestIEs_t *ieDU_UE;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieDU_UE, container,
|
||||
F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true);
|
||||
f1ap_ue_context_setup_req->gNB_DU_ue_id = ieDU_UE->value.choice.GNB_DU_UE_F1AP_ID;
|
||||
f1ap_ue_context_setup_req->gNB_DU_ue_id = ieDU_UE->value.choice.GNB_DU_UE_F1AP_ID;*/
|
||||
|
||||
F1AP_UEContextSetupRequestIEs_t *ieDU_UE;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieDU_UE, container,
|
||||
F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, false);
|
||||
f1ap_ue_context_setup_req->gNB_DU_ue_id = 0;
|
||||
if (ieDU_UE != NULL)
|
||||
f1ap_ue_context_setup_req->gNB_DU_ue_id = ieDU_UE->value.choice.GNB_DU_UE_F1AP_ID;
|
||||
|
||||
|
||||
/* SpCell_ID */
|
||||
F1AP_UEContextSetupRequestIEs_t *ieNet;
|
||||
@@ -170,14 +179,36 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_i
|
||||
F1AP_ProtocolIE_ID_id_CUtoDURRCInformation, false);
|
||||
if(ieCuRrcInfo!=NULL){
|
||||
f1ap_ue_context_setup_req->cu_to_du_rrc_information = (cu_to_du_rrc_information_t *)calloc(1,sizeof(cu_to_du_rrc_information_t));
|
||||
cu_to_du_rrc_information_t *cu2du = f1ap_ue_context_setup_req->cu_to_du_rrc_information;
|
||||
const F1AP_CUtoDURRCInformation_t *cu2duie = &ieCuRrcInfo->value.choice.CUtoDURRCInformation;
|
||||
if(ieCuRrcInfo->value.choice.CUtoDURRCInformation.uE_CapabilityRAT_ContainerList!=NULL){
|
||||
f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList = (uint8_t *)calloc(1,ieCuRrcInfo->value.choice.CUtoDURRCInformation.uE_CapabilityRAT_ContainerList->size);
|
||||
memcpy(f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList, ieCuRrcInfo->value.choice.CUtoDURRCInformation.uE_CapabilityRAT_ContainerList->buf, ieCuRrcInfo->value.choice.CUtoDURRCInformation.uE_CapabilityRAT_ContainerList->size);
|
||||
f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length = ieCuRrcInfo->value.choice.CUtoDURRCInformation.uE_CapabilityRAT_ContainerList->size;
|
||||
LOG_D(F1AP, "Size f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length: %d \n", f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length);
|
||||
}
|
||||
if (cu2duie->iE_Extensions != NULL) {
|
||||
const F1AP_ProtocolExtensionContainer_10696P60_t *ext = (const F1AP_ProtocolExtensionContainer_10696P60_t *)cu2duie->iE_Extensions;
|
||||
for (int i = 0; i < ext->list.count; ++i) {
|
||||
const F1AP_CUtoDURRCInformation_ExtIEs_t *cu2du_info = ext->list.array[i];
|
||||
switch (cu2du_info->id) {
|
||||
case F1AP_ProtocolIE_ID_id_HandoverPreparationInformation:
|
||||
DevAssert(cu2du_info->extensionValue.present == F1AP_CUtoDURRCInformation_ExtIEs__extensionValue_PR_HandoverPreparationInformation);
|
||||
const F1AP_HandoverPreparationInformation_t *hopi = &cu2du_info->extensionValue.choice.MeasurementTimingConfiguration;
|
||||
cu2du->handoverPreparationInfo = calloc(1, hopi->size);
|
||||
AssertFatal(cu2du->handoverPreparationInfo != NULL, "out of memory\n");
|
||||
memcpy(cu2du->handoverPreparationInfo, hopi->buf, hopi->size);
|
||||
cu2du->handoverPreparationInfo_length = hopi->size;
|
||||
break;
|
||||
default:
|
||||
LOG_W(F1AP, "unsupported CUtoDURRCInformation_ExtIE %ld encountered, ignoring\n", cu2du_info->id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* DRB */
|
||||
F1AP_UEContextSetupRequestIEs_t *ieDrb;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieDrb, container,
|
||||
@@ -288,13 +319,14 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_i
|
||||
} else {
|
||||
LOG_W(F1AP, "can't find RRCContainer in UEContextSetupRequestIEs by id %ld \n", F1AP_ProtocolIE_ID_id_RRCContainer);
|
||||
}
|
||||
|
||||
LOG_I(F1AP, "F1AP UE context setup handled in DU\n");
|
||||
ue_context_setup_request(f1ap_ue_context_setup_req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_setup_t *resp)
|
||||
{
|
||||
LOG_I(F1AP, "F1AP UE context setup resp in DU");
|
||||
F1AP_F1AP_PDU_t pdu= {0};
|
||||
F1AP_UEContextSetupResponse_t *out;
|
||||
uint8_t *buffer=NULL;
|
||||
@@ -321,7 +353,7 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_set
|
||||
ie2->criticality = F1AP_Criticality_reject;
|
||||
ie2->value.present = F1AP_UEContextSetupResponseIEs__value_PR_GNB_DU_UE_F1AP_ID;
|
||||
ie2->value.choice.GNB_DU_UE_F1AP_ID = resp->gNB_DU_ue_id;
|
||||
|
||||
LOG_I(F1AP,"DU UE ID in DU_send_UE_CONTEXT_SETUP_RESPONSE %d\n", resp->gNB_DU_ue_id);
|
||||
/* mandatory */
|
||||
/* c3. DUtoCURRCInformation */
|
||||
if(resp->du_to_cu_rrc_information){
|
||||
@@ -352,15 +384,18 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_set
|
||||
|
||||
/* optional */
|
||||
/* c4. C_RNTI */
|
||||
if (0) {
|
||||
if (resp->crnti!=NULL) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie4);
|
||||
ie4->id = F1AP_ProtocolIE_ID_id_C_RNTI;
|
||||
ie4->criticality = F1AP_Criticality_ignore;
|
||||
ie4->value.present = F1AP_UEContextSetupResponseIEs__value_PR_C_RNTI;
|
||||
ie4->value.choice.C_RNTI = *resp->crnti;
|
||||
LOG_I(F1AP,"rnti in DU_send_UE_CONTEXT_SETUP_RESPONSE %d\n", *resp->crnti);
|
||||
|
||||
//C_RNTI_TO_BIT_STRING(rntiP, &ie->value.choice.C_RNTI);
|
||||
ie4->value.choice.C_RNTI=0;
|
||||
AssertFatal(false, "not implemented\n");
|
||||
LOG_E(F1AP,"RNTI to code!\n");
|
||||
//ie4->value.choice.C_RNTI=0;
|
||||
// AssertFatal(false, "not implemented\n");
|
||||
// LOG_E(F1AP,"RNTI to code!\n");
|
||||
}
|
||||
|
||||
/* optional */
|
||||
|
||||
@@ -53,6 +53,8 @@
|
||||
#include "openair2/E1AP/e1ap.h"
|
||||
#include "gnb_config.h"
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "openair2/XNAP/xnap_gNB_task.h"
|
||||
#include "openair2/XNAP/xnap_gNB_management_procedures.h"
|
||||
|
||||
extern unsigned char NB_gNB_INST;
|
||||
|
||||
@@ -154,6 +156,17 @@ void *gNB_app_task(void *args_p)
|
||||
itti_send_msg_to_task(TASK_CUCP_E1, 0, msg);
|
||||
}
|
||||
|
||||
if (is_xnap_enabled()) {
|
||||
if (itti_create_task(TASK_XNAP, xnap_task, NULL) < 0) {
|
||||
LOG_E(XNAP, "Create task for XNAP failed\n");
|
||||
}
|
||||
xnap_net_config_t xn_net_config = Read_IPconfig_Xn();
|
||||
createXninst(0, NULL, &xn_net_config);
|
||||
|
||||
} else {
|
||||
LOG_I(XNAP, "XNAP is disabled.\n");
|
||||
}
|
||||
|
||||
if (node_type == ngran_gNB_CUUP) {
|
||||
AssertFatal(false, "To run CU-UP use executable nr-cuup\n");
|
||||
}
|
||||
|
||||
@@ -2239,6 +2239,70 @@ int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_up
|
||||
return(ret);
|
||||
}
|
||||
|
||||
xnap_net_config_t Read_IPconfig_Xn(void)
|
||||
{
|
||||
char *cidr = NULL;
|
||||
char *address = NULL;
|
||||
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;
|
||||
xnap_net_config_t nc = {0};
|
||||
paramdef_t XnParams[] = XnPARAMS_DESC;
|
||||
paramlist_def_t XnParamList = {GNB_CONFIG_STRING_TARGET_GNB_Xn_IP_ADDRESS, NULL, 0};
|
||||
paramdef_t NETParams[] = GNBNETPARAMS_DESC;
|
||||
paramdef_t SCTPParams[] = GNBSCTPPARAMS_DESC;
|
||||
char aprefix[MAX_OPTNAME_SIZE * 2 + 8];
|
||||
config_getlist(config_get_if(), &XnParamList, XnParams, sizeofArray(XnParams), 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);
|
||||
for (int l = 0; l < XnParamList.numelt; l++) {
|
||||
nc.nb_xn += 1;
|
||||
strcpy(nc.target_gnb_xn_ip_address[l].ipv4_address, *(XnParamList.paramarray[l][GNB_Xn_IPV4_ADDRESS_IDX].strptr));
|
||||
strcpy(nc.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) {
|
||||
nc.target_gnb_xn_ip_address[l].ipv4 = 1;
|
||||
nc.target_gnb_xn_ip_address[l].ipv6 = 0;
|
||||
} else if (strcmp(*(XnParamList.paramarray[l][GNB_Xn_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv6") == 0) {
|
||||
nc.target_gnb_xn_ip_address[l].ipv4 = 0;
|
||||
nc.target_gnb_xn_ip_address[l].ipv6 = 1;
|
||||
} else if (strcmp(*(XnParamList.paramarray[l][GNB_Xn_IP_ADDRESS_PREFERENCE_IDX].strptr), "no") == 0) {
|
||||
nc.target_gnb_xn_ip_address[l].ipv4 = 1;
|
||||
nc.target_gnb_xn_ip_address[l].ipv6 = 1;
|
||||
}
|
||||
}
|
||||
sprintf(aprefix, "%s.[%i].%s", GNB_CONFIG_STRING_GNB_LIST, 0, GNB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
|
||||
// NETWORK_INTERFACES
|
||||
config_get(config_get_if(), NETParams, sizeofArray(NETParams), aprefix);
|
||||
nc.gnb_port_for_XNC = (uint32_t) * (NETParams[GNB_PORT_FOR_XNC_IDX].uptr);
|
||||
if ((NETParams[GNB_IPV4_ADDR_FOR_XNC_IDX].strptr == NULL) || (nc.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);
|
||||
nc.gnb_xn_ip_address.ipv6 = 0;
|
||||
nc.gnb_xn_ip_address.ipv4 = 1;
|
||||
strcpy(nc.gnb_xn_ip_address.ipv4_address, address);
|
||||
|
||||
// SCTP SETTING
|
||||
nc.sctp_streams.sctp_out_streams = SCTP_OUT_STREAMS;
|
||||
nc.sctp_streams.sctp_in_streams = SCTP_IN_STREAMS;
|
||||
if (get_softmodem_params()->sa) {
|
||||
// sprintf(aprefix, "%s.[%i].%s", GNB_CONFIG_STRING_GNB_LIST, 0, GNB_CONFIG_STRING_SCTP_CONFIG);
|
||||
config_get(config_get_if(), SCTPParams, sizeofArray(SCTPParams), aprefix);
|
||||
nc.sctp_streams.sctp_in_streams = (uint16_t) * (SCTPParams[GNB_SCTP_INSTREAMS_IDX].uptr);
|
||||
nc.sctp_streams.sctp_out_streams = (uint16_t) * (SCTPParams[GNB_SCTP_OUTSTREAMS_IDX].uptr);
|
||||
}
|
||||
return nc;
|
||||
}
|
||||
|
||||
|
||||
ngran_node_t get_node_type(void)
|
||||
{
|
||||
paramdef_t MacRLC_Params[] = MACRLCPARAMS_DESC;
|
||||
|
||||
@@ -109,6 +109,7 @@ 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);
|
||||
MessageDef *RCconfig_NR_CU_E1(const E1_t *entity);
|
||||
ngran_node_t get_node_type(void);
|
||||
xnap_net_config_t Read_IPconfig_Xn(void);
|
||||
|
||||
#ifdef E2_AGENT
|
||||
#include "openair2/E2AP/e2_agent_arg.h"
|
||||
|
||||
@@ -131,6 +131,7 @@ typedef enum {
|
||||
#define GNB_CONFIG_STRING_GNB_DU_ID "gNB_DU_ID"
|
||||
#define GNB_CONFIG_STRING_GNB_CU_UP_ID "gNB_CU_UP_ID"
|
||||
|
||||
#define GNB_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_HLP_STRING_DRBS "Number of total DRBs to establish, including the mandatory for PDU SEssion (default=1)\n"
|
||||
@@ -345,6 +346,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"
|
||||
@@ -363,6 +366,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 */
|
||||
@@ -375,6 +382,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} \
|
||||
@@ -382,6 +391,29 @@ 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 */
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#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}, \
|
||||
}
|
||||
|
||||
#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"
|
||||
|
||||
|
||||
@@ -3151,3 +3151,29 @@ void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_
|
||||
};
|
||||
nrmac->mac_rrc.ue_context_modification_required(&required);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const NR_RA_t *find_nr_RA_rnti(const NR_RA_t *ra_base, int ra_count, rnti_t rnti)
|
||||
{
|
||||
for (int i = 0; i < ra_count; ++i) {
|
||||
const NR_RA_t *ra = &ra_base[i];
|
||||
if (ra->ra_state != nrRA_gNB_IDLE && ra->rnti == rnti)
|
||||
return ra;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool nr_mac_get_new_rnti(NR_UEs_t *UEs, const NR_RA_t *ra_base, int ra_count, rnti_t *rnti)
|
||||
{
|
||||
int loop = 0;
|
||||
bool exist_connected_ue, exist_in_pending_ra_ue;
|
||||
do {
|
||||
*rnti = (taus() % 0xffef) + 1;
|
||||
exist_connected_ue = find_nr_UE(UEs, *rnti) != NULL;
|
||||
exist_in_pending_ra_ue = find_nr_RA_rnti(ra_base, ra_count, *rnti) != NULL;
|
||||
loop++;
|
||||
} while (loop < 100 && (exist_connected_ue || exist_in_pending_ra_ue));
|
||||
return loop < 100; // nothing found: loop count 100
|
||||
}
|
||||
|
||||
|
||||
@@ -442,4 +442,6 @@ void nr_mac_check_ul_failure(const gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ct
|
||||
|
||||
void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_t *UE);
|
||||
|
||||
|
||||
bool nr_mac_get_new_rnti(NR_UEs_t *UEs, const NR_RA_t *ra_base, int ra_count, rnti_t *rnti);
|
||||
#endif /*__LAYER2_NR_MAC_PROTO_H__*/
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "uper_decoder.h"
|
||||
#include "uper_encoder.h"
|
||||
#include "NR_HandoverPreparationInformation.h"
|
||||
|
||||
// Standarized 5QI values and Default Priority levels as mentioned in 3GPP TS 23.501 Table 5.7.4-1
|
||||
const uint64_t qos_fiveqi[26] = {1, 2, 3, 4, 65, 66, 67, 71, 72, 73, 74, 76, 5, 6, 7, 8, 9, 69, 70, 79, 80, 82, 83, 84, 85, 86};
|
||||
@@ -371,10 +372,10 @@ static void set_QoSConfig(const f1ap_ue_context_modif_req_t *req, NR_UE_sched_ct
|
||||
}
|
||||
}
|
||||
|
||||
void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
/*void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
{
|
||||
gNB_MAC_INST *mac = RC.nrmac[0];
|
||||
/* response has same type as request... */
|
||||
// response has same type as request...
|
||||
f1ap_ue_context_setup_t resp = {
|
||||
.gNB_CU_ue_id = req->gNB_CU_ue_id,
|
||||
.gNB_DU_ue_id = req->gNB_DU_ue_id,
|
||||
@@ -433,17 +434,202 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
AssertFatal(enc_rval.encoded > 0, "Could not encode CellGroup, failed element %s\n", enc_rval.failed_type->name);
|
||||
resp.du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded + 7) >> 3;
|
||||
|
||||
/* TODO: need to apply after UE context reconfiguration confirmed? */
|
||||
// TODO: need to apply after UE context reconfiguration confirmed?
|
||||
nr_mac_prepare_cellgroup_update(mac, UE, new_CellGroup);
|
||||
|
||||
/* Fill the QoS config in MAC for each active DRB */
|
||||
// Fill the QoS config in MAC for each active DRB
|
||||
set_QoSConfig(req, &UE->UE_sched_ctrl);
|
||||
|
||||
/* Set NSSAI config in MAC for each active DRB */
|
||||
// Set NSSAI config in MAC for each active DRB
|
||||
set_nssaiConfig(req->drbs_to_be_setup_length, req->drbs_to_be_setup, &UE->UE_sched_ctrl);
|
||||
|
||||
NR_SCHED_UNLOCK(&mac->sched_lock);
|
||||
|
||||
// some sanity checks, since we use the same type for request and response
|
||||
DevAssert(resp.cu_to_du_rrc_information == NULL);
|
||||
DevAssert(resp.du_to_cu_rrc_information != NULL);
|
||||
DevAssert(resp.rrc_container == NULL && resp.rrc_container_length == 0);
|
||||
|
||||
mac->mac_rrc.ue_context_setup_response(req, &resp);
|
||||
|
||||
// free the memory we allocated above
|
||||
free(resp.srbs_to_be_setup);
|
||||
free(resp.drbs_to_be_setup);
|
||||
free(resp.du_to_cu_rrc_information->cellGroupConfig);
|
||||
free(resp.du_to_cu_rrc_information);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
static NR_UE_NR_Capability_t *get_nr_cap(const NR_UE_CapabilityRAT_ContainerList_t *clist)
|
||||
{
|
||||
for (int i = 0; i < clist->list.count; i++) {
|
||||
const NR_UE_CapabilityRAT_Container_t *c = clist->list.array[i];
|
||||
if (c->rat_Type != NR_RAT_Type_nr) {
|
||||
LOG_W(NR_MAC, "ignoring capability of type %ld\n", c->rat_Type);
|
||||
continue;
|
||||
}
|
||||
|
||||
NR_UE_NR_Capability_t *cap = NULL;
|
||||
asn_dec_rval_t dec_rval = uper_decode(NULL,
|
||||
&asn_DEF_NR_UE_NR_Capability,
|
||||
(void **)&cap,
|
||||
c->ue_CapabilityRAT_Container.buf,
|
||||
c->ue_CapabilityRAT_Container.size,
|
||||
0,
|
||||
0);
|
||||
if (dec_rval.code != RC_OK) {
|
||||
LOG_W(NR_MAC, "cannot decode NR UE capability, ignoring\n");
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, cap);
|
||||
continue;
|
||||
}
|
||||
return cap;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static NR_UE_NR_Capability_t *get_ue_nr_cap_from_ho_prep_info(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
if (buf == NULL || len == 0)
|
||||
return NULL;
|
||||
NR_HandoverPreparationInformation_t *hpi = NULL;
|
||||
asn_dec_rval_t dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_HandoverPreparationInformation, (void **)&hpi, buf, len);
|
||||
if (dec_rval.code != RC_OK) {
|
||||
LOG_W(NR_MAC, "cannot decode HandoverPreparationInformation, ignoring capabilities\n");
|
||||
return NULL;
|
||||
}
|
||||
NR_UE_NR_Capability_t *cap = NULL;
|
||||
if (hpi->criticalExtensions.present != NR_HandoverPreparationInformation__criticalExtensions_PR_c1
|
||||
|| hpi->criticalExtensions.choice.c1 == NULL
|
||||
|| hpi->criticalExtensions.choice.c1->present
|
||||
!= NR_HandoverPreparationInformation__criticalExtensions__c1_PR_handoverPreparationInformation
|
||||
|| hpi->criticalExtensions.choice.c1->choice.handoverPreparationInformation == NULL) {
|
||||
} else {
|
||||
const NR_HandoverPreparationInformation_IEs_t *hpi_ie = hpi->criticalExtensions.choice.c1->choice.handoverPreparationInformation;
|
||||
cap = get_nr_cap(&hpi_ie->ue_CapabilityRAT_List);
|
||||
}
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_HandoverPreparationInformation, hpi);
|
||||
return cap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static NR_UE_info_t *create_new_UE_handover(gNB_MAC_INST *mac, uint32_t cu_id)
|
||||
{
|
||||
int CC_id = 0;
|
||||
const NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
|
||||
rnti_t rnti;
|
||||
bool found = nr_mac_get_new_rnti(&mac->UE_info, cc->ra, sizeofArray(cc->ra), &rnti);
|
||||
if (!found)
|
||||
return NULL;
|
||||
|
||||
NR_UE_info_t* UE = add_new_nr_ue(mac, rnti, NULL);
|
||||
if (!UE)
|
||||
return NULL;
|
||||
|
||||
f1_ue_data_t new_ue_data = {.secondary_ue = cu_id};
|
||||
du_add_f1_ue_data(rnti, &new_ue_data);
|
||||
|
||||
const NR_ServingCellConfigCommon_t *scc = mac->common_channels[CC_id].ServingCellConfigCommon;
|
||||
const NR_ServingCellConfig_t *sccd = mac->common_channels[CC_id].pre_ServingCellConfig;
|
||||
NR_CellGroupConfig_t *cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, sccd, &mac->radio_config);
|
||||
// note: we don't pass it to add_new_nr_ue() because the internal logic is
|
||||
// such that we then assume having received the ack of Msg4 (which is not the
|
||||
// case)
|
||||
UE->Msg4_ACKed = true;
|
||||
UE->CellGroup = cellGroupConfig;
|
||||
UE->CellGroup->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc);
|
||||
nr_rlc_activate_srb0(UE->rnti, UE, NULL);
|
||||
|
||||
nr_mac_prepare_ra_ue(mac, rnti, UE->CellGroup);
|
||||
return UE;
|
||||
}
|
||||
|
||||
|
||||
void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
{
|
||||
LOG_I(NR_MAC,"UE Context request IN MAC");
|
||||
gNB_MAC_INST *mac = RC.nrmac[0];
|
||||
/* response has same type as request... */
|
||||
f1ap_ue_context_setup_t resp = {
|
||||
.gNB_CU_ue_id = req->gNB_CU_ue_id,
|
||||
.gNB_DU_ue_id = req->gNB_DU_ue_id,
|
||||
};
|
||||
|
||||
/* this is a hack, it should be decided depending on if req->gNB_DU_ue_id is
|
||||
* present or not (because in F1, it's optional, but not in our structures) */
|
||||
bool handover = false;
|
||||
|
||||
NR_UE_NR_Capability_t *ue_cap = NULL;
|
||||
if (req->cu_to_du_rrc_information != NULL) {
|
||||
const cu_to_du_rrc_information_t *cu2du = req->cu_to_du_rrc_information;
|
||||
AssertFatal(cu2du->cG_ConfigInfo == NULL, "CG-ConfigInfo not handled\n");
|
||||
if (cu2du->handoverPreparationInfo != NULL) {
|
||||
handover = true;
|
||||
ue_cap = get_ue_nr_cap_from_ho_prep_info(cu2du->handoverPreparationInfo, cu2du->handoverPreparationInfo_length);
|
||||
} else if (cu2du->uE_CapabilityRAT_ContainerList != NULL) {
|
||||
ue_cap = get_ue_nr_cap(req->gNB_DU_ue_id, cu2du->uE_CapabilityRAT_ContainerList, cu2du->uE_CapabilityRAT_ContainerList_length);
|
||||
}
|
||||
AssertFatal(cu2du->measConfig == NULL, "MeasConfig not handled\n");
|
||||
}
|
||||
|
||||
NR_SCHED_LOCK(&mac->sched_lock);
|
||||
|
||||
NR_UE_info_t *UE = NULL;
|
||||
if (handover) {
|
||||
UE = create_new_UE_handover(mac, req->gNB_CU_ue_id);
|
||||
LOG_I(F1AP,"UE RNTI in ue_context_setup_request %d\n",UE->rnti );
|
||||
resp.gNB_DU_ue_id = UE->rnti;
|
||||
resp.crnti = &UE->rnti;
|
||||
} else {
|
||||
UE = find_nr_UE(&mac->UE_info, req->gNB_DU_ue_id);
|
||||
}
|
||||
AssertFatal(UE, "no UE found or could not be created, but UE Context Setup Failed not implemented\n");
|
||||
|
||||
NR_CellGroupConfig_t *new_CellGroup = clone_CellGroupConfig(UE->CellGroup);
|
||||
|
||||
if (req->srbs_to_be_setup_length > 0) {
|
||||
resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(UE,
|
||||
req->srbs_to_be_setup_length,
|
||||
req->srbs_to_be_setup,
|
||||
&resp.srbs_to_be_setup,
|
||||
new_CellGroup);
|
||||
}
|
||||
|
||||
if (req->drbs_to_be_setup_length > 0) {
|
||||
resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(UE,
|
||||
req->drbs_to_be_setup_length,
|
||||
req->drbs_to_be_setup,
|
||||
&resp.drbs_to_be_setup,
|
||||
new_CellGroup);
|
||||
}
|
||||
|
||||
if (req->rrc_container != NULL) {
|
||||
logical_chan_id_t id = 1;
|
||||
nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, id, req->rrc_container, req->rrc_container_length);
|
||||
}
|
||||
|
||||
UE->capability = ue_cap;
|
||||
if (ue_cap != NULL) {
|
||||
// store the new UE capabilities, and update the cellGroupConfig
|
||||
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
|
||||
update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc);
|
||||
}
|
||||
|
||||
resp.du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t));
|
||||
AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n");
|
||||
resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1,1024);
|
||||
AssertFatal(resp.du_to_cu_rrc_information->cellGroupConfig != NULL, "out of memory\n");
|
||||
asn_enc_rval_t enc_rval =
|
||||
uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, new_CellGroup, resp.du_to_cu_rrc_information->cellGroupConfig, 1024);
|
||||
AssertFatal(enc_rval.encoded > 0, "Could not encode CellGroup, failed element %s\n", enc_rval.failed_type->name);
|
||||
resp.du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded + 7) >> 3;
|
||||
|
||||
nr_mac_prepare_cellgroup_update(mac, UE, new_CellGroup);
|
||||
|
||||
NR_SCHED_UNLOCK(&mac->sched_lock);
|
||||
|
||||
/* some sanity checks, since we use the same type for request and response */
|
||||
DevAssert(resp.cu_to_du_rrc_information == NULL);
|
||||
DevAssert(resp.du_to_cu_rrc_information != NULL);
|
||||
@@ -458,6 +644,7 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
free(resp.du_to_cu_rrc_information);
|
||||
}
|
||||
|
||||
|
||||
void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
|
||||
{
|
||||
gNB_MAC_INST *mac = RC.nrmac[0];
|
||||
|
||||
@@ -102,6 +102,7 @@ static void f1_setup_request_f1ap(const f1ap_setup_req_t *req)
|
||||
|
||||
static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp)
|
||||
{
|
||||
LOG_I(GNB_APP,"UE Context response f1ap");
|
||||
DevAssert(req->drbs_to_be_setup_length == resp->drbs_to_be_setup_length);
|
||||
|
||||
DevAssert(req->srbs_to_be_setup_length == resp->srbs_to_be_setup_length);
|
||||
@@ -124,6 +125,15 @@ static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *req, c
|
||||
for (int i = 0; i < f1ap_msg->drbs_to_be_setup_length; ++i)
|
||||
f1ap_msg->drbs_to_be_setup[i] = resp->drbs_to_be_setup[i];
|
||||
}
|
||||
// LOG_I(GNB_APP,"resp crnti in ue_context_setup_response_f1ap %d\n",*resp->crnti);
|
||||
if (resp->crnti) {
|
||||
|
||||
LOG_I(GNB_APP,"resp crnti in ue_context_setup_response_f1ap and not null %d\n",*resp->crnti);
|
||||
LOG_I(GNB_APP,"resp crnti in ue_context_setup_response_f1ap and not null %p\n",*resp->crnti);
|
||||
f1ap_msg->crnti = calloc(1, sizeof(uint16_t));
|
||||
*f1ap_msg->crnti = *resp->crnti;
|
||||
}
|
||||
|
||||
|
||||
f1ap_msg->du_to_cu_rrc_information = malloc(sizeof(*resp->du_to_cu_rrc_information));
|
||||
AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n");
|
||||
|
||||
@@ -143,6 +143,11 @@
|
||||
#include "common/ran_context.h"
|
||||
#include "conversions.h"
|
||||
|
||||
#include "cmake_targets/ran_build/build/openair2/RRC/NR/MESSAGES/NR_HandoverPreparationInformation.h"
|
||||
#include "cmake_targets/ran_build/build/openair2/RRC/NR/MESSAGES/NR_HandoverPreparationInformation-IEs.h"
|
||||
#include "cmake_targets/ran_build/build/openair2/RRC/NR/MESSAGES/NR_UE-CapabilityRAT-Container.h"
|
||||
#include "NR_HandoverCommand.h"
|
||||
|
||||
//#define XER_PRINT
|
||||
|
||||
typedef struct xer_sprint_string_s {
|
||||
@@ -705,7 +710,7 @@ int16_t do_RRCReconfiguration(const gNB_RRC_UE_t *UE,
|
||||
ie->radioBearerConfig->drb_ToAddModList = DRB_configList;
|
||||
ie->radioBearerConfig->securityConfig = security_config;
|
||||
ie->radioBearerConfig->srb3_ToRelease = NULL;
|
||||
ie->radioBearerConfig->drb_ToReleaseList = DRB_releaseList;
|
||||
|
||||
}
|
||||
|
||||
/******************** Meas Config ********************/
|
||||
@@ -738,13 +743,13 @@ int16_t do_RRCReconfiguration(const gNB_RRC_UE_t *UE,
|
||||
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
|
||||
xer_fprint(stdout, &asn_DEF_NR_DL_DCCH_Message, (void *)&dl_dcch_msg);
|
||||
}
|
||||
|
||||
xer_fprint(stdout, &asn_DEF_NR_DL_DCCH_Message, (void *)&dl_dcch_msg);
|
||||
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_DL_DCCH_Message,
|
||||
NULL,
|
||||
(void *)&dl_dcch_msg,
|
||||
buffer,
|
||||
buffer_size);
|
||||
|
||||
|
||||
AssertFatal(enc_rval.encoded >0, "ASN1 message encoding failed (%s, %lu)!\n",
|
||||
enc_rval.failed_type->name, enc_rval.encoded);
|
||||
|
||||
@@ -760,6 +765,7 @@ int16_t do_RRCReconfiguration(const gNB_RRC_UE_t *UE,
|
||||
}
|
||||
if (ie->nonCriticalExtension)
|
||||
ie->nonCriticalExtension->dedicatedNAS_MessageList = NULL;
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_DL_DCCH_Message, &dl_dcch_msg);
|
||||
LOG_D(NR_RRC,
|
||||
"RRCReconfiguration for UE %d: Encoded %zd bits (%zd bytes)\n",
|
||||
@@ -1230,3 +1236,106 @@ uint8_t do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi)
|
||||
|
||||
return((enc_rval.encoded+7)/8);
|
||||
}
|
||||
|
||||
int do_NRHandoverPreparation(char *ho_buf, int ho_size, NR_UE_NR_Capability_t *ue_nr_cap, int rrc_size) {
|
||||
asn_enc_rval_t enc_rval;
|
||||
NR_HandoverPreparationInformation_t ho;
|
||||
NR_HandoverPreparationInformation_IEs_t *ho_info;
|
||||
NR_UE_CapabilityRAT_Container_t *ue_cap_rat_container;
|
||||
char rrc_buf[rrc_size];
|
||||
memset(rrc_buf, 0, rrc_size);
|
||||
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UE_NR_Capability,
|
||||
NULL,
|
||||
ue_nr_cap,
|
||||
rrc_buf,
|
||||
rrc_size);
|
||||
/* TODO: free the OCTET_STRING */
|
||||
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
|
||||
enc_rval.failed_type->name, enc_rval.encoded);
|
||||
memset(&ho, 0, sizeof(ho));
|
||||
ho.criticalExtensions.present = NR_HandoverPreparationInformation__criticalExtensions_PR_c1;
|
||||
ho.criticalExtensions.choice.c1->present = NR_HandoverPreparationInformation__criticalExtensions__c1_PR_handoverPreparationInformation;
|
||||
ho_info = ho.criticalExtensions.choice.c1->choice.handoverPreparationInformation;
|
||||
{
|
||||
ue_cap_rat_container = (NR_UE_CapabilityRAT_Container_t *)calloc(1,sizeof(NR_UE_CapabilityRAT_Container_t));
|
||||
ue_cap_rat_container->rat_Type = NR_RAT_Type_nr;
|
||||
AssertFatal (OCTET_STRING_fromBuf(
|
||||
&ue_cap_rat_container->ue_CapabilityRAT_Container,
|
||||
rrc_buf, rrc_size) != -1, "fatal: OCTET_STRING_fromBuf failed\n");
|
||||
asn1cSeqAdd(&ho_info->ue_CapabilityRAT_List.list, ue_cap_rat_container);
|
||||
}
|
||||
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_HandoverPreparationInformation,
|
||||
NULL,
|
||||
&ho,
|
||||
ho_buf,
|
||||
ho_size);
|
||||
/* TODO: free the OCTET_STRING */
|
||||
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
|
||||
enc_rval.failed_type->name, enc_rval.encoded);
|
||||
return((enc_rval.encoded+7)/8);
|
||||
}
|
||||
|
||||
|
||||
int16_t do_NR_HandoverCommand(uint8_t *ho_buf, int16_t ho_size, uint8_t *rrc_buffer, int16_t rrc_size) {
|
||||
|
||||
NR_HandoverCommand_t *ho_command = calloc(1,sizeof(NR_HandoverCommand_t));
|
||||
ho_command->criticalExtensions.present = NR_HandoverCommand__criticalExtensions_PR_c1;
|
||||
ho_command->criticalExtensions.choice.c1 = calloc(1,sizeof(struct NR_HandoverCommand__criticalExtensions__c1));
|
||||
ho_command->criticalExtensions.choice.c1->present = NR_HandoverCommand__criticalExtensions__c1_PR_handoverCommand;
|
||||
ho_command->criticalExtensions.choice.c1->choice.handoverCommand = calloc(1,sizeof(struct NR_HandoverCommand_IEs));
|
||||
|
||||
AssertFatal(OCTET_STRING_fromBuf(&ho_command->criticalExtensions.choice.c1->choice.handoverCommand->handoverCommandMessage, (char *)rrc_buffer, rrc_size) != -1,
|
||||
"fatal: OCTET_STRING_fromBuf failed\n");
|
||||
|
||||
|
||||
xer_fprint(stdout,&asn_DEF_NR_HandoverCommand, ho_command);
|
||||
|
||||
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_HandoverCommand,
|
||||
NULL,
|
||||
ho_command,
|
||||
ho_buf,
|
||||
ho_size);
|
||||
|
||||
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
|
||||
enc_rval.failed_type->name, enc_rval.encoded);
|
||||
|
||||
return ((enc_rval.encoded+7)/8);
|
||||
}
|
||||
|
||||
|
||||
int do_NR_HandoverPreparationInformation(const uint8_t *uecap_buf, int uecap_buf_size, uint8_t *buf, int buf_size)
|
||||
{
|
||||
NR_HandoverPreparationInformation_t *hpi = calloc(1, sizeof(*hpi));
|
||||
AssertFatal(hpi != NULL, "out of memory\n");
|
||||
hpi->criticalExtensions.present = NR_HandoverPreparationInformation__criticalExtensions_PR_c1;
|
||||
hpi->criticalExtensions.choice.c1 = calloc(1, sizeof(*hpi->criticalExtensions.choice.c1));
|
||||
AssertFatal(hpi->criticalExtensions.choice.c1 != NULL, "out of memory\n");
|
||||
hpi->criticalExtensions.choice.c1->present =
|
||||
NR_HandoverPreparationInformation__criticalExtensions__c1_PR_handoverPreparationInformation;
|
||||
NR_HandoverPreparationInformation_IEs_t *hpi_ie = calloc(1, sizeof(*hpi_ie));
|
||||
AssertFatal(hpi_ie != NULL, "out of memory\n");
|
||||
hpi->criticalExtensions.choice.c1->choice.handoverPreparationInformation = hpi_ie;
|
||||
|
||||
NR_UE_CapabilityRAT_ContainerList_t *list = NULL;
|
||||
asn_dec_rval_t dec_rval =
|
||||
uper_decode_complete(NULL, &asn_DEF_NR_UE_CapabilityRAT_ContainerList, (void **)&list, uecap_buf, uecap_buf_size);
|
||||
if (dec_rval.code == RC_OK) {
|
||||
hpi_ie->ue_CapabilityRAT_List = *list;
|
||||
free(list); /* list itself is not needed, members below will be freed in ASN_STRUCT_FREE */
|
||||
} else {
|
||||
/* problem with decoding, don't put a capability */
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_UE_CapabilityRAT_ContainerList, list);
|
||||
list = NULL;
|
||||
}
|
||||
|
||||
if (true)
|
||||
xer_fprint(stdout, &asn_DEF_NR_HandoverPreparationInformation, hpi);
|
||||
|
||||
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_HandoverPreparationInformation, NULL, hpi, buf, buf_size);
|
||||
AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded);
|
||||
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_HandoverPreparationInformation, hpi);
|
||||
return (enc_rval.encoded + 7) / 8;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -147,4 +147,8 @@ NR_MeasConfig_t *get_defaultMeasConfig(uint32_t absFreqSSB, int band, int scs);
|
||||
void free_defaultMeasConfig(NR_MeasConfig_t *mc);
|
||||
uint8_t do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi);
|
||||
|
||||
int do_NRHandoverPreparation(char *ho_buf, int ho_size, NR_UE_NR_Capability_t *ue_nr_cap, int rrc_size);
|
||||
int16_t do_NR_HandoverCommand(uint8_t *ho_buf, int16_t ho_size, uint8_t *rrc_buffer, int16_t rrc_size);
|
||||
int do_NR_HandoverPreparationInformation(const uint8_t *uecap_buf, int uecap_buf_size, uint8_t *buf, int buf_size);
|
||||
|
||||
#endif /* __RRC_NR_MESSAGES_ASN1_MSG__H__ */
|
||||
|
||||
@@ -55,6 +55,7 @@ static void ue_context_setup_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_c
|
||||
AssertFatal(f1ap_msg->cu_to_du_rrc_information != NULL, "out of memory\n");
|
||||
AssertFatal(req->cu_to_du_rrc_information->cG_ConfigInfo == NULL && req->cu_to_du_rrc_information->cG_ConfigInfo_length == 0, "cg_ConfigInfo not implemented\n");
|
||||
AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL && req->cu_to_du_rrc_information->measConfig_length == 0, "cg_ConfigInfo not implemented\n");
|
||||
const cu_to_du_rrc_information_t *du2cu_req = req->cu_to_du_rrc_information;
|
||||
if (req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList != NULL) {
|
||||
const cu_to_du_rrc_information_t *du2cu_req = req->cu_to_du_rrc_information;
|
||||
cu_to_du_rrc_information_t* du2cu_new = f1ap_msg->cu_to_du_rrc_information;
|
||||
@@ -64,6 +65,14 @@ static void ue_context_setup_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_c
|
||||
AssertFatal(du2cu_new->uE_CapabilityRAT_ContainerList != NULL, "out of memory\n");
|
||||
memcpy(du2cu_new->uE_CapabilityRAT_ContainerList, du2cu_req->uE_CapabilityRAT_ContainerList, du2cu_new->uE_CapabilityRAT_ContainerList_length);
|
||||
}
|
||||
if (req->cu_to_du_rrc_information->handoverPreparationInfo != NULL) {
|
||||
cu_to_du_rrc_information_t *du2cu_new = f1ap_msg->cu_to_du_rrc_information;
|
||||
DevAssert(du2cu_req->handoverPreparationInfo_length > 0);
|
||||
du2cu_new->handoverPreparationInfo_length = du2cu_req->handoverPreparationInfo_length;
|
||||
du2cu_new->handoverPreparationInfo = malloc(du2cu_new->handoverPreparationInfo_length);
|
||||
AssertFatal(du2cu_new->handoverPreparationInfo != NULL, "out of memory\n");
|
||||
memcpy(du2cu_new->handoverPreparationInfo, du2cu_req->handoverPreparationInfo, du2cu_new->handoverPreparationInfo_length);
|
||||
}
|
||||
}
|
||||
if (req->drbs_to_be_setup_length > 0) {
|
||||
int n = req->drbs_to_be_setup_length;
|
||||
|
||||
@@ -2956,3 +2956,60 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
|
||||
}
|
||||
return secondaryCellGroup;
|
||||
}
|
||||
|
||||
|
||||
NR_ServingCellConfigCommon_t *clone_SCC(const NR_ServingCellConfigCommon_t *orig)
|
||||
{
|
||||
uint8_t buf[16636];
|
||||
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_ServingCellConfigCommon, NULL, orig, buf, sizeof(buf));
|
||||
AssertFatal(enc_rval.encoded > 0, "could not clone Serving Cell Config Common: problem while encoding\n");
|
||||
NR_ServingCellConfigCommon_t *new = NULL;
|
||||
asn_dec_rval_t dec_rval = uper_decode(NULL, &asn_DEF_NR_ServingCellConfigCommon, (void **)&new, buf, enc_rval.encoded, 0, 0);
|
||||
AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed == enc_rval.encoded,
|
||||
"could not clone Serving Cell Config Common: problem while decoding\n");
|
||||
return new;
|
||||
}
|
||||
|
||||
NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t uid, const NR_ServingCellConfigCommon_t *scc)
|
||||
{
|
||||
NR_ReconfigurationWithSync_t *reconfigurationWithSync = calloc(1, sizeof(*reconfigurationWithSync));
|
||||
reconfigurationWithSync->newUE_Identity = rnti;
|
||||
reconfigurationWithSync->t304 = NR_ReconfigurationWithSync__t304_ms2000;
|
||||
reconfigurationWithSync->rach_ConfigDedicated = NULL;
|
||||
reconfigurationWithSync->ext1 = NULL;
|
||||
|
||||
reconfigurationWithSync->spCellConfigCommon = clone_SCC(scc);
|
||||
scc->uplinkConfigCommon->dummy = NR_TimeAlignmentTimer_infinity;
|
||||
|
||||
reconfigurationWithSync->rach_ConfigDedicated = calloc(1, sizeof(*reconfigurationWithSync->rach_ConfigDedicated));
|
||||
reconfigurationWithSync->rach_ConfigDedicated->present = NR_ReconfigurationWithSync__rach_ConfigDedicated_PR_uplink;
|
||||
NR_RACH_ConfigDedicated_t *uplink = calloc(1, sizeof(*uplink));
|
||||
reconfigurationWithSync->rach_ConfigDedicated->choice.uplink = uplink;
|
||||
uplink->ra_Prioritization = NULL;
|
||||
uplink->cfra = calloc(1, sizeof(struct NR_CFRA));
|
||||
uplink->cfra->ext1 = NULL;
|
||||
uplink->cfra->occasions = calloc(1, sizeof(struct NR_CFRA__occasions));
|
||||
memcpy(&uplink->cfra->occasions->rach_ConfigGeneric,
|
||||
&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric,
|
||||
sizeof(NR_RACH_ConfigGeneric_t));
|
||||
asn1cCallocOne(uplink->cfra->occasions->ssb_perRACH_Occasion, NR_CFRA__occasions__ssb_perRACH_Occasion_one);
|
||||
uplink->cfra->resources.present = NR_CFRA__resources_PR_ssb;
|
||||
uplink->cfra->resources.choice.ssb = calloc(1, sizeof(struct NR_CFRA__resources__ssb));
|
||||
uplink->cfra->resources.choice.ssb->ra_ssb_OccasionMaskIndex = 0;
|
||||
|
||||
uint64_t bitmap = get_ssb_bitmap(scc);
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if (((bitmap >> (63 - i)) & 0x01) == 0)
|
||||
continue;
|
||||
|
||||
NR_CFRA_SSB_Resource_t *ssbElem = calloc(1, sizeof(*ssbElem));
|
||||
ssbElem->ssb = i;
|
||||
ssbElem->ra_PreambleIndex = 63 - (uid % 64);
|
||||
asn1cSeqAdd(&uplink->cfra->resources.choice.ssb->ssb_ResourceList.list, ssbElem);
|
||||
}
|
||||
|
||||
return reconfigurationWithSync;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -86,4 +86,6 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
|
||||
const nr_mac_config_t *configuration,
|
||||
int uid);
|
||||
|
||||
NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t uid, const NR_ServingCellConfigCommon_t *scc);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -95,6 +95,7 @@
|
||||
#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,
|
||||
@@ -169,6 +170,28 @@ typedef struct nr_rrc_guami_s {
|
||||
uint8_t amf_pointer;
|
||||
} nr_rrc_guami_t;
|
||||
|
||||
typedef enum {HANDOVER_TYPE_INTRA_CU, HANDOVER_TYPE_INTER_CU} nr_handover_type_t;
|
||||
typedef struct nr_handover_intra_cu_s {
|
||||
sctp_assoc_t source_du;
|
||||
sctp_assoc_t target_du;
|
||||
uint32_t source_secondary_ue;
|
||||
rnti_t new_rnti;
|
||||
uint32_t target_secondary_ue;
|
||||
} nr_handover_intra_cu_t;
|
||||
typedef struct nr_handover_inter_cu_s {
|
||||
// TODO additional data needed?
|
||||
int dummy;
|
||||
} nr_handover_inter_cu_t;
|
||||
typedef struct nr_handover_context_s {
|
||||
nr_handover_type_t type;
|
||||
union {
|
||||
nr_handover_intra_cu_t intra_cu;
|
||||
nr_handover_inter_cu_t inter_cu;
|
||||
} data;
|
||||
// TODO fptr for success, failure
|
||||
} nr_handover_context_t;
|
||||
|
||||
|
||||
typedef enum pdu_session_satus_e {
|
||||
PDU_SESSION_STATUS_NEW,
|
||||
PDU_SESSION_STATUS_DONE,
|
||||
@@ -250,6 +273,7 @@ typedef enum {
|
||||
|
||||
typedef struct gNB_RRC_UE_s {
|
||||
drb_t established_drbs[MAX_DRBS_PER_UE];
|
||||
uint8_t DRB_active[MAX_DRBS_PER_UE];
|
||||
NR_DRB_ToReleaseList_t *DRB_ReleaseList;
|
||||
|
||||
NR_SRB_INFO_TABLE_ENTRY Srb[NR_NUM_SRB];
|
||||
@@ -296,6 +320,7 @@ typedef struct gNB_RRC_UE_s {
|
||||
nr_rrc_guami_t ue_guami;
|
||||
|
||||
ngap_security_capabilities_t security_capabilities;
|
||||
xnap_security_capabilities_t xnap_security_capabilities;
|
||||
//NSA block
|
||||
/* Number of NSA e_rab */
|
||||
uint8_t nb_of_e_rabs;
|
||||
@@ -321,6 +346,7 @@ typedef struct gNB_RRC_UE_s {
|
||||
|
||||
/* hack, see rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ() for more info */
|
||||
int max_delays_pdu_session;
|
||||
nr_handover_context_t *ho_context;
|
||||
|
||||
} gNB_RRC_UE_t;
|
||||
|
||||
@@ -389,6 +415,14 @@ typedef struct nr_rrc_cuup_container_t {
|
||||
sctp_assoc_t assoc_id;
|
||||
} nr_rrc_cuup_container_t;
|
||||
|
||||
typedef struct nr_rrc_neighcells_container_t {
|
||||
/* Tree-related data */
|
||||
RB_ENTRY(nr_rrc_neighcells_container_t) entries;
|
||||
|
||||
uint64_t nr_cellid;
|
||||
sctp_assoc_t assoc_id;
|
||||
} nr_rrc_neighcells_container_t;
|
||||
|
||||
//---NR---(completely change)---------------------
|
||||
typedef struct gNB_RRC_INST_s {
|
||||
|
||||
@@ -411,6 +445,8 @@ typedef struct gNB_RRC_INST_s {
|
||||
|
||||
char *uecap_file;
|
||||
|
||||
// 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;
|
||||
|
||||
@@ -423,6 +459,10 @@ typedef struct gNB_RRC_INST_s {
|
||||
RB_HEAD(rrc_cuup_tree, nr_rrc_cuup_container_t) cuups; // CU-UPs, indexed by assoc_id
|
||||
size_t num_cuups;
|
||||
|
||||
RB_HEAD(rrc_neigh_cell_tree, nr_rrc_neighcells_container_t) neighs; // Neighbouring cells, indexed by assoc_id
|
||||
size_t num_neighs;
|
||||
instance_t f1_instance;
|
||||
|
||||
} gNB_RRC_INST;
|
||||
|
||||
#include "nr_rrc_proto.h" //should be put here otherwise compilation error
|
||||
|
||||
@@ -34,5 +34,7 @@
|
||||
#include "COMMON/mac_rrc_primitives.h"
|
||||
#include "LAYER2/RLC/rlc.h"
|
||||
#include "openair2/RRC/common.h"
|
||||
extern uint16_t ho_rnti_map[NUMBER_OF_DU_PER_CU_MAX][4];
|
||||
|
||||
void openair_rrc_gNB_configuration(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration);
|
||||
#endif
|
||||
|
||||
@@ -99,7 +99,8 @@ rrc_gNB_generate_RRCRelease(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rrc_gNB_ue_context_t *const ue_context_pP
|
||||
);
|
||||
|
||||
void rrc_gNB_process_handoverprepinfo(sctp_assoc_t assoc_id, xnap_handover_req_t *m);
|
||||
void rrc_gNB_process_handover_req_ack(sctp_assoc_t assoc_id, xnap_handover_req_ack_t *m);
|
||||
/**\brief RRC eNB task.
|
||||
\param args_p Pointer on arguments to start the task. */
|
||||
void *rrc_gnb_task(void *args_p);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,11 @@
|
||||
#include "openair2/F1AP/f1ap_common.h"
|
||||
#include "openair2/F1AP/f1ap_ids.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "openair2/XNAP/xnap_gNB_defs.h"
|
||||
#include "openair2/XNAP/xnap_gNB_management_procedures.h"
|
||||
#include "common/utils/ds/seq_arr.h"
|
||||
#include "common/utils/alg/foreach.h"
|
||||
|
||||
|
||||
|
||||
static int du_compare(const nr_rrc_du_container_t *a, const nr_rrc_du_container_t *b)
|
||||
@@ -162,7 +167,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
|
||||
}
|
||||
RB_INSERT(rrc_du_tree, &rrc->dus, du);
|
||||
rrc->num_dus++;
|
||||
|
||||
LOG_I(RRC,"Num_dus %d\n",rrc->num_dus);
|
||||
served_cells_to_activate_t cell = {
|
||||
.plmn = cell_info->plmn,
|
||||
.nr_cellid = cell_info->nr_cellid,
|
||||
@@ -177,6 +182,15 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
|
||||
AssertFatal(num == 3, "could not read RRC version string %s\n", TO_STRING(NR_RRC_VERSION));
|
||||
if (rrc->node_name != NULL)
|
||||
resp.gNB_CU_name = strdup(rrc->node_name);
|
||||
xnap_gNB_instance_t *instance_xn = xnap_gNB_get_instance(0);
|
||||
if (instance_xn != NULL) {
|
||||
LOG_D(NR_RRC, "XNAP is enabled, Triggering SCTP Association \n");
|
||||
void cu_register_xn(uint32_t gnb_id_num,f1ap_served_cell_info_t *cell , xnap_net_config_t nc); //function prototype add
|
||||
if (instance_xn->setup_req.gNB_id == 0) {
|
||||
cu_register_xn(1, cell_info,instance_xn->net_config);
|
||||
}
|
||||
}
|
||||
|
||||
rrc->mac_rrc.f1_setup_response(assoc_id, &resp);
|
||||
|
||||
/*
|
||||
@@ -278,3 +292,28 @@ void dump_du_info(const gNB_RRC_INST *rrc, FILE *f)
|
||||
fprintf(f, ": nrCellID %ld, PCI %d\n", info->nr_cellid, info->nr_pci);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nr_rrc_du_container_t *find_target_du(gNB_RRC_INST *rrc, long nci)
|
||||
{
|
||||
LOG_I(NR_RRC,"Find Target_du \n");
|
||||
/* nr_rrc_du_container_t e = {.assoc_id = assoc_id};
|
||||
nr_rrc_du_container_t *du = RB_FIND(rrc_du_tree, &rrc->dus, &e);
|
||||
if(du != NULL)
|
||||
{
|
||||
return du;
|
||||
}
|
||||
else{
|
||||
LOG_I(NR_RRC,"Target DU is null");
|
||||
}*/
|
||||
nr_rrc_du_container_t *it = NULL;
|
||||
//bool next_du = false;
|
||||
LOG_I(RRC,"Num_dus in find target du %d\n",rrc->num_dus);
|
||||
RB_FOREACH (it, rrc_du_tree, &rrc->dus) {
|
||||
if (it->setup_req->cell[0].info.nr_cellid == nci) {
|
||||
LOG_I(NR_RRC,"ASSOC ID of DU in DU tree %d \n",it->assoc_id);
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -39,5 +39,5 @@ struct nr_rrc_du_container_t *get_du_for_ue(struct gNB_RRC_INST_s *rrc, uint32_t
|
||||
struct nr_rrc_du_container_t *get_du_by_assoc_id(struct gNB_RRC_INST_s *rrc, sctp_assoc_t assoc_id);
|
||||
|
||||
void dump_du_info(const struct gNB_RRC_INST_s *rrc, FILE *f);
|
||||
|
||||
struct nr_rrc_du_container_t *find_target_du(struct gNB_RRC_INST_s *rrc, long nci);
|
||||
#endif /* RRC_GNB_DU_H_ */
|
||||
|
||||
@@ -184,6 +184,25 @@ uint8_t get_next_available_drb_id(gNB_RRC_UE_t *ue)
|
||||
return DRB_INACTIVE;
|
||||
}
|
||||
|
||||
uint8_t next_available_drb(gNB_RRC_UE_t *ue, rrc_pdu_session_param_t *pdusession, bool is_gbr)
|
||||
{
|
||||
uint8_t drb_id;
|
||||
|
||||
if (0 /*!is_gbr*/) { /* Find if Non-GBR DRB exists in the same PDU Session */
|
||||
for (drb_id = 0; drb_id < MAX_DRBS_PER_UE; drb_id++)
|
||||
if (pdusession->param.used_drbs[drb_id] == DRB_ACTIVE_NONGBR)
|
||||
return drb_id + 1;
|
||||
}
|
||||
/* GBR Flow or a Non-GBR DRB does not exist in the same PDU Session, find an available DRB */
|
||||
for (drb_id = 0; drb_id < MAX_DRBS_PER_UE; drb_id++)
|
||||
if (ue->DRB_active[drb_id] == DRB_INACTIVE)
|
||||
return drb_id + 1;
|
||||
/* From this point, we need to handle the case that all DRBs are already used by the UE. */
|
||||
LOG_E(RRC, "Error - All the DRBs are used - Handle this\n");
|
||||
return DRB_INACTIVE;
|
||||
}
|
||||
|
||||
|
||||
bool drb_is_active(gNB_RRC_UE_t *ue, uint8_t drb_id)
|
||||
{
|
||||
drb_t *drb = get_drb(ue, drb_id);
|
||||
|
||||
@@ -60,7 +60,7 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue,
|
||||
|
||||
/// @brief return the next available (inactive) DRB ID of UE ue
|
||||
uint8_t get_next_available_drb_id(gNB_RRC_UE_t *ue);
|
||||
|
||||
uint8_t next_available_drb(gNB_RRC_UE_t *ue, rrc_pdu_session_param_t *pdusession, bool is_gbr);
|
||||
/// @brief check if DRB with ID drb_id of UE ue is active
|
||||
bool drb_is_active(gNB_RRC_UE_t *ue, uint8_t drb_id);
|
||||
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
add_subdirectory(MESSAGES)
|
||||
add_library(xnap xnap_common.c)
|
||||
add_library(xnap
|
||||
xnap_common.c
|
||||
xnap_gNB_generate_messages.c
|
||||
xnap_gNB_management_procedures.c
|
||||
xnap_gNB_task.c
|
||||
xnap_gNB_itti_messaging.c
|
||||
xnap_gNB_handler.c
|
||||
xnap_gNB_interface_management.c
|
||||
xnap_timers.c
|
||||
xnap_ids.c)
|
||||
target_link_libraries(xnap
|
||||
PUBLIC asn1_xnap
|
||||
PRIVATE nr_rrc)
|
||||
|
||||
@@ -19,30 +19,55 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file xnap_common.c
|
||||
* \brief xnap encoder,decoder dunctions for gNB
|
||||
* \author Sreeshma Shiv <sreeshmau@iisc.ac.in>
|
||||
* \date Dec 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"
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -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,7 @@
|
||||
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, sctp_assoc_t assocId, uint32_t stream, XNAP_XnAP_PDU_t *pdu);
|
||||
int xnap_gNB_decode_pdu(XNAP_XnAP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length) __attribute__((warn_unused_result));
|
||||
int xnap_gNB_encode_pdu(XNAP_XnAP_PDU_t *pdu, uint8_t **buffer, uint32_t *len) __attribute__((warn_unused_result));
|
||||
#endif /* XNAP_COMMON_H_ */
|
||||
|
||||
99
openair2/XNAP/xnap_gNB_defs.h
Normal file
99
openair2/XNAP/xnap_gNB_defs.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/* 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"
|
||||
#include "xnap_timers.h"
|
||||
#include "xnap_ids.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;
|
||||
|
||||
struct xnap_gNB_instance_s;
|
||||
|
||||
/* This structure describes association of gNBs over Xn */
|
||||
typedef struct xnap_gNB_data_t {
|
||||
/* gNB descriptors tree, ordered by sctp assoc id */
|
||||
RB_ENTRY(xnap_gNB_data_t) entry;
|
||||
char *gNB_name;
|
||||
long nci;
|
||||
/* target gNB ID */
|
||||
uint64_t gNB_id;
|
||||
/* Current gNB->gNB XnAP association state */
|
||||
xnap_gNB_state_t state;
|
||||
/* Number of input/ouput streams */
|
||||
uint16_t in_streams;
|
||||
uint16_t out_streams;
|
||||
/* Connexion id used between SCTP/XNAP */
|
||||
uint16_t cnx_id;
|
||||
/* SCTP association id */
|
||||
sctp_assoc_t assoc_id;
|
||||
} xnap_gNB_data_t;
|
||||
|
||||
typedef struct xnap_gNB_instance_s {
|
||||
/* 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_tree, xnap_gNB_data_t) xnap_gnbs; // gNBs, indexed by assoc_id
|
||||
size_t num_gnbs;
|
||||
instance_t instance;
|
||||
xnap_setup_req_t setup_req;
|
||||
xnap_id_manager id_manager;
|
||||
/* The gNB IP address to bind */
|
||||
xnap_net_config_t net_config;
|
||||
/* SCTP information */
|
||||
xnap_sctp_t sctp_streams;
|
||||
char *gNB_name;
|
||||
sctp_assoc_t assoc_id_temp;
|
||||
} xnap_gNB_instance_t;
|
||||
|
||||
#endif /* XNAP_GNB_DEFS_H_ */
|
||||
1231
openair2/XNAP/xnap_gNB_generate_messages.c
Normal file
1231
openair2/XNAP/xnap_gNB_generate_messages.c
Normal file
File diff suppressed because it is too large
Load Diff
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(sctp_assoc_t assoc_id, xnap_setup_req_t *req);
|
||||
|
||||
int xnap_gNB_generate_xn_setup_response(sctp_assoc_t assoc_id, xnap_setup_resp_t *resp);
|
||||
|
||||
int xnap_gNB_generate_xn_setup_failure(sctp_assoc_t assoc_id, xnap_setup_failure_t *fail);
|
||||
|
||||
int xnap_gNB_set_cause(XNAP_Cause_t *cause_p, XNAP_Cause_PR cause_type, long cause_value);
|
||||
|
||||
int xnap_gNB_generate_xn_handover_request(sctp_assoc_t assoc_id, xnap_handover_req_t *xnap_handover_req);
|
||||
|
||||
int xnap_gNB_generate_xn_handover_request_ack(sctp_assoc_t assoc_id, xnap_handover_req_ack_t *xnap_handover_req_ack,instance_t instance);
|
||||
|
||||
#endif /* XNAP_GNB_GENERATE_MESSAGES_H_ */
|
||||
202
openair2/XNAP/xnap_gNB_handler.c
Normal file
202
openair2/XNAP/xnap_gNB_handler.c
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* 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_interface_management.h"
|
||||
#include "assertions.h"
|
||||
#include "conversions.h"
|
||||
#include "xnap_ids.h"
|
||||
|
||||
/* Placement of callback functions according to XNAP_ProcedureCode.h */
|
||||
static const xnap_message_decoded_callback xnap_messages_callback[][3] = {
|
||||
{xnap_gNB_handle_handover_request, xnap_gNB_handle_handover_response, 0}, /* handoverPreparation */
|
||||
{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]);
|
||||
}
|
||||
|
||||
int xnap_gNB_handle_message(instance_t instance,
|
||||
sctp_assoc_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:
|
||||
LOG_I(XNAP, "xnap_gNB_decode_initiating_message!\n");
|
||||
/* 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:
|
||||
LOG_I(XNAP, "xnap_gNB_decode_successfuloutcome_message!\n");
|
||||
/* Checking procedure Code and direction of message */
|
||||
if (pdu.choice.successfulOutcome->procedureCode
|
||||
>= sizeof(xnap_messages_callback) / (3 * sizeof(xnap_message_decoded_callback))) {
|
||||
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:
|
||||
LOG_I(XNAP, "xnap_gNB_decode_unsuccessfuloutcome_message!\n");
|
||||
/* Checking procedure Code and direction of message */
|
||||
if (pdu.choice.unsuccessfulOutcome->procedureCode
|
||||
>= sizeof(xnap_messages_callback) / (3 * sizeof(xnap_message_decoded_callback))) {
|
||||
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;
|
||||
}
|
||||
39
openair2/XNAP/xnap_gNB_handler.h
Normal file
39
openair2/XNAP/xnap_gNB_handler.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_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"
|
||||
|
||||
int xnap_gNB_handle_message(instance_t instance,
|
||||
sctp_assoc_t assoc_id,
|
||||
int32_t stream,
|
||||
const uint8_t *const data,
|
||||
const uint32_t data_length);
|
||||
|
||||
#endif /* XNAP_GNB_HANDLERS_H_ */
|
||||
508
openair2/XNAP/xnap_gNB_interface_management.c
Normal file
508
openair2/XNAP/xnap_gNB_interface_management.c
Normal file
@@ -0,0 +1,508 @@
|
||||
/*
|
||||
* 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_interface_management.c
|
||||
* \brief xnap handling interface procedures for gNB
|
||||
* \author Sreeshma Shiv <sreeshmau@iisc.ac.in>
|
||||
* \date Dec 2023
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "intertask_interface.h"
|
||||
#include "xnap_common.h"
|
||||
#include "xnap_gNB_defs.h"
|
||||
#include "xnap_gNB_interface_management.h"
|
||||
#include "xnap_gNB_handler.h"
|
||||
#include "assertions.h"
|
||||
#include "conversions.h"
|
||||
#include "XNAP_GlobalgNB-ID.h"
|
||||
#include "XNAP_ServedCells-NR-Item.h"
|
||||
#include "XNAP_NRFrequencyBandItem.h"
|
||||
#include "XNAP_GlobalNG-RANNode-ID.h"
|
||||
#include "XNAP_NRModeInfoFDD.h"
|
||||
#include "XNAP_NRModeInfoTDD.h"
|
||||
#include "XNAP_SupportedSULBandList.h"
|
||||
#include "XNAP_TAISupport-Item.h"
|
||||
#include "XNAP_BroadcastPLMNinTAISupport-Item.h"
|
||||
#include "xnap_gNB_management_procedures.h"
|
||||
|
||||
int xnap_gNB_handle_xn_setup_request(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, XNAP_XnAP_PDU_t *pdu)
|
||||
{
|
||||
XNAP_XnSetupRequest_t *xnSetupRequest;
|
||||
XNAP_XnSetupRequest_IEs_t *ie;
|
||||
// XNAP_ServedCells_NR_Item_t *servedCellMember;
|
||||
|
||||
DevAssert(pdu != NULL);
|
||||
xnSetupRequest = &pdu->choice.initiatingMessage->value.choice.XnSetupRequest;
|
||||
if (stream != 0) { /* Xn Setup: Non UE related procedure ->stream 0 */
|
||||
LOG_E(XNAP, "Received new XN setup request on stream != 0\n");
|
||||
/* Send a xn setup failure with protocol cause unspecified */
|
||||
MessageDef *message_p = itti_alloc_new_message(TASK_XNAP, 0, XNAP_SETUP_FAILURE);
|
||||
message_p->ittiMsgHeader.originInstance = assoc_id;
|
||||
xnap_setup_failure_t *fail = &XNAP_SETUP_FAILURE(message_p);
|
||||
fail->cause_type = XNAP_CAUSE_PROTOCOL;
|
||||
fail->cause_value = 6;
|
||||
itti_send_msg_to_task(TASK_XNAP, 0, message_p);
|
||||
}
|
||||
LOG_D(XNAP, "Received a new XN setup request\n");
|
||||
MessageDef *message_p = itti_alloc_new_message(TASK_XNAP, 0, XNAP_SETUP_REQ);
|
||||
message_p->ittiMsgHeader.originInstance = assoc_id;
|
||||
xnap_setup_req_t *req = &XNAP_SETUP_REQ(message_p);
|
||||
|
||||
// gNB_id
|
||||
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, "XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID is NULL pointer \n");
|
||||
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 where size != 28 -> notify ? reject ?
|
||||
}
|
||||
req->gNB_id = (gNB_id_buf[0] << 20) + (gNB_id_buf[1] << 12) + (gNB_id_buf[2] << 4) + ((gNB_id_buf[3] & 0xf0) >> 4);
|
||||
} else {
|
||||
// TODO if NSA setup
|
||||
}
|
||||
}
|
||||
LOG_D(XNAP, "Adding gNB to the list of associated gNBs: %lu\n", req->gNB_id);
|
||||
|
||||
XNAP_FIND_PROTOCOLIE_BY_ID(XNAP_XnSetupRequest_IEs_t, ie, xnSetupRequest, XNAP_ProtocolIE_ID_id_TAISupport_list, true);
|
||||
if (ie == NULL) {
|
||||
LOG_E(XNAP, "XNAP_ProtocolIE_ID_id_TAISupport_list is NULL pointer \n");
|
||||
return -1;
|
||||
} else {
|
||||
OCTET_STRING_TO_INT24(&ie->value.choice.TAISupport_List.list.array[0]->tac, req->tai_support);
|
||||
LOG_I(XNAP, "tac %d \n", req->tai_support);
|
||||
}
|
||||
LOG_D(XNAP, "req->gNB id: %lu \n", req->gNB_id);
|
||||
|
||||
LOG_D(XNAP, "Adding gNB to the list of associated gNBs\n");
|
||||
|
||||
XNAP_FIND_PROTOCOLIE_BY_ID(XNAP_XnSetupRequest_IEs_t, ie, xnSetupRequest, XNAP_ProtocolIE_ID_id_List_of_served_cells_NR, true);
|
||||
req->num_cells_available = ie->value.choice.ServedCells_NR.list.count;
|
||||
LOG_D(XNAP, "req->num_cells_available %d \n", req->num_cells_available);
|
||||
|
||||
for (int i = 0; i < req->num_cells_available; i++) {
|
||||
XNAP_ServedCellInformation_NR_t *servedCellMember =
|
||||
&(((XNAP_ServedCells_NR_Item_t *)ie->value.choice.ServedCells_NR.list.array[i])->served_cell_info_NR);
|
||||
req->info.nr_pci = servedCellMember->nrPCI;
|
||||
LOG_D(XNAP, "req->nr_pci[%d] %d \n", i, req->info.nr_pci);
|
||||
/* PLMN */
|
||||
PLMNID_TO_MCC_MNC(servedCellMember->broadcastPLMN.list.array[0],
|
||||
req->info.plmn.mcc,
|
||||
req->info.plmn.mnc,
|
||||
req->info.plmn.mnc_digit_length);
|
||||
BIT_STRING_TO_NR_CELL_IDENTITY(&servedCellMember->cellID.nr_CI, req->info.nr_cellid);
|
||||
LOG_D(XNAP,
|
||||
"[SCTP %d] Received BroadcastPLMN: MCC %d, MNC %d, CELL_ID %llu\n",
|
||||
assoc_id,
|
||||
req->info.plmn.mcc,
|
||||
req->info.plmn.mnc,
|
||||
(long long unsigned int)req->info.nr_cellid);
|
||||
// FDD Cells
|
||||
if (servedCellMember->nrModeInfo.present == XNAP_NRModeInfo_PR_fdd) {
|
||||
req->info.mode = XNAP_MODE_FDD;
|
||||
xnap_fdd_info_t *FDDs = &req->info.fdd;
|
||||
XNAP_NRModeInfoFDD_t *fdd_Info = servedCellMember->nrModeInfo.choice.fdd;
|
||||
FDDs->ul_freqinfo.arfcn = fdd_Info->ulNRFrequencyInfo.nrARFCN;
|
||||
AssertFatal(fdd_Info->ulNRFrequencyInfo.frequencyBand_List.list.count == 1, "cannot handle more than one frequency band\n");
|
||||
for (int f = 0; f < fdd_Info->ulNRFrequencyInfo.frequencyBand_List.list.count; f++) {
|
||||
XNAP_NRFrequencyBandItem_t *FreqItem = fdd_Info->ulNRFrequencyInfo.frequencyBand_List.list.array[f];
|
||||
FDDs->ul_freqinfo.band = FreqItem->nr_frequency_band;
|
||||
AssertFatal(FreqItem->supported_SUL_Band_List->list.count == 0, "cannot handle SUL bands!\n");
|
||||
}
|
||||
FDDs->dl_freqinfo.arfcn = fdd_Info->dlNRFrequencyInfo.nrARFCN;
|
||||
int dlBands = fdd_Info->dlNRFrequencyInfo.frequencyBand_List.list.count;
|
||||
AssertFatal(dlBands == 0, "cannot handle more than one frequency band\n");
|
||||
for (int dlB = 0; dlB < dlBands; dlB++) {
|
||||
XNAP_NRFrequencyBandItem_t *FreqItem = fdd_Info->dlNRFrequencyInfo.frequencyBand_List.list.array[dlB];
|
||||
FDDs->dl_freqinfo.band = FreqItem->nr_frequency_band;
|
||||
int num_available_supported_SULBands = FreqItem->supported_SUL_Band_List->list.count;
|
||||
AssertFatal(num_available_supported_SULBands == 0, "cannot handle SUL bands!\n");
|
||||
}
|
||||
FDDs->ul_tbw.scs = fdd_Info->ulNRTransmissonBandwidth.nRSCS;
|
||||
FDDs->ul_tbw.nrb = fdd_Info->ulNRTransmissonBandwidth.nRNRB;
|
||||
FDDs->dl_tbw.scs = fdd_Info->dlNRTransmissonBandwidth.nRSCS;
|
||||
FDDs->dl_tbw.nrb = fdd_Info->dlNRTransmissonBandwidth.nRNRB;
|
||||
} else if (servedCellMember->nrModeInfo.present == XNAP_NRModeInfo_PR_tdd) {
|
||||
req->info.mode = XNAP_MODE_TDD;
|
||||
xnap_tdd_info_t *TDDs = &req->info.tdd;
|
||||
XNAP_NRModeInfoTDD_t *tdd_Info = servedCellMember->nrModeInfo.choice.tdd;
|
||||
TDDs->freqinfo.arfcn = tdd_Info->nrFrequencyInfo.nrARFCN;
|
||||
AssertFatal(tdd_Info->nrFrequencyInfo.frequencyBand_List.list.count == 1, "cannot handle more than one frequency band\n");
|
||||
for (int f = 0; f < tdd_Info->nrFrequencyInfo.frequencyBand_List.list.count; f++) {
|
||||
XNAP_NRFrequencyBandItem_t *FreqItem = tdd_Info->nrFrequencyInfo.frequencyBand_List.list.array[f];
|
||||
TDDs->freqinfo.band = FreqItem->nr_frequency_band;
|
||||
}
|
||||
TDDs->tbw.scs = tdd_Info->nrTransmissonBandwidth.nRSCS;
|
||||
TDDs->tbw.nrb = tdd_Info->nrTransmissonBandwidth.nRNRB;
|
||||
} else {
|
||||
AssertFatal(false, "unknown NR Mode info \n");
|
||||
}
|
||||
}
|
||||
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, instance, message_p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xnap_gNB_handle_xn_setup_response(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, XNAP_XnAP_PDU_t *pdu)
|
||||
{
|
||||
LOG_D(XNAP, "xnap_gNB_handle_xn_setup_response\n");
|
||||
AssertFatal(pdu->present == XNAP_XnAP_PDU_PR_successfulOutcome, "pdu->present != XNAP_XnAP_PDU_PR_successfulOutcome,\n");
|
||||
AssertFatal(pdu->choice.successfulOutcome->procedureCode == XNAP_ProcedureCode_id_xnSetup,
|
||||
"pdu->choice.successfulOutcome->procedureCode != XNAP_ProcedureCode_id_xnSetup\n");
|
||||
AssertFatal(pdu->choice.successfulOutcome->criticality == XNAP_Criticality_reject,
|
||||
"pdu->choice.successfulOutcome->criticality != XNAP_Criticality_reject\n");
|
||||
AssertFatal(pdu->choice.successfulOutcome->value.present == XNAP_SuccessfulOutcome__value_PR_XnSetupResponse,
|
||||
"pdu->choice.successfulOutcome->value.present != XNAP_SuccessfulOutcome__value_PR_XnSetupResponse\n");
|
||||
|
||||
XNAP_XnSetupResponse_t *xnSetupResponse = &pdu->choice.successfulOutcome->value.choice.XnSetupResponse;
|
||||
XNAP_XnSetupResponse_IEs_t *ie;
|
||||
uint32_t gNB_id = 0;
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_XNAP, 0, XNAP_SETUP_RESP);
|
||||
msg->ittiMsgHeader.originInstance = assoc_id;
|
||||
xnap_setup_resp_t *resp = &XNAP_SETUP_RESP(msg);
|
||||
xnap_gNB_instance_t *instance_p = xnap_gNB_get_instance(instance);
|
||||
xnap_gNB_data_t *xnap_gnb_data_p = xnap_get_gNB(instance, assoc_id);
|
||||
for (int i = 0; i < xnSetupResponse->protocolIEs.list.count; i++) {
|
||||
ie = xnSetupResponse->protocolIEs.list.array[i];
|
||||
|
||||
switch (ie->id) {
|
||||
case XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID:
|
||||
AssertFatal(ie->criticality == XNAP_Criticality_reject, "ie->criticality != XNAP_Criticality_reject\n");
|
||||
AssertFatal(ie->value.present == XNAP_XnSetupResponse_IEs__value_PR_GlobalNG_RANNode_ID,
|
||||
"ie->value.present != XNAP_XnSetupResponse_IEs__value_PR_GlobalNG_RANNode_ID\n");
|
||||
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, "Connected gNB id: %07x\n", gNB_id);
|
||||
LOG_D(XNAP, "Adding gNB to the list of associated gNBs\n");
|
||||
xnap_gnb_data_p->state = XNAP_GNB_STATE_CONNECTED;
|
||||
xnap_gnb_data_p->gNB_id = gNB_id;
|
||||
break;
|
||||
case XNAP_ProtocolIE_ID_id_TAISupport_list:
|
||||
AssertFatal(ie->criticality == XNAP_Criticality_reject, "ie->criticality != XNAP_Criticality_reject\n");
|
||||
AssertFatal(ie->value.present == XNAP_XnSetupResponse_IEs__value_PR_TAISupport_List,
|
||||
"ie->value.present != XNAP_XnSetupResponse_IEs__value_PR_TAISupport_List\n");
|
||||
PLMNID_TO_MCC_MNC(&ie->value.choice.TAISupport_List.list.array[0]->broadcastPLMNs.list.array[0]->plmn_id,
|
||||
resp->info.plmn.mcc,
|
||||
resp->info.plmn.mnc,
|
||||
resp->info.plmn.mnc_digit_length);
|
||||
/*resp.gNB_CU_name = malloc(ie->value.choice.GNB_CU_Name.size+1);
|
||||
memcpy(resp.gNB_CU_name, ie->value.choice.GNB_CU_Name.buf, ie->value.choice.GNB_CU_Name.size);
|
||||
resp.gNB_CU_name[ie->value.choice.GNB_CU_Name.size] = '\0';
|
||||
LOG_D(F1AP, "F1AP: F1Setup-Resp: gNB_CU_name %s\n", resp.gNB_CU_name);*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
// XNAP_ServedCells_NR_Item_t *servedCellMember;
|
||||
|
||||
/* 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)) == 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;
|
||||
}*/
|
||||
/* 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;
|
||||
}
|
||||
|
||||
// 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).info.nr_cellid = 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_p, 0);
|
||||
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, instance_p->instance, msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xnap_gNB_handle_xn_setup_failure(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, XNAP_XnAP_PDU_t *pdu)
|
||||
{
|
||||
DevAssert(pdu != NULL);
|
||||
XNAP_XnSetupFailure_t *xnSetupFailure;
|
||||
XNAP_XnSetupFailure_IEs_t *ie;
|
||||
|
||||
// xnap_gNB_instance_t *instance_p;
|
||||
xnap_gNB_data_t *xnap_gNB_data;
|
||||
|
||||
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(instance, assoc_id)) == 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, assoc_id, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xnap_gNB_handle_handover_request(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, XNAP_XnAP_PDU_t *pdu)
|
||||
{
|
||||
XNAP_HandoverRequest_t *xnHandoverRequest;
|
||||
XNAP_HandoverRequest_IEs_t *ie;
|
||||
xnap_gNB_instance_t *instance_p;
|
||||
xnap_id_manager *id_manager;
|
||||
//xnap_gNB_data_t *xnap_gNB_data;
|
||||
int xn_id;
|
||||
|
||||
instance_p = xnap_gNB_get_instance(instance);
|
||||
updateXninst(0, NULL,NULL,assoc_id);
|
||||
DevAssert(pdu != NULL);
|
||||
xnHandoverRequest = &pdu->choice.initiatingMessage->value.choice.HandoverRequest;
|
||||
if(stream !=0)
|
||||
{
|
||||
LOG_E(XNAP, "Received new XN handover request on stream != 0\n");
|
||||
//sending handover failed
|
||||
MessageDef *message_p = itti_alloc_new_message(TASK_XNAP, 0, XNAP_HANDOVER_REQ_FAILURE);
|
||||
message_p->ittiMsgHeader.originInstance = assoc_id;
|
||||
xnap_handover_req_failure_t *fail = &XNAP_HANDOVER_REQ_FAILURE(message_p);
|
||||
fail->cause_type = XNAP_CAUSE_PROTOCOL;
|
||||
fail->cause_value = 6;
|
||||
itti_send_msg_to_task(TASK_XNAP, 0, message_p);
|
||||
}
|
||||
LOG_D(XNAP, "Received a new XN handover request\n");
|
||||
MessageDef *message_p = itti_alloc_new_message(TASK_XNAP, 0, XNAP_HANDOVER_REQ);
|
||||
message_p->ittiMsgHeader.originInstance = assoc_id;
|
||||
xnap_handover_req_t *req = &XNAP_HANDOVER_REQ(message_p);
|
||||
|
||||
//Source NG-RAN node UE XnAP ID
|
||||
XNAP_FIND_PROTOCOLIE_BY_ID(XNAP_HandoverRequest_IEs_t, ie, xnHandoverRequest, XNAP_ProtocolIE_ID_id_sourceNG_RANnodeUEXnAPID, true);
|
||||
if (ie == NULL) {
|
||||
LOG_E(XNAP, "XNAP_ProtocolIE_ID_id_sourceNG_RANnodeUEXnAPID, is NULL pointer \n");
|
||||
return -1;
|
||||
}else{
|
||||
req->s_ng_node_ue_xnap_id = ie->value.choice.NG_RANnodeUEXnAPID;
|
||||
LOG_I(XNAP, "ue xnap id %d \n", req->s_ng_node_ue_xnap_id);
|
||||
|
||||
}
|
||||
|
||||
|
||||
id_manager = &instance_p->id_manager;
|
||||
xnap_id_manager_init(id_manager);
|
||||
xn_id = xnap_allocate_new_id(id_manager);
|
||||
|
||||
if (xn_id == -1) {
|
||||
LOG_E(XNAP,"could not allocate a new XNAP UE ID\n");
|
||||
/* TODO: cancel handover: send HO preparation failure to source eNB */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//xnap_set_ids(&instance_p->id_manager, xn_id , 0, req->s_ng_node_ue_xnap_id, xn_id);
|
||||
//xnap_id_set_state(&instance_p->id_manager, xn_id, XNID_STATE_TARGET);
|
||||
|
||||
req->t_ng_node_ue_xnap_id = xn_id;
|
||||
|
||||
/*// Target Cell Global ID
|
||||
XNAP_FIND_PROTOCOLIE_BY_ID(XNAP_HandoverRequest_IEs_t, ie, xnHandoverRequest, XNAP_ProtocolIE_ID_id_TargetCellCGI,true);
|
||||
if (ie == NULL) {
|
||||
LOG_E(XNAP, "XNAP_ProtocolIE_ID_id_TargetCellCGI, is NULL pointer \n");
|
||||
return -1;
|
||||
}else{
|
||||
// if (ie->value.choice.Target_CGI.choice.nr->nr_CI.present == XNAP_Target_CGI_PR_nr) { }
|
||||
PLMNID_TO_MCC_MNC(&ie->value.choice.Target_CGI.choice.nr->plmn_id,
|
||||
req->target_cgi.plmn_id.mcc,
|
||||
req->target_cgi.plmn_id.mnc,
|
||||
req->target_cgi.plmn_id.mnc_digit_length);
|
||||
|
||||
BIT_STRING_TO_NR_CELL_IDENTITY( &ie->value.choice.Target_CGI.choice.nr->nr_CI , req->target_cgi.cgi);
|
||||
|
||||
}*/
|
||||
|
||||
// *c = &ie->value.choice.UEContextInfoHORequest.rrc_Context;
|
||||
|
||||
//if (c->size > 8192 /* TODO: this is the size of rrc_buffer in struct x2ap_handover_req_s */){
|
||||
// printf("%s:%d: fatal: buffer too big\n", __FILE__, __LINE__); abort(); }
|
||||
|
||||
|
||||
//memcpy(XNAP_HANDOVER_REQ(msg).rrc_buffer, c->buf, c->size);
|
||||
//XNAP_HANDOVER_REQ(msg).rrc_buffer_size = c->size;
|
||||
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, instance_p->instance, message_p);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int xnap_gNB_handle_handover_response(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, XNAP_XnAP_PDU_t *pdu)
|
||||
{
|
||||
XNAP_HandoverRequestAcknowledge_t *xnHandoverRequestAck;
|
||||
XNAP_HandoverRequestAcknowledge_IEs_t *ie;
|
||||
xnap_gNB_instance_t *instance_p;
|
||||
instance_p = xnap_gNB_get_instance(0);
|
||||
|
||||
/*xnap_id_manager *id_manager;
|
||||
xnap_gNB_data_t *xnap_gNB_data;
|
||||
int ue_id;
|
||||
int id_source;
|
||||
int id_target;
|
||||
int rnti;*/
|
||||
|
||||
DevAssert (pdu != NULL);
|
||||
xnHandoverRequestAck = &pdu->choice.successfulOutcome->value.choice.HandoverRequestAcknowledge;
|
||||
/*
|
||||
if (stream == 0) {
|
||||
LOG_E(XNAP,"Received new xn handover response on stream == 0\n");
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
MessageDef *message_p = itti_alloc_new_message(TASK_XNAP, 0, XNAP_HANDOVER_REQ_ACK);
|
||||
message_p->ittiMsgHeader.originInstance = assoc_id;
|
||||
xnap_handover_req_ack_t *ack = &XNAP_HANDOVER_REQ_ACK(message_p);
|
||||
|
||||
//Source NG-RAN node UE XnAP ID
|
||||
XNAP_FIND_PROTOCOLIE_BY_ID(XNAP_HandoverRequestAcknowledge_IEs_t, ie, xnHandoverRequestAck, XNAP_ProtocolIE_ID_id_sourceNG_RANnodeUEXnAPID, true);
|
||||
if (ie == NULL) {
|
||||
LOG_E(XNAP, "XNAP_ProtocolIE_ID_id_sourceNG_RANnodeUEXnAPID, is NULL pointer \n");
|
||||
itti_free(ITTI_MSG_ORIGIN_ID(message_p),message_p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ack->s_ng_node_ue_xnap_id = ie->value.choice.NG_RANnodeUEXnAPID;
|
||||
|
||||
/* XNAP_FIND_PROTOCOLIE_BY_ID(XNAP_HandoverRequestAcknowledge_IEs_t, ie, xnHandoverRequestAck, XNAP_ProtocolIE_ID_id_targetCellGlobalID, true);
|
||||
if (ie == NULL) {
|
||||
LOG_E(XNAP, "XNAP_ProtocolIE_ID_id_targetCellGlobalID, is NULL pointer \n");
|
||||
itti_free(ITTI_MSG_ORIGIN_ID(message_p),message_p);
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
|
||||
XNAP_FIND_PROTOCOLIE_BY_ID(XNAP_HandoverRequestAcknowledge_IEs_t, ie, xnHandoverRequestAck, XNAP_ProtocolIE_ID_id_Target2SourceNG_RANnodeTranspContainer, true);
|
||||
if (ie == NULL) {
|
||||
LOG_E(XNAP, "iXNAP_ProtocolIE_ID_id_Target2SourceNG_RANnodeTranspContainer is NULL pointer \n");
|
||||
itti_free(ITTI_MSG_ORIGIN_ID(message_p),message_p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
OCTET_STRING_t *c = &ie->value.choice.OCTET_STRING;
|
||||
if (c->size > 1024){
|
||||
LOG_I(XNAP,"c is not NULL");
|
||||
}
|
||||
//{ printf("%s:%d: fatal: buffer too big\n", __FILE__, __LINE__); abort(); }
|
||||
|
||||
memcpy(ack->rrc_buffer, c->buf, c->size);
|
||||
ack->rrc_buffer_size = c->size;
|
||||
|
||||
//memcpy(XNAP_HANDOVER_REQ_ACK(message_p).rrc_buffer, ie->value.choice.OCTET_STRING.buf, ie->value.choice.OCTET_STRING.size);
|
||||
//XNAP_HANDOVER_REQ_ACK(message_p).rrc_buffer_size = ie->value.choice.OCTET_STRING.size;
|
||||
/*
|
||||
id_target = ie->value.choice.NG_RANnodeUEXnAPID_1;
|
||||
ue_id = id_source;
|
||||
|
||||
if (ue_id != xnap_find_id_from_id_source(&instance_p->id_manager, id_source)) {
|
||||
LOG_E(XNAP, "incorrect/unknown XNAP IDs for UE (old ID %d new ID %d), ignoring handover response\n",id_source, id_target);
|
||||
itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
|
||||
return 0;
|
||||
}
|
||||
rnti = xnap_id_get_rnti(&instance_p->id_manager, ue_id);
|
||||
xnap_set_ids(&instance_p->id_manager, ue_id, rnti, id_source, id_target);
|
||||
xnap_id_set_state(&instance_p->id_manager, ue_id, XNID_STATE_SOURCE_OVERALL);
|
||||
//xnap_set_reloc_overall_timer(&instance_p->id_manager, ue_id,xnap_timer_get_tti(&instance_p->timers));
|
||||
|
||||
XNAP_HANDOVER_REQ_ACK(message_p).rnti = rnti;
|
||||
*/
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, instance_p->instance, message_p);
|
||||
return 0;
|
||||
|
||||
}
|
||||
39
openair2/XNAP/xnap_gNB_interface_management.h
Normal file
39
openair2/XNAP/xnap_gNB_interface_management.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_interface_management.h
|
||||
* \brief xnap interface handler procedures for gNB
|
||||
* \date 2023 Dec
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#ifndef XNAP_GNB_INTERFACE_MANAGEMENT_H_
|
||||
#define XNAP_GNB_INTERFACE_MANAGEMENT_H_
|
||||
|
||||
/*Xn Setup*/
|
||||
int xnap_gNB_handle_xn_setup_request(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, XNAP_XnAP_PDU_t *pdu);
|
||||
int xnap_gNB_handle_xn_setup_response(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, XNAP_XnAP_PDU_t *pdu);
|
||||
int xnap_gNB_handle_xn_setup_failure(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, XNAP_XnAP_PDU_t *pdu);
|
||||
int xnap_gNB_handle_handover_request(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, XNAP_XnAP_PDU_t *pdu);
|
||||
int xnap_gNB_handle_handover_response(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, XNAP_XnAP_PDU_t *pdu);
|
||||
|
||||
|
||||
#endif /* XNAP_GNB_INTERFACE_MANAGEMENT_H_ */
|
||||
40
openair2/XNAP/xnap_gNB_itti_messaging.c
Normal file
40
openair2/XNAP/xnap_gNB_itti_messaging.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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(sctp_assoc_t assoc_id, uint8_t *buffer, uint32_t buffer_length, uint16_t stream)
|
||||
{
|
||||
MessageDef *message_p;
|
||||
sctp_data_req_t *sctp_data_req;
|
||||
instance_t instance = 0; // we have only one instance
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
34
openair2/XNAP/xnap_gNB_itti_messaging.h
Normal file
34
openair2/XNAP/xnap_gNB_itti_messaging.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file xnap_gNB_itti_messaging.h
|
||||
* \brief xnap itti messaging 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(sctp_assoc_t assoc_id, uint8_t *buffer, uint32_t buffer_length, uint16_t stream);
|
||||
|
||||
|
||||
#endif /* XNAP_GNB_ITTI_MESSAGING_H_ */
|
||||
203
openair2/XNAP/xnap_gNB_management_procedures.c
Normal file
203
openair2/XNAP/xnap_gNB_management_procedures.c
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
// xnap_gNB_internal_data_t xnap_gNB_internal_data;
|
||||
static xnap_gNB_instance_t *xn_inst[NUMBER_OF_gNB_MAX] = {0};
|
||||
|
||||
static int xnap_gNB_compare_assoc_id(const xnap_gNB_data_t *p1, const xnap_gNB_data_t *p2)
|
||||
{
|
||||
if (p1->assoc_id > p2->assoc_id)
|
||||
return 1;
|
||||
if (p1->assoc_id == p2->assoc_id)
|
||||
return 0;
|
||||
return -1; /* p1->assoc_id < p1->assoc_id */
|
||||
}
|
||||
|
||||
RB_GENERATE(xnap_gnb_tree, xnap_gNB_data_t, 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;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
static pthread_mutex_t xn_inst_mtx = PTHREAD_MUTEX_INITIALIZER;
|
||||
void createXninst(instance_t instanceP, xnap_setup_req_t *req, xnap_net_config_t *nc)
|
||||
{
|
||||
DevAssert(instanceP == 0);
|
||||
pthread_mutex_lock(&xn_inst_mtx);
|
||||
AssertFatal(xn_inst[0] == NULL, "Attempted to initialize multiple Xn instances\n");
|
||||
xn_inst[0] = calloc(1, sizeof(xnap_gNB_instance_t));
|
||||
AssertFatal(xn_inst[0] != NULL, "out of memory\n");
|
||||
if (req)
|
||||
xn_inst[0]->setup_req = *req;
|
||||
if (nc)
|
||||
xn_inst[0]->net_config = *nc;
|
||||
pthread_mutex_unlock(&xn_inst_mtx);
|
||||
}
|
||||
|
||||
void updateXninst(instance_t instanceP, xnap_setup_req_t *req, xnap_net_config_t *nc,sctp_assoc_t assoc_id)
|
||||
{
|
||||
DevAssert(instanceP == 0);
|
||||
pthread_mutex_lock(&xn_inst_mtx);
|
||||
AssertFatal(xn_inst[instanceP] != NULL, "XN instance not found\n");
|
||||
if (req)
|
||||
xn_inst[instanceP]->setup_req = *req;
|
||||
if (nc)
|
||||
xn_inst[instanceP]->net_config = *nc;
|
||||
if (assoc_id)
|
||||
xn_inst[instanceP]->assoc_id_temp = assoc_id;
|
||||
pthread_mutex_unlock(&xn_inst_mtx);
|
||||
}
|
||||
|
||||
|
||||
void xnap_dump_trees(const instance_t instance)
|
||||
{
|
||||
pthread_mutex_lock(&xn_inst_mtx);
|
||||
printf("%ld connected gNBs \n", xn_inst[instance]->num_gnbs);
|
||||
xnap_gNB_data_t *xnap_gnb_data_p = NULL;
|
||||
/* cast is necessary to eliminate warning "discards ‘const’ qualifier" */
|
||||
RB_FOREACH (xnap_gnb_data_p, xnap_gnb_tree, &((xnap_gNB_instance_t *)xn_inst[instance])->xnap_gnbs) {
|
||||
if (xnap_gnb_data_p->assoc_id == -1) {
|
||||
printf("integrated gNB");
|
||||
printf("cnx_id %d\n", xnap_gnb_data_p->cnx_id);
|
||||
} else {
|
||||
printf("assoc_id %d", xnap_gnb_data_p->assoc_id);
|
||||
printf("state %d\n", xnap_gnb_data_p->state);
|
||||
printf("cnx_id %d\n", xnap_gnb_data_p->cnx_id);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&xn_inst_mtx);
|
||||
}
|
||||
|
||||
xnap_gNB_data_t *xnap_get_gNB(instance_t instance, sctp_assoc_t assoc_id)
|
||||
{
|
||||
AssertFatal(assoc_id != 0, "illegal assoc_id == 0: should be -1 or >0)\n");
|
||||
xnap_gNB_data_t e = {.assoc_id = assoc_id};
|
||||
pthread_mutex_lock(&xn_inst_mtx);
|
||||
xnap_gNB_data_t *xnap_gnb = RB_FIND(xnap_gnb_tree, &xn_inst[instance]->xnap_gnbs, &e);
|
||||
if (xnap_gnb == NULL) {
|
||||
LOG_W(NR_RRC, "no gNB connected or not found for assoc_id %d:\n", assoc_id);
|
||||
pthread_mutex_unlock(&xn_inst_mtx);
|
||||
return NULL;
|
||||
}
|
||||
pthread_mutex_unlock(&xn_inst_mtx);
|
||||
return xnap_gnb;
|
||||
}
|
||||
|
||||
xnap_gNB_instance_t *xnap_gNB_get_instance(instance_t instanceP)
|
||||
{
|
||||
DevAssert(instanceP == 0);
|
||||
pthread_mutex_lock(&xn_inst_mtx);
|
||||
xnap_gNB_instance_t *instance_xnap = xn_inst[instanceP];
|
||||
pthread_mutex_unlock(&xn_inst_mtx);
|
||||
return instance_xnap;
|
||||
}
|
||||
|
||||
sctp_assoc_t xnap_gNB_get_assoc_id(xnap_gNB_instance_t *instance, long nci)
|
||||
{
|
||||
struct xnap_gNB_data_t *entry;
|
||||
RB_FOREACH(entry, xnap_gnb_tree, &instance->xnap_gnbs) {
|
||||
if (entry->nci == nci) {
|
||||
LOG_I(XNAP,"ASSOC ID %d \n",entry->assoc_id);
|
||||
return entry->assoc_id;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void xnap_insert_gnb(instance_t instance, xnap_gNB_data_t *xnap_gnb_data_p)
|
||||
{
|
||||
pthread_mutex_lock(&xn_inst_mtx);
|
||||
RB_INSERT(xnap_gnb_tree, &xn_inst[instance]->xnap_gnbs, xnap_gnb_data_p);
|
||||
xn_inst[instance]->num_gnbs++;
|
||||
pthread_mutex_unlock(&xn_inst_mtx);
|
||||
}
|
||||
|
||||
void xnap_handle_xn_setup_message(instance_t instance, sctp_assoc_t assoc_id, int sctp_shutdown)
|
||||
{
|
||||
if (sctp_shutdown) {
|
||||
/* A previously connected gNB has been shutdown */
|
||||
xnap_gNB_data_t *gnb_data_p = xnap_get_gNB(instance, assoc_id);
|
||||
if (gnb_data_p == NULL) {
|
||||
LOG_W(XNAP, "no gNB connected or not found for assoc_id %d:\n", assoc_id);
|
||||
return;
|
||||
}
|
||||
pthread_mutex_lock(&xn_inst_mtx);
|
||||
if (gnb_data_p->state == XNAP_GNB_STATE_CONNECTED) {
|
||||
gnb_data_p->state = XNAP_GNB_STATE_DISCONNECTED;
|
||||
// Removing the gNB data from tree
|
||||
RB_REMOVE(xnap_gnb_tree, &xn_inst[instance]->xnap_gnbs, gnb_data_p);
|
||||
if (xn_inst[instance]->xn_target_gnb_associated_nb > 0) {
|
||||
/* Decrease associated gNB number */
|
||||
xn_inst[instance]->xn_target_gnb_associated_nb--;
|
||||
}
|
||||
|
||||
/* If there are no more associated gNB */
|
||||
if (xn_inst[instance]->xn_target_gnb_associated_nb == 0) {
|
||||
// TODO : Inform GNB_APP ???
|
||||
LOG_I(XNAP, "No more associated gNBs- Number of connected gNBS : %d \n", xn_inst[instance]->xn_target_gnb_associated_nb);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Check that at least one setup message is pending */
|
||||
DevCheck(xn_inst[instance]->xn_target_gnb_pending_nb > 0, instance, xn_inst[instance]->xn_target_gnb_pending_nb, 0);
|
||||
|
||||
if (xn_inst[instance]->xn_target_gnb_pending_nb > 0) {
|
||||
/* Decrease pending messages number */
|
||||
xn_inst[instance]->xn_target_gnb_pending_nb--;
|
||||
}
|
||||
|
||||
/* If there are no more pending messages */
|
||||
if (xn_inst[instance]->xn_target_gnb_pending_nb == 0) {
|
||||
// TODO : Need to inform GNB_APP??
|
||||
LOG_I(XNAP, "No more pending messages- Number of connected gNBS : %d", xn_inst[instance]->xn_target_gnb_associated_nb);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&xn_inst_mtx);
|
||||
}
|
||||
|
||||
47
openair2/XNAP/xnap_gNB_management_procedures.h
Normal file
47
openair2/XNAP/xnap_gNB_management_procedures.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef __XNAP_GNB_MANAGEMENT_PROCEDURES__H__
|
||||
#define __XNAP_GNB_MANAGEMENT_PROCEDURES__H__
|
||||
|
||||
// void xnap_gNB_prepare_internal_data(void);
|
||||
void createXninst(instance_t instanceP, xnap_setup_req_t *req, xnap_net_config_t *nc);
|
||||
void updateXninst(instance_t instanceP, xnap_setup_req_t *req, xnap_net_config_t *nc,sctp_assoc_t assoc_id);
|
||||
sctp_assoc_t xnap_gNB_get_assoc_id(xnap_gNB_instance_t *instance, long nci);
|
||||
// void xnap_dump_trees(void);
|
||||
void xnap_dump_trees(const instance_t instance);
|
||||
// void xnap_gNB_insert_new_instance(xnap_gNB_instance_t *new_instance_p);
|
||||
xnap_gNB_instance_t *xnap_gNB_get_instance(instance_t instanceP);
|
||||
|
||||
// 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);
|
||||
|
||||
xnap_gNB_data_t *xnap_get_gNB(instance_t instance, sctp_assoc_t assoc_id);
|
||||
void xnap_insert_gnb(instance_t instance, xnap_gNB_data_t *xnap_gnb_data_p);
|
||||
void xnap_handle_xn_setup_message(instance_t instance, sctp_assoc_t assoc_id, int sctp_shutdown);
|
||||
#endif /* __XNAP_GNB_MANAGEMENT_PROCEDURES__H__ */
|
||||
362
openair2/XNAP/xnap_gNB_task.c
Normal file
362
openair2/XNAP/xnap_gNB_task.c
Normal file
@@ -0,0 +1,362 @@
|
||||
/* 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 "queue.h"
|
||||
#include "assertions.h"
|
||||
#include "conversions.h"
|
||||
#include "xnap_gNB_generate_messages.h"
|
||||
#include "gnb_config.h"
|
||||
#include "xnap_ids.h"
|
||||
|
||||
RB_PROTOTYPE(xnap_gnb_tree, xnap_gNB_data_t, 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_send_sctp_assoc_req(instance_t instance_p, xnap_net_config_t *nc, int index);
|
||||
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_xn = xnap_gNB_get_instance(instance); // managementproc;
|
||||
DevAssert(sctp_new_association_resp != NULL);
|
||||
DevAssert(instance_xn != NULL);
|
||||
/*Return if connection to gNB failed- to be modified if needed. (Exit on error in X2AP)*/
|
||||
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");
|
||||
return;
|
||||
}
|
||||
if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
|
||||
LOG_W(XNAP,
|
||||
"Received unsuccessful result for SCTP association state (%u), assoc_id (%d), instance %ld, cnx_id %u \n",
|
||||
sctp_new_association_resp->sctp_state,
|
||||
sctp_new_association_resp->assoc_id,
|
||||
instance,
|
||||
sctp_new_association_resp->ulp_cnx_id);
|
||||
xnap_handle_xn_setup_message(instance,
|
||||
sctp_new_association_resp->assoc_id,
|
||||
sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
|
||||
// sleep(3);
|
||||
// xnap_gNB_send_sctp_assoc_req(instance, &instance_xn->net_config, sctp_new_association_resp->ulp_cnx_id);
|
||||
return; // exit -1 for debugging
|
||||
}
|
||||
|
||||
xnap_gNB_data_t *xnap_gnb_data_p = calloc(1, sizeof(*xnap_gnb_data_p));
|
||||
AssertFatal(xnap_gnb_data_p != NULL, "out of memory\n");
|
||||
xnap_gnb_data_p->cnx_id = sctp_new_association_resp->ulp_cnx_id;
|
||||
xnap_gnb_data_p->assoc_id = sctp_new_association_resp->assoc_id;
|
||||
xnap_gnb_data_p->state = XNAP_GNB_STATE_WAITING;
|
||||
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_gnb_data_p->nci = 12345678;
|
||||
xnap_insert_gnb(instance, xnap_gnb_data_p);
|
||||
xnap_dump_trees(instance);
|
||||
xnap_gNB_generate_xn_setup_request(sctp_new_association_resp->assoc_id, &instance_xn->setup_req);
|
||||
}
|
||||
|
||||
int xnap_gNB_init_sctp(instance_t instance_p, xnap_net_config_t *nc)
|
||||
{
|
||||
// Create and alloc new message
|
||||
MessageDef *message;
|
||||
sctp_init_t *sctp_init = NULL;
|
||||
DevAssert(nc != NULL);
|
||||
message = itti_alloc_new_message(TASK_XNAP, 0, SCTP_INIT_MSG_MULTI_REQ);
|
||||
sctp_init = &message->ittiMsg.sctp_init_multi;
|
||||
sctp_init->port = nc->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,
|
||||
nc->gnb_xn_ip_address,
|
||||
sizeof(*nc->gnb_xn_ip_address));
|
||||
#endif
|
||||
sctp_init->ipv4_address[0] = inet_addr(nc->gnb_xn_ip_address.ipv4_address);
|
||||
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, message);
|
||||
}
|
||||
|
||||
static void xnap_gNB_send_sctp_assoc_req(instance_t instance, xnap_net_config_t *nc, int index)
|
||||
{
|
||||
MessageDef *message = NULL;
|
||||
sctp_new_association_req_t *sctp_new_association_req = NULL;
|
||||
DevAssert(nc != NULL);
|
||||
message = itti_alloc_new_message(TASK_XNAP, 0, SCTP_NEW_ASSOCIATION_REQ);
|
||||
sctp_new_association_req = &message->ittiMsg.sctp_new_association_req;
|
||||
sctp_new_association_req->port = nc->gnb_port_for_XNC;
|
||||
sctp_new_association_req->ppid = XNAP_SCTP_PPID;
|
||||
sctp_new_association_req->in_streams = nc->sctp_streams.sctp_in_streams;
|
||||
sctp_new_association_req->out_streams = nc->sctp_streams.sctp_out_streams;
|
||||
|
||||
memcpy(&sctp_new_association_req->remote_address,
|
||||
&nc->target_gnb_xn_ip_address[index],
|
||||
sizeof(nc->target_gnb_xn_ip_address[index]));
|
||||
memcpy(&sctp_new_association_req->local_address, &nc->gnb_xn_ip_address, sizeof(nc->gnb_xn_ip_address));
|
||||
sctp_new_association_req->ulp_cnx_id = index;
|
||||
itti_send_msg_to_task(TASK_SCTP, instance, message);
|
||||
}
|
||||
|
||||
static void xnap_gNB_handle_sctp_init_msg_multi_cnf(instance_t instance, sctp_init_msg_multi_cnf_t *m)
|
||||
{
|
||||
xnap_gNB_instance_t *instance_xn = xnap_gNB_get_instance(instance);
|
||||
DevAssert(m != NULL);
|
||||
DevAssert(instance_xn != NULL);
|
||||
// instance->multi_sd = m->multi_sd;
|
||||
|
||||
/* Exit if CNF message reports failure.
|
||||
* Failure means multi_sd < 0.
|
||||
*/
|
||||
if (m->multi_sd < 0) {
|
||||
LOG_E(XNAP, "Error: be sure to properly configure XN in your configuration file.\n");
|
||||
DevAssert(m->multi_sd >= 0);
|
||||
}
|
||||
|
||||
/* Trying to connect to the provided list of gNB ip address */
|
||||
|
||||
for (int index = 0; index < instance_xn->net_config.nb_xn; index++) {
|
||||
LOG_I(XNAP, "gNB[%ld] gNB id %lx index %d acting as an initiator (client)\n", instance, instance_xn->setup_req.gNB_id, index);
|
||||
instance_xn->xn_target_gnb_pending_nb++;
|
||||
xnap_gNB_send_sctp_assoc_req(instance, &instance_xn->net_config, index);
|
||||
}
|
||||
}
|
||||
|
||||
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_get_instance(instance);
|
||||
DevAssert(instance_p != NULL);
|
||||
xnap_gNB_data_t *xnap_gnb_data_p;
|
||||
DevAssert(sctp_new_association_ind != NULL);
|
||||
LOG_W(XNAP, "SCTP Association IND Received.\n");
|
||||
//xnap_dump_trees(instance);
|
||||
xnap_gnb_data_p = xnap_get_gNB(instance, sctp_new_association_ind->assoc_id);
|
||||
if (xnap_gnb_data_p == NULL) {
|
||||
LOG_W(XNAP, "xnap_gnb_data_p does not exist, creating new descriptor\n");
|
||||
/* TODO: Create new gNB descriptor-not yet associated? */
|
||||
xnap_gNB_data_t *xnap_gnb_data_p = calloc(1, sizeof(*xnap_gnb_data_p));
|
||||
AssertFatal(xnap_gnb_data_p != NULL, "out of memory\n");
|
||||
xnap_gnb_data_p->assoc_id = sctp_new_association_ind->assoc_id;
|
||||
xnap_gnb_data_p->nci = 12345678;
|
||||
xnap_gnb_data_p->state = XNAP_GNB_STATE_WAITING;
|
||||
xnap_gnb_data_p->in_streams = sctp_new_association_ind->in_streams;
|
||||
xnap_gnb_data_p->out_streams = sctp_new_association_ind->out_streams;
|
||||
//xnap_dump_trees(instance);
|
||||
xnap_insert_gnb(instance, xnap_gnb_data_p);
|
||||
xnap_dump_trees(instance);
|
||||
} else {
|
||||
xnap_gnb_data_p->in_streams = sctp_new_association_ind->in_streams;
|
||||
xnap_gnb_data_p->out_streams = sctp_new_association_ind->out_streams;
|
||||
LOG_W(XNAP, "Updated streams for assoc id: %d \n", sctp_new_association_ind->assoc_id);
|
||||
}
|
||||
xnap_dump_trees(instance);
|
||||
}
|
||||
|
||||
static
|
||||
void xnap_gNB_handle_handover_prep(instance_t instance,
|
||||
xnap_handover_req_t *xnap_handover_req)
|
||||
{
|
||||
xnap_gNB_instance_t *instance_p;
|
||||
xnap_id_manager *id_manager;
|
||||
int ue_id;
|
||||
sctp_assoc_t assoc_id;
|
||||
|
||||
instance_p = xnap_gNB_get_instance(instance);
|
||||
DevAssert(instance_p != NULL);
|
||||
int target_nci = xnap_handover_req->target_cgi.cgi;
|
||||
assoc_id = xnap_gNB_get_assoc_id(instance_p,target_nci);
|
||||
|
||||
/* allocate xnap ID */
|
||||
id_manager = &instance_p->id_manager;
|
||||
xnap_id_manager_init(id_manager);
|
||||
int xn_id = xnap_allocate_new_id(id_manager);
|
||||
|
||||
LOG_I(XNAP, "NR Cell ID: %d \n",target_nci);
|
||||
LOG_I(XNAP, "Association ID: %d \n",assoc_id);
|
||||
//xnap_handover_req_t *req = &XNAP_HANDOVER_REQ(message_p);
|
||||
if (xn_id == -1) {
|
||||
LOG_E(XNAP,"could not allocate a new XNAP UE ID\n");
|
||||
/* TODO: cancel handover: send (to be defined) message to RRC */
|
||||
exit(1);
|
||||
}
|
||||
xnap_handover_req->s_ng_node_ue_xnap_id = xn_id;
|
||||
xnap_set_ids(id_manager, xnap_handover_req->s_ng_node_ue_xnap_id, xnap_handover_req->ue_id, xnap_handover_req->s_ng_node_ue_xnap_id, 0);
|
||||
/* id_source is ue_id, id_target is unknown yet */
|
||||
//xnap_set_ids(id_manager, ue_id, xnap_handover_req->rnti, ue_id, -1); //use?ho req structure wont have rnti- take from where it belongs to.
|
||||
//xnap_id_set_state(id_manager, ue_id, XNID_STATE_SOURCE_PREPARE);// use?
|
||||
//xnap_set_reloc_prep_timer(id_manager, ue_id,
|
||||
//xnap_timer_get_tti(&instance_p->timers));
|
||||
//xnap_id_set_target(id_manager, ue_id, target);
|
||||
|
||||
//xnap_gNB_generate_xn_handover_request(instance_p, target, xnap_handover_req, ue_id); //Review removed target here but needs it
|
||||
xnap_gNB_generate_xn_handover_request(assoc_id, xnap_handover_req);
|
||||
}
|
||||
|
||||
|
||||
void *xnap_task(void *arg)
|
||||
{
|
||||
MessageDef *received_msg = NULL;
|
||||
int result;
|
||||
LOG_D(XNAP, "Starting XNAP layer\n");
|
||||
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_net_config_t *xn_nc = &XNAP_REGISTER_GNB_REQ(received_msg).net_config;
|
||||
xnap_gNB_init_sctp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), xn_nc);
|
||||
} break;
|
||||
|
||||
case XNAP_SETUP_FAILURE: // from rrc/xnap
|
||||
xnap_gNB_generate_xn_setup_failure(ITTI_MSG_ORIGIN_INSTANCE(received_msg), &XNAP_SETUP_FAILURE(received_msg));
|
||||
break;
|
||||
|
||||
case XNAP_SETUP_RESP: // from rrc
|
||||
xnap_gNB_generate_xn_setup_response(ITTI_MSG_ORIGIN_INSTANCE(received_msg), &XNAP_SETUP_RESP(received_msg));
|
||||
break;
|
||||
|
||||
case XNAP_HANDOVER_REQ: // from rrc
|
||||
xnap_gNB_handle_handover_prep(ITTI_MSG_ORIGIN_INSTANCE(received_msg),
|
||||
&XNAP_HANDOVER_REQ(received_msg));
|
||||
break;
|
||||
case XNAP_HANDOVER_REQ_ACK:
|
||||
LOG_I(XNAP,"HANDOVER_ACK going into the function \n");
|
||||
xnap_gNB_generate_xn_handover_request_ack(ITTI_MSG_ORIGIN_INSTANCE(received_msg), &XNAP_HANDOVER_REQ_ACK(received_msg),ITTI_MSG_DESTINATION_INSTANCE(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(config_get_if(), p, sizeofArray(p), "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(config_get_if(), p, sizeofArray(p), "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);
|
||||
}
|
||||
41
openair2/XNAP/xnap_gNB_task.h
Normal file
41
openair2/XNAP/xnap_gNB_task.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
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#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(instance_t instance_p, xnap_net_config_t *nc);
|
||||
|
||||
void *xnap_task(void *arg);
|
||||
|
||||
int is_xnap_enabled(void);
|
||||
void xnap_trigger(void);
|
||||
|
||||
#endif /* XNAP_H_ */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
149
openair2/XNAP/xnap_ids.c
Normal file
149
openair2/XNAP/xnap_ids.c
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
/* Poornima */
|
||||
#include "xnap_ids.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
void xnap_id_manager_init(xnap_id_manager *m)
|
||||
{
|
||||
int i;
|
||||
memset(m, 0, sizeof(xnap_id_manager));
|
||||
for (i = 0; i < XNAP_MAX_IDS; i++)
|
||||
m->ids[i].cu_ue_id = -1;
|
||||
}
|
||||
|
||||
int xnap_allocate_new_id(xnap_id_manager *m)
|
||||
{
|
||||
int i;
|
||||
printf("cu_ue_id: %d \n",m->ids[0].cu_ue_id);
|
||||
for (i = 0; i < XNAP_MAX_IDS; i++)
|
||||
if (m->ids[i].cu_ue_id == -1) {
|
||||
m->ids[i].cu_ue_id = 0;
|
||||
m->ids[i].id_source = -1;
|
||||
m->ids[i].id_target = -1;
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void xnap_release_id(xnap_id_manager *m, int id)
|
||||
{
|
||||
m->ids[id].cu_ue_id = -1;
|
||||
}
|
||||
|
||||
int xnap_find_id(xnap_id_manager *m, int id_source, int id_target)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < XNAP_MAX_IDS; i++)
|
||||
if (m->ids[i].cu_ue_id != -1 &&
|
||||
m->ids[i].id_source == id_source &&
|
||||
m->ids[i].id_target == id_target)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int xnap_find_id_from_id_source(xnap_id_manager *m, int id_source)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < XNAP_MAX_IDS; i++)
|
||||
if (m->ids[i].cu_ue_id != -1 &&
|
||||
m->ids[i].id_source == id_source)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int xnap_find_id_from_id_target(xnap_id_manager *m, int id_target)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < XNAP_MAX_IDS; i++)
|
||||
if (m->ids[i].cu_ue_id != -1 &&
|
||||
m->ids[i].id_target == id_target)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int xnap_find_id_from_cu_ue_id(xnap_id_manager *m, int cu_ue_id)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < XNAP_MAX_IDS; i++)
|
||||
if (m->ids[i].cu_ue_id == cu_ue_id)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void xnap_set_ids(xnap_id_manager *m, int ue_id, int cu_ue_id, int id_source, int id_target)
|
||||
{
|
||||
m->ids[ue_id].cu_ue_id = cu_ue_id;
|
||||
m->ids[ue_id].id_source = id_source;
|
||||
m->ids[ue_id].id_target = id_target;
|
||||
}
|
||||
|
||||
/* real type of target is xnap_gNB_data_t * */
|
||||
void xnap_id_set_target(xnap_id_manager *m, int ue_id, void *target)
|
||||
{
|
||||
m->ids[ue_id].target = target;
|
||||
}
|
||||
|
||||
void xnap_id_set_state(xnap_id_manager *m, int ue_id, xnid_state_t state)
|
||||
{
|
||||
m->ids[ue_id].state = state;
|
||||
}
|
||||
|
||||
void xnap_set_reloc_prep_timer(xnap_id_manager *m, int ue_id, uint64_t time)
|
||||
{
|
||||
m->ids[ue_id].t_reloc_prep_start = time;
|
||||
}
|
||||
|
||||
void xnap_set_reloc_overall_timer(xnap_id_manager *m, int ue_id, uint64_t time)
|
||||
{
|
||||
m->ids[ue_id].tx2_reloc_overall_start = time;
|
||||
}
|
||||
|
||||
void xnap_set_dc_prep_timer(xnap_id_manager *m, int ue_id, uint64_t time)
|
||||
{
|
||||
m->ids[ue_id].t_dc_prep_start = time;
|
||||
}
|
||||
|
||||
void xnap_set_dc_overall_timer(xnap_id_manager *m, int ue_id, uint64_t time)
|
||||
{
|
||||
m->ids[ue_id].t_dc_overall_start = time;
|
||||
}
|
||||
|
||||
int xnap_id_get_id_source(xnap_id_manager *m, int ue_id)
|
||||
{
|
||||
return m->ids[ue_id].id_source;
|
||||
}
|
||||
|
||||
int xnap_id_get_id_target(xnap_id_manager *m, int ue_id)
|
||||
{
|
||||
return m->ids[ue_id].id_target;
|
||||
}
|
||||
|
||||
int xnap_id_get_ueid(xnap_id_manager *m, int xn_id)
|
||||
{
|
||||
return m->ids[xn_id].cu_ue_id;
|
||||
}
|
||||
|
||||
void *xnap_id_get_target(xnap_id_manager *m, int ue_id)
|
||||
{
|
||||
return m->ids[ue_id].target;
|
||||
}
|
||||
88
openair2/XNAP/xnap_ids.h
Normal file
88
openair2/XNAP/xnap_ids.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
/* Poornima */
|
||||
#ifndef XNAP_IDS_H_
|
||||
#define XNAP_IDS_H_
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* maximum number of simultaneous handovers, do not set too high */
|
||||
#define XNAP_MAX_IDS 16
|
||||
|
||||
/*
|
||||
* state:
|
||||
* - when starting handover in source, UE is in state XNID_STATE_SOURCE_PREPARE
|
||||
* - after receiving HO_ack in source, UE is in state XNID_STATE_SOURCE_OVERALL
|
||||
* - in target, UE is in state XNID_STATE_TARGET
|
||||
* The state is used to check timers.
|
||||
*/
|
||||
typedef enum {
|
||||
XNID_STATE_SOURCE_PREPARE,
|
||||
XNID_STATE_SOURCE_OVERALL,
|
||||
XNID_STATE_TARGET,
|
||||
XNID_STATE_NSA_GNB_PREPARE,
|
||||
XNID_STATE_NSA_GNB_OVERALL,
|
||||
} xnid_state_t;
|
||||
|
||||
typedef struct {
|
||||
int cu_ue_id; /* -1 when free */
|
||||
int id_source;
|
||||
int id_target;
|
||||
|
||||
/* the target eNB. Real type is x2ap_eNB_data_t * */
|
||||
void *target;
|
||||
|
||||
/* state: needed to check timers */
|
||||
xnid_state_t state;
|
||||
|
||||
/* timers */
|
||||
uint64_t t_reloc_prep_start;
|
||||
uint64_t tx2_reloc_overall_start;
|
||||
uint64_t t_dc_prep_start;
|
||||
uint64_t t_dc_overall_start;
|
||||
} xnap_id;
|
||||
|
||||
typedef struct {
|
||||
xnap_id ids[XNAP_MAX_IDS];
|
||||
} xnap_id_manager;
|
||||
|
||||
void xnap_id_manager_init(xnap_id_manager *m);
|
||||
int xnap_allocate_new_id(xnap_id_manager *m);
|
||||
void xnap_release_id(xnap_id_manager *m, int id);
|
||||
int xnap_find_id(xnap_id_manager *, int id_source, int id_target);
|
||||
int xnap_find_id_from_id_source(xnap_id_manager *, int id_source);
|
||||
int xnap_find_id_from_id_target(xnap_id_manager *, int id_source);
|
||||
int xnap_find_id_from_rnti(xnap_id_manager *, int rnti);
|
||||
void xnap_set_ids(xnap_id_manager *m, int ue_id, int rnti, int id_source, int id_target);
|
||||
void xnap_id_set_state(xnap_id_manager *m, int ue_id, xnid_state_t state);
|
||||
/* real type of target is x2ap_eNB_data_t * */
|
||||
void xnap_id_set_target(xnap_id_manager *m, int ue_id, void *target);
|
||||
void xnap_set_reloc_prep_timer(xnap_id_manager *m, int ue_id, uint64_t time);
|
||||
void xnap_set_reloc_overall_timer(xnap_id_manager *m, int ue_id, uint64_t time);
|
||||
void xnap_set_dc_prep_timer(xnap_id_manager *m, int ue_id, uint64_t time);
|
||||
void xnap_set_dc_overall_timer(xnap_id_manager *m, int ue_id, uint64_t time);
|
||||
int xnap_id_get_id_source(xnap_id_manager *m, int ue_id);
|
||||
int xnap_id_get_id_target(xnap_id_manager *m, int ue_id);
|
||||
int xnap_id_get_ueid(xnap_id_manager *m, int xn_id);
|
||||
//int xnap_id_get_rnti(xnap_id_manager *m, int ue_id);
|
||||
void *xnap_id_get_target(xnap_id_manager *m, int ue_id);
|
||||
|
||||
#endif /* X2AP_IDS_H_ */
|
||||
163
openair2/XNAP/xnap_timers.c
Normal file
163
openair2/XNAP/xnap_timers.c
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* 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 "xnap_timers.h"
|
||||
#include "assertions.h"
|
||||
#include "PHY/defs_common.h" /* TODO: try to not include this */
|
||||
#include "xnap_messages_types.h"
|
||||
#include "xnap_gNB_defs.h"
|
||||
#include "xnap_ids.h"
|
||||
#include "xnap_gNB_management_procedures.h"
|
||||
#include "xnap_gNB_generate_messages.h"
|
||||
|
||||
void xnap_timers_init(xnap_timers_t *t,
|
||||
int t_reloc_prep,
|
||||
int tx2_reloc_overall,
|
||||
int t_dc_prep,
|
||||
int t_dc_overall)
|
||||
{
|
||||
t->tti = 0;
|
||||
t->t_reloc_prep = t_reloc_prep;
|
||||
t->tx2_reloc_overall = tx2_reloc_overall;
|
||||
t->t_dc_prep = t_dc_prep;
|
||||
t->t_dc_overall = t_dc_overall;
|
||||
}
|
||||
/*
|
||||
void xnap_check_timers(instance_t instance)
|
||||
{
|
||||
xnap_gNB_instance_t *instance_p;
|
||||
xnap_timers_t *t;
|
||||
xnap_id_manager *m;
|
||||
int i;
|
||||
xnap_handover_cancel_cause_t cause;
|
||||
void *target;
|
||||
MessageDef *msg;
|
||||
int xnap_ongoing;
|
||||
|
||||
instance_p = xnap_gNB_get_instance(instance);
|
||||
DevAssert(instance_p != NULL);
|
||||
|
||||
t = &instance_p->timers;
|
||||
m = &instance_p->id_manager;
|
||||
|
||||
// increment subframe count
|
||||
t->tti++;
|
||||
|
||||
xnap_ongoing = 0;
|
||||
|
||||
for (i = 0; i < XNAP_MAX_IDS; i++) {
|
||||
if (m->ids[i].rnti == -1) continue;
|
||||
|
||||
if (m->ids[i].state == XNAPID_STATE_SOURCE_PREPARE ||
|
||||
m->ids[i].state == XNAPID_STATE_SOURCE_OVERALL)
|
||||
xnap_ongoing++;
|
||||
|
||||
if (m->ids[i].state == XNAPID_STATE_SOURCE_PREPARE &&
|
||||
t->tti > m->ids[i].t_reloc_prep_start + t->t_reloc_prep) {
|
||||
LOG_I(XNAP, "XNAP timeout reloc prep\n");
|
||||
// t_reloc_prep timed out
|
||||
cause = XNAP_T_RELOC_PREP_TIMEOUT;
|
||||
goto xnap_handover_timeout;
|
||||
}
|
||||
|
||||
if (m->ids[i].state == XNAPID_STATE_SOURCE_OVERALL &&
|
||||
t->tti > m->ids[i].tx2_reloc_overall_start + t->tx2_reloc_overall) {
|
||||
LOG_I(XNAP, "XNAP timeout reloc overall\n");
|
||||
// tx2_reloc_overall timed out
|
||||
cause = XNAP_TX2_RELOC_OVERALL_TIMEOUT;
|
||||
goto xnap_handover_timeout;
|
||||
}
|
||||
|
||||
if (m->ids[i].state == XNAPID_STATE_NSA_GNB_PREPARE &&
|
||||
t->tti > m->ids[i].t_dc_prep_start + t->t_dc_prep) {
|
||||
int id_source;
|
||||
int id_target;
|
||||
|
||||
LOG_I(XNAP, "XNAP timeout DC prep\n");
|
||||
// t_dc_prep timed out
|
||||
target = xnap_id_get_target(m, i);
|
||||
id_source = xnap_id_get_id_source(m, i);
|
||||
id_target = xnap_id_get_id_target(m, i);
|
||||
xnap_gNB_generate_ENDC_xnap_SgNB_release_request(instance_p, target,
|
||||
id_source, id_target,
|
||||
XNAP_CAUSE_T_DC_PREP_TIMEOUT);
|
||||
|
||||
// inform RRC of timeout
|
||||
msg = itti_alloc_new_message(TASK_XNAP, 0, XNAP_ENDC_DC_PREP_TIMEOUT);
|
||||
XNAP_ENDC_DC_PREP_TIMEOUT(msg).rnti = xnap_id_get_rnti(m, i);
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, instance_p->instance, msg);
|
||||
|
||||
// remove UE from XNAP
|
||||
xnap_release_id(m, i);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m->ids[i].state == XNAPID_STATE_NSA_GNB_OVERALL &&
|
||||
t->tti > m->ids[i].t_dc_overall_start + t->t_dc_overall) {
|
||||
int id_source;
|
||||
int id_target;
|
||||
|
||||
LOG_I(XNAP, "XNAP timeout DC overall\n");
|
||||
// t_dc_overall timed out
|
||||
target = xnap_id_get_target(m, i);
|
||||
id_source = xnap_id_get_id_source(m, i);
|
||||
id_target = xnap_id_get_id_target(m, i);
|
||||
xnap_gNB_generate_ENDC_xnap_SgNB_release_required(instance_p, target,
|
||||
id_source, id_target, XNAP_CAUSE_T_DC_OVERALL_TIMEOUT);
|
||||
|
||||
// inform RRC of timeout
|
||||
msg = itti_alloc_new_message(TASK_XNAP, 0, XNAP_ENDC_DC_OVERALL_TIMEOUT);
|
||||
XNAP_ENDC_DC_OVERALL_TIMEOUT(msg).rnti = xnap_id_get_rnti(m, i);
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, instance_p->instance, msg);
|
||||
|
||||
// remove UE from X2AP
|
||||
xnap_release_id(m, i);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// no timeout -> check next UE
|
||||
continue;
|
||||
|
||||
xnap_handover_timeout:
|
||||
// inform target about timeout
|
||||
target = xnap_id_get_target(m, i);
|
||||
xnap_gNB_generate_xnap_handover_cancel(instance_p, target, i, cause);
|
||||
|
||||
// inform RRC of cancellation
|
||||
msg = itti_alloc_new_message(TASK_XNAP, 0, XNAP_HANDOVER_CANCEL);
|
||||
XNAP_HANDOVER_CANCEL(msg).rnti = xnap_id_get_rnti(m, i);
|
||||
XNAP_HANDOVER_CANCEL(msg).cause = cause;
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, instance_p->instance, msg);
|
||||
|
||||
// remove UE from XNAP
|
||||
xnap_release_id(m, i);
|
||||
}
|
||||
|
||||
if (xnap_ongoing && t->tti % 1000 == 0)
|
||||
LOG_I(XNAP, "XNAP has %d process ongoing\n", xnap_ongoing);
|
||||
}
|
||||
|
||||
uint64_t xnap_timer_get_tti(xnap_timers_t *t)
|
||||
{
|
||||
return t->tti;
|
||||
} **/
|
||||
51
openair2/XNAP/xnap_timers.h
Normal file
51
openair2/XNAP/xnap_timers.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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_TIMERS_H_
|
||||
#define XNAP_TIMERS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
//#include "platform_types.h"
|
||||
|
||||
typedef struct {
|
||||
/* incremented every TTI (every millisecond when in realtime).
|
||||
* Used to check timers.
|
||||
* 64 bits gives us more than 500 million years of (realtime) processing.
|
||||
* It should be enough.
|
||||
*/
|
||||
uint64_t tti;
|
||||
|
||||
/* timer values (unit: TTI, ie. millisecond when in realtime) */
|
||||
int t_reloc_prep;
|
||||
int tx2_reloc_overall;
|
||||
int t_dc_prep;
|
||||
int t_dc_overall;
|
||||
} xnap_timers_t;
|
||||
|
||||
void xnap_timers_init(xnap_timers_t *t,
|
||||
int t_reloc_prep,
|
||||
int tx2_reloc_overall,
|
||||
int t_dc_prep,
|
||||
int t_dc_overall);
|
||||
//void xnap_check_timers(instance_t instance);
|
||||
uint64_t xnap_timer_get_tti(xnap_timers_t *t);
|
||||
|
||||
#endif /* X2AP_TIMERS_H_ */
|
||||
Reference in New Issue
Block a user