diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index e53ad60685..f8d69e942a 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -271,6 +271,40 @@ typedef struct pdu_session_param_s { uint8_t cause_value; } rrc_pdu_session_param_t; +typedef struct drb_s { + int status; + int defaultDRBid; + int drb_id; + int reestablishPDCP; + int recoverPDCP; + int daps_Config_r16; + struct cnAssociation_s { + 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; +} drb_t; + typedef struct gNB_RRC_UE_s { uint8_t primaryCC_id; NR_SRB_ToAddModList_t *SRB_configList; @@ -278,6 +312,7 @@ typedef struct gNB_RRC_UE_s { NR_DRB_ToAddModList_t *DRB_configList; NR_DRB_ToAddModList_t *DRB_configList2[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER]; NR_DRB_ToReleaseList_t *DRB_Release_configList2[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER]; + drb_t established_drbs[NGAP_MAX_DRBS_PER_UE]; uint8_t DRB_active[NGAP_MAX_DRBS_PER_UE]; NR_SRB_INFO_TABLE_ENTRY Srb[maxSRBs]; // 3gpp max is 3 SRBs, number 1..3, we waste the entry 0 for code simplicity diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 8bdc83d58a..f9447fc57a 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -643,7 +643,8 @@ void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, if(drb_is_active(ue_p, drb_id)){ /* Non-GBR flow using the same DRB or a GBR flow with no available DRBs*/ nb_drb_to_setup--; } else { - NR_DRB_ToAddMod_t *DRB_config = generateDRB(ue_p, drb_id, &ue_p->pduSession[i], rrc->configuration.enable_sdap, rrc->security.do_drb_integrity, rrc->security.do_drb_ciphering); + generateDRB(ue_p, drb_id, &ue_p->pduSession[i], rrc->configuration.enable_sdap, rrc->security.do_drb_integrity, rrc->security.do_drb_ciphering); + NR_DRB_ToAddMod_t *DRB_config = generateDRB_ASN1(&ue_p->established_drbs[drb_id-1]); if (drb_id_to_setup_start == 0) drb_id_to_setup_start = DRB_config->drb_Identity; asn1cSeqAdd(&ue_p->DRB_configList->list, DRB_config); @@ -1279,39 +1280,38 @@ void rrc_gNB_generate_RRCReestablishment(const protocol_ctxt_t *ctxt_pP, nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, deliver_pdu_srb_f1, rrc); } -//----------------------------------------------------------------------------- -void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctxt_pP, const rnti_t reestablish_rnti, rrc_gNB_ue_context_t *ue_context_pP, const uint8_t xid) -//----------------------------------------------------------------------------- +/* + * Handle RRC Reestablishment Complete Functions + */ + +/// @brief Function used in RRCReestablishmentComplete procedure to reestablish the SRB2. +/// @param old_xid The old RRC transaction id. +/// @param new_xid The new RRC transaction id. +void RRCReestablishmentComplete_fill_SRB2_configList(const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP, + const uint8_t old_xid, + const uint8_t new_xid) { gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - LOG_I(NR_RRC, "[RAPROC] UE %04x Logical Channel UL-DCCH, processing NR_RRCReestablishmentComplete from UE (SRB1 Active)\n", ue_p->rnti); - - NR_DRB_ToAddModList_t *DRB_configList = ue_p->DRB_configList; + NR_SRB_ToAddMod_t *SRB2_config = NULL; NR_SRB_ToAddModList_t *SRB_configList = ue_p->SRB_configList; - NR_SRB_ToAddModList_t **SRB_configList2 = NULL; - NR_DRB_ToAddModList_t **DRB_configList2 = NULL; - NR_SRB_ToAddMod_t *SRB2_config = NULL; - NR_DRB_ToAddMod_t *DRB_config = NULL; - //NR_SDAP_Config_t *sdap_config = NULL; - int i = 0; + NR_SRB_ToAddModList_t **SRB_configList2 = NULL; - uint8_t new_xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); - int ret = 0; - ue_p->StatusRrc = NR_RRC_CONNECTED; - ue_p->ue_rrc_inactivity_timer = 1; // set rrc inactivity when UE goes into RRC_CONNECTED - ue_p->reestablishment_xid = new_xid; - SRB_configList2 = &ue_p->SRB_configList2[xid]; + SRB_configList2 = &ue_p->SRB_configList2[old_xid]; // get old configuration of SRB2 if (*SRB_configList2 != NULL) { - if((*SRB_configList2)->list.count!=0) { - LOG_D(NR_RRC, "SRB_configList2(%p) count is %d\n SRB_configList2->list.array[0] addr is %p", - SRB_configList2, (*SRB_configList2)->list.count, (*SRB_configList2)->list.array[0]); + if ((*SRB_configList2)->list.count != 0) { + LOG_D(NR_RRC, + "RRC Reestablishment - SRB_configList2(%p) count is %d\n SRB_configList2->list.array[0] addr is %p\n", + SRB_configList2, + (*SRB_configList2)->list.count, + (*SRB_configList2)->list.array[0]); } - for (i = 0; (i < (*SRB_configList2)->list.count) && (i < 3); i++) { - if ((*SRB_configList2)->list.array[i]->srb_Identity == 2 ) { - LOG_D(NR_RRC, "get SRB2_config from (ue_p->SRB_configList2[%d])\n", xid); + for (int i = 0; (i < (*SRB_configList2)->list.count) && (i < 3); i++) { + if ((*SRB_configList2)->list.array[i]->srb_Identity == 2) { + LOG_D(NR_RRC, "RRC Reestablishment - get SRB2_config from (ue_p->SRB_configList2[%d])\n", old_xid); SRB2_config = (*SRB_configList2)->list.array[i]; SRB2_config->reestablishPDCP = CALLOC(1, sizeof(*SRB2_config->reestablishPDCP)); *SRB2_config->reestablishPDCP = NR_SRB_ToAddMod__reestablishPDCP_true; @@ -1320,15 +1320,11 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx } } - // SRB2_config = CALLOC(1, sizeof(*SRB2_config)); - // SRB2_config->srb_Identity = 2; - SRB_configList2 = &(ue_p->SRB_configList2[new_xid]); - DRB_configList2 = &(ue_p->DRB_configList2[new_xid]); if (*SRB_configList2) { free(*SRB_configList2); - LOG_D(NR_RRC, "free(ue_p->SRB_configList2[%d])\n", new_xid); + LOG_D(NR_RRC, "RRC Reestablishment - free(ue_p->SRB_configList2[%d])\n", new_xid); } *SRB_configList2 = CALLOC(1, sizeof(**SRB_configList2)); @@ -1337,42 +1333,74 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx // Add SRB2 to SRB configuration list asn1cSeqAdd(&SRB_configList->list, SRB2_config); asn1cSeqAdd(&(*SRB_configList2)->list, SRB2_config); - LOG_D(NR_RRC, "Add SRB2_config (srb_Identity:%ld) to ue_p->SRB_configList\n", SRB2_config->srb_Identity); - LOG_D(NR_RRC, "Add SRB2_config (srb_Identity:%ld) to ue_p->SRB_configList2[%d]\n", SRB2_config->srb_Identity, new_xid); + LOG_D(NR_RRC, "RRC Reestablishment - Add SRB2_config (srb_Identity:%ld) to ue_p->SRB_configList\n", SRB2_config->srb_Identity); + LOG_D(NR_RRC, + "RRC Reestablishment - Add SRB2_config (srb_Identity:%ld) to ue_p->SRB_configList2[%d]\n", + SRB2_config->srb_Identity, + new_xid); } else { // SRB configuration list only contains SRB1. - LOG_W(NR_RRC,"SRB2 configuration does not exist in SRB configuration list\n"); - } - - if (*DRB_configList2) { - free(*DRB_configList2); - LOG_D(NR_RRC, "free(ue_p->DRB_configList2[%d])\n", new_xid); - } - - *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); - - if (DRB_configList != NULL) { - LOG_D(NR_RRC, "get DRB_config from (ue_p->DRB_configList)\n"); - - for (i = 0; (i < DRB_configList->list.count) && (i < 3); i++) { - DRB_config = DRB_configList->list.array[i]; - asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true); - // Add DRB to DRB configuration list, for LTE_RRCConnectionReconfigurationComplete - asn1cSeqAdd(&(*DRB_configList2)->list, DRB_config); - } + LOG_W(NR_RRC, "RRC Reestablishment - SRB2 configuration does not exist in SRB configuration list\n"); } ue_p->Srb[1].Active = 1; if (get_softmodem_params()->sa) { - LOG_W(NR_RRC, "Rework identity mapping need to be done properly!\n"); - gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0}; + uint8_t send_security_mode_command = false; + nr_rrc_pdcp_config_security(ctxt_pP, ue_context_pP, send_security_mode_command); + LOG_D(NR_RRC, "RRC Reestablishment - set security successfully \n"); + } +} + +/// @brief Function used in RRCReestablishmentComplete procedure to reestablish the DRBs +/// that the UE previously had, it gets the information from the established_drbs +/// struct. +/// @param new_xid The new RRC transaction id. +void RRCReestablishmentComplete_fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP, + const uint8_t new_xid) +{ + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + NR_DRB_ToAddMod_t *DRB_config = NULL; + NR_DRB_ToAddModList_t **DRB_configList2 = &(ue_p->DRB_configList2[new_xid]); + + if (*DRB_configList2) { + free(*DRB_configList2); + LOG_D(NR_RRC, "RRC Reestablishment - free(ue_p->DRB_configList2[%d])\n", new_xid); + } + + *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); + + for (int i = 0; i < NGAP_MAX_DRBS_PER_UE; i++) { + if (ue_p->established_drbs[i].status != DRB_INACTIVE) { + ue_p->established_drbs[i].reestablishPDCP = NR_DRB_ToAddMod__reestablishPDCP_true; + DRB_config = generateDRB_ASN1(&ue_p->established_drbs[i]); + asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true); + asn1cSeqAdd(&(*DRB_configList2)->list, DRB_config); + } + } +} + +/// @brief Function used in RRCReestablishmentComplete procedure to update the NGU Tunnels. +/// @param reestablish_rnti is the old C-RNTI +void RRCReestablishmentComplete_update_ngu_tunnel(const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP, + const rnti_t reestablish_rnti) +{ + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + int i = 0; + int j = 0; + int ret = 0; + + if (get_softmodem_params()->sa) { + LOG_W(NR_RRC, "RRC Reestablishment - Rework identity mapping need to be done properly!\n"); + gtpv1u_gnb_create_tunnel_req_t create_tunnel_req = {0}; /* Save e RAB information for later */ - int j; + for (j = 0, i = 0; i < NB_RB_MAX; i++) { if (ue_p->pduSession[i].status == PDU_SESSION_STATUS_ESTABLISHED || ue_p->pduSession[i].status == PDU_SESSION_STATUS_DONE) { create_tunnel_req.pdusession_id[j] = ue_p->pduSession[i].param.pdusession_id; - create_tunnel_req.incoming_rb_id[j] = i+1; + create_tunnel_req.incoming_rb_id[j] = i + 1; create_tunnel_req.outgoing_teid[j] = ue_p->pduSession[i].param.gtp_teid; // to be developped, use the first QFI only create_tunnel_req.outgoing_qfi[j] = ue_p->pduSession[i].param.qos[0].qfi; @@ -1383,14 +1411,11 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx } create_tunnel_req.ue_id = ctxt_pP->rntiMaybeUEid; // warning put zero above - create_tunnel_req.num_tunnels = j; - ret = gtpv1u_update_ngu_tunnel( - ctxt_pP->instance, - &create_tunnel_req, - reestablish_rnti); + create_tunnel_req.num_tunnels = j; + ret = gtpv1u_update_ngu_tunnel(ctxt_pP->instance, &create_tunnel_req, reestablish_rnti); - if ( ret != 0 ) { - LOG_E(NR_RRC, "gtpv1u_update_ngu_tunnel failed,start to release UE %x\n", reestablish_rnti); + if (ret != 0) { + LOG_E(NR_RRC, "RRC Reestablishment - gtpv1u_update_ngu_tunnel failed,start to release UE %x\n", reestablish_rnti); ue_p->ue_release_timer_s1 = 1; ue_p->ue_release_timer_thres_s1 = 100; ue_p->ue_release_timer = 0; @@ -1400,34 +1425,72 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx return; } } +} + +/// @brief Function used in RRCReestablishmentComplete procedure to update the NAS PDUSessions and the xid. +/// @param old_xid Refers to the old transaction identifier passed to rrc_gNB_process_RRCReestablishmentComplete as xid. +/// @todo parameters yet to process inside the for loop. +/// @todo should test if pdu session are Ok before! inside the for loop. +void RRCReestablishmentComplete_nas_pdu_update(rrc_gNB_ue_context_t *ue_context_pP, const uint8_t old_xid) +{ + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + /* Add all NAS PDUs to the list */ + for (int i = 0; i < ue_p->nb_of_pdusessions; i++) { + ue_p->pduSession[i].status = PDU_SESSION_STATUS_DONE; + ue_p->pduSession[i].xid = old_xid; + LOG_D(NR_RRC, + "RRC Reestablishment - setting the status for the default DRB (index %d) to (%d,%s)\n", + i, + ue_p->pduSession[i].status, + "PDU_SESSION_STATUS_DONE"); + } +} + +/// @brief Function used in RRCReestablishmentComplete procedure to Free all the NAS PDU buffers. +void RRCReestablishmentComplete_nas_pdu_free(rrc_gNB_ue_context_t *ue_context_pP) +{ + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + /* Free all NAS PDUs */ + for (int i = 0; i < ue_p->nb_of_pdusessions; i++) { + if (ue_p->pduSession[i].param.nas_pdu.buffer != NULL) { + /* Free the NAS PDU buffer and invalidate it */ + free(ue_p->pduSession[i].param.nas_pdu.buffer); + ue_p->pduSession[i].param.nas_pdu.buffer = NULL; + } + } +} + +/// @brief Function tha processes RRCReestablishmentComplete message sent by the UE, after RRCReestasblishment request. +/// @param ctxt_pP Protocol context containing information regarding the UE and gNB +/// @param reestablish_rnti is the old C-RNTI +/// @param ue_context_pP UE context container information regarding the UE +/// @param xid Transaction Identifier used in RRC messages +void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctxt_pP, + const rnti_t reestablish_rnti, + rrc_gNB_ue_context_t *ue_context_pP, + const uint8_t xid) +{ + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + LOG_I(NR_RRC, + "[RAPROC] UE %04x Logical Channel UL-DCCH, processing NR_RRCReestablishmentComplete from UE (SRB1 Active)\n", + ue_p->rnti); + + int i = 0; + + uint8_t new_xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); + ue_p->StatusRrc = NR_RRC_CONNECTED; + ue_p->ue_rrc_inactivity_timer = 1; // set rrc inactivity when UE goes into RRC_CONNECTED + ue_p->reestablishment_xid = new_xid; + + RRCReestablishmentComplete_fill_SRB2_configList(ctxt_pP, ue_context_pP, xid, new_xid); + RRCReestablishmentComplete_fill_DRB_configList(ctxt_pP, ue_context_pP, new_xid); + RRCReestablishmentComplete_update_ngu_tunnel(ctxt_pP, ue_context_pP, reestablish_rnti); + RRCReestablishmentComplete_nas_pdu_update(ue_context_pP, xid); /* Update RNTI in ue_context */ - LOG_I(NR_RRC, "Updating UEid from %04x to %lx\n", ue_p->rnti, ctxt_pP->rntiMaybeUEid); + LOG_I(NR_RRC, "RRC Reestablishment - Updating UEid from %04x to %lx\n", ue_p->rnti, ctxt_pP->rntiMaybeUEid); rrc_gNB_update_ue_context_rnti(ctxt_pP->rntiMaybeUEid, RC.nrrrc[ctxt_pP->module_id], ue_p->gNB_ue_ngap_id); - if (get_softmodem_params()->sa) { - uint8_t send_security_mode_command = false; - nr_rrc_pdcp_config_security( - ctxt_pP, - ue_context_pP, - send_security_mode_command ? 0 : 1); - LOG_D(NR_RRC, "set security successfully \n"); - } - - uint8_t drb_id_to_setup_start = DRB_configList ? DRB_configList->list.array[0]->drb_Identity : 1; - uint8_t nb_drb_to_setup = DRB_configList ? DRB_configList->list.count : ue_p->nb_of_pdusessions; - /* TODO: hardcoded to 13 for the time being, to be changed? */ - long drb_priority[NGAP_MAX_DRBS_PER_UE] = {13}; - - /* Add all NAS PDUs to the list */ - for (i = 0; i < ue_p->nb_of_pdusessions; i++) { - /* TODO parameters yet to process ... */ - /* TODO should test if pdu session are Ok before! */ - ue_p->pduSession[i].status = PDU_SESSION_STATUS_DONE; - ue_p->pduSession[i].xid = xid; - LOG_D(NR_RRC, "setting the status for the default DRB (index %d) to (%d,%s)\n", i, ue_p->pduSession[i].status, "PDU_SESSION_STATUS_DONE"); - } - gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; NR_CellGroupConfig_t *cellGroupConfig = calloc(1, sizeof(NR_CellGroupConfig_t)); @@ -1435,51 +1498,62 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx ue_p->masterCellGroup->spCellConfig = ue_p->spCellConfigReestablishment; ue_p->spCellConfigReestablishment = NULL; cellGroupConfig->spCellConfig = ue_p->masterCellGroup->spCellConfig; -cellGroupConfig->physicalCellGroupConfig = ue_p->masterCellGroup->physicalCellGroupConfig; + cellGroupConfig->physicalCellGroupConfig = ue_p->masterCellGroup->physicalCellGroupConfig; - fill_mastercellGroupConfig(cellGroupConfig, ue_p->masterCellGroup, rrc->um_on_default_drb, (drb_id_to_setup_start < 2) ? 1 : 0, drb_id_to_setup_start, nb_drb_to_setup, drb_priority); + uint8_t drb_id_to_setup_start = ue_p->DRB_configList ? ue_p->DRB_configList->list.array[0]->drb_Identity : 1; + uint8_t nb_drb_to_setup = ue_p->DRB_configList ? ue_p->DRB_configList->list.count : ue_p->nb_of_pdusessions; + /* TODO: hardcoded to 13 for the time being, to be changed? */ + long drb_priority[NGAP_MAX_DRBS_PER_UE] = {13}; - for(i = 0; i < cellGroupConfig->rlc_BearerToAddModList->list.count; i++) { - cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC = CALLOC(1, sizeof(*cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC)); + fill_mastercellGroupConfig(cellGroupConfig, + ue_p->masterCellGroup, + rrc->um_on_default_drb, + (drb_id_to_setup_start < 2) ? 1 : 0, + drb_id_to_setup_start, + nb_drb_to_setup, + drb_priority); + + for (i = 0; i < cellGroupConfig->rlc_BearerToAddModList->list.count; i++) { + cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC = + CALLOC(1, sizeof(*cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC)); *cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC = NR_RLC_BearerConfig__reestablishRLC_true; } uint8_t buffer[RRC_BUF_SIZE] = {0}; int size = do_RRCReconfiguration(ctxt_pP, - buffer, - RRC_BUF_SIZE, - new_xid, - *SRB_configList2, - DRB_configList, - NULL, - NULL, - NULL, - NULL, // MeasObj_list, - NULL, - ue_context_pP, - &rrc->carrier, - NULL, - NULL, - cellGroupConfig); + buffer, + RRC_BUF_SIZE, + new_xid, + ue_p->SRB_configList2[new_xid], + ue_p->DRB_configList2[new_xid], + NULL, + NULL, + NULL, + NULL, // MeasObj_list, + NULL, + ue_context_pP, + &rrc->carrier, + NULL, + NULL, + cellGroupConfig); - LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size, "[MSG] RRC Reconfiguration\n"); + LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)buffer, size, "[MSG] RRC Reconfiguration\n"); - /* Free all NAS PDUs */ - for (i = 0; i < ue_p->nb_of_pdusessions; i++) { - if (ue_p->pduSession[i].param.nas_pdu.buffer != NULL) { - /* Free the NAS PDU buffer and invalidate it */ - free(ue_p->pduSession[i].param.nas_pdu.buffer); - ue_p->pduSession[i].param.nas_pdu.buffer = NULL; - } - } + RRCReestablishmentComplete_nas_pdu_free(ue_context_pP); if (size < 0) { LOG_E(NR_RRC, "RRC decode err!!! do_RRCReconfiguration\n"); return; } else { - LOG_I(NR_RRC, "[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate NR_RRCReconfiguration (bytes %d, UE id %04x)\n", ctxt_pP->module_id, ctxt_pP->frame, size, ue_p->rnti); + LOG_I(NR_RRC, + "[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate NR_RRCReconfiguration (bytes %d, UE id %04x)\n", + ctxt_pP->module_id, + ctxt_pP->frame, + size, + ue_p->rnti); LOG_D(NR_RRC, - "[FRAME %05d][RRC_gNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (RRCReconfiguration to UE %04x MUI %d) --->][PDCP][MOD %u][RB %u]\n", + "[FRAME %05d][RRC_gNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (RRCReconfiguration to UE %04x MUI %d) --->][PDCP][MOD " + "%u][RB %u]\n", ctxt_pP->frame, ctxt_pP->module_id, size, @@ -1493,12 +1567,16 @@ cellGroupConfig->physicalCellGroupConfig = ue_p->masterCellGroup->physicalCellGr } if (NODE_IS_DU(RC.nrrrc[ctxt_pP->module_id]->node_type) || NODE_IS_MONOLITHIC(RC.nrrrc[ctxt_pP->module_id]->node_type)) { - uint32_t delay_ms = ue_p->masterCellGroup && ue_p->masterCellGroup->spCellConfig && ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated + uint32_t delay_ms = ue_p->masterCellGroup && ue_p->masterCellGroup->spCellConfig + && ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated && ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList ? NR_RRC_RECONFIGURATION_DELAY_MS + NR_RRC_BWP_SWITCHING_DELAY_MS : NR_RRC_RECONFIGURATION_DELAY_MS; - nr_mac_enable_ue_rrc_processing_timer(ctxt_pP->module_id, ue_p->rnti, *RC.nrrrc[ctxt_pP->module_id]->carrier.servingcellconfigcommon->ssbSubcarrierSpacing, delay_ms); + nr_mac_enable_ue_rrc_processing_timer(ctxt_pP->module_id, + ue_p->rnti, + *RC.nrrrc[ctxt_pP->module_id]->carrier.servingcellconfigcommon->ssbSubcarrierSpacing, + delay_ms); } } //----------------------------------------------------------------------------- diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index 1848601de8..b4d6c55762 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -36,65 +36,109 @@ rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create) return ue->pduSession + j; } -NR_DRB_ToAddMod_t *generateDRB(gNB_RRC_UE_t *ue, uint8_t drb_id, rrc_pdu_session_param_t *pduSession, bool enable_sdap, int do_drb_integrity, int do_drb_ciphering) +void generateDRB(gNB_RRC_UE_t *ue, + uint8_t drb_id, + rrc_pdu_session_param_t *pduSession, + bool enable_sdap, + int do_drb_integrity, + int do_drb_ciphering) +{ + int i; + int qos_flow_index; + drb_t *est_drb = &ue->established_drbs[drb_id - 1]; + if (est_drb->status == DRB_INACTIVE) { + /* DRB Management */ + est_drb->drb_id = drb_id; + est_drb->reestablishPDCP = -1; + est_drb->recoverPDCP = -1; + for (i = 0; i < NGAP_MAX_DRBS_PER_UE; i++) { + if ((est_drb->cnAssociation.sdap_config.pdusession_id == 0 + || est_drb->cnAssociation.sdap_config.pdusession_id == pduSession->param.pdusession_id) + && est_drb->defaultDRBid == 0) { + est_drb->cnAssociation.sdap_config.defaultDRB = true; + est_drb->defaultDRBid = drb_id; + } + } + /* SDAP Configuration */ + est_drb->cnAssociation.present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; + est_drb->cnAssociation.sdap_config.pdusession_id = pduSession->param.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; + } else { + 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 (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) + est_drb->status = DRB_ACTIVE_NONGBR; + else + est_drb->status = DRB_ACTIVE; + } + /* PDCP Configuration */ + est_drb->pdcp_config.discardTimer = NR_PDCP_Config__drb__discardTimer_infinity; + est_drb->pdcp_config.pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits; + est_drb->pdcp_config.pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; + est_drb->pdcp_config.t_Reordering = NR_PDCP_Config__t_Reordering_ms100; + est_drb->pdcp_config.headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; + est_drb->pdcp_config.headerCompression.NotUsed = 0; + if (do_drb_integrity) + est_drb->pdcp_config.integrityProtection = NR_PDCP_Config__drb__integrityProtection_enabled; + else + est_drb->pdcp_config.integrityProtection = 1; + if (do_drb_ciphering) + est_drb->pdcp_config.ext1.cipheringDisabled = 1; + else + est_drb->pdcp_config.ext1.cipheringDisabled = NR_PDCP_Config__ext1__cipheringDisabled_true; + } +} + +NR_DRB_ToAddMod_t *generateDRB_ASN1(const drb_t *drb_asn1) { NR_DRB_ToAddMod_t *DRB_config = CALLOC(1, sizeof(*DRB_config)); - DRB_config->drb_Identity = drb_id; + NR_SDAP_Config_t *SDAP_config = CALLOC(1, sizeof(NR_SDAP_Config_t)); + asn1cCalloc(DRB_config->cnAssociation, association); - association->present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; + asn1cCalloc(SDAP_config->mappedQoS_FlowsToAdd, sdapFlows); + asn1cCalloc(DRB_config->pdcp_Config, pdcpConfig); + asn1cCalloc(pdcpConfig->drb, drb); + + DRB_config->drb_Identity = drb_asn1->drb_id; + association->present = drb_asn1->cnAssociation.present; /* SDAP Configuration */ - NR_SDAP_Config_t *SDAP_config = CALLOC(1, sizeof(NR_SDAP_Config_t)); - asn1cCalloc(SDAP_config->mappedQoS_FlowsToAdd, sdapFlows); + SDAP_config->pdu_Session = drb_asn1->cnAssociation.sdap_config.pdusession_id; + SDAP_config->sdap_HeaderDL = drb_asn1->cnAssociation.sdap_config.sdap_HeaderDL; + SDAP_config->sdap_HeaderUL = drb_asn1->cnAssociation.sdap_config.sdap_HeaderUL; + SDAP_config->defaultDRB = drb_asn1->cnAssociation.sdap_config.defaultDRB; - SDAP_config->pdu_Session = pduSession->param.pdusession_id; - - if (enable_sdap) { - SDAP_config->sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_present; - SDAP_config->sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_present; - } else { - SDAP_config->sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_absent; - SDAP_config->sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_absent; - } - - SDAP_config->defaultDRB = true; - - for (int qos_flow_index = 0; qos_flow_index < pduSession->param.nb_qos; qos_flow_index++) - { - asn1cSequenceAdd(sdapFlows->list, NR_QFI_t, qfi); - *qfi = pduSession->param.qos[qos_flow_index].qfi; - if(pduSession->param.qos[qos_flow_index].fiveQI > 5) - pduSession->param.used_drbs[drb_id - 1] = DRB_ACTIVE_NONGBR; - else - pduSession->param.used_drbs[drb_id - 1] = DRB_ACTIVE; + for (int qos_flow_index = 0; qos_flow_index < QOSFLOW_MAX_VALUE; qos_flow_index++) { + if (drb_asn1->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index] != 0) { + asn1cSequenceAdd(sdapFlows->list, NR_QFI_t, qfi); + *qfi = drb_asn1->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index]; + } } association->choice.sdap_Config = SDAP_config; /* PDCP Configuration */ - asn1cCalloc(DRB_config->pdcp_Config, pdcpConfig); - asn1cCalloc(pdcpConfig->drb, drb); + asn1cCallocOne(drb->discardTimer, drb_asn1->pdcp_config.discardTimer); + asn1cCallocOne(drb->pdcp_SN_SizeUL, drb_asn1->pdcp_config.pdcp_SN_SizeUL); + asn1cCallocOne(drb->pdcp_SN_SizeDL, drb_asn1->pdcp_config.pdcp_SN_SizeDL); + asn1cCallocOne(pdcpConfig->t_Reordering, drb_asn1->pdcp_config.t_Reordering); - asn1cCallocOne(drb->discardTimer, NR_PDCP_Config__drb__discardTimer_infinity); + drb->headerCompression.present = drb_asn1->pdcp_config.headerCompression.present; + drb->headerCompression.choice.notUsed = drb_asn1->pdcp_config.headerCompression.NotUsed; - asn1cCallocOne(drb->pdcp_SN_SizeUL, NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits); - asn1cCallocOne(drb->pdcp_SN_SizeDL, NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits); - - drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; - drb->headerCompression.choice.notUsed = 0; - - asn1cCallocOne(pdcpConfig->t_Reordering, NR_PDCP_Config__t_Reordering_ms100); - - if (do_drb_integrity) { - asn1cCallocOne(drb->integrityProtection, NR_PDCP_Config__drb__integrityProtection_enabled); + if (!drb_asn1->pdcp_config.integrityProtection) { + asn1cCallocOne(drb->integrityProtection, drb_asn1->pdcp_config.integrityProtection); } - if (!do_drb_ciphering) { + if (!drb_asn1->pdcp_config.ext1.cipheringDisabled) { asn1cCalloc(pdcpConfig->ext1, ext1); - asn1cCallocOne(ext1->cipheringDisabled, NR_PDCP_Config__ext1__cipheringDisabled_true); + asn1cCallocOne(ext1->cipheringDisabled, drb_asn1->pdcp_config.ext1.cipheringDisabled); } - ue->DRB_active[drb_id-1] = DRB_ACTIVE; - return DRB_config; } diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.h b/openair2/RRC/NR/rrc_gNB_radio_bearers.h index 62065c1d87..219bc21948 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.h +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.h @@ -35,7 +35,24 @@ #define GBR_FLOW (1) #define NONGBR_FLOW (0) -NR_DRB_ToAddMod_t *generateDRB(gNB_RRC_UE_t *rrc_ue, uint8_t drb_id, rrc_pdu_session_param_t *pduSession, bool enable_sdap, int do_drb_integrity, int do_drb_ciphering); +/// @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 Creates and stores a DRB in the gNB_RRC_UE_t struct, it doesn't create the actual entity, +/// to create the actual entity use the generateDRB_ASN1. +/// @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 +void generateDRB(gNB_RRC_UE_t *ue, + uint8_t drb_id, + rrc_pdu_session_param_t *pduSession, + bool enable_sdap, + int do_drb_integrity, + int do_drb_ciphering); uint8_t next_available_drb(gNB_RRC_UE_t *ue, rrc_pdu_session_param_t *pdusession, bool is_gbr); bool drb_is_active(gNB_RRC_UE_t *ue, uint8_t drb_id);