Commit d10fa9f6 authored by Jaroslava Fiedlerova's avatar Jaroslava Fiedlerova

Merge remote-tracking branch 'origin/rrc-pdusession-handling-improvements'...

Merge remote-tracking branch 'origin/rrc-pdusession-handling-improvements' into integration_2025_w39 (!3513)

Improvements to RRC PDU session and DRB handling logic

This merge request introduces a major simplification and cleanup of the gNB RRC
PDU Sessions and DRBs handling logic. The core goals of this work are to:

- Replace fixed-size PDU Session, DRBs and QoS arrays with dynamic containers
- Simplify and modularize helper functions for session/DRB management
- Prepare for further refactoring of the PDU Session state machine
- Improve code safety and maintainability through better bounds checking
parents 08812063 e6d8d6a0
...@@ -1167,6 +1167,7 @@ set(L2_NR_SRC ...@@ -1167,6 +1167,7 @@ set(L2_NR_SRC
${NR_RRC_DIR}/rrc_gNB.c ${NR_RRC_DIR}/rrc_gNB.c
${NR_RRC_DIR}/mac_rrc_dl_direct.c ${NR_RRC_DIR}/mac_rrc_dl_direct.c
${NR_RRC_DIR}/mac_rrc_dl_f1ap.c ${NR_RRC_DIR}/mac_rrc_dl_f1ap.c
${NR_RRC_DIR}/rrc_gNB_asn1.c
${NR_RRC_DIR}/rrc_gNB_nsa.c ${NR_RRC_DIR}/rrc_gNB_nsa.c
${NR_RRC_DIR}/rrc_gNB_UE_context.c ${NR_RRC_DIR}/rrc_gNB_UE_context.c
${NR_RRC_DIR}/rrc_gNB_NGAP.c ${NR_RRC_DIR}/rrc_gNB_NGAP.c
...@@ -1893,6 +1894,7 @@ target_link_libraries(nr-cuup PRIVATE ...@@ -1893,6 +1894,7 @@ target_link_libraries(nr-cuup PRIVATE
CONFIG_LIB ITTI SCTP_CLIENT CONFIG_LIB ITTI SCTP_CLIENT
GTPV1U e1ap f1ap GTPV1U e1ap f1ap
time_management time_management
alg
z dl pthread shlib_loader ${T_LIB}) z dl pthread shlib_loader ${T_LIB})
target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
if(E2_AGENT) if(E2_AGENT)
......
...@@ -55,4 +55,53 @@ typedef enum { ...@@ -55,4 +55,53 @@ typedef enum {
typedef enum { NON_DYNAMIC, DYNAMIC } fiveQI_t; typedef enum { NON_DYNAMIC, DYNAMIC } fiveQI_t;
/* QoS Priority Level */
typedef enum {
QOS_PRIORITY_SPARE = 0,
QOS_PRIORITY_HIGHEST,
QOS_PRIORITY_2,
QOS_PRIORITY_3,
QOS_PRIORITY_4,
QOS_PRIORITY_5,
QOS_PRIORITY_6,
QOS_PRIORITY_7,
QOS_PRIORITY_8,
QOS_PRIORITY_9,
QOS_PRIORITY_10,
QOS_PRIORITY_11,
QOS_PRIORITY_12,
QOS_PRIORITY_13,
QOS_PRIORITY_LOWEST,
QOS_NO_PRIORITY
} qos_priority_t;
/* Pre-emption Capability */
typedef enum {
PEC_SHALL_NOT_TRIGGER_PREEMPTION = 0,
PEC_MAY_TRIGGER_PREEMPTION,
PEC_MAX,
} qos_pec_t;
/* Pre-emption Vulnerability */
typedef enum {
PEV_NOT_PREEMPTABLE = 0,
PEV_PREEMPTABLE = 1,
PEV_MAX,
} qos_pev_t;
/* Allocation Retention Priority */
typedef struct {
qos_priority_t priority_level;
qos_pec_t pre_emp_capability;
qos_pev_t pre_emp_vulnerability;
} qos_arp_t;
typedef struct pdusession_level_qos_parameter_s {
uint8_t qfi;
uint64_t fiveQI;
uint64_t qos_priority;
fiveQI_t fiveQI_type;
qos_arp_t arp;
} pdusession_level_qos_parameter_t;
#endif #endif
...@@ -97,4 +97,7 @@ ...@@ -97,4 +97,7 @@
#define UNUSED_VARIABLE(vARIABLE) (void)(vARIABLE) #define UNUSED_VARIABLE(vARIABLE) (void)(vARIABLE)
#define NUM_PRACH_RX_FOR_NOISE_ESTIMATE 100 #define NUM_PRACH_RX_FOR_NOISE_ESTIMATE 100
// SDAP
#define MAX_QOS_FLOWS 64
#endif /* __PLATFORM_CONSTANTS_H__ */ #endif /* __PLATFORM_CONSTANTS_H__ */
This diff is collapsed.
...@@ -27,10 +27,11 @@ ...@@ -27,10 +27,11 @@
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
#include "openair2/E2AP/flexric/src/util/time_now_us.h" #include "openair2/E2AP/flexric/src/util/time_now_us.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
#include "ds/seq_arr.h"
#if defined (NGRAN_GNB_CUCP) #if defined (NGRAN_GNB_CUCP)
#include "openair2/RRC/NR/rrc_gNB_UE_context.h" #include "openair2/RRC/NR/rrc_gNB_UE_context.h"
#include "openair2/RRC/NR/rrc_gNB_radio_bearers.h"
#endif #endif
bool read_gtp_sm(void * data) bool read_gtp_sm(void * data)
...@@ -62,16 +63,15 @@ bool read_gtp_sm(void * data) ...@@ -62,16 +63,15 @@ bool read_gtp_sm(void * data)
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[0], ue_id_list[i]); rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[0], ue_id_list[i]);
gtp->msg.ngut[i].rnti = ue_id_list[i]; gtp->msg.ngut[i].rnti = ue_id_list[i];
int nb_pdu_session = ue_context_p->ue_context.nb_of_pdusessions; FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t*, session, &ue_context_p->ue_context.pduSessions) {
if (nb_pdu_session > 0) { gtp->msg.ngut[i].teidgnb = session->param.n3_outgoing.teid;
int nb_pdu_idx = nb_pdu_session - 1; gtp->msg.ngut[i].teidupf = session->param.n3_incoming.teid;
gtp->msg.ngut[i].teidgnb = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.n3_outgoing.teid;
gtp->msg.ngut[i].teidupf = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.n3_incoming.teid;
// TODO: one PDU session has multiple QoS Flow // TODO: one PDU session has multiple QoS Flow
int nb_qos_flow = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.nb_qos; DevAssert(seq_arr_size(&session->param.qos) == 1);
if (nb_qos_flow > 0) { FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos, &session->param.qos) {
gtp->msg.ngut[i].qfi = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.qos[nb_qos_flow - 1].qfi; gtp->msg.ngut[i].qfi = qos->qos.qfi;
} }
break;
} }
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "openair2/E1AP/e1ap_common.h" #include "openair2/E1AP/e1ap_common.h"
#include "openair2/E2AP/flexric/src/util/time_now_us.h" #include "openair2/E2AP/flexric/src/util/time_now_us.h"
#include "openair2/F1AP/f1ap_ids.h" #include "openair2/F1AP/f1ap_ids.h"
#include "ds/seq_arr.h"
static pthread_once_t once_kpm_mutex = PTHREAD_ONCE_INIT; static pthread_once_t once_kpm_mutex = PTHREAD_ONCE_INIT;
...@@ -212,8 +213,8 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_cu(const test_info_lst_t test_info) ...@@ -212,8 +213,8 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_cu(const test_info_lst_t test_info)
/* UE has no AMF UE NGAP ID yet => can't send message */ /* UE has no AMF UE NGAP ID yet => can't send message */
if (ue->amf_ue_ngap_id >= (1LL << 40)) if (ue->amf_ue_ngap_id >= (1LL << 40))
continue; continue;
for (int p = 0; p < ue->nb_of_pdusessions; ++p) { FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t*, item, &ue->pduSessions) {
pdusession_t *pdu = &ue->pduSession[p].param; pdusession_t* pdu = &item->param;
if (nssai_matches(pdu->nssai, sst, sd)) { if (nssai_matches(pdu->nssai, sst, sd)) {
arr_ue_id.ue_id[arr_ue_id.sz] = fill_ue_id_data[ngran_gNB_CU](ue, 0, 0); arr_ue_id.ue_id[arr_ue_id.sz] = fill_ue_id_data[ngran_gNB_CU](ue, 0, 0);
......
...@@ -1344,7 +1344,7 @@ void config_rlc(configmodule_interface_t *cfg, nr_rlc_configuration_t *rlc_confi ...@@ -1344,7 +1344,7 @@ void config_rlc(configmodule_interface_t *cfg, nr_rlc_configuration_t *rlc_confi
rlc_config->drb_um.sn_field_length = config_get_processedint(cfg, &rlc_drb_um_params[CONFIG_NR_RLC_DRB_UM_SN_FIELD_LENGTH_IDX]); rlc_config->drb_um.sn_field_length = config_get_processedint(cfg, &rlc_drb_um_params[CONFIG_NR_RLC_DRB_UM_SN_FIELD_LENGTH_IDX]);
} }
void config_pdcp(configmodule_interface_t *cfg, nr_pdcp_configuration_t *pdcp_config) static void config_pdcp(configmodule_interface_t *cfg, nr_pdcp_configuration_t *pdcp_config)
{ {
/* DRB configuration */ /* DRB configuration */
paramdef_t pdcp_params[] = NR_PDCP_DRB_GLOBALPARAMS_DESC; paramdef_t pdcp_params[] = NR_PDCP_DRB_GLOBALPARAMS_DESC;
......
add_subdirectory(MESSAGES) add_subdirectory(MESSAGES)
if(ENABLE_TESTS)
add_subdirectory(tests)
endif()
...@@ -319,51 +319,6 @@ int do_RRCReject(uint8_t *const buffer) ...@@ -319,51 +319,6 @@ int do_RRCReject(uint8_t *const buffer)
return (enc_rval.encoded + 7) / 8; return (enc_rval.encoded + 7) / 8;
} }
/* returns a default radio bearer config suitable for NSA etc */
NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id,
int rb_id,
e_NR_CipheringAlgorithm ciphering_algorithm,
e_NR_SecurityConfig__keyToUse key_to_use,
const nr_pdcp_configuration_t *pdcp_config)
{
NR_RadioBearerConfig_t *rbconfig = calloc(1, sizeof(*rbconfig));
rbconfig->srb_ToAddModList = NULL;
rbconfig->srb3_ToRelease = NULL;
rbconfig->drb_ToAddModList = calloc(1,sizeof(*rbconfig->drb_ToAddModList));
NR_DRB_ToAddMod_t *drb_ToAddMod = calloc(1,sizeof(*drb_ToAddMod));
drb_ToAddMod->cnAssociation = calloc(1,sizeof(*drb_ToAddMod->cnAssociation));
drb_ToAddMod->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity;
drb_ToAddMod->cnAssociation->choice.eps_BearerIdentity= eps_bearer_id;
drb_ToAddMod->drb_Identity = rb_id;
drb_ToAddMod->reestablishPDCP = NULL;
drb_ToAddMod->recoverPDCP = NULL;
drb_ToAddMod->pdcp_Config = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config));
asn1cCalloc(drb_ToAddMod->pdcp_Config->drb, drb);
asn1cCallocOne(drb->discardTimer, encode_discard_timer(pdcp_config->drb.discard_timer));
asn1cCallocOne(drb->pdcp_SN_SizeUL, encode_sn_size_ul(pdcp_config->drb.sn_size));
asn1cCallocOne(drb->pdcp_SN_SizeDL, encode_sn_size_dl(pdcp_config->drb.sn_size));
drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed;
drb->headerCompression.choice.notUsed = 0;
drb->integrityProtection = NULL;
drb->statusReportRequired = NULL;
drb->outOfOrderDelivery = NULL;
drb_ToAddMod->pdcp_Config->moreThanOneRLC = NULL;
asn1cCallocOne(drb_ToAddMod->pdcp_Config->t_Reordering, encode_t_reordering(pdcp_config->drb.t_reordering));
drb_ToAddMod->pdcp_Config->ext1 = NULL;
asn1cSeqAdd(&rbconfig->drb_ToAddModList->list,drb_ToAddMod);
rbconfig->drb_ToReleaseList = NULL;
asn1cCalloc(rbconfig->securityConfig, secConf);
asn1cCalloc(secConf->securityAlgorithmConfig, secConfAlgo);
secConfAlgo->cipheringAlgorithm = ciphering_algorithm;
secConfAlgo->integrityProtAlgorithm = NULL;
asn1cCallocOne(secConf->keyToUse, key_to_use);
return rbconfig;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
int do_RRCSetup(uint8_t *const buffer, int do_RRCSetup(uint8_t *const buffer,
size_t buffer_size, size_t buffer_size,
......
...@@ -89,12 +89,6 @@ int do_SIB2_NR(uint8_t **msg_SIB2, NR_SSB_MTC_t *ssbmtc); ...@@ -89,12 +89,6 @@ int do_SIB2_NR(uint8_t **msg_SIB2, NR_SSB_MTC_t *ssbmtc);
int do_RRCReject(uint8_t *const buffer); int do_RRCReject(uint8_t *const buffer);
NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id,
int rb_id,
e_NR_CipheringAlgorithm ciphering_algorithm,
e_NR_SecurityConfig__keyToUse key_to_use,
const nr_pdcp_configuration_t *pdcp_config);
int do_RRCSetup(uint8_t *const buffer, int do_RRCSetup(uint8_t *const buffer,
size_t buffer_size, size_t buffer_size,
const uint8_t transaction_id, const uint8_t transaction_id,
......
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#include "intertask_interface.h" #include "intertask_interface.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_configuration.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_configuration.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_configuration.h" #include "openair2/LAYER2/nr_rlc/nr_rlc_configuration.h"
#include "openair2/SDAP/nr_sdap/nr_sdap_configuration.h"
typedef enum { typedef enum {
NR_RRC_OK=0, NR_RRC_OK=0,
...@@ -103,9 +104,8 @@ typedef struct pdusession_s { ...@@ -103,9 +104,8 @@ typedef struct pdusession_s {
/* Unique pdusession_id for the UE. */ /* Unique pdusession_id for the UE. */
int pdusession_id; int pdusession_id;
byte_array_t nas_pdu; byte_array_t nas_pdu;
uint8_t nb_qos;
/* Quality of service for this pdusession */ /* Quality of service for this pdusession */
pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE]; seq_arr_t qos;
/* The transport layer address for the IP packets */ /* The transport layer address for the IP packets */
pdu_session_type_t pdu_session_type; pdu_session_type_t pdu_session_type;
// NG-RAN endpoint of the NG-U (N3) transport bearer // NG-RAN endpoint of the NG-U (N3) transport bearer
...@@ -113,6 +113,8 @@ typedef struct pdusession_s { ...@@ -113,6 +113,8 @@ typedef struct pdusession_s {
// UPF endpoint of the NG-U (N3) transport bearer // UPF endpoint of the NG-U (N3) transport bearer
gtpu_tunnel_t n3_incoming; gtpu_tunnel_t n3_incoming;
nssai_t nssai; nssai_t nssai;
// PDU Session specific SDAP configuration
nr_sdap_configuration_t sdap_config;
} pdusession_t; } pdusession_t;
typedef struct pdu_session_param_s { typedef struct pdu_session_param_s {
...@@ -125,35 +127,13 @@ typedef struct pdu_session_param_s { ...@@ -125,35 +127,13 @@ typedef struct pdu_session_param_s {
typedef struct drb_s { typedef struct drb_s {
int status; int status;
int drb_id; int drb_id;
struct cnAssociation_s { int pdusession_id;
int present;
int eps_BearerIdentity;
struct sdap_config_s {
bool defaultDRB;
int pdusession_id;
int sdap_HeaderDL;
int sdap_HeaderUL;
int mappedQoS_FlowsToAdd[QOSFLOW_MAX_VALUE];
} sdap_config;
} cnAssociation;
struct pdcp_config_s {
int discardTimer;
int pdcp_SN_SizeUL;
int pdcp_SN_SizeDL;
int t_Reordering;
int integrityProtection;
struct headerCompression_s {
int NotUsed;
int present;
} headerCompression;
struct ext1_s {
int cipheringDisabled;
} ext1;
} pdcp_config;
// F1-U Downlink Tunnel Config (on DU side) // F1-U Downlink Tunnel Config (on DU side)
gtpu_tunnel_t du_tunnel_config; gtpu_tunnel_t du_tunnel_config;
// F1-U Uplink Tunnel Config (on CU-UP side) // F1-U Uplink Tunnel Config (on CU-UP side)
gtpu_tunnel_t cuup_tunnel_config; gtpu_tunnel_t cuup_tunnel_config;
// DRB-specific PDCP configuration
nr_pdcp_configuration_t pdcp_config;
} drb_t; } drb_t;
typedef enum { typedef enum {
...@@ -176,13 +156,17 @@ typedef struct nr_redcap_ue_cap { ...@@ -176,13 +156,17 @@ typedef struct nr_redcap_ue_cap {
bool rlc_am_drb_long_sn_redcap_r17; bool rlc_am_drb_long_sn_redcap_r17;
} nr_redcap_ue_cap_t; } nr_redcap_ue_cap_t;
typedef struct {
int drb_id;
pdusession_level_qos_parameter_t qos;
} nr_rrc_qos_t;
/* forward declaration */ /* forward declaration */
typedef struct nr_handover_context_s nr_handover_context_t; typedef struct nr_handover_context_s nr_handover_context_t;
typedef struct gNB_RRC_UE_s { typedef struct gNB_RRC_UE_s {
time_t last_seen; // last time this UE has been accessed time_t last_seen; // last time this UE has been accessed
drb_t established_drbs[MAX_DRBS_PER_UE];
NR_DRB_ToReleaseList_t *DRB_ReleaseList; NR_DRB_ToReleaseList_t *DRB_ReleaseList;
NR_SRB_INFO_TABLE_ENTRY Srb[NR_NUM_SRB]; NR_SRB_INFO_TABLE_ENTRY Srb[NR_NUM_SRB];
...@@ -238,8 +222,10 @@ typedef struct gNB_RRC_UE_s { ...@@ -238,8 +222,10 @@ typedef struct gNB_RRC_UE_s {
rb_id_t nsa_gtp_psi[S1AP_MAX_E_RAB]; rb_id_t nsa_gtp_psi[S1AP_MAX_E_RAB];
//SA block //SA block
int nb_of_pdusessions; seq_arr_t pduSessions;
rrc_pdu_session_param_t pduSession[NGAP_MAX_PDU_SESSION]; // Established DRBs
seq_arr_t drbs;
rrc_action_t xids[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER]; rrc_action_t xids[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER];
uint8_t e_rab_release_command_flag; uint8_t e_rab_release_command_flag;
uint32_t ue_rrc_inactivity_timer; uint32_t ue_rrc_inactivity_timer;
...@@ -400,6 +386,7 @@ typedef struct gNB_RRC_INST_s { ...@@ -400,6 +386,7 @@ typedef struct gNB_RRC_INST_s {
RB_HEAD(rrc_cuup_tree, nr_rrc_cuup_container_t) cuups; // CU-UPs, indexed by assoc_id RB_HEAD(rrc_cuup_tree, nr_rrc_cuup_container_t) cuups; // CU-UPs, indexed by assoc_id
size_t num_cuups; size_t num_cuups;
// PDCP configuration parameters loaded during startup
nr_pdcp_configuration_t pdcp_config; nr_pdcp_configuration_t pdcp_config;
nr_rlc_configuration_t rlc_config; nr_rlc_configuration_t rlc_config;
} gNB_RRC_INST; } gNB_RRC_INST;
......
...@@ -122,11 +122,10 @@ byte_array_t rrc_gNB_encode_RRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t * ...@@ -122,11 +122,10 @@ byte_array_t rrc_gNB_encode_RRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t *
nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t srb_reest_bitmap, bool drb_reestablish); nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t srb_reest_bitmap, bool drb_reestablish);
pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi, rrc_pdu_session_param_t *pduSession);
f1ap_qos_flow_param_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param); f1ap_qos_flow_param_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param);
void openair_rrc_gNB_configuration(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration); void openair_rrc_gNB_configuration(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration);
NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, uint8_t reestablish); NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, uint8_t reestablish);
NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish); NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish, bool do_integrity, bool do_ciphering);
void activate_srb(gNB_RRC_UE_t *UE, int srb_id); void activate_srb(gNB_RRC_UE_t *UE, int srb_id);
void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_setup_t *drbs, const ngap_drb_status_t *drb_status); void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_setup_t *drbs, const ngap_drb_status_t *drb_status);
......
This diff is collapsed.
This diff is collapsed.
...@@ -74,10 +74,7 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_REQ(MessageDef *msg_p, instance_t in ...@@ -74,10 +74,7 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_REQ(MessageDef *msg_p, instance_t in
int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_t instance); int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_t instance);
void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, uint32_t gNB_ue_ngap_id, seq_arr_t *pduSessions);
uint32_t gNB_ue_ngap_id,
int num_pdu,
uint32_t pdu_session_id[256]);
void rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const NR_UECapabilityInformation_t *const ue_cap_info); void rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const NR_UECapabilityInformation_t *const ue_cap_info);
...@@ -107,7 +104,11 @@ void rrc_gNB_free_Handover_Command(ngap_handover_command_t *msg); ...@@ -107,7 +104,11 @@ void rrc_gNB_free_Handover_Command(ngap_handover_command_t *msg);
void rrc_gNB_send_NGAP_HANDOVER_NOTIFY(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE); void rrc_gNB_send_NGAP_HANDOVER_NOTIFY(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE);
void rrc_gNB_send_NGAP_HANDOVER_CANCEL(int module_id, gNB_RRC_UE_t *UE, ngap_cause_t cause); void rrc_gNB_send_NGAP_HANDOVER_CANCEL(int module_id, gNB_RRC_UE_t *UE, ngap_cause_t cause);
int rrc_gNB_send_NGAP_ul_ran_status_transfer(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const int n_to_mod, const e1_pdcp_status_info_t *pdcp_status); int rrc_gNB_send_NGAP_ul_ran_status_transfer(gNB_RRC_INST *rrc,
gNB_RRC_UE_t *UE,
const int n_to_mod,
const int *drb_ids,
const e1_pdcp_status_info_t *pdcp_status);
int rrc_gNB_process_NGAP_DL_RAN_STATUS_TRANSFER(MessageDef *msg_p, instance_t instance); int rrc_gNB_process_NGAP_DL_RAN_STATUS_TRANSFER(MessageDef *msg_p, instance_t instance);
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "linear_alloc.h" #include "linear_alloc.h"
#include "openair2/F1AP/f1ap_ids.h" #include "openair2/F1AP/f1ap_ids.h"
#include "tree.h" #include "tree.h"
#include "rrc_gNB_radio_bearers.h"
static void rrc_gNB_ue_context_update_time(rrc_gNB_ue_context_t *ctxt) static void rrc_gNB_ue_context_update_time(rrc_gNB_ue_context_t *ctxt)
{ {
...@@ -78,9 +79,6 @@ rrc_gNB_ue_context_t *rrc_gNB_allocate_new_ue_context(gNB_RRC_INST *rrc_instance ...@@ -78,9 +79,6 @@ rrc_gNB_ue_context_t *rrc_gNB_allocate_new_ue_context(gNB_RRC_INST *rrc_instance
new_p->ue_context.rrc_ue_id = uid_linear_allocator_new(&rrc_instance_pP->uid_allocator) + 1; new_p->ue_context.rrc_ue_id = uid_linear_allocator_new(&rrc_instance_pP->uid_allocator) + 1;
rrc_gNB_ue_context_update_time(new_p); rrc_gNB_ue_context_update_time(new_p);
for(int i = 0; i < NB_RB_MAX; i++)
new_p->ue_context.pduSession[i].xid = -1;
LOG_D(NR_RRC, "Returning new RRC UE context RRC ue id: %d\n", new_p->ue_context.rrc_ue_id); LOG_D(NR_RRC, "Returning new RRC UE context RRC ue id: %d\n", new_p->ue_context.rrc_ue_id);
return(new_p); return(new_p);
} }
...@@ -211,6 +209,11 @@ rrc_gNB_ue_context_t *rrc_gNB_create_ue_context(sctp_assoc_t assoc_id, ...@@ -211,6 +209,11 @@ rrc_gNB_ue_context_t *rrc_gNB_create_ue_context(sctp_assoc_t assoc_id,
ue->max_delays_pdu_session = 20; /* see rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ() */ ue->max_delays_pdu_session = 20; /* see rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ() */
ue->ongoing_pdusession_setup_request = false; ue->ongoing_pdusession_setup_request = false;
// Initialise setup PDU Sessions list
seq_arr_init(&ue->pduSessions, sizeof(rrc_pdu_session_param_t));
// Initialise setup DRBs list
seq_arr_init(&ue->drbs, sizeof(drb_t));
RB_INSERT(rrc_nr_ue_tree_s, &rrc_instance_pP->rrc_ue_head, ue_context_p); RB_INSERT(rrc_nr_ue_tree_s, &rrc_instance_pP->rrc_ue_head, ue_context_p);
LOG_UE_EVENT(ue, LOG_UE_EVENT(ue,
"Create UE context: CU UE ID %u DU UE ID %u (rnti: %04x, random ue id %lx)\n", "Create UE context: CU UE ID %u DU UE ID %u (rnti: %04x, random ue id %lx)\n",
......
/*
* 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 <stdbool.h>
#include "NR_DRB-ToAddMod.h"
#include "NR_RadioBearerConfig.h"
#include "common/utils/oai_asn1.h"
#include "common/utils/LOG/log.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_configuration.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_asn1_utils.h"
NR_PDCP_Config_t *nr_rrc_build_pdcp_config_ie(const bool integrity, const bool ciphering, const nr_pdcp_configuration_t *pdcp)
{
NR_PDCP_Config_t *out = calloc_or_fail(1, sizeof(*out));
asn1cCallocOne(out->t_Reordering, encode_t_reordering(pdcp->drb.t_reordering));
if (!ciphering) {
asn1cCalloc(out->ext1, ext1);
asn1cCallocOne(ext1->cipheringDisabled, NR_PDCP_Config__ext1__cipheringDisabled_true);
}
asn1cCalloc(out->drb, drb);
asn1cCallocOne(drb->discardTimer, encode_discard_timer(pdcp->drb.discard_timer));
asn1cCallocOne(drb->pdcp_SN_SizeUL, encode_sn_size_ul(pdcp->drb.sn_size));
asn1cCallocOne(drb->pdcp_SN_SizeDL, encode_sn_size_dl(pdcp->drb.sn_size));
drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed;
drb->headerCompression.choice.notUsed = 0;
if (integrity) {
asn1cCallocOne(drb->integrityProtection, NR_PDCP_Config__drb__integrityProtection_enabled);
}
return out;
}
/*
* 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 _RRC_GNB_ASN1_H_
#define _RRC_GNB_ASN1_H_
#include <stdbool.h>
#include "seq_arr.h"
#include "NR_DRB-ToAddMod.h"
#include "NR_RadioBearerConfig.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_configuration.h"
NR_PDCP_Config_t *nr_rrc_build_pdcp_config_ie(const bool integrity, const bool ciphering, const nr_pdcp_configuration_t *pdcp);
#endif
...@@ -63,24 +63,20 @@ static void free_ho_ctx(nr_handover_context_t *ho_ctx) ...@@ -63,24 +63,20 @@ static void free_ho_ctx(nr_handover_context_t *ho_ctx)
free(ho_ctx); free(ho_ctx);
} }
/** @brief Fill DRB to Be Setup List in F1 UE Context Setup Request (optional list)
* @return 0 if list is empty, list size otherwise */
static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_drb_to_setup_t drbs[MAX_DRBS_PER_UE]) static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_drb_to_setup_t drbs[MAX_DRBS_PER_UE])
{ {
int nb_drb = 0; int nb_drb = 0;
for (int i = 0; i < MAX_DRBS_PER_UE; ++i) {
drb_t *rrc_drb = &ue->established_drbs[i];
if (rrc_drb->status == DRB_INACTIVE)
continue;
FOR_EACH_SEQ_ARR(drb_t *, rrc_drb, &ue->drbs) {
DevAssert(nb_drb < MAX_DRBS_PER_UE);
f1ap_drb_to_setup_t *drb = &drbs[nb_drb]; f1ap_drb_to_setup_t *drb = &drbs[nb_drb];
nr_pdcp_configuration_t *pdcp = &rrc_drb->pdcp_config;
nb_drb++; nb_drb++;
/* fetch an existing PDU session for this DRB */ /* fetch an existing PDU session for this DRB */
rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue, rrc_drb->drb_id); rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue, rrc_drb->drb_id);
AssertFatal(pdu != NULL, "no PDU session for DRB ID %d\n", rrc_drb->drb_id); AssertFatal(pdu != NULL, "no PDU session for DRB ID %d\n", rrc_drb->drb_id);
// for the moment, we only support one QoS flow. Put a reminder in case
// this changes
AssertFatal(pdu->param.nb_qos == 1, "only 1 Qos flow supported\n");
int qfi = rrc_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[0];
pdusession_level_qos_parameter_t *qos_param = get_qos_characteristics(qfi, pdu);
drb->id = rrc_drb->drb_id; drb->id = rrc_drb->drb_id;
...@@ -88,9 +84,14 @@ static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_ ...@@ -88,9 +84,14 @@ static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_
drb->nr.nssai = pdu->param.nssai; drb->nr.nssai = pdu->param.nssai;
drb->nr.flows_len = 1; drb->nr.flows_len = 1;
drb->nr.flows = calloc_or_fail(1, sizeof(*drb->nr.flows)); drb->nr.flows = calloc_or_fail(1, sizeof(*drb->nr.flows));
DevAssert(qfi > 0);
drb->nr.flows[0].qfi = qfi; // Find the QoS flow associated with this DRB
drb->nr.flows[0].param = get_qos_char_from_qos_flow_param(qos_param); // Since we don't have QFI mapping in the new structure, we'll use the first QoS flow
AssertFatal(seq_arr_size(&pdu->param.qos) == 1, "only 1 Qos flow supported\n");
nr_rrc_qos_t *qos_param = (nr_rrc_qos_t *)seq_arr_at(&pdu->param.qos, 0);
DevAssert(qos_param->qos.qfi > 0);
drb->nr.flows[0].qfi = qos_param->qos.qfi;
drb->nr.flows[0].param = get_qos_char_from_qos_flow_param(&qos_param->qos);
/* the DRB QoS parameters: we just reuse the ones from the first flow */ /* the DRB QoS parameters: we just reuse the ones from the first flow */
drb->nr.drb_qos = drb->nr.flows[0].param; drb->nr.drb_qos = drb->nr.flows[0].param;
...@@ -99,10 +100,11 @@ static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_ ...@@ -99,10 +100,11 @@ static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_
drb->up_ul_tnl_len = 1; drb->up_ul_tnl_len = 1;
drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM; drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM;
DevAssert(pdcp->drb.sn_size == 18 || pdcp->drb.sn_size == 12);
drb->dl_pdcp_sn_len = malloc_or_fail(sizeof(*drb->dl_pdcp_sn_len)); drb->dl_pdcp_sn_len = malloc_or_fail(sizeof(*drb->dl_pdcp_sn_len));
*drb->dl_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeDL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B; *drb->dl_pdcp_sn_len = pdcp->drb.sn_size == 18 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B;
drb->ul_pdcp_sn_len = malloc_or_fail(sizeof(*drb->ul_pdcp_sn_len)); drb->ul_pdcp_sn_len = malloc_or_fail(sizeof(*drb->ul_pdcp_sn_len));
*drb->ul_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeUL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B;; *drb->ul_pdcp_sn_len = pdcp->drb.sn_size == 18 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B;
} }
return nb_drb; return nb_drb;
} }
......
...@@ -33,7 +33,11 @@ typedef struct nr_rrc_du_container_t nr_rrc_du_container_t; ...@@ -33,7 +33,11 @@ typedef struct nr_rrc_du_container_t nr_rrc_du_container_t;
typedef struct NR_CellGroupConfig NR_CellGroupConfig_t; typedef struct NR_CellGroupConfig NR_CellGroupConfig_t;
typedef void (*ho_cancel_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue); typedef void (*ho_cancel_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue);
typedef int (*ho_status_transfer_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const int n_to_mod, const e1_pdcp_status_info_t *pdcp_status); typedef int (*ho_status_transfer_t)(gNB_RRC_INST *rrc,
gNB_RRC_UE_t *UE,
const int n_to_mod,
const int *drb_ids,
const e1_pdcp_status_info_t *pdcp_status);
typedef struct nr_ho_source_cu { typedef struct nr_ho_source_cu {
/// pointer to the (source) DU structure /// pointer to the (source) DU structure
......
...@@ -72,6 +72,7 @@ ...@@ -72,6 +72,7 @@
#include "xer_encoder.h" #include "xer_encoder.h"
#include "f1ap_common.h" #include "f1ap_common.h"
#include "lib/f1ap_ue_context.h" #include "lib/f1ap_ue_context.h"
#include "rrc_gNB_asn1.h"
// In case of phy-test and do-ra mode, read UE capabilities directly from file // In case of phy-test and do-ra mode, read UE capabilities directly from file
// and put it into a CG-ConfigInfo field // and put it into a CG-ConfigInfo field
...@@ -134,6 +135,32 @@ static instance_t get_f1_gtp_instance(void) ...@@ -134,6 +135,32 @@ static instance_t get_f1_gtp_instance(void)
return inst->gtpInst; return inst->gtpInst;
} }
/* returns a default radio bearer config suitable for NSA etc */
static NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id,
int rb_id,
e_NR_CipheringAlgorithm ciphering_algorithm,
e_NR_SecurityConfig__keyToUse key_to_use,
const nr_pdcp_configuration_t *pdcp_config)
{
NR_RadioBearerConfig_t *rbconfig = calloc_or_fail(1, sizeof(*rbconfig));
rbconfig->drb_ToAddModList = calloc_or_fail(1, sizeof(*rbconfig->drb_ToAddModList));
NR_DRB_ToAddMod_t *drb_ToAddMod = calloc_or_fail(1, sizeof(*drb_ToAddMod));
drb_ToAddMod->drb_Identity = rb_id;
drb_ToAddMod->pdcp_Config = nr_rrc_build_pdcp_config_ie(false, false, pdcp_config);
asn1cCalloc(drb_ToAddMod->cnAssociation, cn_association);
cn_association->present = NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity;
cn_association->choice.eps_BearerIdentity = eps_bearer_id;
asn1cSeqAdd(&rbconfig->drb_ToAddModList->list, drb_ToAddMod);
asn1cCalloc(rbconfig->securityConfig, secConf);
asn1cCalloc(secConf->securityAlgorithmConfig, secConfAlgo);
secConfAlgo->cipheringAlgorithm = ciphering_algorithm;
secConfAlgo->integrityProtAlgorithm = NULL;
asn1cCallocOne(secConf->keyToUse, key_to_use);
if (LOG_DEBUGFLAG(DEBUG_ASN1))
xer_fprint(stdout, &asn_DEF_NR_DRB_ToAddMod, drb_ToAddMod);
return rbconfig;
}
/* generate prototypes for the tree management functions (RB_INSERT used in rrc_add_nsa_user) */ /* generate prototypes for the tree management functions (RB_INSERT used in rrc_add_nsa_user) */
RB_PROTOTYPE(rrc_nr_ue_tree_s, rrc_gNB_ue_context_s, entries, RB_PROTOTYPE(rrc_nr_ue_tree_s, rrc_gNB_ue_context_s, entries,
rrc_gNB_compare_ue_rnti_id); rrc_gNB_compare_ue_rnti_id);
......
This diff is collapsed.
...@@ -24,61 +24,38 @@ ...@@ -24,61 +24,38 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "NR_DRB-ToAddMod.h"
#include "e1ap_messages_types.h" #include "e1ap_messages_types.h"
#include "nr_rrc_defs.h" #include "nr_rrc_defs.h"
#define DRB_ACTIVE_NONGBR (2) /* DRB is used for Non-GBR Flows */
#define DRB_ACTIVE (1)
#define DRB_INACTIVE (0)
#define GBR_FLOW (1)
#define NONGBR_FLOW (0)
/// @brief Generates an ASN1 DRB-ToAddMod, from the established_drbs in gNB_RRC_UE_t.
/// @param drb_t drb_asn1
/// @return Returns the ASN1 DRB-ToAddMod structs.
NR_DRB_ToAddMod_t *generateDRB_ASN1(const drb_t *drb_asn1);
/// @brief retrieve the data structure representing DRB with ID drb_id of UE ue /// @brief retrieve the data structure representing DRB with ID drb_id of UE ue
drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id); drb_t *get_drb(seq_arr_t *seq, int id);
/// @brief Creates and stores a DRB in the gNB_RRC_UE_t struct
/// @param ue The gNB_RRC_UE_t struct that holds information for the UEs
/// @param drb_id The Data Radio Bearer Identity to be created for the established DRB.
/// @param pduSession The PDU Session that the DRB is created for.
/// @param enable_sdap If true the SDAP header will be added to the packet, else it will not add or search for SDAP header.
/// @param do_drb_integrity
/// @param do_drb_ciphering
/// @param pdcp_config
/// @return returns a pointer to the generated DRB structure
drb_t *generateDRB(gNB_RRC_UE_t *ue,
uint8_t drb_id,
const rrc_pdu_session_param_t *pduSession,
bool enable_sdap,
int do_drb_integrity,
int do_drb_ciphering,
const nr_pdcp_configuration_t *pdcp_config);
/// @brief return the next available (inactive) DRB ID of UE ue
uint8_t get_next_available_drb_id(gNB_RRC_UE_t *ue);
/// @brief returns the number of active DRBs for this UE /// @brief retrieve PDU session of UE ue with ID id
int get_number_active_drbs(gNB_RRC_UE_t *ue); rrc_pdu_session_param_t *find_pduSession(seq_arr_t *seq, int id);
/// @brief retrieve PDU session of UE ue with ID id, optionally creating it if /// @brief Add a new PDU session for UE @param ue and configuration @param in
/// create is true rrc_pdu_session_param_t *add_pduSession(seq_arr_t *sessions_ptr, const pdusession_t *in);
rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create);
/// @brief get PDU session of UE ue through the DRB drb_id /// @brief get PDU session of UE ue through the DRB drb_id
rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id); rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id);
/// @brief get the PDU sessions of this UE in a single array /// @brief set PDCP configuration in E1 Bearer Context Management message
void get_pduSession_array(gNB_RRC_UE_t *ue, uint32_t pdu_sessions[NGAP_MAX_PDU_SESSION]); bearer_context_pdcp_config_t set_bearer_context_pdcp_config(const nr_pdcp_configuration_t pdcp,
bool um_on_default_drb,
const nr_redcap_ue_cap_t *redcap_cap);
void free_pdusession(void *ptr);
/// @brief Add DRB to RRC list
drb_t *nr_rrc_add_drb(seq_arr_t *drb_ptr, int pdusession_id, nr_pdcp_configuration_t *pdcp);
/// @brief Function to free DRB in RRC
void free_drb(void *ptr);
/// @brief set PDCP configuration in a bearer context management message /// @brief retrieve QoS flow associated to @param qfi
void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, drb_t *rrc_drb, bool um_on_default_drb); nr_rrc_qos_t *find_qos(seq_arr_t *seq, int qfi);
/// @brief Deep copy an instance of struct pdusession_t /// @brief Add a new QoS to the list
void cp_pdusession(pdusession_t *dst, const pdusession_t *src); nr_rrc_qos_t *add_qos(seq_arr_t *qos, const pdusession_level_qos_parameter_t *in);
#endif #endif
add_executable(rrc_bearers_test rrc_bearers_test.c ../rrc_gNB_radio_bearers.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c)
add_dependencies(tests rrc_bearers_test)
add_test(NAME rrc_bearers_test COMMAND rrc_bearers_test)
target_include_directories(rrc_bearers_test PRIVATE ./common/utils/ds common/utils/LOG)
target_link_libraries(rrc_bearers_test PRIVATE ds alg asn1_e1ap asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs LOG T)
target_compile_definitions(rrc_bearers_test PRIVATE ENABLE_TESTS)
/*
* 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>
#include <assert.h>
#include <string.h>
#include "common/utils/utils.h"
#include "common/utils/assertions.h"
#include "openair2/RRC/NR/rrc_gNB_radio_bearers.h"
#include "ds/seq_arr.h"
#include "common/utils/LOG/log.h"
int nr_rlc_get_available_tx_space(int module_id, int rnti, int drb_id) { return 0; }
softmodem_params_t *get_softmodem_params(void) { return NULL; }
configmodule_interface_t *uniqCfg = NULL;
void exit_function(const char *file, const char *function, const int line, const char *s, const int assert)
{
printf("detected error at %s:%d:%s: %s\n", file, line, function, s);
abort();
}
static void test_rrc_pdu_session(void)
{
const int pdu_session_id = 3;
gNB_RRC_UE_t ue = {0};
seq_arr_init(&ue.pduSessions, sizeof(rrc_pdu_session_param_t));
/* test add */
pdusession_t p1 = {0};
seq_arr_init(&p1.qos, sizeof(nr_rrc_qos_t));
p1.pdusession_id = pdu_session_id;
p1.n3_incoming.teid = 2002;
LOG_I(NR_RRC, "Adding first PDU Session with ID %d\n", p1.pdusession_id);
rrc_pdu_session_param_t *s1 = add_pduSession(&ue.pduSessions, &p1); // add 1st PDU Session
AssertFatal(s1 != NULL, "Could not add PDU Session\n");
AssertFatal(s1->param.pdusession_id == p1.pdusession_id, "PDU Session ID mismatch in added PDU Session\n");
AssertFatal(s1->param.n3_incoming.teid == p1.n3_incoming.teid, "teid mismatch in added PDU Session\n");
LOG_A(NR_RRC, "First PDU Session added successfully\n");
/* test find */
rrc_pdu_session_param_t *a1 = find_pduSession(&ue.pduSessions, p1.pdusession_id);
AssertFatal(a1 != NULL, "Could not find PDU Session\n");
AssertFatal(a1 == s1, "Found PDU Session mismatch\n");
LOG_A(NR_RRC, "PDU Session find test passed\n");
/* test add duplicate */
pdusession_t input2 = {0};
seq_arr_init(&input2.qos, sizeof(nr_rrc_qos_t));
input2.pdusession_id = pdu_session_id;
input2.n3_incoming.teid = 9999;
rrc_pdu_session_param_t *s2 = add_pduSession(&ue.pduSessions, &input2); // add 2nd PDU Session
AssertFatal(s2 == NULL, "Duplicated PDU session was added!\n");
LOG_A(NR_RRC, "Duplicated PDU session test passed\n");
seq_arr_free(&input2.qos, NULL);
/* add DRB and fetch PDU Session */
seq_arr_init(&ue.drbs, sizeof(drb_t));
nr_pdcp_configuration_t pdcp = {.drb.discard_timer = 100, .drb.sn_size = 18, .drb.t_reordering = 50};
drb_t *added = nr_rrc_add_drb(&ue.drbs, pdu_session_id, &pdcp);
AssertFatal(added != NULL, "Failed to add DRB");
rrc_pdu_session_param_t *a2 = find_pduSession_from_drbId(&ue, added->drb_id);
AssertFatal(a2 && a2->param.pdusession_id == pdu_session_id, "find_pduSession_from_drbId failed");
seq_arr_free(&ue.pduSessions, free_pdusession);
seq_arr_free(&ue.drbs, free_drb);
}
// ---------------- DRB TESTS ----------------
static void test_rrc_drb(void)
{
LOG_I(NR_RRC, "Starting DRB test\n");
seq_arr_t pduSessions = {0};
seq_arr_t drbs = {0};
seq_arr_init(&pduSessions, sizeof(rrc_pdu_session_param_t));
seq_arr_init(&drbs, sizeof(drb_t));
/* test add 1 DRB to 1st PDU session */
const int id1 = 1;
pdusession_t s1 = {0};
seq_arr_init(&s1.qos, sizeof(nr_rrc_qos_t));
s1.pdusession_id = id1;
add_pduSession(&pduSessions, &s1); // add PDU session
nr_pdcp_configuration_t pdcp = {.drb.discard_timer = 100, .drb.sn_size = 18, .drb.t_reordering = 50};
drb_t *in1 = nr_rrc_add_drb(&drbs, id1, &pdcp); // add DRB
AssertFatal(in1, "add_rrc_drb failed");
LOG_A(NR_RRC, "First DRB created with ID %d\n", in1->drb_id);
drb_t *out1 = get_drb(&drbs, 1); // fetch DRB
AssertFatal(out1 && out1 == in1, "get_drb failed");
LOG_A(NR_RRC, "DRB retrieval test passed\n");
/* test add DRB to 2nd PDU session */
const int id2 = 2;
pdusession_t s2 = {0};
seq_arr_init(&s2.qos, sizeof(nr_rrc_qos_t));
s2.pdusession_id = id2;
add_pduSession(&pduSessions, &s2); // add 2nd PDU session
drb_t *in2 = nr_rrc_add_drb(&drbs, id2, &pdcp); // add DRB to 2nd PDU session
AssertFatal(in2, "add_rrc_drb failed");
LOG_A(NR_RRC, "Second DRB created with ID %d\n", in2->drb_id);
drb_t *out2 = get_drb(&drbs, 2);
AssertFatal(out2 && out2->drb_id == 2, "get_drb failed");
LOG_A(NR_RRC, "Second DRB retrieval test passed\n");
seq_arr_free(&pduSessions, free_pdusession);
seq_arr_free(&drbs, free_drb);
}
// ---------------- DRB TESTS ----------------
static void test_rrc_qos(void)
{
seq_arr_t pduSessions = {0};
seq_arr_init(&pduSessions, sizeof(rrc_pdu_session_param_t));
const int session_id = 70;
pdusession_t in = {0};
in.pdusession_id = session_id;
seq_arr_init(&in.qos, sizeof(nr_rrc_qos_t));
add_pduSession(&pduSessions, &in);
LOG_A(NR_RRC, "Created PDU Session %d for QoS test\n", session_id);
const int qfi = 4;
const pdusession_level_qos_parameter_t param = { .fiveQI = 9, .fiveQI_type = NON_DYNAMIC, .qfi = qfi };
LOG_A(NR_RRC, "Adding QoS flow with QFI %d\n", qfi);
nr_rrc_qos_t *added = add_qos(&in.qos, &param);
AssertFatal(added, "add_qos failed");
LOG_A(NR_RRC, "QoS flow added successfully\n");
nr_rrc_qos_t *found = find_qos(&in.qos, qfi);
AssertFatal(found && found == added, "find_qos failed");
LOG_A(NR_RRC, "QoS flow find test passed\n");
seq_arr_free(&pduSessions, free_pdusession);
}
int main()
{
// Initialize logging system
logInit();
// Set logging level for NR_RRC to show INFO messages
set_log(NR_RRC, OAILOG_INFO);
// PDU Session
test_rrc_pdu_session();
// DRB
test_rrc_drb();
// QoS
test_rrc_qos();
LOG_A(NR_RRC, "All RRC Bearers tests passed successfully!\n");
return 0;
}
/*
* 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 _NR_SDAP_CONFIGURATION_H_
#define _NR_SDAP_CONFIGURATION_H_
#include "stdbool.h"
typedef struct {
// SDAP Headers
bool header_dl_absent;
bool header_ul_absent;
} nr_sdap_configuration_t;
#endif /* _NR_SDAP_CONFIGURATION_H_ */
...@@ -577,12 +577,11 @@ bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) ...@@ -577,12 +577,11 @@ bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id)
{ {
nr_sdap_entity_t *entityPtr = sdap_info.sdap_entity_llist; nr_sdap_entity_t *entityPtr = sdap_info.sdap_entity_llist;
nr_sdap_entity_t *entityPrev = NULL; nr_sdap_entity_t *entityPrev = NULL;
bool ret = false;
int upperBound = 0; int upperBound = 0;
if (entityPtr == NULL && (pdusession_id) * (pdusession_id - NGAP_MAX_PDU_SESSION) > 0) { if (entityPtr == NULL && (pdusession_id) * (pdusession_id - NGAP_MAX_PDU_SESSION) > 0) {
LOG_E(SDAP, "SDAP entities not established or Invalid range of pdusession_id [0, 256].\n"); LOG_E(SDAP, "SDAP entities not established or Invalid range of pdusession_id [0, 256].\n");
return ret; return false;
} }
LOG_D(SDAP, "Deleting SDAP entity for UE %lx and PDU Session id %d\n", ue_id, entityPtr->pdusession_id); LOG_D(SDAP, "Deleting SDAP entity for UE %lx and PDU Session id %d\n", ue_id, entityPtr->pdusession_id);
...@@ -592,7 +591,7 @@ bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) ...@@ -592,7 +591,7 @@ bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id)
remove_ip_if(entityPtr); remove_ip_if(entityPtr);
free(entityPtr); free(entityPtr);
LOG_D(SDAP, "Successfully deleted Entity.\n"); LOG_D(SDAP, "Successfully deleted Entity.\n");
ret = true; return true;
} else { } else {
while ((entityPtr->ue_id != ue_id || entityPtr->pdusession_id != pdusession_id) && entityPtr->next_entity != NULL while ((entityPtr->ue_id != ue_id || entityPtr->pdusession_id != pdusession_id) && entityPtr->next_entity != NULL
&& upperBound < SDAP_MAX_NUM_OF_ENTITIES) { && upperBound < SDAP_MAX_NUM_OF_ENTITIES) {
...@@ -608,11 +607,11 @@ bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) ...@@ -608,11 +607,11 @@ bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id)
} }
free(entityPtr); free(entityPtr);
LOG_D(SDAP, "Successfully deleted Entity.\n"); LOG_D(SDAP, "Successfully deleted Entity.\n");
ret = true; return true;
} }
} }
LOG_E(SDAP, "Entity does not exist or it was not found.\n"); LOG_E(SDAP, "Entity does not exist or it was not found.\n");
return ret; return false;
} }
bool nr_sdap_delete_ue_entities(ue_id_t ue_id) bool nr_sdap_delete_ue_entities(ue_id_t ue_id)
......
...@@ -201,9 +201,9 @@ pdusession_level_qos_parameter_t fill_qos(uint8_t qfi, const NGAP_QosFlowLevelQo ...@@ -201,9 +201,9 @@ pdusession_level_qos_parameter_t fill_qos(uint8_t qfi, const NGAP_QosFlowLevelQo
} }
// Allocation and Retention Priority // Allocation and Retention Priority
const NGAP_AllocationAndRetentionPriority_t *arp = &params->allocationAndRetentionPriority; const NGAP_AllocationAndRetentionPriority_t *arp = &params->allocationAndRetentionPriority;
out.allocation_retention_priority.priority_level = arp->priorityLevelARP; out.arp.priority_level = arp->priorityLevelARP;
out.allocation_retention_priority.pre_emp_capability = arp->pre_emptionCapability; out.arp.pre_emp_capability = arp->pre_emptionCapability;
out.allocation_retention_priority.pre_emp_vulnerability = arp->pre_emptionVulnerability; out.arp.pre_emp_vulnerability = arp->pre_emptionVulnerability;
return out; return out;
} }
......
...@@ -88,7 +88,9 @@ NGAP_NGAP_PDU_t *encode_ng_handover_required(const ngap_handover_required_t *msg ...@@ -88,7 +88,9 @@ NGAP_NGAP_PDU_t *encode_ng_handover_required(const ngap_handover_required_t *msg
asn1cSequenceAdd(ie6->value.choice.PDUSessionResourceListHORqd.list, NGAP_PDUSessionResourceItemHORqd_t, hoRequiredPduSession); asn1cSequenceAdd(ie6->value.choice.PDUSessionResourceListHORqd.list, NGAP_PDUSessionResourceItemHORqd_t, hoRequiredPduSession);
// PDU Session ID (M) // PDU Session ID (M)
hoRequiredPduSession->pDUSessionID = msg->pdusessions[i].pdusession_id; hoRequiredPduSession->pDUSessionID = msg->pdusessions[i].pdusession_id;
// Handover Required Transfer (M) // Handover Required Transfer (M) - ASN.1 encoding of empty transfer structure
// This is a mandatory field in the NGAP Handover Required message, however it contains
// only Direct Forwarding Path Availability IE, which is optional and is not sent
NGAP_HandoverRequiredTransfer_t hoRequiredTransfer = {0}; NGAP_HandoverRequiredTransfer_t hoRequiredTransfer = {0};
uint8_t ho_req_transfer_transparent_container_buffer[128] = {0}; uint8_t ho_req_transfer_transparent_container_buffer[128] = {0};
if (LOG_DEBUGFLAG(DEBUG_ASN1)) if (LOG_DEBUGFLAG(DEBUG_ASN1))
...@@ -123,7 +125,7 @@ NGAP_NGAP_PDU_t *encode_ng_handover_required(const ngap_handover_required_t *msg ...@@ -123,7 +125,7 @@ NGAP_NGAP_PDU_t *encode_ng_handover_required(const ngap_handover_required_t *msg
// PDU Session Resource Information List (O) // PDU Session Resource Information List (O)
asn1cCalloc(source2target->pDUSessionResourceInformationList, pduSessionList); asn1cCalloc(source2target->pDUSessionResourceInformationList, pduSessionList);
for (uint8_t i = 0; i < msg->nb_of_pdusessions; ++i) { for (uint16_t i = 0; i < msg->nb_of_pdusessions; ++i) {
const pdusession_resource_t *pduSession = &msg->pdusessions[i]; const pdusession_resource_t *pduSession = &msg->pdusessions[i];
NGAP_DEBUG("Handover Required: preparing PDU Session Resource Information List for PDU Session ID %d\n", NGAP_DEBUG("Handover Required: preparing PDU Session Resource Information List for PDU Session ID %d\n",
pduSession->pdusession_id); pduSession->pdusession_id);
......
...@@ -1206,11 +1206,10 @@ int ngap_gNB_pdusession_release_resp(instance_t instance, ngap_pdusession_releas ...@@ -1206,11 +1206,10 @@ int ngap_gNB_pdusession_release_resp(instance_t instance, ngap_pdusession_releas
/* UE associated signalling -> use the allocated stream */ /* UE associated signalling -> use the allocated stream */
ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, ue_context_p->amf_ref->assoc_id, buffer, length, ue_context_p->tx_stream); ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, ue_context_p->amf_ref->assoc_id, buffer, length, ue_context_p->tx_stream);
NGAP_INFO("pdusession_release_response sended gNB_UE_NGAP_ID %u amf_ue_ngap_id %lu nb_of_pdusessions_released %d nb_of_pdusessions_failed %d\n", NGAP_INFO("pdusession_release_response sended gNB_UE_NGAP_ID %u amf_ue_ngap_id %lu nb_of_pdusessions_released %d \n",
pdusession_release_resp_p->gNB_ue_ngap_id, pdusession_release_resp_p->gNB_ue_ngap_id,
(uint64_t)ue_context_p->amf_ue_ngap_id, (uint64_t)ue_context_p->amf_ue_ngap_id,
pdusession_release_resp_p->nb_of_pdusessions_released, pdusession_release_resp_p->nb_of_pdusessions_released);
pdusession_release_resp_p->nb_of_pdusessions_failed);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment