diff --git a/CMakeLists.txt b/CMakeLists.txt index 058bfd7a39..528b3e6482 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1893,6 +1893,7 @@ target_link_libraries(nr-cuup PRIVATE CONFIG_LIB ITTI SCTP_CLIENT GTPV1U e1ap f1ap time_management + alg z dl pthread shlib_loader ${T_LIB}) target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) if(E2_AGENT) diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c index 158c126c39..4213ea8aa3 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c @@ -27,10 +27,11 @@ #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" #include "openair2/E2AP/flexric/src/util/time_now_us.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h" - +#include "ds/seq_arr.h" #if defined (NGRAN_GNB_CUCP) #include "openair2/RRC/NR/rrc_gNB_UE_context.h" +#include "openair2/RRC/NR/rrc_gNB_radio_bearers.h" #endif 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]); gtp->msg.ngut[i].rnti = ue_id_list[i]; - int nb_pdu_session = ue_context_p->ue_context.nb_of_pdusessions; - if (nb_pdu_session > 0) { - int nb_pdu_idx = nb_pdu_session - 1; - 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; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t*, session, &ue_context_p->ue_context.pduSessions) { + gtp->msg.ngut[i].teidgnb = session->param.n3_outgoing.teid; + gtp->msg.ngut[i].teidupf = session->param.n3_incoming.teid; // TODO: one PDU session has multiple QoS Flow - int nb_qos_flow = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.nb_qos; + int nb_qos_flow = session->param.nb_qos; if (nb_qos_flow > 0) { - 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 = session->param.qos[nb_qos_flow - 1].qfi; } + break; } } diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c index aa68ba7d9d..02760c4984 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c @@ -27,6 +27,7 @@ #include "openair2/E1AP/e1ap_common.h" #include "openair2/E2AP/flexric/src/util/time_now_us.h" #include "openair2/F1AP/f1ap_ids.h" +#include "ds/seq_arr.h" 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) /* UE has no AMF UE NGAP ID yet => can't send message */ if (ue->amf_ue_ngap_id >= (1LL << 40)) continue; - for (int p = 0; p < ue->nb_of_pdusessions; ++p) { - pdusession_t *pdu = &ue->pduSession[p].param; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t*, item, &ue->pduSessions) { + pdusession_t* pdu = &item->param; 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); diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index f670dc4f86..4f06fbd0d0 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -238,8 +238,8 @@ typedef struct gNB_RRC_UE_s { rb_id_t nsa_gtp_psi[S1AP_MAX_E_RAB]; //SA block - int nb_of_pdusessions; - rrc_pdu_session_param_t pduSession[NGAP_MAX_PDU_SESSION]; + seq_arr_t pduSessions; + rrc_action_t xids[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER]; uint8_t e_rab_release_command_flag; uint32_t ue_rrc_inactivity_timer; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 2ade816666..ca8a46a705 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -656,14 +656,16 @@ nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC .srb_config_list = SRBs}; UE->DRB_ReleaseList = NULL; // pointer transferred to params - for (int i = 0; i < UE->nb_of_pdusessions; i++) { - if (UE->pduSession[i].param.nas_pdu.len > 0) { - params.dedicated_NAS_msg_list[params.num_nas_msg++] = UE->pduSession[i].param.nas_pdu; - UE->pduSession[i].param.nas_pdu.buf = NULL; - UE->pduSession[i].param.nas_pdu.len = 0; - LOG_D(NR_RRC, "Transfer NAS info with size %ld (pdusession idx %d) to RRCReconfiguration params\n", UE->pduSession[i].param.nas_pdu.len, i); + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &UE->pduSessions) { + pdusession_t *session = &item->param; + if (session->nas_pdu.len > 0) { + params.dedicated_NAS_msg_list[params.num_nas_msg++] = session->nas_pdu; + session->nas_pdu.buf = NULL; + session->nas_pdu.len = 0; + LOG_D(NR_RRC, "Transfer NAS info with size %ld to RRCReconfiguration params\n", session->nas_pdu.len); } } + if (UE->nas_pdu.len > 0) { params.dedicated_NAS_msg_list[params.num_nas_msg++] = UE->nas_pdu; UE->nas_pdu.buf = NULL; @@ -696,12 +698,11 @@ static void rrc_gNB_generate_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_ return; } - for (int i = 0; i < ue_p->nb_of_pdusessions; i++) { - if (ue_p->pduSession[i].param.nas_pdu.buf != NULL) { - ue_p->pduSession[i].xid = params.transaction_id; - } - if (ue_p->pduSession[i].status < PDU_SESSION_STATUS_ESTABLISHED) { - ue_p->pduSession[i].status = PDU_SESSION_STATUS_DONE; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &ue_p->pduSessions) { + if (item->param.nas_pdu.buf) + item->xid = params.transaction_id; + if (item->status < PDU_SESSION_STATUS_ESTABLISHED) { + item->status = PDU_SESSION_STATUS_DONE; } } @@ -718,40 +719,41 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t nr_rrc_reconfig_param_t params = get_RRCReconfiguration_params(rrc, ue_p, 0, false); ue_p->xids[params.transaction_id] = RRC_PDUSESSION_MODIFY; - for (int i = 0; i < ue_p->nb_of_pdusessions; i++) { - rrc_pdu_session_param_t *session = &ue_p->pduSession[i]; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &ue_p->pduSessions) { + pdusession_t *session = &item->param; // bypass the new and already configured pdu sessions - if (session->status >= PDU_SESSION_STATUS_DONE) { - session->xid = params.transaction_id; + if (item->status >= PDU_SESSION_STATUS_DONE) { + item->xid = params.transaction_id; continue; } - if (session->cause.type != NGAP_CAUSE_NOTHING) { + if (item->cause.type != NGAP_CAUSE_NOTHING) { // set xid of failure pdu session - session->xid = params.transaction_id; - session->status = PDU_SESSION_STATUS_FAILED; + item->xid = params.transaction_id; + item->status = PDU_SESSION_STATUS_FAILED; continue; } // search exist DRB_config int j; - for (j = 0; i < MAX_DRBS_PER_UE; j++) { + for (j = 0; j < MAX_DRBS_PER_UE; j++) { if (ue_p->established_drbs[j].status != DRB_INACTIVE - && ue_p->established_drbs[j].cnAssociation.sdap_config.pdusession_id == session->param.pdusession_id) + && ue_p->established_drbs[j].cnAssociation.sdap_config.pdusession_id == session->pdusession_id) break; } if (j == MAX_DRBS_PER_UE) { ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CauseRadioNetwork_unspecified}; - session->xid = params.transaction_id; - session->status = PDU_SESSION_STATUS_FAILED; - session->cause = cause; + item->xid = params.transaction_id; + item->status = PDU_SESSION_STATUS_FAILED; + item->cause = cause; continue; } // Reference TS23501 Table 5.7.4-1: Standardized 5QI to QoS characteristics mapping - for (qos_flow_index = 0; qos_flow_index < session->param.nb_qos; qos_flow_index++) { - switch (session->param.qos[qos_flow_index].fiveQI) { + for (qos_flow_index = 0; qos_flow_index < session->nb_qos; qos_flow_index++) { + pdusession_level_qos_parameter_t *qos = &session->qos[qos_flow_index]; + switch (qos->fiveQI) { case 1: //100ms case 2: //150ms case 3: //50ms @@ -765,18 +767,17 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t break; default: - LOG_E(NR_RRC, "not supported 5qi %lu\n", session->param.qos[qos_flow_index].fiveQI); + LOG_E(NR_RRC, "not supported 5qi %lu\n", qos->fiveQI); ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CauseRadioNetwork_not_supported_5QI_value}; - session->status = PDU_SESSION_STATUS_FAILED; - session->xid = params.transaction_id; - session->cause = cause; + item->status = PDU_SESSION_STATUS_FAILED; + item->xid = params.transaction_id; + item->cause = cause; continue; } - LOG_I(NR_RRC, "index %d, QOS flow %d, 5QI %ld \n", i, qos_flow_index, session->param.qos[qos_flow_index].fiveQI); + LOG_I(NR_RRC, "PDU Session ID %d, QOS flow %d, 5QI %ld \n", session->pdusession_id, qos_flow_index, qos->fiveQI); } - - session->status = PDU_SESSION_STATUS_DONE; - session->xid = params.transaction_id; + item->status = PDU_SESSION_STATUS_DONE; + item->xid = params.transaction_id; } byte_array_t msg = do_RRCReconfiguration(¶ms); @@ -800,16 +801,18 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration_release(gNB_RRC_INST *rrc, uint8_t *nas_buffer) //----------------------------------------------------------------------------- { - NR_DRB_ToReleaseList_t *DRB_Release_configList2 = CALLOC(sizeof(*DRB_Release_configList2), 1); + nr_rrc_reconfig_param_t params = {.transaction_id = xid}; - for (int i = 0; i < NB_RB_MAX; i++) { - if ((ue_p->pduSession[i].status == PDU_SESSION_STATUS_TORELEASE) && ue_p->pduSession[i].xid == xid) { - asn1cSequenceAdd(DRB_Release_configList2->list, NR_DRB_Identity_t, DRB_release); - *DRB_release = i + 1; + NR_DRB_ToReleaseList_t *to_release = CALLOC(sizeof(*to_release), 1); + int i = 0; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &ue_p->pduSessions) { + if ((item->status == PDU_SESSION_STATUS_TORELEASE) && item->xid == xid) { + asn1cSequenceAdd(to_release->list, NR_DRB_Identity_t, DRB_release); + *DRB_release = ++i; // DRB ID } } + params.drb_release_list = to_release; - nr_rrc_reconfig_param_t params = {.drb_release_list = DRB_Release_configList2, .transaction_id = xid}; if (nas_length > 0) { params.dedicated_NAS_msg_list[params.num_nas_msg].buf = nas_buffer; params.dedicated_NAS_msg_list[params.num_nas_msg++].len = nas_length; @@ -1783,8 +1786,12 @@ static void handle_rrcReconfigurationComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *U UE->n_initial_pdu = 0; free(UE->initial_pdus); UE->initial_pdus = NULL; - } else if (UE->nb_of_pdusessions > 0) + } else if (seq_arr_size(&UE->pduSessions) > 0) rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(rrc, UE, xid); + else + LOG_W(NR_RRC, + "UE %d: RRC Reconfiguration Complete for PDU session establishment, but no PDU sessions were setup\n", + UE->rrc_ue_id); break; case RRC_PDUSESSION_MODIFY: rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(rrc, UE, xid); @@ -2288,6 +2295,7 @@ static void rrc_delete_ue_data(gNB_RRC_UE_t *UE) free_MeasConfig(UE->measConfig); free(UE->redcap_cap); UE->redcap_cap = NULL; + seq_arr_free(&UE->pduSessions, free_pdusession); } void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p) @@ -2318,9 +2326,7 @@ static void rrc_CU_process_ue_context_release_complete(MessageDef *msg_p) /* only trigger release if it has been requested by core * otherwise, it might be CU that requested release on a DU during normal * operation (i.e, handover) */ - uint32_t pdu_sessions[NGAP_MAX_PDU_SESSION]; - get_pduSession_array(UE, pdu_sessions); - rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(0, UE->rrc_ue_id, UE->nb_of_pdusessions, pdu_sessions); + rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(0, UE->rrc_ue_id, &UE->pduSessions); rrc_remove_ue(RC.nrrrc[0], ue_context_p); } } @@ -2500,7 +2506,7 @@ static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc, { int nb_drb = 0; for (int p = 0; p < numPduSession; ++p) { - rrc_pdu_session_param_t *pdu = find_pduSession(UE, pduSession[p].id, false); + rrc_pdu_session_param_t *pdu = find_pduSession(&UE->pduSessions, pduSession[p].id); DevAssert(pdu); for (int i = 0; i < pduSession[p].numDRBSetup; i++) { const DRB_nGRAN_setup_t *drb_config = &pduSession[p].DRBnGRanList[i]; @@ -2569,7 +2575,7 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp // save the tunnel address for the PDU sessions for (int i = 0; i < resp->numPDUSessions; i++) { pdu_session_setup_t *e1_pdu = &resp->pduSession[i]; - rrc_pdu_session_param_t *rrc_pdu = find_pduSession(UE, e1_pdu->id, false); + rrc_pdu_session_param_t *rrc_pdu = find_pduSession(&UE->pduSessions, e1_pdu->id); if (rrc_pdu == NULL) { LOG_W(RRC, "E1: received setup for PDU session %ld, but has not been requested\n", e1_pdu->id); continue; @@ -2774,11 +2780,8 @@ static bool write_rrc_stats(const gNB_RRC_INST *rrc) time_t last_seen = now - ue_ctxt->last_seen; fprintf(f, " last RRC activity: %ld seconds ago\n", last_seen); - if (ue_ctxt->nb_of_pdusessions == 0) - fprintf(f, " (no PDU sessions)\n"); - for (int nb_pdu = 0; nb_pdu < ue_ctxt->nb_of_pdusessions; ++nb_pdu) { - const rrc_pdu_session_param_t *pdu = &ue_ctxt->pduSession[nb_pdu]; - fprintf(f, " PDU session %d ID %d status %s\n", nb_pdu, pdu->param.pdusession_id, get_pdusession_status_text(pdu->status)); + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, pdu, &ue_ctxt->pduSessions) { + fprintf(f, " PDU session ID %d status %s\n", pdu->param.pdusession_id, get_pdusession_status_text(pdu->status)); } fprintf(f, " associated DU: "); diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index a087942837..b1f1e3fc85 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -88,6 +88,7 @@ #include "uper_encoder.h" #include "rrc_gNB_mobility.h" #include "rrc_gNB_du.h" +#include "common/utils/alg/find.h" #ifdef E2_AGENT #include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h" @@ -278,9 +279,14 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession e1ap_nssai_t cuup_nssai = {0}; for (int i = 0; i < n; i++) { - rrc_pdu_session_param_t *pduSession = find_pduSession(UE, sessions[i].pdusession_id, true); + rrc_pdu_session_param_t *pduSession = add_pduSession(&UE->pduSessions, &sessions[i]); + if (!pduSession) { + LOG_E(NR_RRC, "Could not add PDU Session %d for UE %d\n", sessions[i].pdusession_id, UE->rrc_ue_id); + continue; + } pdusession_t *session = &pduSession->param; - cp_pdusession(session, &sessions[i]); + LOG_I(NR_RRC, "Add PDU Session %d (total nb of sessions = %ld)\n", session->pdusession_id, seq_arr_size(&UE->pduSessions)); + // Fill E1 Bearer Context Modification Request bearer_req.gNB_cu_cp_ue_id = UE->rrc_ue_id; security_information_t *secInfo = &bearer_req.secInfo; secInfo->cipheringAlgorithm = rrc->security.do_drb_ciphering ? UE->ciphering_algorithm : 0; @@ -312,7 +318,7 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession int drb_id = get_next_available_drb_id(UE); drb_t *rrc_drb = generateDRB(UE, drb_id, - pduSession, + session, rrc->configuration.enable_sdap, rrc->security.do_drb_integrity, rrc->security.do_drb_ciphering, @@ -522,8 +528,8 @@ void rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_ resp->gNB_ue_ngap_id = UE->rrc_ue_id; - for (int pdusession = 0; pdusession < UE->nb_of_pdusessions; pdusession++) { - rrc_pdu_session_param_t *session = &UE->pduSession[pdusession]; + // Optional: PDU Sessions to Setup + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) { if (session->status == PDU_SESSION_STATUS_DONE) { resp->pdusessions[pdu_sessions_done++] = fill_ngap_pdusession_setup(&session->param); } else if (session->status != PDU_SESSION_STATUS_ESTABLISHED) { @@ -705,8 +711,7 @@ void rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE ngap_pdusession_setup_resp_t *resp = &NGAP_PDUSESSION_SETUP_RESP(msg_p); resp->gNB_ue_ngap_id = UE->rrc_ue_id; - for (int pdusession = 0; pdusession < UE->nb_of_pdusessions; pdusession++) { - rrc_pdu_session_param_t *session = &UE->pduSession[pdusession]; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) { if (session->status == PDU_SESSION_STATUS_DONE) { resp->pdusessions[pdu_sessions_done++] = fill_ngap_pdusession_setup(&session->param); session->status = PDU_SESSION_STATUS_ESTABLISHED; @@ -727,8 +732,8 @@ void rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE itti_send_msg_to_task(TASK_NGAP, rrc->module_id, msg_p); } - for(int i = 0; i < NB_RB_MAX; i++) { - UE->pduSession[i].xid = -1; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) { + session->xid = -1; } return; @@ -816,7 +821,7 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins // might be more work than is worth it. See 8.2.1.4 in 38.413 for (int i = 0; i < msg->nb_pdusessions_tosetup; ++i) { const pdusession_resource_item_t *p = &msg->pdusession[i]; - rrc_pdu_session_param_t *exist = find_pduSession(UE, p->pdusession_id, false /* don't create */); + rrc_pdu_session_param_t *exist = find_pduSession(&UE->pduSessions, p->pdusession_id); if (exist) { LOG_E(NR_RRC, "UE %d: already has existing PDU session %d rejecting PDU Session Resource Setup Request\n", UE->rrc_ue_id, p->pdusession_id); ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_MULTIPLE_PDU_SESSION_ID_INSTANCES}; @@ -883,33 +888,21 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins gNB_RRC_UE_t *UE = &ue_context_p->ue_context; bool all_failed = true; for (int i = 0; i < req->nb_pdusessions_tomodify; i++) { - rrc_pdu_session_param_t *sess; - const pdusession_resource_item_t *sessMod = req->pdusession + i; - for (sess = UE->pduSession; sess < UE->pduSession + UE->nb_of_pdusessions; sess++) - if (sess->param.pdusession_id == sessMod->pdusession_id) - break; - if (sess == UE->pduSession + UE->nb_of_pdusessions) { + const pdusession_resource_item_t *sessMod = &req->pdusession[i]; + rrc_pdu_session_param_t *session = find_pduSession(&UE->pduSessions, sessMod->pdusession_id); + if (!session) { LOG_W(NR_RRC, "Requested modification of non-existing PDU session, refusing modification\n"); - UE->nb_of_pdusessions++; - sess->status = PDU_SESSION_STATUS_FAILED; - sess->param.pdusession_id = sessMod->pdusession_id; - sess->cause.type = NGAP_CAUSE_RADIO_NETWORK; - UE->pduSession[i].cause.type = NGAP_CAUSE_RADIO_NETWORK; - UE->pduSession[i].cause.value = NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_PDU_SESSION_ID; + rrc_pdu_session_param_t to_add = {0}; + to_add.status = PDU_SESSION_STATUS_FAILED; + to_add.param.pdusession_id = sessMod->pdusession_id; + to_add.cause.type = NGAP_CAUSE_RADIO_NETWORK; + to_add.cause.value = NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_PDU_SESSION_ID; + seq_arr_push_back(&UE->pduSessions, &to_add, sizeof(to_add)); } else { all_failed = false; - sess->status = PDU_SESSION_STATUS_NEW; - sess->param.pdusession_id = sessMod->pdusession_id; - sess->cause.type = NGAP_CAUSE_RADIO_NETWORK; - sess->cause.value = NGAP_CAUSE_RADIO_NETWORK_MULTIPLE_PDU_SESSION_ID_INSTANCES; - sess->status = PDU_SESSION_STATUS_NEW; - sess->param.pdusession_id = sessMod->pdusession_id; - sess->cause.type = NGAP_CAUSE_NOTHING; - if (sessMod->nas_pdu.buf != NULL) { - UE->pduSession[i].param.nas_pdu = sessMod->nas_pdu; - } - for (int i = 0; i < req->nb_pdusessions_tomodify; ++i) - cp_pdusession_resource_item_to_pdusession(&UE->pduSession[i].param, &req->pdusession[i]); + session->status = PDU_SESSION_STATUS_NEW; + session->cause.type = NGAP_CAUSE_NOTHING; + cp_pdusession_resource_item_to_pdusession(&session->param, sessMod); } } @@ -927,11 +920,12 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins msg->gNB_ue_ngap_id = req->gNB_ue_ngap_id; msg->nb_of_pdusessions = 0; - for (int i = 0; i < UE->nb_of_pdusessions; i++) { - if (UE->pduSession[i].status == PDU_SESSION_STATUS_FAILED) { - msg->pdusessions_failed[i].pdusession_id = UE->pduSession[i].param.pdusession_id; - msg->pdusessions_failed[i].cause.type = UE->pduSession[i].cause.type; - msg->pdusessions_failed[i].cause.value = UE->pduSession[i].cause.value; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) { + if (session->status == PDU_SESSION_STATUS_FAILED) { + msg->pdusessions_failed[msg->nb_of_pdusessions_failed].pdusession_id = session->param.pdusession_id; + msg->pdusessions_failed[msg->nb_of_pdusessions_failed].cause.type = session->cause.type; + msg->pdusessions_failed[msg->nb_of_pdusessions_failed].cause.value = session->cause.value; + msg->nb_of_pdusessions_failed++; } } itti_send_msg_to_task(TASK_NGAP, instance, msg_fail_p); @@ -945,6 +939,11 @@ int rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE uint16_t pdu_sessions_failed = 0; uint16_t pdu_sessions_done = 0; + if (!seq_arr_size(&UE->pduSessions)) { + LOG_W(NR_RRC, "UE %d: No PDU sessions in the list, don't send NG PDU Session Modify Response\n", UE->rrc_ue_id); + return -1; + } + msg_p = itti_alloc_new_message (TASK_RRC_GNB, rrc->module_id, NGAP_PDUSESSION_MODIFY_RESP); if (msg_p == NULL) { LOG_E(NR_RRC, "itti_alloc_new_message failed, msg_p is NULL \n"); @@ -955,63 +954,54 @@ int rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE resp->gNB_ue_ngap_id = UE->rrc_ue_id; - for (int i = 0; i < UE->nb_of_pdusessions; i++) { - if (xid != UE->pduSession[i].xid) { - LOG_W(NR_RRC, "xid does not correspond (context pdu session index %d, status %d, xid %d/%d) \n ", i, UE->pduSession[i].status, xid, UE->pduSession[i].xid); + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) { + if (xid != session->xid) { + LOG_W(NR_RRC, + "xid does not correspond (PDU Session %d, status %d, xid %d/%d) \n ", + session->param.pdusession_id, + session->status, + xid, + session->xid); continue; } - if (UE->pduSession[i].status == PDU_SESSION_STATUS_DONE) { - rrc_pdu_session_param_t *pduSession = find_pduSession(UE, UE->pduSession[i].param.pdusession_id, false); - if (pduSession) { - LOG_I(NR_RRC, "update pdu session %d \n", pduSession->param.pdusession_id); - // Update UE->pduSession - pduSession->status = PDU_SESSION_STATUS_ESTABLISHED; - pduSession->cause.type = NGAP_CAUSE_NOTHING; - for (int qos_flow_index = 0; qos_flow_index < UE->pduSession[i].param.nb_qos; qos_flow_index++) { - pduSession->param.qos[qos_flow_index] = UE->pduSession[i].param.qos[qos_flow_index]; - } - resp->pdusessions[pdu_sessions_done].pdusession_id = UE->pduSession[i].param.pdusession_id; - for (int qos_flow_index = 0; qos_flow_index < UE->pduSession[i].param.nb_qos; qos_flow_index++) { - resp->pdusessions[pdu_sessions_done].qos[qos_flow_index].qfi = UE->pduSession[i].param.qos[qos_flow_index].qfi; - } - resp->pdusessions[pdu_sessions_done].pdusession_id = UE->pduSession[i].param.pdusession_id; - resp->pdusessions[pdu_sessions_done].nb_of_qos_flow = UE->pduSession[i].param.nb_qos; - LOG_I(NR_RRC, - "Modify Resp (msg index %d, pdu session index %d, status %d, xid %d): nb_of_pduSessions %d, pdusession_id %d \n ", - pdu_sessions_done, - i, - UE->pduSession[i].status, - xid, - UE->nb_of_pdusessions, - resp->pdusessions[pdu_sessions_done].pdusession_id); - pdu_sessions_done++; - } else { - LOG_W(NR_RRC, "PDU SESSION modify of a not existing pdu session %d \n", UE->pduSession[i].param.pdusession_id); - resp->pdusessions_failed[pdu_sessions_failed].pdusession_id = UE->pduSession[i].param.pdusession_id; - ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_PDU_SESSION_ID}; - resp->pdusessions_failed[pdu_sessions_failed].cause = cause; - pdu_sessions_failed++; + if (session->status == PDU_SESSION_STATUS_DONE) { + LOG_I(NR_RRC, "Successfully modified PDU Session %d \n", session->param.pdusession_id); + // Update status + session->status = PDU_SESSION_STATUS_ESTABLISHED; + session->cause.type = NGAP_CAUSE_NOTHING; + // Fill response + DevAssert(pdu_sessions_done < NGAP_MAX_PDU_SESSION); + resp->pdusessions[pdu_sessions_done].pdusession_id = session->param.pdusession_id; + for (int qos_flow_index = 0; qos_flow_index < session->param.nb_qos; qos_flow_index++) { + resp->pdusessions[pdu_sessions_done].qos[qos_flow_index].qfi = session->param.qos[qos_flow_index].qfi; } - } else if ((UE->pduSession[i].status == PDU_SESSION_STATUS_NEW) || (UE->pduSession[i].status == PDU_SESSION_STATUS_ESTABLISHED)) { + resp->pdusessions[pdu_sessions_done].pdusession_id = session->param.pdusession_id; + resp->pdusessions[pdu_sessions_done].nb_of_qos_flow = session->param.nb_qos; + LOG_I(NR_RRC, + "Modify Resp (msg index %d, status %d, xid %d): nb_of_pduSessions %ld, pdusession_id %d \n ", + pdu_sessions_done, + session->status, + xid, + seq_arr_size(&UE->pduSessions), + resp->pdusessions[pdu_sessions_done].pdusession_id); + pdu_sessions_done++; + } else if ((session->status == PDU_SESSION_STATUS_NEW) || (session->status == PDU_SESSION_STATUS_ESTABLISHED)) { LOG_D(NR_RRC, "PDU SESSION is NEW or already ESTABLISHED\n"); - } else if (UE->pduSession[i].status == PDU_SESSION_STATUS_FAILED) { - resp->pdusessions_failed[pdu_sessions_failed].pdusession_id = UE->pduSession[i].param.pdusession_id; - resp->pdusessions_failed[pdu_sessions_failed].cause.type = UE->pduSession[i].cause.type; - resp->pdusessions_failed[pdu_sessions_failed].cause.value = UE->pduSession[i].cause.value; + } else if (session->status == PDU_SESSION_STATUS_FAILED) { + DevAssert(pdu_sessions_failed < NGAP_MAX_PDU_SESSION); + resp->pdusessions_failed[pdu_sessions_failed].pdusession_id = session->param.pdusession_id; + resp->pdusessions_failed[pdu_sessions_failed].cause.type = session->cause.type; + resp->pdusessions_failed[pdu_sessions_failed].cause.value = session->cause.value; pdu_sessions_failed++; - } - else - LOG_W(NR_RRC, - "Modify pdu session %d, unknown state %d \n ", - UE->pduSession[i].param.pdusession_id, - UE->pduSession[i].status); + } else + LOG_W(NR_RRC, "Modify pdu session %d, unknown state %d \n ", session->param.pdusession_id, session->status); } resp->nb_of_pdusessions = pdu_sessions_done; resp->nb_of_pdusessions_failed = pdu_sessions_failed; if (pdu_sessions_done > 0 || pdu_sessions_failed > 0) { - LOG_D(NR_RRC, "NGAP_PDUSESSION_MODIFY_RESP: sending the message (total pdu session %d)\n", UE->nb_of_pdusessions); + LOG_D(NR_RRC, "NGAP_PDUSESSION_MODIFY_RESP: sending the message (total pdu session %ld)\n", seq_arr_size(&UE->pduSessions)); itti_send_msg_to_task (TASK_NGAP, rrc->module_id, msg_p); } else { itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p); @@ -1036,8 +1026,10 @@ void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ(const module_id_t gnb_mod_idP, req->gNB_ue_ngap_id = UE->rrc_ue_id; req->cause.type = causeP.type; req->cause.value = causeP.value; - for (int i = 0; i < UE->nb_of_pdusessions; i++) { - req->pdusessions[i].pdusession_id = UE->pduSession[i].param.pdusession_id; + // PDU Session Resource List (optional) + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) { + DevAssert(req->nb_of_pdusessions < NGAP_MAX_PDU_SESSION); + req->pdusessions[req->nb_of_pdusessions].pdusession_id = session->param.pdusession_id; req->nb_of_pdusessions++; } itti_send_msg_to_task(TASK_NGAP, GNB_MODULE_ID_TO_INSTANCE(gnb_mod_idP), msg); @@ -1255,7 +1247,7 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_ LOG_W(NR_RRC, "[gNB %ld] In NGAP_UE_CONTEXT_RELEASE_COMMAND: unknown UE from gNB_ue_ngap_id (%u)\n", instance, gNB_ue_ngap_id); - rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance, gNB_ue_ngap_id, 0, NULL); + rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance, gNB_ue_ngap_id, NULL); return -1; } @@ -1286,25 +1278,24 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_ /* UE will be freed after UE context release complete */ } else { // the DU is offline already - uint32_t pdu_sessions[NGAP_MAX_PDU_SESSION]; - get_pduSession_array(UE, pdu_sessions); - rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(0, UE->rrc_ue_id, UE->nb_of_pdusessions, pdu_sessions); + rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(0, UE->rrc_ue_id, &UE->pduSessions); rrc_remove_ue(rrc, ue_context_p); } return 0; } -void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, - uint32_t gNB_ue_ngap_id, - int num_pdu, - uint32_t pdu_session_id[256]) +void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, uint32_t gNB_ue_ngap_id, seq_arr_t *pdusessions) { MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_UE_CONTEXT_RELEASE_COMPLETE); - NGAP_UE_CONTEXT_RELEASE_COMPLETE(msg).gNB_ue_ngap_id = gNB_ue_ngap_id; - NGAP_UE_CONTEXT_RELEASE_COMPLETE(msg).num_pdu_sessions = num_pdu; - for (int i = 0; i < num_pdu; ++i) - NGAP_UE_CONTEXT_RELEASE_COMPLETE(msg).pdu_session_id[i] = pdu_session_id[i]; + ngap_ue_release_complete_t *complete = &NGAP_UE_CONTEXT_RELEASE_COMPLETE(msg); + complete->gNB_ue_ngap_id = gNB_ue_ngap_id; + // PDU Session Resource List (Optional) + if (pdusessions && seq_arr_size(pdusessions)) { + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, pdusessions) { + complete->pdu_session_id[complete->num_pdu_sessions++] = session->param.pdusession_id; + } + } itti_send_msg_to_task(TASK_NGAP, instance, msg); } @@ -1361,14 +1352,14 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(gNB_RRC_INST *rrc, gNB_RRC_U // AMF UE NGAP ID msg->amf_ue_ngap_id = UE->amf_ue_ngap_id; // PDU Session Resource Admitted List - msg->nb_of_pdusessions = UE->nb_of_pdusessions; - for (int i = 0; i < UE->nb_of_pdusessions; i++) { - rrc_pdu_session_param_t *session = &UE->pduSession[i]; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t*, session, &UE->pduSessions) { session->status = PDU_SESSION_STATUS_ESTABLISHED; // PDU Session ID - msg->pdusessions[i].pdu_session_id = session->param.pdusession_id; + DevAssert(msg->nb_of_pdusessions < NGAP_MAX_PDU_SESSION); + pdu_session_resource_admitted_t *pdu = &msg->pdusessions[msg->nb_of_pdusessions++]; + pdu->pdu_session_id = session->param.pdusession_id; // Handover Request Acknowledge Transfer - ho_request_ack_transfer_t *transfer = &msg->pdusessions[i].ack_transfer; + ho_request_ack_transfer_t *transfer = &pdu->ack_transfer; transfer->gtp_teid = session->param.n3_outgoing.teid; memcpy(transfer->gNB_addr.buffer, session->param.n3_outgoing.addr.buffer, session->param.n3_outgoing.addr.length); transfer->gNB_addr.length = session->param.n3_outgoing.addr.length; @@ -1439,19 +1430,19 @@ void rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(gNB_RRC_INST *rrc, gNB_RRC_UE memset(resp, 0, sizeof(*resp)); resp->gNB_ue_ngap_id = UE->rrc_ue_id; - for (int i = 0; i < UE->nb_of_pdusessions; i++) { - if (xid == UE->pduSession[i].xid) { - resp->pdusession_release[pdu_sessions_released].pdusession_id = UE->pduSession[i].param.pdusession_id; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) { + if (xid == session->xid) { + const pdusession_t *pdusession = &session->param; + resp->pdusession_release[pdu_sessions_released].pdusession_id = pdusession->pdusession_id; + session->status = PDU_SESSION_STATUS_RELEASED; pdu_sessions_released++; - //clear - memset(&UE->pduSession[i], 0, sizeof(*UE->pduSession)); - UE->pduSession[i].status = PDU_SESSION_STATUS_RELEASED; - LOG_W(NR_RRC, "Released pdu session, but code to finish to free memory\n"); } } resp->nb_of_pdusessions_released = pdu_sessions_released; resp->nb_of_pdusessions_failed = 0; + DevAssert(resp->nb_of_pdusessions_released < NGAP_MAX_PDU_SESSION); + LOG_I(NR_RRC, "NGAP PDUSESSION RELEASE RESPONSE: rrc_ue_id %u release_pdu_sessions %d\n", resp->gNB_ue_ngap_id, pdu_sessions_released); itti_send_msg_to_task (TASK_NGAP, rrc->module_id, msg_p); } @@ -1479,14 +1470,15 @@ int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_ uint8_t xid = rrc_gNB_get_next_transaction_identifier(rrc->module_id); UE->xids[xid] = RRC_PDUSESSION_RELEASE; for (int pdusession = 0; pdusession < cmd->nb_pdusessions_torelease; pdusession++) { - rrc_pdu_session_param_t *pduSession = find_pduSession(UE, cmd->pdusession_release_params[pdusession].pdusession_id, false); + rrc_pdu_session_param_t *pduSession = find_pduSession(&UE->pduSessions, cmd->pdusession_release_params[pdusession].pdusession_id); if (!pduSession) { LOG_I(NR_RRC, "no pdusession_id, AMF requested to close it id=%d\n", cmd->pdusession_release_params[pdusession].pdusession_id); - int j=UE->nb_of_pdusessions++; - UE->pduSession[j].status = PDU_SESSION_STATUS_FAILED; - UE->pduSession[j].param.pdusession_id = cmd->pdusession_release_params[pdusession].pdusession_id; + rrc_pdu_session_param_t item = {0}; + item.status = PDU_SESSION_STATUS_FAILED; + item.param.pdusession_id = cmd->pdusession_release_params[pdusession].pdusession_id; ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_PDU_SESSION_ID}; - UE->pduSession[j].cause = cause; + item.cause = cause; + seq_arr_push_back(&UE->pduSessions, &item, sizeof(item)); continue; } if (pduSession->status == PDU_SESSION_STATUS_FAILED) { @@ -1578,7 +1570,6 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(gNB_RRC_INST *rrc, ngap_handover_required_t msg = { .amf_ue_ngap_id = UE->amf_ue_ngap_id, .gNB_ue_ngap_id = UE->rrc_ue_id, - .nb_of_pdusessions = UE->nb_of_pdusessions, .cause.type = NGAP_CAUSE_RADIO_NETWORK, .cause.value = NGAP_CAUSE_RADIO_NETWORK_HANDOVER_DESIRABLE_FOR_RADIO_REASON, .handoverType = HANDOVER_TYPE_INTRA5GS, @@ -1607,22 +1598,21 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(gNB_RRC_INST *rrc, /* Fill both PDU Session Resource List IE (M) in Handover Required and PDU Session Resource Information List IE (O) in the Source NG-RAN Node to Target NG-RAN Node Transparent Container */ - for (int i = 0; i < UE->nb_of_pdusessions; ++i) { - if (UE->pduSession[i].status == PDU_SESSION_STATUS_DONE || UE->pduSession[i].status == PDU_SESSION_STATUS_ESTABLISHED) { - rrc_pdu_session_param_t *pduSession = find_pduSession(UE, UE->pduSession[i].param.pdusession_id, false); - if (!pduSession) - continue; - pdusession_t *session = &pduSession->param; - // PDU Session ID - msg.pdusessions[i].pdusession_id = session->pdusession_id; - // PDU Session Resource Information List (O) - pdusession_resource_info_t *pdu_info = &msg.source2target->pdu_session_resource[msg.source2target->nb_pdu_session_resource++]; - pdu_info->pdusession_id = session->pdusession_id; - pdu_info->nb_of_qos_flow = session->nb_qos; - for (int j = 0; j < session->nb_qos; ++j) { - pdu_info->qos_flow_info[j].qfi = session->qos[j].qfi; - } - msg.source2target->nb_pdu_session_resource++; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t*, pduSession, &UE->pduSessions) { + if (pduSession->status != PDU_SESSION_STATUS_DONE && pduSession->status != PDU_SESSION_STATUS_ESTABLISHED) + continue; + pdusession_t *session = &pduSession->param; + DevAssert(msg.nb_of_pdusessions < NGAP_MAX_PDU_SESSION); + pdusession_resource_t *pdu = &msg.pdusessions[msg.nb_of_pdusessions++]; + // PDU Session ID + pdu->pdusession_id = session->pdusession_id; + // PDU Session Resource Information List (O) + DevAssert(msg.source2target->nb_pdu_session_resource < NGAP_MAX_PDU_SESSION); + pdusession_resource_info_t *pdu_info = &msg.source2target->pdu_session_resource[msg.source2target->nb_pdu_session_resource++]; + pdu_info->pdusession_id = session->pdusession_id; + pdu_info->nb_of_qos_flow = session->nb_qos; + for (int j = 0; j < pdu_info->nb_of_qos_flow; ++j) { + pdu_info->qos_flow_info[j].qfi = session->qos[j].qfi; } } diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h index b90d9a1493..c07cb04be0 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.h +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -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); -void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, - uint32_t gNB_ue_ngap_id, - int num_pdu, - uint32_t pdu_session_id[256]); +void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, uint32_t gNB_ue_ngap_id, seq_arr_t *pduSessions); 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); diff --git a/openair2/RRC/NR/rrc_gNB_UE_context.c b/openair2/RRC/NR/rrc_gNB_UE_context.c index cb3a04fbce..d8d83505b9 100644 --- a/openair2/RRC/NR/rrc_gNB_UE_context.c +++ b/openair2/RRC/NR/rrc_gNB_UE_context.c @@ -40,6 +40,7 @@ #include "linear_alloc.h" #include "openair2/F1AP/f1ap_ids.h" #include "tree.h" +#include "rrc_gNB_radio_bearers.h" 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 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); - 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); return(new_p); } @@ -211,6 +209,9 @@ 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->ongoing_pdusession_setup_request = false; + // Initialise setup PDU Sessions list + seq_arr_init(&ue->pduSessions, sizeof(rrc_pdu_session_param_t)); + RB_INSERT(rrc_nr_ue_tree_s, &rrc_instance_pP->rrc_ue_head, ue_context_p); LOG_UE_EVENT(ue, "Create UE context: CU UE ID %u DU UE ID %u (rnti: %04x, random ue id %lx)\n", diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 07b742e16c..40ff7d8ab2 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -76,6 +76,7 @@ static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_ /* fetch an existing PDU session for this DRB */ 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); + // 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"); diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index d91c866cd4..0192203af1 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -31,6 +31,14 @@ #include "ngap_messages_types.h" #include "oai_asn1.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_asn1_utils.h" +#include "common/utils/alg/find.h" + +static bool eq_pdu_session_id(const void *vval, const void *vit) +{ + const int id = *(const int *)vval; + const rrc_pdu_session_param_t *elem = vit; + return elem->param.pdusession_id == id; +} /** @brief Deep copy pdusession_t */ void cp_pdusession(pdusession_t *dst, const pdusession_t *src) @@ -41,19 +49,49 @@ void cp_pdusession(pdusession_t *dst, const pdusession_t *src) dst->nas_pdu = copy_byte_array(src->nas_pdu); } -rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create) +/** @brief Free pdusession_t */ +void free_pdusession(void *ptr) { - int j; - for (j = 0; j < ue->nb_of_pdusessions; j++) - if (id == ue->pduSession[j].param.pdusession_id) - break; - if (j == ue->nb_of_pdusessions) { - if (create) - ue->nb_of_pdusessions++; - else - return NULL; + rrc_pdu_session_param_t *elem = ptr; + free_byte_array(elem->param.nas_pdu); +} + +/** @brief Retrieves PDU Session for the input ID + * @return pointer to the found PDU Session, NULL if not found */ +rrc_pdu_session_param_t *find_pduSession(seq_arr_t *seq, int id) +{ + DevAssert(seq); + elm_arr_t elm = find_if(seq, &id, eq_pdu_session_id); + if (elm.found) + return (rrc_pdu_session_param_t *)elm.it; + return NULL; +} + +/** @brief Adds a new PDU Session to the list + * @return pointer to the new PDU Session */ +rrc_pdu_session_param_t *add_pduSession(seq_arr_t *sessions_ptr, const pdusession_t *in) +{ + DevAssert(sessions_ptr); + DevAssert(in); + + if (seq_arr_size(sessions_ptr) == NGAP_MAX_PDU_SESSION) { + LOG_W(NR_RRC, "Reached maximum number of PDU Session = %ld\n", seq_arr_size(sessions_ptr)); + return NULL; } - return ue->pduSession + j; + + rrc_pdu_session_param_t *exists = find_pduSession(sessions_ptr, in->pdusession_id); + if (exists) { + LOG_E(NR_RRC, "Trying to add an already existing PDU Session with ID=%d\n", in->pdusession_id); + return NULL; + } + + rrc_pdu_session_param_t new = {.param = *in, .status = PDU_SESSION_STATUS_NEW, .xid = -1}; + seq_arr_push_back(sessions_ptr, &new, sizeof(rrc_pdu_session_param_t)); + rrc_pdu_session_param_t *added = find_pduSession(sessions_ptr, in->pdusession_id); + DevAssert(added); + LOG_I(NR_RRC, "Added PDU Session %d, (total nb of sessions = %ld)\n", in->pdusession_id, seq_arr_size(sessions_ptr)); + + return added; } rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id) @@ -65,13 +103,7 @@ rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id return NULL; } int id = drb->cnAssociation.sdap_config.pdusession_id; - return find_pduSession(ue, id, false); -} - -void get_pduSession_array(gNB_RRC_UE_t *ue, uint32_t pdu_sessions[NGAP_MAX_PDU_SESSION]) -{ - for (int i = 0; i < ue->nb_of_pdusessions && i < NGAP_MAX_PDU_SESSION; ++i) - pdu_sessions[i] = ue->pduSession[i].param.pdusession_id; + return find_pduSession(&ue->pduSessions, id); } drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id) @@ -117,7 +149,7 @@ void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, d drb_t *generateDRB(gNB_RRC_UE_t *ue, uint8_t drb_id, - const rrc_pdu_session_param_t *pduSession, + const pdusession_t *pduSession, bool enable_sdap, int do_drb_integrity, int do_drb_ciphering, @@ -125,7 +157,7 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue, { DevAssert(ue != NULL); - LOG_I(NR_RRC, "UE %d: configure DRB ID %d for PDU session ID %d\n", ue->rrc_ue_id, drb_id, pduSession->param.pdusession_id); + LOG_I(NR_RRC, "UE %d: configure DRB ID %d for PDU session ID %d\n", ue->rrc_ue_id, drb_id, pduSession->pdusession_id); drb_t *est_drb = &ue->established_drbs[drb_id - 1]; DevAssert(est_drb->status == DRB_INACTIVE); @@ -136,7 +168,7 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue, /* SDAP Configuration */ est_drb->cnAssociation.present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; - est_drb->cnAssociation.sdap_config.pdusession_id = pduSession->param.pdusession_id; + est_drb->cnAssociation.sdap_config.pdusession_id = pduSession->pdusession_id; if (enable_sdap) { est_drb->cnAssociation.sdap_config.sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_present; est_drb->cnAssociation.sdap_config.sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_present; @@ -144,9 +176,9 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue, est_drb->cnAssociation.sdap_config.sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_absent; est_drb->cnAssociation.sdap_config.sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_absent; } - for (int qos_flow_index = 0; qos_flow_index < pduSession->param.nb_qos; qos_flow_index++) { - est_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index] = pduSession->param.qos[qos_flow_index].qfi; - if (pduSession->param.qos[qos_flow_index].fiveQI > 5) + for (int qos_flow_index = 0; qos_flow_index < pduSession->nb_qos; qos_flow_index++) { + est_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index] = pduSession->qos[qos_flow_index].qfi; + if (pduSession->qos[qos_flow_index].fiveQI > 5) est_drb->status = DRB_ACTIVE_NONGBR; else est_drb->status = DRB_ACTIVE; diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.h b/openair2/RRC/NR/rrc_gNB_radio_bearers.h index 1eac60a609..fd37f82de0 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.h +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.h @@ -53,7 +53,7 @@ drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id); /// @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, + const pdusession_t *pduSession, bool enable_sdap, int do_drb_integrity, int do_drb_ciphering, @@ -65,20 +65,21 @@ uint8_t get_next_available_drb_id(gNB_RRC_UE_t *ue); /// @brief returns the number of active DRBs for this UE int get_number_active_drbs(gNB_RRC_UE_t *ue); -/// @brief retrieve PDU session of UE ue with ID id, optionally creating it if -/// create is true -rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create); +/// @brief retrieve PDU session of UE ue with ID id +rrc_pdu_session_param_t *find_pduSession(seq_arr_t *seq, int id); + +/// @brief Add a new PDU session for UE @param ue and configuration @param in +rrc_pdu_session_param_t *add_pduSession(seq_arr_t *sessions_ptr, const pdusession_t *in); /// @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); -/// @brief get the PDU sessions of this UE in a single array -void get_pduSession_array(gNB_RRC_UE_t *ue, uint32_t pdu_sessions[NGAP_MAX_PDU_SESSION]); - /// @brief set PDCP configuration in a bearer context management message void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, drb_t *rrc_drb, bool um_on_default_drb); /// @brief Deep copy an instance of struct pdusession_t void cp_pdusession(pdusession_t *dst, const pdusession_t *src); +void free_pdusession(void *ptr); + #endif