X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=src%2Fcu_stub%2Fcu_f1ap_msg_hdl.c;h=39b0c1fa48ef91a694d5aa18b4083be7c956ac80;hb=05d098e6b94f629a932caaff404f2b703b123852;hp=aef220d44bdaad9badc136feb179d59d01cd0fbe;hpb=0bb62f25ad9d8f9ff8724572f96e51a898937f0c;p=o-du%2Fl2.git diff --git a/src/cu_stub/cu_f1ap_msg_hdl.c b/src/cu_stub/cu_f1ap_msg_hdl.c index aef220d44..39b0c1fa4 100644 --- a/src/cu_stub/cu_f1ap_msg_hdl.c +++ b/src/cu_stub/cu_f1ap_msg_hdl.c @@ -24,7 +24,18 @@ #include "ProtocolIE-Field.h" #include "ProtocolExtensionField.h" #include "ProtocolIE-SingleContainer.h" +#include "F1SetupResponse.h" +#include "SuccessfulOutcome.h" +#include "InitiatingMessage.h" +#include "NonDynamic5QIDescriptor.h" +#include "AveragingWindow.h" +#include "MaxDataBurstVolume.h" +#include "Flows-Mapped-To-DRB-Item.h" +#include "SliceSupportItem.h" +#include "ServedPLMNs-Item.h" #include "F1AP-PDU.h" +#include "ULUPTNLInformation-ToBeSetup-Item.h" +#include "ULConfiguration.h" #include "ModulationOrder.h" #include "BandNR.h" #include "UE-CapabilityRAT-Container.h" @@ -130,6 +141,7 @@ #include "CNUEPagingIdentity.h" #include "PagingCell-Item.h" #include "UL-DCCH-Message.h" +#include "DRX-ConfigRrc.h" #include "cu_stub_sctp.h" #include "cu_stub_egtp.h" @@ -165,7 +177,7 @@ S16 SendF1APMsg(Region region, Pool pool, uint32_t duId) { ODU_PRINT_MSG(mBuf, 0,0); - if(sctpSend(duId, mBuf) != ROK) + if(sctpSend(F1_INTERFACE, duId, mBuf) != ROK) { DU_LOG("\nERROR --> F1AP : SCTP Send failed"); ODU_PUT_MSG_BUF(mBuf); @@ -212,10 +224,10 @@ uint8_t BuildAndSendF1SetupRsp(uint32_t duId, BIT_STRING_t *nrcellId) uint8_t idx,ieIdx; uint8_t elementCnt,cellCnt; F1AP_PDU_t *f1apMsg = NULL; - F1SetupResponse_t *f1SetupRsp; - GNB_CU_Name_t *cuName; + F1SetupResponse_t *f1SetupRsp = NULL; + GNB_CU_Name_t *cuName = NULL; Cells_to_be_Activated_List_t *cellToActivate; - RRC_Version_t *rrcVer; + RRC_Version_t *rrcVer = NULL; asn_enc_rval_t encRetVal; DU_LOG("\nINFO --> F1AP : Building F1 Setup Response\n"); @@ -242,7 +254,7 @@ uint8_t BuildAndSendF1SetupRsp(uint32_t duId, BIT_STRING_t *nrcellId) SuccessfulOutcome__value_PR_F1SetupResponse; f1SetupRsp = &f1apMsg->choice.successfulOutcome->value.choice.F1SetupResponse; - elementCnt = 4; + elementCnt = 3; f1SetupRsp->protocolIEs.list.count = elementCnt; f1SetupRsp->protocolIEs.list.size = elementCnt*sizeof(F1SetupResponseIEs_t *); @@ -279,58 +291,54 @@ uint8_t BuildAndSendF1SetupRsp(uint32_t duId, BIT_STRING_t *nrcellId) F1SetupResponseIEs__value_PR_TransactionID; f1SetupRsp->protocolIEs.list.array[idx]->value.choice.TransactionID =\ TRANS_ID; - +#if 0 + /* CU name IE is of type printableString_t which wireshark is unable to decode. + * However this string is decoded successfully on online decoders. + * Since this is an optional IE and the value received in it are not + * used as of now, eliminating this IE for now to avoid wireshark error. + */ /*CU Name*/ idx++; f1SetupRsp->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_gNB_CU_Name; f1SetupRsp->protocolIEs.list.array[idx]->criticality = Criticality_ignore; - f1SetupRsp->protocolIEs.list.array[idx]->value.present = \ - F1SetupResponseIEs__value_PR_GNB_CU_Name; + f1SetupRsp->protocolIEs.list.array[idx]->value.present = F1SetupResponseIEs__value_PR_GNB_CU_Name; cuName = &f1SetupRsp->protocolIEs.list.array[idx]->value.choice.GNB_CU_Name; - cuName->size = sizeof(cuCb.cuCfgParams.cuName); + cuName->size = strlen((char *)cuCb.cuCfgParams.cuName); - CU_ALLOC(cuName->buf, sizeof(cuName->size)); + CU_ALLOC(cuName->buf, cuName->size); if(cuName->buf == NULLP) { for(ieIdx=0; ieIdxprotocolIEs.list.array[ieIdx],\ - sizeof(F1SetupResponseIEs_t)); + CU_FREE(f1SetupRsp->protocolIEs.list.array[ieIdx], sizeof(F1SetupResponseIEs_t)); } - CU_FREE(f1SetupRsp->protocolIEs.list.array,\ - elementCnt * sizeof(F1SetupResponseIEs_t *)); - CU_FREE(f1apMsg->choice.successfulOutcome,\ - sizeof(SuccessfulOutcome_t)); + CU_FREE(f1SetupRsp->protocolIEs.list.array, elementCnt * sizeof(F1SetupResponseIEs_t *)); + CU_FREE(f1apMsg->choice.successfulOutcome, sizeof(SuccessfulOutcome_t)); CU_FREE(f1apMsg, sizeof(F1AP_PDU_t)); return RFAILED; } strcpy((char*)cuName->buf, (char*)cuCb.cuCfgParams.cuName); +#endif /*Cells to be activated list*/ idx++; - f1SetupRsp->protocolIEs.list.array[idx]->id = \ - ProtocolIE_ID_id_Cells_to_be_Activated_List ; + f1SetupRsp->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_Cells_to_be_Activated_List ; f1SetupRsp->protocolIEs.list.array[idx]->criticality = Criticality_reject; - f1SetupRsp->protocolIEs.list.array[idx]->value.present = \ - F1SetupResponseIEs__value_PR_Cells_to_be_Activated_List; - cellToActivate = &f1SetupRsp->protocolIEs.list.array[idx]->value.choice.\ - Cells_to_be_Activated_List; + f1SetupRsp->protocolIEs.list.array[idx]->value.present = F1SetupResponseIEs__value_PR_Cells_to_be_Activated_List; + cellToActivate = &f1SetupRsp->protocolIEs.list.array[idx]->value.choice.Cells_to_be_Activated_List; + cellCnt=1; cellToActivate->list.count = cellCnt; - cellToActivate->list.size = \ - cellCnt*sizeof(struct Cells_to_be_Activated_List_ItemIEs *); - CU_ALLOC(cellToActivate->list.array,\ - sizeof(struct Cells_to_be_Activated_List_ItemIEs *)); + cellToActivate->list.size = cellCnt * sizeof(struct Cells_to_be_Activated_List_ItemIEs *); + CU_ALLOC(cellToActivate->list.array, sizeof(struct Cells_to_be_Activated_List_ItemIEs *)); if(cellToActivate->list.array == NULLP) { CU_FREE(cuName->buf, sizeof(cuName->size)); for(ieIdx=0; ieIdxprotocolIEs.list.array[ieIdx],\ - sizeof(F1SetupResponseIEs_t)); + CU_FREE(f1SetupRsp->protocolIEs.list.array[ieIdx], sizeof(F1SetupResponseIEs_t)); } - CU_FREE(f1SetupRsp->protocolIEs.list.array,\ - elementCnt * sizeof(F1SetupResponseIEs_t *)); + CU_FREE(f1SetupRsp->protocolIEs.list.array, elementCnt * sizeof(F1SetupResponseIEs_t *)); CU_FREE(f1apMsg->choice.successfulOutcome, sizeof(SuccessfulOutcome_t)); CU_FREE(f1apMsg, sizeof(F1AP_PDU_t)); return RFAILED; @@ -340,18 +348,14 @@ uint8_t BuildAndSendF1SetupRsp(uint32_t duId, BIT_STRING_t *nrcellId) CU_ALLOC(cellToActivate->list.array[ieIdx],sizeof(struct Cells_to_be_Activated_List_ItemIEs )); if(cellToActivate->list.array[ieIdx] == NULLP) { - CU_FREE(cellToActivate->list.array,\ - sizeof(struct Cells_to_be_Activated_List_ItemIEs *)); + CU_FREE(cellToActivate->list.array, sizeof(struct Cells_to_be_Activated_List_ItemIEs *)); CU_FREE(cuName->buf, sizeof(cuName->size)); for(ieIdx=0; ieIdxprotocolIEs.list.array[ieIdx], \ - sizeof(F1SetupResponseIEs_t)); + CU_FREE(f1SetupRsp->protocolIEs.list.array[ieIdx], sizeof(F1SetupResponseIEs_t)); } - CU_FREE(f1SetupRsp->protocolIEs.list.array, \ - elementCnt * sizeof(F1SetupResponseIEs_t *)); - CU_FREE(f1apMsg->choice.successfulOutcome, \ - sizeof(SuccessfulOutcome_t)); + CU_FREE(f1SetupRsp->protocolIEs.list.array, elementCnt * sizeof(F1SetupResponseIEs_t *)); + CU_FREE(f1apMsg->choice.successfulOutcome, sizeof(SuccessfulOutcome_t)); CU_FREE(f1apMsg, sizeof(F1AP_PDU_t)); return RFAILED; } @@ -427,6 +431,7 @@ uint8_t BuildAndSendF1SetupRsp(uint32_t duId, BIT_STRING_t *nrcellId) return RFAILED; } memcpy(&cellToActivate->list.array[0]->value.choice.Cells_to_be_Activated_List_Item.nRCGI.nRCellIdentity, nrcellId, sizeof(BIT_STRING_t)); + /* RRC Version */ idx++; f1SetupRsp->protocolIEs.list.array[idx]->id = \ @@ -561,8 +566,10 @@ uint8_t BuildAndSendF1SetupRsp(uint32_t duId, BIT_STRING_t *nrcellId) encRetVal = aper_encode(&asn_DEF_F1AP_PDU, 0, f1apMsg, PrepFinalEncBuf, encBuf); /* Clean up */ - CU_FREE(rrcVer->latest_RRC_Version.buf, sizeof(uint8_t)); - CU_FREE(cuName->buf, sizeof(cuName->size)); + if(rrcVer) + CU_FREE(rrcVer->latest_RRC_Version.buf, sizeof(uint8_t)); + if(cuName) + CU_FREE(cuName->buf, cuName->size); for(idx=0; idxprotocolIEs.list.array[idx], sizeof(F1SetupResponseIEs_t)); @@ -1101,7 +1108,7 @@ uint8_t fillDlCcchRrcMsg(CuUeCb *ueCb, RRCContainer_t *rrcContainer) xer_fprint(stdout, &asn_DEF_DL_CCCH_MessageType, &dl_CCCH_Msg); memset(encBuf, 0, ENC_BUF_MAX_LEN); encBufSize = 0; - encRetVal = aper_encode(&asn_DEF_DL_CCCH_MessageType, 0, &dl_CCCH_Msg, PrepFinalEncBuf, encBuf); + encRetVal = uper_encode(&asn_DEF_DL_CCCH_MessageType, 0, &dl_CCCH_Msg, PrepFinalEncBuf, encBuf); /* Encode results */ if(encRetVal.encoded == ENCODE_FAIL) { @@ -1394,7 +1401,7 @@ uint8_t fillRrcReconfigIE(RRCReconfiguration_IEs_t *rrcReconfigMsg) * * ****************************************************************/ -uint8_t fillDlDcchRrcMsg(CuUeCb *ueCb, RRCContainer_t *rrcContainer) +uint8_t fillDlDcchRrcMsg(CuUeCb *ueCb, RRCContainer_t *rrcContainer, bool updateAllRbCfg) { uint8_t ret = ROK; uint16_t idx2 = 0, drbIdx = 0, srbIdx = 0; @@ -1414,7 +1421,7 @@ uint8_t fillDlDcchRrcMsg(CuUeCb *ueCb, RRCContainer_t *rrcContainer) if(dl_DCCH_Msg.message.choice.c1->choice.rrcReconfiguration != NULLP) { DU_LOG("\nDEBUG --> F1AP : Filling DL DCCH RRC Reconfiguration Message "); - fillRrcReconfig(ueCb, dl_DCCH_Msg.message.choice.c1->choice.rrcReconfiguration, false); + fillRrcReconfig(ueCb, dl_DCCH_Msg.message.choice.c1->choice.rrcReconfiguration, updateAllRbCfg); if(ret == ROK) { /* If RB configuration are filled successfully in RRC Reconfiguration, mark these @@ -1434,7 +1441,7 @@ uint8_t fillDlDcchRrcMsg(CuUeCb *ueCb, RRCContainer_t *rrcContainer) xer_fprint(stdout, &asn_DEF_DL_DCCH_MessageType, &dl_DCCH_Msg); memset(encBuf, 0, ENC_BUF_MAX_LEN); encBufSize = 0; - encRetVal = aper_encode(&asn_DEF_DL_DCCH_MessageType, 0, &dl_DCCH_Msg, PrepFinalEncBuf, encBuf); + encRetVal = uper_encode(&asn_DEF_DL_DCCH_MessageType, 0, &dl_DCCH_Msg, PrepFinalEncBuf, encBuf); /* Encode results */ if(encRetVal.encoded == ENCODE_FAIL) { @@ -1513,8 +1520,49 @@ uint8_t BuildDLRRCContainer(CuUeCb *ueCb, uint8_t rrcMsgType, RRCContainer_t *rr } else if(rrcMsgType == RRC_SETUP_COMPLETE) { - DU_LOG("\nINFO --> F1AP : Sending Security mode command"); - char secModeBuf[9]={0x00, 0x02, 0x22, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}; + DU_LOG("\nINFO --> F1AP : Sending NAS Authentication Request"); + char authReqBuf[51] = {0x00, ueCb->pdcpSn++, 0x2a, 0x85, 0x4f, 0xc0, 0x0a, 0xc0, 0x40, 0x40, 0x00, 0x04, 0x2f, 0x58, 0x39, 0x12,\ + 0x37, 0x15, 0x74, 0x16, 0x4c, 0x8d, 0xd3, 0x95, 0xa6, 0x9e, 0x94, 0x03, 0x24, 0x02, 0x00, 0x6f,\ + 0x0b, 0x39, 0x5e, 0xbc, 0xb0, 0x00, 0x1a, 0xb1, 0xc1, 0x3f, 0x84, 0x4f, 0x77, 0xe3, 0x20, 0x00,\ + 0x00, 0x00, 0x00}; + bufLen = 51; + rrcContainer->size = bufLen; + CU_ALLOC(rrcContainer->buf, rrcContainer->size); + if(rrcContainer->buf != NULLP) + { + memset(rrcContainer->buf, 0, bufLen); + memcpy(rrcContainer->buf, authReqBuf, bufLen); + } + else + { + DU_LOG("\nERROR --> F1AP : Memory allocation failure for RRC Container buffer"); + ret = RFAILED; + + } + } + else if(rrcMsgType == NAS_AUTHENTICATION_RSP) + { + DU_LOG("\nINFO --> F1AP : Sending NAS Security mode command"); + char secModeBuf[30]={0x00, ueCb->pdcpSn++, 0x2e, 0x82, 0xaf, 0xc0, 0x7d, 0x1c, 0x4e, 0xfc, 0x80, 0x0f, 0xc0, + 0x0b, 0xa0, 0x20, 0x40, 0x9e, 0x0e, 0x1e, 0x0e, 0x1c, 0x26, 0xc0, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00}; + bufLen =30; + rrcContainer->size = bufLen; + CU_ALLOC(rrcContainer->buf, rrcContainer->size); + if(rrcContainer->buf != NULLP) + { + memset(rrcContainer->buf, 0, bufLen); + memcpy(rrcContainer->buf, secModeBuf, bufLen); + } + else + { + DU_LOG("\nERROR --> F1AP : Memory allocation failure for RRC Container buffer"); + ret = RFAILED; + } + } + else if(rrcMsgType == NAS_SECURITY_MODE_COMPLETE) + { + DU_LOG("\nINFO --> F1AP : Sending RRC Security mode command"); + char secModeBuf[9]={0x00, ueCb->pdcpSn++, 0x22, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}; bufLen =9; rrcContainer->size = bufLen; CU_ALLOC(rrcContainer->buf, rrcContainer->size); @@ -1529,11 +1577,11 @@ uint8_t BuildDLRRCContainer(CuUeCb *ueCb, uint8_t rrcMsgType, RRCContainer_t *rr ret = RFAILED; } } - else if(rrcMsgType == SECURITY_MODE_COMPLETE) + else if(rrcMsgType == RRC_SECURITY_MODE_COMPLETE) { /*Hardcoded RRC Container from reference logs*/ DU_LOG("\nINFO --> F1AP : Sending Registration accept"); - char buf[14] ={0x00, 0x03, 0x2a, 0x80, 0xaf, 0xc0, 0x08, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00}; + char buf[14] ={0x00, ueCb->pdcpSn++, 0x2a, 0x80, 0xaf, 0xc0, 0x08, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00}; bufLen =14; rrcContainer->size = bufLen; CU_ALLOC(rrcContainer->buf, rrcContainer->size); @@ -1550,8 +1598,22 @@ uint8_t BuildDLRRCContainer(CuUeCb *ueCb, uint8_t rrcMsgType, RRCContainer_t *rr } else if(rrcMsgType == UE_CONTEXT_SETUP_RSP) { + uint16_t tmpBufIdx = 0, bufIdx = 0; + RRCContainer_t rrcContainerTmp; DU_LOG("\nINFO --> F1AP : Filling DL DCCH RRC Message for RRC Reconfiguration "); - ret = fillDlDcchRrcMsg(ueCb, rrcContainer); + ret = fillDlDcchRrcMsg(ueCb, &rrcContainerTmp, false); + rrcContainer->size = rrcContainerTmp.size + 2; + CU_ALLOC(rrcContainer->buf, rrcContainer->size); + if(rrcContainer->buf != NULLP) + { + memset(rrcContainer->buf, 0, rrcContainer->size); + rrcContainer->buf[0] = 0x00; + rrcContainer->buf[1] = ueCb->pdcpSn++; //PDCP SN + for(bufIdx = 2, tmpBufIdx = 0; bufIdx < rrcContainer->size; bufIdx++, tmpBufIdx++) + { + rrcContainer->buf[bufIdx] = rrcContainerTmp.buf[tmpBufIdx]; + } + } if(ret == RFAILED) DU_LOG("\nERROR --> F1AP: Failed to fill DL-DCCH Msg for RRC Reconfiguration"); } @@ -1767,8 +1829,14 @@ uint8_t setDlRRCMsgType(CuUeCb *ueCb) case RRC_SETUP_COMPLETE: rrcMsgType = RRC_SETUP_COMPLETE; break; - case SECURITY_MODE_COMPLETE: - rrcMsgType = SECURITY_MODE_COMPLETE; + case NAS_AUTHENTICATION_RSP: + rrcMsgType = NAS_AUTHENTICATION_RSP; + break; + case NAS_SECURITY_MODE_COMPLETE: + rrcMsgType = NAS_SECURITY_MODE_COMPLETE; + break; + case RRC_SECURITY_MODE_COMPLETE: + rrcMsgType = RRC_SECURITY_MODE_COMPLETE; break; case REGISTRATION_COMPLETE: rrcMsgType = REGISTRATION_COMPLETE; @@ -1785,6 +1853,187 @@ uint8_t setDlRRCMsgType(CuUeCb *ueCb) return rrcMsgType; } +#ifdef NR_DRX +/******************************************************************* + * + * @brief fill long cycle offset value of drx + * + * @details + * + * Function : fillLongCycleOffsetValue + * + * Functionality: fill long cycle offset value of drx + * + * @params[in] DrxLongCycleStartOffset drxLongCycleStartOffset, + * struct DRX_ConfigRrc__drx_LongCycleStartOffset recvedLongCycleOffsetVal + * + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +void fillLongCycleOffsetValue(DrxLongCycleStartOffset *drxLongCycleStartOffset, struct DRX_ConfigRrc__drx_LongCycleStartOffset *recvedLongCycleOffsetVal) +{ + + drxLongCycleStartOffset->drxLongCycleStartOffsetChoice = recvedLongCycleOffsetVal->present; + switch(recvedLongCycleOffsetVal->present) + { + case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms10: + { + drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms10; + break; + } + case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms20: + { + drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms20; + break; + } + case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms32: + { + drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms32; + break; + } + case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms40: + { + drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms40; + break; + } + case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms60: + { + drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms60; + break; + } + case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms64: + { + drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms64; + break; + } + case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms70: + { + drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms70; + break; + } + case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms80: + { + drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms80; + break; + } + case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms128: + { + drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms128; + break; + } + case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms160: + { + drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms160; + break; + } + case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms256: + { + drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms256; + break; + } + case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms320: + { + drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms320; + break; + } + case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms512: + { + drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms512; + break; + } + case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms640: + { + drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms640; + break; + } + case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms1024: + { + drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms1024; + break; + } + case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms1280: + { + drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms1280; + break; + } + case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms2048: + { + drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms2048; + break; + } + case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms2560: + { + drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms2560; + break; + } + case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms5120: + { + drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms5120; + break; + } + case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms10240: + { + drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms10240; + break; + } + default : + break; + } +} + +/******************************************************************* + * + * @brief Extract configuration from DRX_ConfigRrc + * and store the drx configuration in UeCb + * + * @details + * + * Function : storeDrxCfgInUeCb + * + * Functionality: Store drx configuration in UeCb + * + * @params[in] (struct DRX_ConfigRrc *setup, DrxCfg *drxCfg) + * + * @return void + * ****************************************************************/ +void storeDrxCfgInUeCb(struct DRX_ConfigRrc *drxSetup, DrxCfg *drxCfg) +{ + switch(drxSetup->drx_onDurationTimer.present) + { + case DRX_ConfigRrc__drx_onDurationTimer_PR_NOTHING: + break; + case DRX_ConfigRrc__drx_onDurationTimer_PR_milliSeconds: + { + drxCfg->drxOnDurationTimer.onDurationTimerValInMs = true; + drxCfg->drxOnDurationTimer.onDurationtimerValue.milliSeconds=drxSetup->drx_onDurationTimer.choice.milliSeconds; + break; + } + case DRX_ConfigRrc__drx_onDurationTimer_PR_subMilliSeconds: + { + drxCfg->drxOnDurationTimer.onDurationTimerValInMs = false; + drxCfg->drxOnDurationTimer.onDurationtimerValue.subMilliSeconds = drxSetup->drx_onDurationTimer.choice.subMilliSeconds; + break; + } + } + fillLongCycleOffsetValue(&drxCfg->drxLongCycleStartOffset, &drxSetup->drx_LongCycleStartOffset); + drxCfg->drxInactivityTimer = drxSetup->drx_InactivityTimer; + drxCfg->drxHarqRttTimerDl = drxSetup->drx_HARQ_RTT_TimerDL; + drxCfg->drxHarqRttTimerUl = drxSetup->drx_HARQ_RTT_TimerUL; + drxCfg->drxRetransmissionTimerDl = drxSetup->drx_RetransmissionTimerDL; + drxCfg->drxRetransmissionTimerUl = drxSetup->drx_RetransmissionTimerUL; + drxCfg->drxSlotOffset = drxSetup->drx_SlotOffset; + if(drxSetup->shortDRX) + { + drxCfg->shortDrxPres=true; + drxCfg->shortDrx.drxShortCycle = drxSetup->shortDRX->drx_ShortCycle; + drxCfg->shortDrx.drxShortCycleTimer = drxSetup->shortDRX->drx_ShortCycleTimer; + } + else + drxCfg->shortDrxPres=false; +} +#endif + /******************************************************************* * * @brief Extract configuration from CellGroupConfig @@ -1814,6 +2063,9 @@ uint8_t extractCellGroupConfig(CuUeCb *ueCb, CellGroupConfigRrc_t *cellGrpCfg) RLC_BearerConfig_t *rlcCfg = NULLP; RLC_Config_t *rlcLcCfg = NULLP; LogicalChannelConfig_t *macLcCfg = NULLP; +#ifdef NR_DRX + DrxCfg drxCfg; +#endif if(ueCb == NULLP) { @@ -1827,6 +2079,33 @@ uint8_t extractCellGroupConfig(CuUeCb *ueCb, CellGroupConfigRrc_t *cellGrpCfg) return RFAILED; } +#ifdef NR_DRX + if(cellGrpCfg->mac_CellGroupConfig) + { + if(cellGrpCfg->mac_CellGroupConfig->drx_ConfigRrc) + { + switch(cellGrpCfg->mac_CellGroupConfig->drx_ConfigRrc->present) + { + case MAC_CellGroupConfig__drx_ConfigRrc_PR_NOTHING: + break; + + case MAC_CellGroupConfig__drx_ConfigRrc_PR_setup: + { + if(cellGrpCfg->mac_CellGroupConfig->drx_ConfigRrc->choice.setup) + { + ueCb->drxCfgPresent = true; + storeDrxCfgInUeCb(cellGrpCfg->mac_CellGroupConfig->drx_ConfigRrc->choice.setup, &ueCb->drxCfg); + } + break; + } + + case MAC_CellGroupConfig__drx_ConfigRrc_PR_release: + break; + } + } + } +#endif + for(rbIdx = 0; rbIdx < cellGrpCfg->rlc_BearerToAddModList->list.count; rbIdx++) { srbFound = false; @@ -1960,11 +2239,11 @@ uint8_t extractDuToCuRrcCont(CuUeCb *ueCb, OCTET_STRING_t rrcCont) cellGrpCfgMsg = &cellGrpCfg; memset(cellGrpCfgMsg, 0, sizeof(CellGroupConfigRrc_t)); - rval = aper_decode(0, &asn_DEF_CellGroupConfigRrc, (void **)&cellGrpCfgMsg, rrcCont.buf, rrcCont.size, 0, 0); + rval = uper_decode(0, &asn_DEF_CellGroupConfigRrc, (void **)&cellGrpCfgMsg, rrcCont.buf, rrcCont.size, 0, 0); if(rval.code == RC_FAIL || rval.code == RC_WMORE) { - DU_LOG("\nERROR --> F1AP : ASN decode failed"); + DU_LOG("\nERROR --> F1AP : ASN decode failed in extractDuToCuRrcCont"); return RFAILED; } printf("\n"); @@ -2287,9 +2566,9 @@ uint8_t BuildQOSInfo(QosInfo *qosInfo, QoSFlowLevelQoSParameters_t *drbQos, uint return RFAILED; } - if(hoInProgress) + if(hoInProgress == Inter_DU_HO) drbQos->qoS_Characteristics.choice.non_Dynamic_5QI->fiveQI = qosInfo->nonDynFiveQI ; - else + else if(hoInProgress == false || hoInProgress == Xn_Based_Inter_CU_HO) { /*FiveQI*/ if(actionType == ProtocolIE_ID_id_DRBs_ToBeModified_Item) @@ -2328,7 +2607,7 @@ uint8_t BuildQOSInfo(QosInfo *qosInfo, QoSFlowLevelQoSParameters_t *drbQos, uint drbQos->nGRANallocationRetentionPriority.pre_emptionCapability = qosInfo->preemptionCapability; drbQos->nGRANallocationRetentionPriority.pre_emptionVulnerability = qosInfo->preemptionVulnerability; } - else + else if((hoInProgress == false) || (hoInProgress == Xn_Based_Inter_CU_HO)) { drbQos->nGRANallocationRetentionPriority.priorityLevel = PriorityLevel_lowest; drbQos->nGRANallocationRetentionPriority.pre_emptionCapability = Pre_emptionCapability_may_trigger_pre_emption; @@ -2414,6 +2693,12 @@ uint8_t BuildQOSInfo(QosInfo *qosInfo, QoSFlowLevelQoSParameters_t *drbQos, uint uint8_t BuildSNSSAI(DrbInfo *drbInfo, SNSSAI_t *snssai, Snssai *snssaiToCopy, bool hoInProgress) { /*SNSSAI*/ + /* In case of non-HO UE context creation and Xn Based HO, DRB's SNSSAI + * configuration is not known beforehand. In these 2 case, the following + * condition will hit */ + if(!hoInProgress || (hoInProgress == Xn_Based_Inter_CU_HO)) + drbInfo->snssai = snssaiToCopy; + /*ssT*/ snssai->sST.size = sizeof(uint8_t); CU_ALLOC(snssai->sST.buf, snssai->sST.size); @@ -2421,10 +2706,7 @@ uint8_t BuildSNSSAI(DrbInfo *drbInfo, SNSSAI_t *snssai, Snssai *snssaiToCopy, bo { return RFAILED; } - if(!hoInProgress) - memcpy(snssai->sST.buf, &snssaiToCopy->sst, snssai->sST.size); - else - memcpy(snssai->sST.buf, &drbInfo->snssai->sst, snssai->sST.size); + memcpy(snssai->sST.buf, &drbInfo->snssai->sst, snssai->sST.size); /*sD*/ CU_ALLOC(snssai->sD, sizeof(OCTET_STRING_t)); @@ -2438,13 +2720,8 @@ uint8_t BuildSNSSAI(DrbInfo *drbInfo, SNSSAI_t *snssai, Snssai *snssaiToCopy, bo { return RFAILED; } - if(!hoInProgress) - memcpy(snssai->sD->buf, snssaiToCopy->sd, snssai->sD->size); - else - memcpy(snssai->sD->buf, drbInfo->snssai->sd, snssai->sD->size); + memcpy(snssai->sD->buf, drbInfo->snssai->sd, snssai->sD->size); - if(!hoInProgress) - drbInfo->snssai = snssaiToCopy; return ROK; }/*End of BuildSNSSAI*/ @@ -2469,10 +2746,14 @@ uint8_t BuildFlowsMap(DrbInfo *drbInfo, Flows_Mapped_To_DRB_List_t *flowMap , ui uint8_t ret = ROK, idx = 0, flowCnt = 0, flowIdx = 0; FlowsMapped *qosFlow; - if(!hoInProgress) + /* In case of non-HO UE context creation and Xn Based HO, DRB's SNSSAI + * configuration is not known beforehand. In these 2 case, the following + * condition will hit */ + if(!hoInProgress || (hoInProgress == Xn_Based_Inter_CU_HO)) flowCnt = 1; else flowCnt = drbInfo->numFlowMap; + flowMap->list.count = flowCnt; flowMap->list.size = flowCnt * sizeof(Flows_Mapped_To_DRB_Item_t *); CU_ALLOC(flowMap->list.array,flowMap->list.size); @@ -2490,7 +2771,7 @@ uint8_t BuildFlowsMap(DrbInfo *drbInfo, Flows_Mapped_To_DRB_List_t *flowMap , ui return RFAILED; } - if(!hoInProgress) + if(!hoInProgress || (hoInProgress == Xn_Based_Inter_CU_HO)) { flowMap->list.array[idx]->qoSFlowIdentifier = 0; if(actionType == ProtocolIE_ID_id_DRBs_ToBeModified_Item) @@ -2524,7 +2805,7 @@ uint8_t BuildFlowsMap(DrbInfo *drbInfo, Flows_Mapped_To_DRB_List_t *flowMap , ui return RFAILED; } - if((!hoInProgress) && (actionType != ProtocolIE_ID_id_DRBs_ToBeModified_Item)) + if(((!hoInProgress) && (actionType != ProtocolIE_ID_id_DRBs_ToBeModified_Item)) || (hoInProgress == Xn_Based_Inter_CU_HO)) drbInfo->numFlowMap++; } return ROK; @@ -2587,7 +2868,7 @@ uint8_t BuildULTnlInfo(uint8_t duId, TnlInfo *ulUpTnlInfo, ULUPTNLInformation_To return RFAILED; } - if(!hoInProgress) + if((!hoInProgress) || (hoInProgress == Xn_Based_Inter_CU_HO)) { /* NOTE: Below IP address must be changed if running on different IP configuration */ ulInfo->list.array[idx]->uLUPTNLInformation.choice.gTPTunnel->transportLayerAddress.buf[0] = 192; @@ -2620,7 +2901,7 @@ uint8_t BuildULTnlInfo(uint8_t duId, TnlInfo *ulUpTnlInfo, ULUPTNLInformation_To return RFAILED; } - if(!hoInProgress) + if((!hoInProgress) || (hoInProgress == Xn_Based_Inter_CU_HO)) { ulInfo->list.array[idx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf[0] = 0; ulInfo->list.array[idx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf[1] = 0; @@ -2660,6 +2941,7 @@ uint8_t BuildULTnlInfo(uint8_t duId, TnlInfo *ulUpTnlInfo, ULUPTNLInformation_To * ****************************************************************/ uint8_t BuildDRBSetup(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet) { + uint16_t snssaiIdx=0; uint8_t idx = 0, extIeIdx = 0; uint8_t elementCnt = 0, drbCnt = 0; uint8_t BuildQOSInforet = 0,BuildSNSSAIret = 0; @@ -2720,7 +3002,7 @@ uint8_t BuildDRBSetup(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet choice_extension->value.choice.DRB_Information.dRB_QoS, ProtocolIE_ID_id_DRBs_ToBeSetup_Item, PDU_SESSION_ID_1, FALSE); else BuildQOSInforet = BuildQOSInfo(&ueCb->drbList[idx].qos, &drbSetItem->qoSInformation.choice.\ - choice_extension->value.choice.DRB_Information.dRB_QoS, ProtocolIE_ID_id_DRBs_ToBeSetup_Item, PDU_SESSION_ID_1, TRUE); + choice_extension->value.choice.DRB_Information.dRB_QoS, ProtocolIE_ID_id_DRBs_ToBeSetup_Item, PDU_SESSION_ID_1, ueCb->hoInfo.HOType); if(BuildQOSInforet != ROK) { DU_LOG("\nERROR --> F1AP : Failed to build QOS Info in BuildDRBSetup"); @@ -2728,12 +3010,13 @@ uint8_t BuildDRBSetup(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet } /*SNSSAI*/ + snssaiIdx = (idx% cuCb.numSnssaiSupported); if(ueCb->state != UE_HANDOVER_IN_PROGRESS) BuildSNSSAIret = BuildSNSSAI(&ueCb->drbList[ueCb->numDrb], &drbSetItem->qoSInformation.choice.\ - choice_extension->value.choice.DRB_Information.sNSSAI, cuCb.snssaiList[0], FALSE); + choice_extension->value.choice.DRB_Information.sNSSAI, cuCb.snssaiList[snssaiIdx], FALSE); else BuildSNSSAIret = BuildSNSSAI(&ueCb->drbList[idx], &drbSetItem->qoSInformation.choice.\ - choice_extension->value.choice.DRB_Information.sNSSAI, cuCb.snssaiList[0], TRUE); + choice_extension->value.choice.DRB_Information.sNSSAI, cuCb.snssaiList[snssaiIdx], ueCb->hoInfo.HOType); if(BuildSNSSAIret != ROK) { DU_LOG("\nERROR --> F1AP : Failed to build SNSSAI Info in BuildDRBSetup"); @@ -2746,7 +3029,7 @@ uint8_t BuildDRBSetup(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet value.choice.DRB_Information.flows_Mapped_To_DRB_List, ProtocolIE_ID_id_DRBs_ToBeSetup_Item, FALSE); else BuildFlowsMapret = BuildFlowsMap(&ueCb->drbList[idx], &drbSetItem->qoSInformation.choice.choice_extension->\ - value.choice.DRB_Information.flows_Mapped_To_DRB_List, ProtocolIE_ID_id_DRBs_ToBeSetup_Item, TRUE); + value.choice.DRB_Information.flows_Mapped_To_DRB_List, ProtocolIE_ID_id_DRBs_ToBeSetup_Item, ueCb->hoInfo.HOType); if(BuildFlowsMapret != ROK) { DU_LOG("\nERROR --> F1AP : Failed to build Flow Map Info in BuildDRBSetup"); @@ -2759,7 +3042,7 @@ uint8_t BuildDRBSetup(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet FALSE); else BuildULTnlInforet = BuildULTnlInfo(duId, &ueCb->drbList[idx].ulUpTnlInfo, &drbSetItem->uLUPTNLInformation_ToBeSetup_List,\ - TRUE); + ueCb->hoInfo.HOType); if(BuildULTnlInforet != ROK) { DU_LOG("\nERROR --> F1AP : Failed to build tunnel Info in BuildDRBSetup"); @@ -2767,7 +3050,7 @@ uint8_t BuildDRBSetup(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet } /*RLCMode*/ - if(ueCb->state != UE_HANDOVER_IN_PROGRESS) + if((ueCb->state != UE_HANDOVER_IN_PROGRESS) || (ueCb->hoInfo.HOType == Xn_Based_Inter_CU_HO)) { drbSetItem->rLCMode = RLCMode_rlc_um_bidirectional; ueCb->drbList[ueCb->numDrb].rlcMode = drbSetItem->rLCMode; @@ -5268,7 +5551,7 @@ uint8_t BuildSchedulingReqConfig(struct SchedulingRequestConfig *schedulingReque * ****************************************************************/ uint8_t BuildMacCellGrpCfg(MAC_CellGroupConfig_t *macCellGrpCfg) { - macCellGrpCfg->drx_Config = NULLP; + macCellGrpCfg->drx_ConfigRrc = NULLP; macCellGrpCfg->schedulingRequestConfig = NULLP; CU_ALLOC(macCellGrpCfg->schedulingRequestConfig, sizeof(struct SchedulingRequestConfig)); if(!macCellGrpCfg->schedulingRequestConfig) @@ -6491,7 +6774,7 @@ uint8_t fillCellGrpCfg(CuUeCb *ueCb, OCTET_STRING_t *cellGrp, bool updateAllRbCf xer_fprint(stdout, &asn_DEF_CellGroupConfigRrc, &cellGrpCfg); cmMemset((uint8_t *)encBuf, 0, ENC_BUF_MAX_LEN); encBufSize = 0; - encRetVal = aper_encode(&asn_DEF_CellGroupConfigRrc, 0, &cellGrpCfg, PrepFinalEncBuf, encBuf); + encRetVal = uper_encode(&asn_DEF_CellGroupConfigRrc, 0, &cellGrpCfg, PrepFinalEncBuf, encBuf); /* Encode results */ if(encRetVal.encoded == ENCODE_FAIL) { @@ -6879,7 +7162,7 @@ uint8_t fillUeCapRatCont(OCTET_STRING_t *ueCapRatContBuf) xer_fprint(stdout, &asn_DEF_UE_NR_Capability, &ueNrCap); cmMemset((uint8_t *)encBuf, 0, ENC_BUF_MAX_LEN); encBufSize = 0; - encRetVal = aper_encode(&asn_DEF_UE_NR_Capability, 0, &ueNrCap, PrepFinalEncBuf, encBuf); + encRetVal = uper_encode(&asn_DEF_UE_NR_Capability, 0, &ueNrCap, PrepFinalEncBuf, encBuf); /* Encode results */ if(encRetVal.encoded == ENCODE_FAIL) @@ -7007,7 +7290,7 @@ uint8_t fillUeCapRatContListBuf(UE_CapabilityRAT_ContainerList_t *ueCapablityLis xer_fprint(stdout, &asn_DEF_UE_CapabilityRAT_ContainerListRRC, &ueCapablityList); cmMemset((uint8_t *)encBuf, 0, ENC_BUF_MAX_LEN); encBufSize = 0; - encRetVal = aper_encode(&asn_DEF_UE_CapabilityRAT_ContainerListRRC, 0, \ + encRetVal = uper_encode(&asn_DEF_UE_CapabilityRAT_ContainerListRRC, 0, \ &ueCapablityList, PrepFinalEncBuf, encBuf); /* Encode results */ @@ -7205,7 +7488,7 @@ uint8_t fillMeasTimingConfigBuf(MeasConfig_t *measTimingConfigBuf) xer_fprint(stdout, &asn_DEF_MeasurementTimingConfigurationRrc, &measTimingConfig); cmMemset((uint8_t *)encBuf, 0, ENC_BUF_MAX_LEN); encBufSize = 0; - encRetVal = aper_encode(&asn_DEF_MeasurementTimingConfigurationRrc, 0, &measTimingConfig, PrepFinalEncBuf, encBuf); + encRetVal = uper_encode(&asn_DEF_MeasurementTimingConfigurationRrc, 0, &measTimingConfig, PrepFinalEncBuf, encBuf); /* Encode results */ if(encRetVal.encoded == ENCODE_FAIL) @@ -8018,7 +8301,7 @@ uint8_t fillMeasObjToAddModList(MeasObjectToAddModList_t *measObjList) /* RSRQ offset for SSB */ CU_ALLOC(measObject->offsetMO.rsrqOffsetSSB, sizeof(Q_OffsetRange_t)); - if(!measObject->offsetMO.rsrpOffsetSSB) + if(!measObject->offsetMO.rsrqOffsetSSB) { DU_LOG("\nERROR --> F1AP: Memory allocation failed for SSB RSRQ offset in fillMeasObjToAddModList"); return RFAILED; @@ -8573,7 +8856,7 @@ uint8_t fillRrcReconfigBuf(CuUeCb *ueCb, OCTET_STRING_t *rrcReconfigBuf, bool u xer_fprint(stdout, &asn_DEF_RRCReconfiguration, rrcReconfig); cmMemset((uint8_t *)encBuf, 0, ENC_BUF_MAX_LEN); encBufSize = 0; - encRetVal = aper_encode(&asn_DEF_RRCReconfiguration, 0, rrcReconfig, PrepFinalEncBuf, encBuf); + encRetVal = uper_encode(&asn_DEF_RRCReconfiguration, 0, rrcReconfig, PrepFinalEncBuf, encBuf); /* Encode results */ if(encRetVal.encoded == ENCODE_FAIL) @@ -8684,7 +8967,7 @@ uint8_t fillHOPreparationInfoBuf(CuUeCb *ueCb, HandoverPreparationInformation_t xer_fprint(stdout, &asn_DEF_HandoverPreparationInformationRrc, &hoPrepInfo); cmMemset((uint8_t *)encBuf, 0, ENC_BUF_MAX_LEN); encBufSize = 0; - encRetVal = aper_encode(&asn_DEF_HandoverPreparationInformationRrc, 0, \ + encRetVal = uper_encode(&asn_DEF_HandoverPreparationInformationRrc, 0, \ &hoPrepInfo, PrepFinalEncBuf, encBuf); /* Encode results */ @@ -8739,16 +9022,34 @@ uint8_t fillCuToDuContainer(CuUeCb *ueCb, CUtoDURRCInformation_t *rrcMsg) { uint8_t elementCnt = 0; uint8_t ret = ROK; - uint8_t idx, idx2, rrcBufLen; + uint8_t idx; - /* UE Capabulity RAT Container List */ - CU_ALLOC(rrcMsg->uE_CapabilityRAT_ContainerList, sizeof(UE_CapabilityRAT_ContainerList_t)); - if(!rrcMsg->uE_CapabilityRAT_ContainerList) + if((ueCb->state != UE_HANDOVER_IN_PROGRESS) || ((ueCb->state == UE_HANDOVER_IN_PROGRESS) && (ueCb->hoInfo.HOType == Inter_DU_HO))) { - DU_LOG("\nERROR --> F1AP : Memory allocation for UE capability RAT container list failed"); - return RFAILED; + /* UE Capabulity RAT Container List */ + CU_ALLOC(rrcMsg->uE_CapabilityRAT_ContainerList, sizeof(UE_CapabilityRAT_ContainerList_t)); + if(!rrcMsg->uE_CapabilityRAT_ContainerList) + { + DU_LOG("\nERROR --> F1AP : Memory allocation for UE capability RAT container list failed"); + return RFAILED; + } + ret = fillUeCapRatContListBuf(rrcMsg->uE_CapabilityRAT_ContainerList); } - ret = fillUeCapRatContListBuf(rrcMsg->uE_CapabilityRAT_ContainerList); + +#if 0 + + /* Commenting this because: + * CUToDURRCInformation->MeasConfig contains measurement gap configurations. + * Howeever measurement gap is not supported in our code. Measurement Gap will + * be required if we want to support inter-RAT handover or handover to + * neighbouring cells operating on a different frequency than serving cell. + * + * In case we plan to use this IE in future, following fixes are required: + * As of now, we are filling MeasurementTimingConfigurationRrc_t into rrcMsg->measConfig. + * This is incorrect. We must fill MeasConfigRrc_t in rrcMsg->measConfig. + * MeasurementTimingConfigurationRrc_t should be filled in + * rrcMsg->iE_Extensions->MeasurementTimingConfiguration, if required. + */ CU_ALLOC(rrcMsg->measConfig, sizeof(MeasConfig_t)); if(!rrcMsg->measConfig) @@ -8757,6 +9058,7 @@ uint8_t fillCuToDuContainer(CuUeCb *ueCb, CUtoDURRCInformation_t *rrcMsg) return RFAILED; } ret = fillMeasTimingConfigBuf(rrcMsg->measConfig); +#endif if(ueCb->state == UE_HANDOVER_IN_PROGRESS) { @@ -8807,7 +9109,42 @@ uint8_t fillCuToDuContainer(CuUeCb *ueCb, CUtoDURRCInformation_t *rrcMsg) } return ret; } - +/******************************************************************* + * + * @brief Build the drx cycle + * + * @details + * + * Function : BuildDrxCycle + * + * Functionality: Build drx cycle IE + * + * @params[in] pointer to DRXCycle_t + * + * @return ROK - success + * RFAILED - failure + * + ******************************************************************/ +uint8_t BuildDrxCycle(DRXCycle_t *drxCycle) +{ + drxCycle->longDRXCycleLength = LongDRXCycleLength_ms80; + CU_ALLOC(drxCycle->shortDRXCycleLength, sizeof(ShortDRXCycleLength_t)); + if(!drxCycle->shortDRXCycleLength) + { + DU_LOG("\nERROR --> F1AP : Memory allocation failed for shortDRXCycleLength"); + return RFAILED; + } + *(drxCycle->shortDRXCycleLength) = ShortDRXCycleLength_ms4; + + CU_ALLOC(drxCycle->shortDRXCycleTimer, sizeof(ShortDRXCycleTimer_t)); + if(!drxCycle->shortDRXCycleTimer) + { + DU_LOG("\nERROR --> F1AP : Memory allocation failed for shortDRXCycleTimer"); + return RFAILED; + } + *(drxCycle->shortDRXCycleTimer) = 4; + return ROK; +} /******************************************************************* * * @brief Free CuToDuContainer @@ -8896,6 +9233,7 @@ uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb) uint8_t elementCnt; uint8_t idx, idx1, bufLen, duIdx; uint32_t spCellId; + uint32_t targetDuId; DuDb *targetDuDb = NULLP; F1AP_PDU_t *f1apMsg = NULLP; UEContextSetupRequest_t *ueSetReq = NULLP; @@ -8930,7 +9268,13 @@ uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb) if(ueCb->state == UE_HANDOVER_IN_PROGRESS) elementCnt = 7; else + { +#ifdef NR_DRX + elementCnt = 12; +#else elementCnt = 11; +#endif + } ueSetReq->protocolIEs.list.count = elementCnt; ueSetReq->protocolIEs.list.size = elementCnt * sizeof(UEContextSetupRequestIEs_t *); @@ -8975,16 +9319,23 @@ uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb) ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_SpCell_ID; ueSetReq->protocolIEs.list.array[idx]->criticality = Criticality_reject; ueSetReq->protocolIEs.list.array[idx]->value.present = UEContextSetupRequestIEs__value_PR_NRCGI; + + /* Spec 38.473 Sec 9.2.2.1 : For handover case, this IE shall be considered as target cell. */ if(ueCb->state == UE_HANDOVER_IN_PROGRESS) { - /* Spec 38.473 Sec 9.2.2.1 : For handover case, this IE shall be considered as target cell. */ - SEARCH_DU_DB(duIdx, ueCb->hoInfo.targetDuId, targetDuDb); + if(ueCb->hoInfo.HOType == Inter_DU_HO) + targetDuId = ueCb->hoInfo.tgtNodeId; + else + targetDuId = duId; + + SEARCH_DU_DB(duIdx, targetDuId, targetDuDb); /* Since we are supporting only one cell per DU, accessing 0th index to * get target cell info */ spCellId = targetDuDb->cellCb[0].nrCellId; } else spCellId = ueCb->cellCb->nrCellId; + Nrcgiret = BuildNrcgi(&ueSetReq->protocolIEs.list.array[idx]->value.choice.NRCGI, spCellId); if(Nrcgiret != ROK) { @@ -9020,6 +9371,18 @@ uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb) if(ueCb->state != UE_HANDOVER_IN_PROGRESS) { + /*Drx cycle*/ +#ifdef NR_DRX + idx++; + ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_DRXCycle; + ueSetReq->protocolIEs.list.array[idx]->criticality = Criticality_ignore; + ueSetReq->protocolIEs.list.array[idx]->value.present = UEContextSetupRequestIEs__value_PR_DRXCycle; + if(BuildDrxCycle(&ueSetReq->protocolIEs.list.array[idx]->value.choice.DRXCycle) != ROK) + { + DU_LOG("\nERROR --> F1AP : Failed to build drx cycle"); + break; + } +#endif /*Special Cells to be SetupList*/ idx++; ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_SCell_ToBeSetup_List; @@ -9212,9 +9575,9 @@ uint8_t addDrbTunnels(uint32_t duId, uint8_t teId) * RFAILED - failure * * ****************************************************************/ -uint8_t procDrbSetupList(uint32_t duId, DRBs_Setup_List_t *drbSetupList) +uint8_t procDrbSetupList(uint32_t duId, CuUeCb *ueCb, DRBs_Setup_List_t *drbSetupList) { - uint8_t arrIdx = 0; + uint8_t arrIdx = 0, drbIdx = 0; uint32_t teId = 0; DRBs_Setup_ItemIEs_t *drbItemIe = NULLP; @@ -9229,10 +9592,21 @@ uint8_t procDrbSetupList(uint32_t duId, DRBs_Setup_List_t *drbSetupList) teId = extractTeId(&drbItemIe->value.choice.DRBs_Setup_Item.dLUPTNLInformation_ToBeSetup_List); if(teId > 0) { - if(addDrbTunnels(duId, teId)== ROK) - { - DU_LOG("\nDEBUG --> EGTP: Tunnel Added for TeId %d", teId); - } + if(addDrbTunnels(duId, teId)== ROK) + { + DU_LOG("\nDEBUG --> EGTP: Tunnel Added for TeId %d", teId); + } + /* As per Spec 38.473, in UE COntext Response, Tunnel information + * are sent to CU for setting up of Tunnels in DL direction. + * Search for DRB ID in CU databse */ + for(drbIdx = 0; drbIdx < ueCb->numDrb; drbIdx++) + { + if(ueCb->drbList[drbIdx].drbId == drbItemIe->value.choice.DRBs_Setup_Item.dRBID) + { + fillTeIdString(3, teId, ueCb->drbList[drbIdx].dlUpTnlInfo.teId); + break; + } + } } else return RFAILED; @@ -9257,7 +9631,7 @@ uint8_t procDrbSetupList(uint32_t duId, DRBs_Setup_List_t *drbSetupList) * RFAILED - failure * * ****************************************************************/ -uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) +uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg, char *recvBuf, MsgLen recvBufLen) { uint8_t duIdx = 0, idx = 0, ueIdx = 0, rrcMsgType=0; uint8_t duUeF1apId = 0, cuUeF1apId = 0; @@ -9289,14 +9663,27 @@ uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) { /* Creating UE context in target DU */ memset(ueCb, 0, sizeof(CuUeCb)); - ueCb->cellCb = &duDb->cellCb[0]; - ueCb->gnbDuUeF1apId = duUeF1apId; - ueCb->gnbCuUeF1apId = cuUeF1apId; - ueCb->state = UE_HANDOVER_IN_PROGRESS; - ueCb->hoInfo.targetDuId = duId; - (duDb->numUe)++; - ueCb->cellCb->ueCb[ueCb->cellCb->numUe] = ueCb; + /* Check if UE is under Inter-CU handover */ + if(duDb->tempUeCtxtInHo && (duDb->tempUeCtxtInHo->gnbCuUeF1apId == cuUeF1apId)) + { + memcpy(ueCb, duDb->tempUeCtxtInHo, sizeof(CuUeCb)); + ueCb->gnbDuUeF1apId = duUeF1apId; + CU_FREE(duDb->tempUeCtxtInHo, sizeof(CuUeCb)); + } + else + { + /* In case of Inter DU Handover */ + ueCb->cellCb = &duDb->cellCb[0]; + ueCb->gnbDuUeF1apId = duUeF1apId; + ueCb->gnbCuUeF1apId = cuUeF1apId; + ueCb->state = UE_HANDOVER_IN_PROGRESS; + ueCb->hoInfo.HOType = Inter_DU_HO; + ueCb->hoInfo.tgtNodeId = duId; + } + (duDb->numUe)++; + + ueCb->cellCb->ueCb[ueCb->cellCb->numUe] = ueCb; ueCb->cellCb->numUe++; } break; @@ -9309,7 +9696,7 @@ uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) case ProtocolIE_ID_id_DRBs_Setup_List: { /* Adding Tunnels for successful DRB */ - procDrbSetupList(duId, &ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.DRBs_Setup_List); + procDrbSetupList(duId, ueCb, &ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.DRBs_Setup_List); break; } case ProtocolIE_ID_id_DUtoCURRCInformation: @@ -9328,65 +9715,73 @@ uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) } } - /* If the UE is in handover, UE context modification request is to be sent to - * source DU once UE context setup response is received from target DU */ - if(ueCb->state == UE_HANDOVER_IN_PROGRESS) + if(ueCb->state != UE_HANDOVER_IN_PROGRESS) { - DuDb *srcDuDb = NULLP; - CuUeCb *ueCbInSrcDu = NULLP; + ueCb->f1apMsgDb.dlRrcMsgCount++; + rrcMsgType = setDlRRCMsgType(ueCb); - /* Since Source DU Id and DU UE F1AP ID assigned to UE by source DU is not known here, we - * need to find Source DU and UE CB in source DU using CU UE F1AP ID */ - for(duIdx=0; duIdx < cuCb.numDu; duIdx++) + DU_LOG("\nINFO --> F1AP: Sending DL RRC MSG for RRC reconfiguration"); + if(BuildAndSendDLRRCMessageTransfer(duId, ueCb, SRB1, rrcMsgType) != ROK) + { + DU_LOG("\nINFO --> F1AP: Failed to build and send DL RRC MSG for RRC reconfiguration"); + return RFAILED; + } + } + else + { + if(ueCb->hoInfo.HOType == Inter_DU_HO) { - /* UE context setup response is received from target DU. Search all - * DUs to find source DU except this target DU Id.*/ - if(cuCb.duInfo[duIdx].duId != duId) + /* If the UE is in Inter-DU handover, UE context modification request is to be sent to + * source DU once UE context setup response is received from target DU */ + + DuDb *srcDuDb = NULLP; + CuUeCb *ueCbInSrcDu = NULLP; + + /* Since Source DU Id and DU UE F1AP ID assigned to UE by source DU is not known here, we + * need to find Source DU and UE CB in source DU using CU UE F1AP ID */ + for(duIdx=0; duIdx < cuCb.numDu; duIdx++) { - for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++) + /* UE context setup response is received from target DU. Search all + * DUs to find source DU except this target DU Id.*/ + if(cuCb.duInfo[duIdx].duId != duId) { - /* Check following: - * 1. CU UE F1AP ID in srcDU->ueCb should be same as cuUeF1apId - * received in UE context setup response since CU UE F1AP ID does not - * change for UE in handover. - * 2. srcDU->UeCb->uestate should be UE_HANDOVER_IN_PROGRESS - */ - if((cuCb.duInfo[duIdx].ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId) && - (cuCb.duInfo[duIdx].ueCb[ueIdx].state == UE_HANDOVER_IN_PROGRESS)) + for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++) { - srcDuDb = &cuCb.duInfo[duIdx]; - ueCbInSrcDu = &cuCb.duInfo[duIdx].ueCb[ueIdx]; + /* Check following: + * 1. CU UE F1AP ID in srcDU->ueCb should be same as cuUeF1apId + * received in UE context setup response since CU UE F1AP ID does not + * change for UE in handover. + * 2. srcDU->UeCb->uestate should be UE_HANDOVER_IN_PROGRESS + */ + if((cuCb.duInfo[duIdx].ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId) && + (cuCb.duInfo[duIdx].ueCb[ueIdx].state == UE_HANDOVER_IN_PROGRESS)) + { + srcDuDb = &cuCb.duInfo[duIdx]; + ueCbInSrcDu = &cuCb.duInfo[duIdx].ueCb[ueIdx]; - /* Store source DU info in the new UE context created in - * tareget DU */ - ueCb->hoInfo.sourceDuId = srcDuDb->duId; + /* Store source DU info in the new UE context created in + * tareget DU */ + ueCb->hoInfo.srcNodeId = srcDuDb->duId; - /* Copy the received container to UeCb */ - memcpy(&ueCbInSrcDu->f1apMsgDb.duToCuContainer, duToCuRrcContainer, sizeof(OCTET_STRING_t)); + /* Copy the received container to UeCb */ + memcpy(&ueCbInSrcDu->f1apMsgDb.duToCuContainer, duToCuRrcContainer, sizeof(OCTET_STRING_t)); - if(BuildAndSendUeContextModificationReq(srcDuDb->duId, ueCbInSrcDu, STOP_DATA_TX) != ROK) - { - DU_LOG("\nERROR -> F1AP : Failed at BuildAndSendUeContextModificationReq()"); - return RFAILED; + if(BuildAndSendUeContextModificationReq(srcDuDb->duId, ueCbInSrcDu, STOP_DATA_TX) != ROK) + { + DU_LOG("\nERROR -> F1AP : Failed at BuildAndSendUeContextModificationReq()"); + return RFAILED; + } + break; } - break; } } + if(srcDuDb && ueCbInSrcDu) + break; } - if(srcDuDb && ueCbInSrcDu) - break; } - } - else - { - ueCb->f1apMsgDb.dlRrcMsgCount++; - rrcMsgType = setDlRRCMsgType(ueCb); - - DU_LOG("\nINFO --> F1AP: Sending DL RRC MSG for RRC reconfiguration"); - if(BuildAndSendDLRRCMessageTransfer(duId, ueCb, SRB1, rrcMsgType) != ROK) + else if(ueCb->hoInfo.HOType == Xn_Based_Inter_CU_HO) { - DU_LOG("\nINFO --> F1AP: Failed to build and send DL RRC MSG for RRC reconfiguration"); - return RFAILED; + BuildAndSendHOReqAck(ueCb, duToCuRrcContainer->buf, duToCuRrcContainer->size); } } @@ -9454,29 +9849,36 @@ uint8_t procUlRrcMsg(uint32_t duId, F1AP_PDU_t *f1apMsg) if(duDb->ueCb[duUeF1apId-1].state == UE_HANDOVER_IN_PROGRESS) { - uint8_t ueIdx = 0; - uint8_t srcDuId = duDb->ueCb[duUeF1apId-1].hoInfo.sourceDuId; - DuDb *srcDuDb = NULLP; - - /* In target DU DB, mark UE as active and delete HO info */ - duDb->ueCb[duUeF1apId-1].state = UE_ACTIVE; - memset(&duDb->ueCb[duUeF1apId-1].hoInfo, 0, sizeof(HandoverInfo)); - - /* Release UE context in source DU because the UE is now - * attached to target DU */ - SEARCH_DU_DB(duIdx, srcDuId, srcDuDb); - for(ueIdx = 0; ueIdx < srcDuDb->numUe; ueIdx++) + if(duDb->ueCb[duUeF1apId-1].hoInfo.HOType == Inter_DU_HO) { - if(srcDuDb->ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId) + uint8_t ueIdx = 0; + uint8_t srcDuId = duDb->ueCb[duUeF1apId-1].hoInfo.srcNodeId; + DuDb *srcDuDb = NULLP; + + /* Release UE context in source DU because the UE is now + * attached to target DU */ + SEARCH_DU_DB(duIdx, srcDuId, srcDuDb); + for(ueIdx = 0; ueIdx < srcDuDb->numUe; ueIdx++) { - ret = BuildAndSendUeContextReleaseCommand(srcDuId, srcDuDb->ueCb[ueIdx].gnbCuUeF1apId, srcDuDb->ueCb[ueIdx].gnbDuUeF1apId); - if(ret != ROK) + if(srcDuDb->ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId) { - DU_LOG("\nINFO --> F1AP: Failed to build and send UE context release command to source DU Id [%d]", srcDuId); + ret = BuildAndSendUeContextReleaseCommand(srcDuId, srcDuDb->ueCb[ueIdx].gnbCuUeF1apId, srcDuDb->ueCb[ueIdx].gnbDuUeF1apId); + if(ret != ROK) + { + DU_LOG("\nINFO --> F1AP: Failed to build and send UE context release command to source DU Id [%d]", srcDuId); + } + break; } - break; } } + else + { + BuildAndSendUeContextRelease(&duDb->ueCb[duUeF1apId-1]); + } + + /* In target DU DB, mark UE as active and delete HO info */ + duDb->ueCb[duUeF1apId-1].state = UE_ACTIVE; + memset(&duDb->ueCb[duUeF1apId-1].hoInfo, 0, sizeof(HandoverInfo)); return ret; } break; @@ -9493,17 +9895,7 @@ uint8_t procUlRrcMsg(uint32_t duId, F1AP_PDU_t *f1apMsg) ueCb = &duDb->ueCb[duUeF1apId-1]; ueCb->f1apMsgDb.dlRrcMsgCount++; rrcMsgType = setDlRRCMsgType(ueCb); - if(rrcMsgType == RRC_SETUP_COMPLETE) - { - DU_LOG("\nINFO --> F1AP: Sending DL RRC MSG for Security Mode Command"); - ret = BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType); - } - else if(rrcMsgType == SECURITY_MODE_COMPLETE) - { - DU_LOG("\nINFO --> F1AP: Sending DL RRC MSG for RRC Registration Accept"); - BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType); - } - else if(rrcMsgType == REGISTRATION_COMPLETE) + if(rrcMsgType == REGISTRATION_COMPLETE) { DU_LOG("\nINFO --> F1AP: Sending Ue Context Setup Request"); ret = BuildAndSendUeContextSetupReq(duId, ueCb); @@ -9513,6 +9905,11 @@ uint8_t procUlRrcMsg(uint32_t duId, F1AP_PDU_t *f1apMsg) DU_LOG("\nINFO --> F1AP: Sending UE Context Modification Request"); BuildAndSendUeContextModificationReq(duId, ueCb, RRC_RECONFIG_COMPLETE_IND); } + else + { + /* In case rrcMsgType is RRC_SETUP_COMPLETE / NAS_AUTHENTICATION_RSP / NAS_SECURITY_MODE_COMPLETE / RRC_SECURITY_MODE_COMPLETE */ + BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType); + } } return ret; } @@ -10391,6 +10788,95 @@ uint8_t BuildDrbToBeModifiedList(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeModified_ return ret; } +/******************************************************************* +* +* @brief Builds the DRB to be released Item IE +* +* @details +* +* Function : FillDrbToBeRelItemList +* +* Functionality: Constructs the DRB to be modified Mod Item Ies +* +* @params[in] struct DRBs_ToBeReleased_ItemIEs *drbItemIe +* +* @return ROK - success +* RFAILED - failure +* +* ****************************************************************/ + +uint8_t FillDrbToBeRelItemList(uint32_t duId, CuUeCb *ueCb, uint8_t arrIdx, struct DRBs_ToBeReleased_ItemIEs *drbItemIe) +{ + uint8_t drbIdx; + + drbItemIe->id = ProtocolIE_ID_id_DRBs_ToBeReleased_Item; + drbItemIe->criticality = Criticality_reject; + drbItemIe->value.present = DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item; + drbItemIe->value.choice.DRBs_ToBeReleased_Item.dRBID = DRB1 + arrIdx; + + for(drbIdx = 0; drbIdx < ueCb->numDrb; drbIdx++) + { + if(ueCb->drbList[drbIdx].drbId == drbItemIe->value.choice.DRBs_ToBeReleased_Item.dRBID) + { + deleteEgtpTunnel(duId, ueCb->drbList[drbIdx].dlUpTnlInfo.teId); + CU_FREE(ueCb->drbList[drbIdx].snssai, sizeof(Snssai)); + break; + } + } + return ROK; +} + +/******************************************************************* +* +* @brief Builds the DRB to be released list +* +* @details +* +* Function : BuildDrbToBeReleasedList +* +* Functionality: Constructs the DRB to be released list +* +* @params[in] DRBs_ToBeReleased_List_t *drbSet +* +* @return ROK - success +* RFAILED - failure +* +* ****************************************************************/ + +uint8_t BuildDrbToBeReleasedList(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeReleased_List_t *drbSet) +{ + uint8_t ret = ROK; + uint8_t arrIdx =0; + uint8_t drbCnt =0; + + drbCnt = MAX_DRB_MODIFIED_UE_MOD_REQ; + drbSet->list.count = drbCnt; + drbSet->list.size = drbCnt * sizeof(DRBs_ToBeReleased_ItemIEs_t *); + CU_ALLOC(drbSet->list.array, drbSet->list.size); + if(drbSet->list.array == NULLP) + { + DU_LOG("\nERROR --> F1AP : Memory allocation failed in BuildDrbToBeReleasedList"); + return RFAILED; + } + for(arrIdx=0; arrIdxlist.array[arrIdx], sizeof(DRBs_ToBeReleased_ItemIEs_t)); + if(drbSet->list.array[arrIdx] == NULLP) + { + DU_LOG("\nERROR --> F1AP : Memory allocation failed in BuildDrbToBeReleasedList"); + return RFAILED; + } + + ret = FillDrbToBeRelItemList(duId, ueCb, arrIdx, (DRBs_ToBeReleased_ItemIEs_t *)drbSet->list.array[arrIdx]); + if(ret != ROK) + { + DU_LOG("\nERROR --> F1AP : FillDrbToBeRelItemList failed"); + } + } + + return ret; +} + /******************************************************************* * * @brief freeing the DRB item @@ -10512,6 +10998,40 @@ void FreeDrbToBeModifiedList(DRBs_ToBeModified_List_t *drbSet) } +/******************************************************************* +* +* @brief free the DRB to be modfified list +* +* @details +* +* Function : FreeDrbToBeReleasedList +* +* Functionality: free the DRB to be Release list +* +* @params[in] FreeDrbToBeReleasedList_t *drbSet +* +* @return ROK - success +* RFAILED - failure +* +* ****************************************************************/ +void FreeDrbToBeReleasedList(DRBs_ToBeReleased_List_t *drbSet) +{ + uint8_t arrIdx =0; + struct DRBs_ToBeReleased_ItemIEs *drbItemIe; + + if(drbSet->list.array) + { + for(arrIdx=0; arrIdxlist.count ; arrIdx++) + { + if(drbSet->list.array[arrIdx] != NULLP) + { + CU_FREE(drbSet->list.array[arrIdx], sizeof(DRBs_ToBeReleased_ItemIEs_t)); + } + } + CU_FREE(drbSet->list.array, drbSet->list.size); + } +} + /******************************************************************* * * @brief free the UeContextModification Request @@ -10563,6 +11083,12 @@ void FreeUeContextModicationRequest(F1AP_PDU_t *f1apMsg) choice.DRBs_ToBeModified_List); break; } + case ProtocolIE_ID_id_DRBs_ToBeReleased_List: + { + FreeDrbToBeReleasedList(&ueContextModifyReq->protocolIEs.list.array[arrIdx]->value.\ + choice.DRBs_ToBeReleased_List); + break; + } case ProtocolIE_ID_id_TransmissionActionIndicator: break; case ProtocolIE_ID_id_RRCContainer: @@ -10604,9 +11130,11 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt uint8_t ieIdx = 0; uint8_t elementCnt = 0; uint8_t ret = RFAILED; + uint16_t tmpBufIdx = 0, bufIdx = 0; CuUeCb *ueCb = (CuUeCb *)cuUeCb; F1AP_PDU_t *f1apMsg = NULLP; UEContextModificationRequest_t *ueContextModifyReq = NULLP; + RRCContainer_t rrcContainerTmp, *rrcContainer = NULLP; asn_enc_rval_t encRetVal; DU_LOG("\nINFO --> F1AP : Building Ue context modification request\n"); while(1) @@ -10633,14 +11161,23 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt ueContextModifyReq =&f1apMsg->choice.initiatingMessage->value.choice.UEContextModificationRequest; if(action == MODIFY_UE) - elementCnt = 4; + elementCnt = 5; else if(action == QUERY_CONFIG) elementCnt = 3; else if(action == RRC_RECONFIG_COMPLETE_IND) elementCnt = 3; else if((action == STOP_DATA_TX) || (action == RESTART_DATA_TX)) - elementCnt = 5; - + { + if(ueCb->state != UE_HANDOVER_IN_PROGRESS) + elementCnt = 5; + else + elementCnt = 4; + } + +#ifdef NR_DRX + if(DRX_TO_BE_RELEASE && ueCb->drxCfgPresent) + elementCnt++; +#endif ueContextModifyReq->protocolIEs.list.count = elementCnt; ueContextModifyReq->protocolIEs.list.size = elementCnt*sizeof(UEContextModificationRequest_t *); @@ -10696,15 +11233,26 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt ret = BuildDrbToBeModifiedList(duId, ueCb, &(ueContextModifyReq->protocolIEs.list.array[ieIdx]->\ value.choice.DRBs_ToBeModified_List)); - /* TODO: DRB to be release list */ - if(ret != ROK) { DU_LOG("\nERROR --> F1AP : BuildAndSendUeContextModificationReq(): Failed to build drb to be modified list"); break; } - /* TODO: fill the RRC reconfiguration information in RRC Contaiiner ie in case of MODIFY_UE */ + /* DRB to be released list */ + ieIdx++; + ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_DRBs_ToBeReleased_List; + ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject; + ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present =\ + UEContextModificationRequestIEs__value_PR_DRBs_ToBeReleased_List; + ret = BuildDrbToBeReleasedList(duId, ueCb, &(ueContextModifyReq->protocolIEs.list.array[ieIdx]->\ + value.choice.DRBs_ToBeReleased_List)); + + if(ret != ROK) + { + DU_LOG("\nERROR --> F1AP : BuildAndSendUeContextModificationReq(): Failed to build drb to be deleted list"); + break; + } } else if(action == QUERY_CONFIG) { @@ -10750,21 +11298,48 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt ieIdx++; ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_RRCContainer; ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject; - ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = \ - UEContextModificationRequestIEs__value_PR_RRCContainer; - if(fillRrcReconfigBuf(ueCb, &ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.RRCContainer, true) != ROK) + ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = UEContextModificationRequestIEs__value_PR_RRCContainer; + if(fillDlDcchRrcMsg(ueCb, &rrcContainerTmp, true) != ROK) { DU_LOG( "\nERROR --> F1AP : Failed to fill Rrc reconfiguration buffer"); return RFAILED; } + rrcContainer = &ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.RRCContainer; + rrcContainer->size = rrcContainerTmp.size + 2; /* 2 bytes of PDCP SN */ + CU_ALLOC(rrcContainer->buf, rrcContainer->size); + memset(rrcContainer->buf, 0, rrcContainer->size); + rrcContainer->buf[0] = 0x00; + rrcContainer->buf[1] = ueCb->pdcpSn; //PDCP SN + for(bufIdx = 2, tmpBufIdx = 0; bufIdx < rrcContainer->size; bufIdx++, tmpBufIdx++) + { + rrcContainer->buf[bufIdx] = rrcContainerTmp.buf[tmpBufIdx]; + } + /* RRC delivery status request */ + if(ueCb->state != UE_HANDOVER_IN_PROGRESS) + { + ieIdx++; + ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_RRCDeliveryStatusRequest; + ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_ignore; + ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = UEContextModificationRequestIEs__value_PR_RRCDeliveryStatusRequest; + ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.RRCDeliveryStatusRequest = RRCDeliveryStatusRequest_true; + } + } + +#ifdef NR_DRX + if(DRX_TO_BE_RELEASE && ueCb->drxCfgPresent) + { + /* DRX Configuration Indicator */ ieIdx++; - ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_RRCDeliveryStatusRequest; + ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_DRXConfigurationIndicator; ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_ignore; - ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = UEContextModificationRequestIEs__value_PR_RRCDeliveryStatusRequest; - ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.RRCDeliveryStatusRequest = RRCDeliveryStatusRequest_true; + ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = UEContextModificationRequestIEs__value_PR_DRXConfigurationIndicator; + ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.DRXConfigurationIndicator = DRXConfigurationIndicator_release; + ueCb->drxCfgPresent = false; + memset(&ueCb->drxCfg, 0, sizeof(DrxCfg)); } +#endif xer_fprint(stdout, &asn_DEF_F1AP_PDU, f1apMsg); @@ -11280,17 +11855,17 @@ uint8_t procDrbSetupModList(uint32_t duId, CuUeCb *ueCb, DRBs_SetupMod_List_t *d if(ueCb->state != UE_HANDOVER_IN_PROGRESS) { - /* extracting teId */ - teId = extractTeId(&drbItemIe->value.choice.DRBs_SetupMod_Item.dLUPTNLInformation_ToBeSetup_List); - if(teId > 0) - { - if(addDrbTunnels(duId, teId)== ROK) - { - DU_LOG("\nDEBUG --> EGTP: Tunnel Added for TeId %d", teId); - } - } - else - return RFAILED; + /* extracting teId */ + teId = extractTeId(&drbItemIe->value.choice.DRBs_SetupMod_Item.dLUPTNLInformation_ToBeSetup_List); + if(teId > 0) + { + if(addDrbTunnels(duId, teId)== ROK) + { + DU_LOG("\nDEBUG --> EGTP: Tunnel Added for TeId %d", teId); + } + } + else + return RFAILED; } } } @@ -11372,7 +11947,7 @@ uint8_t procServedCellPlmnList(ServedPLMNs_List_t *srvPlmn) * RFAILED - failure * * ****************************************************************/ -uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) +uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg, char *recvBuf, MsgLen recvBufLen) { uint8_t idx=0, duIdx=0; uint8_t duUeF1apId = 0, cuUeF1apId = 0; @@ -11382,6 +11957,10 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) SEARCH_DU_DB(duIdx, duId, duDb); ueCtxtModRsp = &f1apMsg->choice.successfulOutcome->value.choice.UEContextModificationResponse; + + /* In case of Inter-CU Handover request received from peer CU */ + if(duDb->tempUeCtxtInHo) + ueCb = duDb->tempUeCtxtInHo; for(idx=0; idx < ueCtxtModRsp->protocolIEs.list.count; idx++) { @@ -11389,13 +11968,35 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) { case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: { - cuUeF1apId = ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.GNB_CU_UE_F1AP_ID; + if(ueCb == NULLP) + { + cuUeF1apId = ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.GNB_CU_UE_F1AP_ID; + } + else + { + /* In case of Inter-CU Handover request received from peer CU */ + cuUeF1apId = ueCb->gnbCuUeF1apId; + } break; } case ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: { - duUeF1apId = ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.GNB_DU_UE_F1AP_ID; - ueCb = &duDb->ueCb[duUeF1apId-1]; + if(!ueCb) + { + duUeF1apId = ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.GNB_DU_UE_F1AP_ID; + ueCb = &duDb->ueCb[duUeF1apId-1]; + + /* In case UE context modification response is received at source GNB CU from source GNB DU + * for a UE in handover, send HO request to target GNB only if not sent already. + * If HO Req is already sent to target GNB, and an HO Req Ack is received, then + * ueCb->hoInfo.cuUeF1apIdTgt will be non-zero + */ + if((ueCb->state == UE_HANDOVER_IN_PROGRESS) && (ueCb->hoInfo.HOType == Xn_Based_Inter_CU_HO) && \ + (ueCb->hoInfo.cuUeF1apIdTgt == 0)) + { + BuildAndSendHOReq(ueCb, recvBuf, recvBufLen); + } + } break; } case ProtocolIE_ID_id_DRBs_SetupMod_List: @@ -11405,6 +12006,11 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) break; } + case ProtocolIE_ID_id_DRBs_Modified_List: + { + DU_LOG("\nINFO --> Received DRBs Modified List"); + break; + } case ProtocolIE_ID_id_SRBs_SetupMod_List: { procSrbSetupModList(ueCb, &ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.SRBs_SetupMod_List); @@ -11430,10 +12036,20 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) if(ueCb->state == UE_HANDOVER_IN_PROGRESS) { uint8_t ueIdx = 0; + uint8_t tgtDuId = 0; DuDb *tgtDuDb = NULLP; CuUeCb *ueCbInTgtDu = NULLP; - SEARCH_DU_DB(duIdx, ueCb->hoInfo.targetDuId, tgtDuDb); + if(ueCb->hoInfo.HOType == Inter_DU_HO) + { + tgtDuId = ueCb->hoInfo.tgtNodeId; + } + else if (ueCb->hoInfo.HOType == Xn_Based_Inter_CU_HO) + { + tgtDuId = duId; + } + + SEARCH_DU_DB(duIdx, tgtDuId, tgtDuDb); if(tgtDuDb) { /* Since DU UE F1AP ID assigned by target DU to this UE in handover is @@ -11448,11 +12064,11 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) } } - /* If UE context is not found in Target DU DU, send UE context setup + /* If UE context is not found in Target DU, send UE context setup * request */ if(ueCbInTgtDu == NULLP) { - if((BuildAndSendUeContextSetupReq(ueCb->hoInfo.targetDuId, ueCb)) != ROK) + if((BuildAndSendUeContextSetupReq(tgtDuId, ueCb)) != ROK) { DU_LOG("\nERROR -> F1AP : Failed at BuildAndSendUeContextSetupReq"); return RFAILED; @@ -11460,7 +12076,11 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) } } } - + +#ifdef START_DL_UL_DATA + startDlData(); +#endif + return ROK; } @@ -11492,6 +12112,10 @@ void procF1SetupReq(uint32_t *destDuId, F1AP_PDU_t *f1apMsg) GNB_DU_Served_Cells_Item_t *srvCellItem = NULLP; GNB_DU_Served_Cells_List_t *duServedCell = NULLP; + /* Triggering XN setup request before F1 setup establishment */ + if(LOCAL_NODE_TYPE == CLIENT) + BuildAndSendXnSetupReq(); + f1SetupReq = &f1apMsg->choice.initiatingMessage->value.choice.F1SetupRequest; for(ieIdx=0; ieIdx < f1SetupReq->protocolIEs.list.count; ieIdx++) { @@ -11504,13 +12128,11 @@ void procF1SetupReq(uint32_t *destDuId, F1AP_PDU_t *f1apMsg) if(duDb == NULLP) { duDb = &cuCb.duInfo[cuCb.numDu]; - memset(duDb, 0, sizeof(DuDb)); - duDb->duId = duId; cuCb.numDu++; - *destDuId = duId; } - else - return; + memset(duDb, 0, sizeof(DuDb)); + duDb->duId = duId; + *destDuId = duId; break; } case ProtocolIE_ID_id_gNB_DU_Name: @@ -11581,7 +12203,7 @@ void procF1SetupReq(uint32_t *destDuId, F1AP_PDU_t *f1apMsg) * ****************************************************************/ void procUeContextReleaseComplete(uint32_t duId, F1AP_PDU_t *f1apMsg) { - uint8_t duIdx = 0, ieIdx = 0, ueIdx = 0; + uint8_t duIdx = 0, ieIdx = 0, ueIdx = 0, drbIdx = 0; uint8_t gnbDuUeF1apId = 0, gnbCuUeF1apId = 0; DuDb *duDb = NULLP; CuUeCb *ueCb = NULLP; @@ -11615,6 +12237,10 @@ void procUeContextReleaseComplete(uint32_t duId, F1AP_PDU_t *f1apMsg) if((ueCb->cellCb->ueCb[ueIdx]->gnbCuUeF1apId == gnbCuUeF1apId) && (ueCb->cellCb->ueCb[ueIdx]->gnbDuUeF1apId == gnbDuUeF1apId)) { + for(drbIdx = 0; drbIdx < ueCb->numDrb; drbIdx++) + { + deleteEgtpTunnel(duId, ueCb->drbList[drbIdx].dlUpTnlInfo.teId); + } ueCb->cellCb->ueCb[ueIdx] = NULLP; ueCb->cellCb->numUe--; if((ueCb->cellCb->numUe == 0) && (ueCb->cellCb->cellStatus == CELL_DELETION_IN_PROGRESS)) @@ -11825,6 +12451,11 @@ uint8_t BuildAndSendPagingMsg(uint64_t gsTmsi, uint8_t duId) DU_LOG("\nERROR --> F1AP : BuildAndSendPagingMsg(): DuDb is empty"); return ret; } + if(duDb->numCells == 0) + { + DU_LOG("\nERROR --> F1AP : BuildAndSendPagingMsg(): No CELL is UP!"); + return ret; + } while(true) { @@ -11992,7 +12623,7 @@ uint8_t BuildAndSendPagingMsg(uint64_t gsTmsi, uint8_t duId) /******************************************************************* * - * @brief Handles received F1AP message and sends back response + * @brief Decode received character string into F1AP message * * @details * @@ -12000,61 +12631,86 @@ uint8_t BuildAndSendPagingMsg(uint64_t gsTmsi, uint8_t duId) * * Functionality: * - Decodes received F1AP control message - * - Prepares response message, encodes and sends to SCTP * * @params[in] * @return ROK - success * RFAILED - failure * * ****************************************************************/ -void F1APMsgHdlr(uint32_t *duId, Buffer *mBuf) +uint8_t F1APDecodeMsg(F1AP_PDU_t *f1apMsg, Buffer *mBuf, char **recvBuf, MsgLen *recvBufLen) { int i; - char *recvBuf; MsgLen copyCnt; - MsgLen recvBufLen; - F1AP_PDU_t *f1apMsg = NULLP; asn_dec_rval_t rval; /* Decoder return value */ - F1AP_PDU_t f1apasnmsg ; - - DU_LOG("\nINFO --> F1AP : Received F1AP message buffer"); - ODU_PRINT_MSG(mBuf, 0,0); /* Copy mBuf into char array to decode it */ - ODU_GET_MSG_LEN(mBuf, &recvBufLen); - CU_ALLOC(recvBuf, (Size)recvBufLen); - - if(recvBuf == NULLP) + ODU_GET_MSG_LEN(mBuf, recvBufLen); + CU_ALLOC(*recvBuf, (Size)(*recvBufLen)); + if(*recvBuf == NULLP) { DU_LOG("\nERROR --> F1AP : Memory allocation failed"); - return; + return RFAILED; } - if(ODU_COPY_MSG_TO_FIX_BUF(mBuf, 0, recvBufLen, (Data *)recvBuf, ©Cnt) != ROK) + if(ODU_COPY_MSG_TO_FIX_BUF(mBuf, 0, *recvBufLen, (Data *)*recvBuf, ©Cnt) != ROK) { DU_LOG("\nERROR --> F1AP : Failed while copying %d", copyCnt); - return; + return RFAILED; } - DU_LOG("\nDEBUG --> F1AP : Received flat buffer to be decoded : "); - for(i=0; i< recvBufLen; i++) + DU_LOG("\nDEBUG --> F1AP : Received flat buffer to be decoded : \n"); + for(i=0; i< *recvBufLen; i++) { - DU_LOG("%x",recvBuf[i]); + DU_LOG("%x ",(*recvBuf)[i]); } /* Decoding flat buffer into F1AP messsage */ - f1apMsg = &f1apasnmsg; - memset(f1apMsg, 0, sizeof(F1AP_PDU_t)); - - rval = aper_decode(0, &asn_DEF_F1AP_PDU, (void **)&f1apMsg, recvBuf, recvBufLen, 0, 0); - CU_FREE(recvBuf, (Size)recvBufLen); - + rval = aper_decode(0, &asn_DEF_F1AP_PDU, (void **)&f1apMsg, *recvBuf, *recvBufLen, 0, 0); if(rval.code == RC_FAIL || rval.code == RC_WMORE) { DU_LOG("\nERROR --> F1AP : ASN decode failed"); - return; + return RFAILED; } + + /* Printing the decoded F1AP PDU */ DU_LOG("\n"); xer_fprint(stdout, &asn_DEF_F1AP_PDU, f1apMsg); + return ROK; +} + +/******************************************************************* + * + * @brief Handles received F1AP message and sends back response + * + * @details + * + * Function : F1APMsgHdlr + * + * Functionality: + * - Decodes received F1AP control message + * - Prepares response message, encodes and sends to SCTP + * + * @params[in] + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +void F1APMsgHdlr(uint32_t *duId, Buffer *mBuf) +{ + char *recvBuf; + MsgLen recvBufLen; + F1AP_PDU_t *f1apMsg = NULLP; + F1AP_PDU_t f1apasnmsg ; + + DU_LOG("\nINFO --> F1AP : Received F1AP message buffer"); + ODU_PRINT_MSG(mBuf, 0,0); + + f1apMsg = &f1apasnmsg; + memset(f1apMsg, 0, sizeof(F1AP_PDU_t)); + if(F1APDecodeMsg(f1apMsg, mBuf, &recvBuf, &recvBufLen) != ROK) + { + DU_LOG("\nERROR --> F1AP : F1AP PDU decode failed"); + return; + } switch(f1apMsg->present) { @@ -12128,13 +12784,13 @@ void F1APMsgHdlr(uint32_t *duId, Buffer *mBuf) case SuccessfulOutcome__value_PR_UEContextSetupResponse: { DU_LOG("\nINFO --> F1AP : UE ContextSetupResponse received"); - procUeContextSetupResponse(*duId, f1apMsg); + procUeContextSetupResponse(*duId, f1apMsg, recvBuf, recvBufLen); break; } case SuccessfulOutcome__value_PR_UEContextModificationResponse: { DU_LOG("\nINFO --> F1AP : UE Context Modification Response received"); - procUeContextModificationResponse(*duId, f1apMsg); + procUeContextModificationResponse(*duId, f1apMsg, recvBuf, recvBufLen); break; } case SuccessfulOutcome__value_PR_UEContextReleaseComplete: @@ -12159,6 +12815,7 @@ void F1APMsgHdlr(uint32_t *duId, Buffer *mBuf) } }/* End of switch(f1apMsg->present) */ + CU_FREE(recvBuf, (Size)(recvBufLen)); } /* End of F1APMsgHdlr */ /**********************************************************************