* 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;
{
duUeF1apId = ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.GNB_DU_UE_F1AP_ID;
ueCb = &duDb->ueCb[duUeF1apId-1];
+
+ if((ueCb->state == UE_HANDOVER_IN_PROGRESS) && (ueCb->hoInfo.HOType == Xn_Based_Inter_CU_HO))
+ {
+ BuildAndSendHOReq(ueCb, HO_REQ, recvBuf, recvBufLen);
+ }
break;
}
case ProtocolIE_ID_id_DRBs_SetupMod_List:
/* If UE is in handover and UE context is not yet created at target DU, then send
* UE context setup request to target DU */
- if(ueCb->state == UE_HANDOVER_IN_PROGRESS && ueCb->hoInfo.HOType == Inter_DU_HO)
+ if(ueCb->state == UE_HANDOVER_IN_PROGRESS)
{
- uint8_t ueIdx = 0;
- DuDb *tgtDuDb = NULLP;
- CuUeCb *ueCbInTgtDu = NULLP;
-
- SEARCH_DU_DB(duIdx, ueCb->hoInfo.targetId, tgtDuDb);
- if(tgtDuDb)
+ if(ueCb->hoInfo.HOType == Inter_DU_HO)
{
- /* Since DU UE F1AP ID assigned by target DU to this UE in handover is
- * not known here, using CU UE F1AP ID to search for UE Cb in target DU
- * DB */
- for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++)
+ uint8_t ueIdx = 0;
+ DuDb *tgtDuDb = NULLP;
+ CuUeCb *ueCbInTgtDu = NULLP;
+
+ SEARCH_DU_DB(duIdx, ueCb->hoInfo.targetId, tgtDuDb);
+ if(tgtDuDb)
{
- if(tgtDuDb->ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId)
+ /* Since DU UE F1AP ID assigned by target DU to this UE in handover is
+ * not known here, using CU UE F1AP ID to search for UE Cb in target DU
+ * DB */
+ for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++)
{
- ueCbInTgtDu = &tgtDuDb->ueCb[ueIdx];
- break;
+ if(tgtDuDb->ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId)
+ {
+ ueCbInTgtDu = &tgtDuDb->ueCb[ueIdx];
+ break;
+ }
}
- }
- /* If UE context is not found in Target DU DU, send UE context setup
- * request */
- if(ueCbInTgtDu == NULLP)
- {
- if((BuildAndSendUeContextSetupReq(ueCb->hoInfo.targetId, ueCb)) != ROK)
+ /* If UE context is not found in Target DU DU, send UE context setup
+ * request */
+ if(ueCbInTgtDu == NULLP)
{
- DU_LOG("\nERROR -> F1AP : Failed at BuildAndSendUeContextSetupReq");
- return RFAILED;
+ if((BuildAndSendUeContextSetupReq(ueCb->hoInfo.targetId, ueCb)) != ROK)
+ {
+ DU_LOG("\nERROR -> F1AP : Failed at BuildAndSendUeContextSetupReq");
+ return RFAILED;
+ }
}
}
}
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++)
{
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:
for(destIdx=0; destIdx < sctpCb.sctpCfg.xnSctpInfo.numDestNode; destIdx++)
{
sctpCb.assocCb[assocIdx].intf = XN_INTERFACE;
- sctpCb.assocCb[assocIdx].destId = CU_ID + destIdx +1;
sctpCb.assocCb[assocIdx].destPort = sctpCb.sctpCfg.xnSctpInfo.destCb[destIdx].destPort;
sctpCb.assocCb[assocIdx].bReadFdSet = ROK;
memset(&sctpCb.assocCb[assocIdx].sockFd, -1, sizeof(CmInetFd));
}
else if(assocCb->connUp && assocCb->intf == XN_INTERFACE)
{
- //TODO : Handler for messages on XN interface to be added in future commits
DU_LOG("\nDEBUG --> SCTP : Received message at XN interface");
ODU_PRINT_MSG(pollParams->mBuf, 0,0);
+ XNAPMsgHdlr(&assocCb->destId, pollParams->mBuf);
ODU_PUT_MSG_BUF(pollParams->mBuf);
}
else
return ROK;
}/* End of sctpSockPoll() */
+/*******************************************************************
+ *
+ * @brief Send message on an SCTP Association
+ *
+ * @details
+ *
+ * Function : sendOnSctpAssoc
+ *
+ * Functionality:
+ * Send message on SCTP association
+ *
+ * @params[in]
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t sendOnSctpAssoc(CuSctpAssocCb *assocCb, Buffer *mBuf)
+{
+ uint8_t ret = ROK;
+ MsgLen len = 0; /* number of actually sent octets */
+ CmInetMemInfo memInfo;
+
+ memset(&memInfo , 0, sizeof(CmInetMemInfo));
+ memInfo.region = CU_APP_MEM_REG;
+ memInfo.pool = CU_POOL;
+
+ ret = cmInetSctpSendMsg(&assocCb->sockFd, &assocCb->destIpNetAddr, assocCb->destPort, &memInfo, mBuf, &len, 0, \
+ FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
+
+ if(ret != ROK && ret != RWOULDBLOCK)
+ {
+ DU_LOG("\nERROR --> SCTP : Send message failed");
+ return RFAILED;
+ }
+ return ROK;
+}
+
/*******************************************************************
*
* @brief Send message on SCTP socket
* ****************************************************************/
uint8_t sctpSend(InterfaceType intf, uint32_t destId, Buffer *mBuf)
{
- uint8_t ret = ROK, assocIdx = 0;
- MsgLen len = 0; /* number of actually sent octets */
- CmInetMemInfo memInfo;
-
- memset(&memInfo , 0, sizeof(CmInetMemInfo));
- memInfo.region = CU_APP_MEM_REG;
- memInfo.pool = CU_POOL;
+ uint8_t assocIdx = 0;
for(assocIdx=0; assocIdx < sctpCb.numAssoc; assocIdx++)
{
if((sctpCb.assocCb[assocIdx].intf == intf) && (sctpCb.assocCb[assocIdx].destId == destId))
{
- ret = cmInetSctpSendMsg(&sctpCb.assocCb[assocIdx].sockFd, &sctpCb.assocCb[assocIdx].destIpNetAddr, \
- sctpCb.assocCb[assocIdx].destPort, &memInfo, mBuf, &len, 0, FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
-
- if(ret != ROK && ret != RWOULDBLOCK)
- {
- DU_LOG("\nERROR --> SCTP : Send message failed");
- return RFAILED;
- }
- return ROK;
+ if(sendOnSctpAssoc(&sctpCb.assocCb[assocIdx], mBuf) == ROK)
+ return ROK;
+ else
+ break;
}
}
DU_LOG("\nERROR --> SCTP : Dest ID [%d] at Interface [%d] not found in SCTP DestCb list. Failed to send message", destId, intf);
--- /dev/null
+/*******************************************************************************
+################################################################################
+# Copyright (c) [2017-2019] [Radisys] #
+# #
+# Licensed under the Apache License, Version 2.0 (the "License"); #
+# you may not use this file except in compliance with the License. #
+# You may obtain a copy of the License at #
+# #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+# #
+# Unless required by applicable law or agreed to in writing, software #
+# distributed under the License is distributed on an "AS IS" BASIS, #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+# See the License for the specific language governing permissions and #
+# limitations under the License. #
+################################################################################
+*******************************************************************************/
+
+/* This file contains F1AP message handler functions */
+#include "common_def.h"
+#include "cu_stub_sctp.h"
+#include "cu_stub_egtp.h"
+#include "OCTET_STRING.h"
+#include "cu_f1ap_msg_hdl.h"
+#include "cu_stub.h"
+
+/*******************************************************************
+ *
+ * @brief Build And send dummy Xn Setup request
+ *
+ * @details
+ *
+ * Function : BuildAndSendXnSetupReq
+ *
+ * Functionality:
+ * Build And send dummy Xn Setup request
+ *
+ * @params[in]
+ * @return void
+ *
+ ******************************************************************/
+void BuildAndSendXnSetupReq()
+{
+ uint8_t assocIdx = 0;
+ Buffer *mBuf = NULLP;
+ CuSctpAssocCb *assocCb = NULLP;
+
+ for(assocIdx = 0; assocIdx < sctpCb.numAssoc; assocIdx++)
+ {
+ assocCb = &sctpCb.assocCb[assocIdx];
+ if(assocCb->connUp && assocCb->intf == XN_INTERFACE && assocCb->destId == 0)
+ {
+ if(ODU_GET_MSG_BUF(1, 1, &mBuf) == ROK)
+ {
+ CMCHKPK(oduUnpackUInt8,(Data *)CU_ID, mBuf);
+ CMCHKPK(oduUnpackUInt8,XN_SETUP_REQ, mBuf);
+ ODU_PRINT_MSG(mBuf, 0,0);
+ if(sendOnSctpAssoc(assocCb, mBuf) != ROK)
+ {
+ DU_LOG("\nERROR --> CU_STUB: Failed to send XN setup request to peer CU");
+ }
+ }
+ break;
+ }
+ }
+}
+
+/*******************************************************************
+ *
+ * @brief Process received Xn Setup request
+ *
+ * @details
+ *
+ * Function : XNAPProcXnSetupReq
+ *
+ * Functionality:
+ * Fetch peer CU ID and store in assocCb
+ *
+ * @params[in] Pointer to destination Id
+ * Pointer to message buffer
+ * @return void
+ *
+ ******************************************************************/
+void XNAPProcXnSetupReq(uint32_t *destId, Buffer *mBuf)
+{
+ uint8_t cuId;
+
+ DU_LOG("\nINFO --> CU STUB : Received XN Setup Request");
+ CMCHKUNPK(oduPackUInt8, &(cuId), mBuf)
+ *destId = cuId;
+
+ BuildAndSendXnSetupRsp(*destId);
+}
+
+/*******************************************************************
+ *
+ * @brief Build And send dummy Xn Setup response
+ *
+ * @details
+ *
+ * Function : BuildAndSendXnSetupRsp
+ *
+ * Functionality:
+ * Build And send dummy Xn Setup response
+ *
+ * @params[in]
+ * @return void
+ *
+ ******************************************************************/
+void BuildAndSendXnSetupRsp(uint32_t destId)
+{
+ Buffer *mBuf = NULLP;
+
+ if(ODU_GET_MSG_BUF(1, 1, &mBuf) == ROK)
+ {
+ CMCHKPK(oduUnpackUInt8, CU_ID, mBuf);
+ CMCHKPK(oduUnpackUInt8, XN_SETUP_RSP, mBuf);
+ if(sctpSend(XN_INTERFACE, destId, mBuf))
+ {
+ DU_LOG("\nERROR --> CU_STUB: Failed to send XN setup response to peer CU");
+ }
+ }
+}
+
+/*******************************************************************
+ *
+ * @brief Process received Xn Setup response
+ *
+ * @details
+ *
+ * Function : XNAPProcXnSetupRsp
+ *
+ * Functionality:
+ * Fetch peer CU ID and store in assocCb
+ *
+ * @params[in] Pointer to destination Id
+ * Pointer to message buffer
+ * @return void
+ *
+ ******************************************************************/
+void XNAPProcXnSetupRsp(uint32_t *destId, Buffer *mBuf)
+{
+ uint8_t cuId;
+
+ DU_LOG("\nINFO --> CU STUB : Received XN Setup Response");
+ CMCHKUNPK(oduPackUInt8, &(cuId), mBuf)
+ *destId = cuId;
+}
+
+/*******************************************************************
+ *
+ * @brief Build And send dummy Handover request to Peer CU
+ *
+ * @details
+ *
+ * Function : BuildAndSendHOReq
+ *
+ * Functionality:
+ * Build And send dummy Handover request to Peer CU
+ *
+ * @params[in] Pointer to UE Cb
+ * Event type
+ * Message to be sent
+ * Message Length
+ * @return void
+ *
+ ******************************************************************/
+void BuildAndSendHOReq(CuUeCb *ueCb, XnEventType event, char *xnMsg, MsgLen xnMsgLen)
+{
+ Buffer *mBuf = NULLP;
+
+ if(ODU_GET_MSG_BUF(1, 1, &mBuf) == ROK)
+ {
+ if(ODU_ADD_POST_MSG_MULT((Data *)xnMsg, xnMsgLen, mBuf) == ROK)
+ {
+ CMCHKPK(oduUnpackUInt8, event, mBuf);
+ if(sctpSend(XN_INTERFACE, ueCb->hoInfo.targetId, mBuf) != ROK)
+ {
+ DU_LOG("\nERROR --> CU_STUB: Failed to send handover request to peer CU");
+ ueCb->state = UE_ACTIVE;
+ memset(&ueCb->hoInfo, 0, sizeof(HandoverInfo));
+ }
+ }
+ }
+}
+
+/*******************************************************************
+ *
+ * @brief Handle incoming messages at Xn interface
+ *
+ * @details
+ *
+ * Function : XNAPMsgHdlr
+ *
+ * Functionality:
+ * Fetch event type from message buffer and call appropriate
+ * handler
+ *
+ * @params[in] Pointer to destination Id
+ * Pointer to message buffer
+ * @return void
+ *
+ ******************************************************************/
+void XNAPMsgHdlr(uint32_t *destId, Buffer *mBuf)
+{
+ XnEventType event;
+
+ CMCHKUNPK(oduPackUInt8, &event, mBuf);
+
+ switch(event)
+ {
+ case XN_SETUP_REQ:
+ {
+ XNAPProcXnSetupReq(destId, mBuf);
+ break;
+ }
+
+ case XN_SETUP_RSP:
+ {
+ XNAPProcXnSetupRsp(destId, mBuf);
+ break;
+ }
+
+ case HO_REQ:
+ {
+ DU_LOG("\nINFO --> CU STUB : Received Handover Request at XNAP");
+
+//Handling of HO Request to be added in next gerrit
+#if 0
+ char *recvBuf;
+ MsgLen copyCnt;
+ MsgLen recvBufLen;
+ F1AP_PDU_t *f1apMsg = NULLP;
+ asn_dec_rval_t rval; /* Decoder return value */
+ F1AP_PDU_t f1apasnmsg ;
+
+ 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)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed");
+ return;
+ }
+ if(ODU_COPY_MSG_TO_FIX_BUF(mBuf, 0, recvBufLen, (Data *)recvBuf, ©Cnt) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : Failed while copying %d", copyCnt);
+ return;
+ }
+
+ DU_LOG("\nDEBUG --> F1AP : Received flat buffer to be decoded : ");
+ for(i=0; i< recvBufLen; 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);
+
+ if(rval.code == RC_FAIL || rval.code == RC_WMORE)
+ {
+ DU_LOG("\nERROR --> F1AP : ASN decode failed");
+ return;
+ }
+ DU_LOG("\n");
+ xer_fprint(stdout, &asn_DEF_F1AP_PDU, f1apMsg);
+
+ procUeContextModificationResponse(0, f1apMsg, recvBuf, recvBufLen);
+#endif
+ break;
+ }
+ default:
+ DU_LOG("\nERROR --> CU_STUB : Invalid event [%d] received at XN interface", event);
+ break;
+ }
+}
+
+/**********************************************************************
+ End of file
+ **********************************************************************/