1 /*******************************************************************************
2 ################################################################################
3 # Copyright (c) [2017-2019] [Radisys] #
5 # Licensed under the Apache License, Version 2.0 (the "License"); #
6 # you may not use this file except in compliance with the License. #
7 # You may obtain a copy of the License at #
9 # http://www.apache.org/licenses/LICENSE-2.0 #
11 # Unless required by applicable law or agreed to in writing, software #
12 # distributed under the License is distributed on an "AS IS" BASIS, #
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
14 # See the License for the specific language governing permissions and #
15 # limitations under the License. #
16 ################################################################################
17 *******************************************************************************/
19 /* This file contains F1AP message handler functions */
20 #include "common_def.h"
21 #include "cu_stub_sctp.h"
22 #include "cu_stub_egtp.h"
23 #include "OCTET_STRING.h"
25 #include "cu_f1ap_msg_hdl.h"
28 /*******************************************************************
30 * @brief Build And send dummy Xn Setup request
34 * Function : BuildAndSendXnSetupReq
37 * Build And send dummy Xn Setup request
42 ******************************************************************/
43 void BuildAndSendXnSetupReq()
47 CuSctpAssocCb *assocCb = NULLP;
49 for(assocIdx = 0; assocIdx < sctpCb.numAssoc; assocIdx++)
51 assocCb = &sctpCb.assocCb[assocIdx];
52 if(assocCb->connUp && assocCb->intf == XN_INTERFACE && assocCb->destId == 0)
54 if(ODU_GET_MSG_BUF(1, 1, &mBuf) == ROK)
56 CMCHKPK(oduUnpackUInt8,(Data *)CU_ID, mBuf);
57 CMCHKPK(oduUnpackUInt8,XN_SETUP_REQ, mBuf);
58 ODU_PRINT_MSG(mBuf, 0,0);
59 if(sendOnSctpAssoc(assocCb, mBuf) != ROK)
61 DU_LOG("\nERROR --> CU_STUB: Failed to send XN setup request to peer CU");
69 /*******************************************************************
71 * @brief Process received Xn Setup request
75 * Function : XNAPProcXnSetupReq
78 * Fetch peer CU ID and store in assocCb
80 * @params[in] Pointer to destination Id
81 * Pointer to message buffer
84 ******************************************************************/
85 void XNAPProcXnSetupReq(uint32_t *destId, Buffer *mBuf)
89 DU_LOG("\nINFO --> CU STUB : Received XN Setup Request");
90 CMCHKUNPK(oduPackUInt8, &(cuId), mBuf)
93 BuildAndSendXnSetupRsp(*destId);
96 /*******************************************************************
98 * @brief Build And send dummy Xn Setup response
102 * Function : BuildAndSendXnSetupRsp
105 * Build And send dummy Xn Setup response
110 ******************************************************************/
111 void BuildAndSendXnSetupRsp(uint32_t destId)
113 Buffer *mBuf = NULLP;
115 if(ODU_GET_MSG_BUF(1, 1, &mBuf) == ROK)
117 CMCHKPK(oduUnpackUInt8, CU_ID, mBuf);
118 CMCHKPK(oduUnpackUInt8, XN_SETUP_RSP, mBuf);
119 if(sctpSend(XN_INTERFACE, destId, mBuf))
121 DU_LOG("\nERROR --> CU_STUB: Failed to send XN setup response to peer CU");
126 /*******************************************************************
128 * @brief Process received Xn Setup response
132 * Function : XNAPProcXnSetupRsp
135 * Fetch peer CU ID and store in assocCb
137 * @params[in] Pointer to destination Id
138 * Pointer to message buffer
141 ******************************************************************/
142 void XNAPProcXnSetupRsp(uint32_t *destId, Buffer *mBuf)
146 DU_LOG("\nINFO --> CU STUB : Received XN Setup Response");
147 CMCHKUNPK(oduPackUInt8, &(cuId), mBuf)
151 /*******************************************************************
153 * @brief Build And send dummy Handover request to Peer CU
157 * Function : BuildAndSendHOReq
160 * Build And send dummy Handover request to Peer CU
162 * @params[in] Pointer to UE Cb
168 ******************************************************************/
169 void BuildAndSendHOReq(CuUeCb *ueCb, char *xnMsg, MsgLen xnMsgLen)
171 Buffer *mBuf = NULLP;
173 if(ODU_GET_MSG_BUF(1, 1, &mBuf) == ROK)
175 if(ODU_ADD_POST_MSG_MULT((Data *)xnMsg, xnMsgLen, mBuf) == ROK)
177 CMCHKPK(oduUnpackUInt8, ueCb->hoInfo.cuUeF1apIdSrc, mBuf);
178 CMCHKPK(oduUnpackUInt32, ueCb->hoInfo.tgtCellId, mBuf);
179 CMCHKPK(oduUnpackUInt8, HO_REQ, mBuf);
180 if(sctpSend(XN_INTERFACE, ueCb->hoInfo.tgtNodeId, mBuf) != ROK)
182 DU_LOG("\nERROR --> CU_STUB: Failed to send handover request to peer CU");
183 ueCb->state = UE_ACTIVE;
184 memset(&ueCb->hoInfo, 0, sizeof(HandoverInfo));
190 /*******************************************************************
192 * @brief Process received Handover Request
196 * Function : XNAPProcHandoverReq
199 * 1. Unpack Cell Id from msg and find DU to which it belongs
200 * 2. Create UE context for UE in handover and store in DU DB
201 * 3. Decode the F1AP UE context modification msg received in
202 * XNAP message buffer and extract UE configurations
203 * 4. Send UE context setup request to DU with these configs
205 * @params[in] Pointer to destination Id
206 * Pointer to message buffer
209 ******************************************************************/
210 void XNAPProcHandoverReq(uint32_t destId, Buffer *mBuf)
212 uint8_t duIdx, cellIdx;
213 uint8_t cuUeF1apIdSrc;
218 DU_LOG("\nINFO --> CU STUB : Received Handover Request");
220 /* Find DU Db and Cell Cb from cellId */
221 CMCHKUNPK(oduPackUInt32, &(cellId), mBuf);
222 for(duIdx = 0; duIdx < cuCb.numDu; duIdx++)
224 duDb = &cuCb.duInfo[duIdx];
225 SEARCH_CELL_DB(cellIdx, duDb, cellId, cellCb)
231 DU_LOG("\nERROR --> CU_STUB: Failed to find Cell Id [%d] received in HO Request", cellId);
235 /* Fetch CU UE F1AP ID of UE in handover assigned by source CU */
236 CMCHKUNPK(oduPackUInt8, &(cuUeF1apIdSrc), mBuf);
238 /* Filling temporary UE context which will be used to create actual UE context at
240 CU_ALLOC(duDb->tempUeCtxtInHo, sizeof(CuUeCb));
241 if(!duDb->tempUeCtxtInHo)
243 DU_LOG("\nERROR --> XNAP : Failed to allocate memory to temporary UE context for UE in handover");
246 memset(duDb->tempUeCtxtInHo, 0, sizeof(CuUeCb));
247 duDb->tempUeCtxtInHo->cellCb = cellCb;
248 duDb->tempUeCtxtInHo->gnbCuUeF1apId = ++cuCb.gnbCuUeF1apIdGenerator;
249 duDb->tempUeCtxtInHo->state = UE_HANDOVER_IN_PROGRESS;
250 duDb->tempUeCtxtInHo->hoInfo.HOType = Xn_Based_Inter_CU_HO;
251 duDb->tempUeCtxtInHo->hoInfo.srcNodeId = destId;
252 duDb->tempUeCtxtInHo->hoInfo.tgtNodeId = cuCb.cuCfgParams.cuId;
253 duDb->tempUeCtxtInHo->hoInfo.tgtCellId = cellId;
254 duDb->tempUeCtxtInHo->hoInfo.cuUeF1apIdSrc = cuUeF1apIdSrc;
255 duDb->tempUeCtxtInHo->hoInfo.cuUeF1apIdTgt = duDb->tempUeCtxtInHo->gnbCuUeF1apId;
257 /* Decode UE context modification response msg received in Xn Msg */
259 MsgLen recvBufLen, copyLen;
260 F1AP_PDU_t *f1apMsg = NULLP;
261 F1AP_PDU_t f1apasnmsg ;
263 f1apMsg = &f1apasnmsg;
264 memset(f1apMsg, 0, sizeof(F1AP_PDU_t));
265 if(F1APDecodeMsg(f1apMsg, mBuf, &recvBuf, &recvBufLen) != ROK)
267 DU_LOG("\nERROR --> F1AP : F1AP PDU decode failed");
270 CU_FREE(recvBuf, recvBufLen);
271 procUeContextModificationResponse(duDb->duId, f1apMsg, NULL, 0);
274 /*******************************************************************
276 * @brief Build And send dummy Handover request ack to Peer CU
280 * Function : BuildAndSendHOReqAck
283 * Build And send dummy Handover request ack to Peer CU
285 * @params[in] Pointer to UE Cb
290 ******************************************************************/
291 void BuildAndSendHOReqAck(CuUeCb *ueCb, char *xnMsg, MsgLen xnMsgLen)
293 Buffer *mBuf = NULLP;
295 if(ODU_GET_MSG_BUF(1, 1, &mBuf) == ROK)
297 if(ODU_ADD_POST_MSG_MULT((Data *)xnMsg, xnMsgLen, mBuf) == ROK)
299 CMCHKPK(oduUnpackUInt8, ueCb->gnbCuUeF1apId, mBuf);
300 CMCHKPK(oduUnpackUInt8, ueCb->hoInfo.cuUeF1apIdSrc, mBuf);
301 CMCHKPK(oduUnpackUInt8, HO_REQ_ACK, mBuf);
302 if(sctpSend(XN_INTERFACE, ueCb->hoInfo.srcNodeId, mBuf) != ROK)
304 DU_LOG("\nERROR --> CU_STUB: Failed to send handover request ack to peer CU");
310 /*******************************************************************
312 * @brief Process received Handover Request Ack
316 * Function : XNAPProcHandoverReqAck
319 * 1. Unpack CU UE F1AP ID (by SCU) and fetch UE CB and
320 * the corresponding DU DB (SDU)
321 * 2. Unpack CU UE F1AP ID (by TCU) and fill in UEcb->hoInfo
322 * 3. Decode DU to CU RRC Container received in XNAP message
323 * buffer and extract UE configurations.
324 * 4. Send UE Context modification response to SDU conatining
325 * RRC Reconfig Message and command to stop transmission
328 * @params[in] Destination Id
329 * Pointer to message buffer
332 ******************************************************************/
333 void XNAPProcHandoverReqAck(uint32_t destId, Buffer *mBuf)
335 uint8_t duIdx, duId, ueIdx;
336 uint8_t cuUeF1apIdSrc;
337 uint8_t cuUeF1apIdTgt;
341 DU_LOG("\nINFO --> CU STUB : Received Handover Request Acknowledgement");
343 /* Fetch UE CB and DU DB in Source CU for UE under Inter-CU Handover */
344 CMCHKUNPK(oduPackUInt8, &(cuUeF1apIdSrc), mBuf);
345 for(duIdx = 0; duIdx < cuCb.numDu; duIdx++)
347 for(ueIdx = 0; ueIdx < MAX_NUM_CELL * MAX_NUM_UE; ueIdx++)
349 if(cuCb.duInfo[duIdx].ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apIdSrc)
351 duDb = &cuCb.duInfo[duIdx];
352 ueCb = &cuCb.duInfo[duIdx].ueCb[ueIdx];
361 DU_LOG("\nERROR --> CU STUB : UE CB not found for CU UE F1AP ID [%d]", cuUeF1apIdSrc);
365 /* Decode CU UE F1AP ID assigned by Target CU to UE in handover and store
366 * this in hoInfo block for use during future message exchange between the
368 CMCHKUNPK(oduPackUInt8, &(cuUeF1apIdTgt), mBuf);
369 ueCb->hoInfo.cuUeF1apIdTgt = cuUeF1apIdTgt;
371 /* Decode DU to CU RRC Container received in Xn Msg */
372 OCTET_STRING_t rrcCont;
375 /* Copy mBuf into char array to decode it */
376 memset(&rrcCont, 0, sizeof(OCTET_STRING_t));
377 ODU_GET_MSG_LEN(mBuf, &rrcCont.size);
378 CU_ALLOC(rrcCont.buf, rrcCont.size);
379 if(rrcCont.buf == NULLP)
381 DU_LOG("\nERROR --> XNAP : Memory allocation failed");
384 if(ODU_COPY_MSG_TO_FIX_BUF(mBuf, 0, rrcCont.size, (Data *)rrcCont.buf, ©Cnt) != ROK)
386 DU_LOG("\nERROR --> F1AP : Failed while copying %d", copyCnt);
390 /* Extract DU to CU RRC container information and store in UE CB */
391 extractDuToCuRrcCont(ueCb, rrcCont);
393 CU_FREE(rrcCont.buf, rrcCont.size);
395 /* Send UE Context Modification request after filling it using the information received in
396 * Xn Handover Request Ack */
397 if(BuildAndSendUeContextModificationReq(duDb->duId, ueCb, STOP_DATA_TX) != ROK)
399 DU_LOG("\nERROR -> F1AP : Failed at BuildAndSendUeContextModificationReq()");
404 /*******************************************************************
406 * @brief Build And send dummy UE Context Release to Peer CU
410 * Function : BuildAndSendUeContextRelease
413 * Build And send dummy UE Context Release to Peer CU
415 * @params[in] Pointer to UE Cb
418 ******************************************************************/
419 void BuildAndSendUeContextRelease(CuUeCb *ueCb)
421 Buffer *mBuf = NULLP;
423 if(ODU_GET_MSG_BUF(1, 1, &mBuf) == ROK)
425 CMCHKPK(oduUnpackUInt8, ueCb->hoInfo.cuUeF1apIdSrc, mBuf);
426 CMCHKPK(oduUnpackUInt8, UE_CTXT_REL, mBuf);
427 if(sctpSend(XN_INTERFACE, ueCb->hoInfo.srcNodeId, mBuf) != ROK)
429 DU_LOG("\nERROR --> CU_STUB: Failed to send UE context release to peer CU");
436 /*******************************************************************
437 * @brief Process received UE Context Release
441 * Function : XNAPProcUeContextRel
444 * 1. Unpack CU UE F1AP ID (by SCU) and fetch UE CB and
445 * the corresponding DU DB (SDU)
446 * 2. Send UE Context release command to SDU
448 * @params[in] Destination Id
449 * Pointer to message buffer
452 ******************************************************************/
453 void XNAPProcUeContextRel(uint32_t destId, Buffer *mBuf)
455 uint8_t duIdx, duId, ueIdx;
456 uint8_t cuUeF1apIdSrc;
460 DU_LOG("\nINFO --> CU STUB : Received UE Context Release");
462 /* Fetch UE CB and DU DB in Source CU for UE under Inter-CU Handover */
463 CMCHKUNPK(oduPackUInt8, &(cuUeF1apIdSrc), mBuf);
464 for(duIdx = 0; duIdx < cuCb.numDu; duIdx++)
466 for(ueIdx = 0; ueIdx < MAX_NUM_CELL * MAX_NUM_UE; ueIdx++)
468 if(cuCb.duInfo[duIdx].ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apIdSrc)
470 duDb = &cuCb.duInfo[duIdx];
471 ueCb = &duDb->ueCb[ueIdx];
480 DU_LOG("\nERROR --> CU STUB : UE CB not found for CU UE F1AP ID [%d]", cuUeF1apIdSrc);
484 BuildAndSendUeContextReleaseCommand(duDb->duId, ueCb->gnbCuUeF1apId, ueCb->gnbDuUeF1apId);
487 /*******************************************************************
489 * @brief Handle incoming messages at Xn interface
493 * Function : XNAPMsgHdlr
496 * Fetch event type from message buffer and call appropriate
499 * @params[in] Pointer to destination Id
500 * Pointer to message buffer
503 ******************************************************************/
504 void XNAPMsgHdlr(uint32_t *destId, Buffer *mBuf)
508 CMCHKUNPK(oduPackUInt8, &event, mBuf);
514 XNAPProcXnSetupReq(destId, mBuf);
520 XNAPProcXnSetupRsp(destId, mBuf);
526 XNAPProcHandoverReq(*destId, mBuf);
532 XNAPProcHandoverReqAck(*destId, mBuf);
537 XNAPProcUeContextRel(*destId, mBuf);
541 DU_LOG("\nERROR --> CU_STUB : Invalid event [%d] received at XN interface", event);
546 /**********************************************************************
548 **********************************************************************/