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 *******************************************************************************/
18 #include "common_def.h"
24 #include "du_app_mac_inf.h"
25 #include "du_app_rlc_inf.h"
26 #include "du_e2ap_mgr.h"
27 #include "du_e2_conversions.h"
28 #include "du_e2ap_msg_hdl.h"
32 #include "du_mgr_main.h"
35 /*******************************************************************
37 * @brief Assigns new transaction id to DU initiated procedure
41 * Function : assignTransactionId
43 * Functionality: Assigns new transaction id to a DU initiated
46 * @params[in] Region region
48 * @return ROK - success
51 * ****************************************************************/
52 uint8_t assignTransactionId()
54 uint8_t currTransId = duCb.e2apDb.e2TransInfo.transIdCounter;
56 /* Update to next valid value */
57 duCb.e2apDb.e2TransInfo.transIdCounter++;
58 if(duCb.e2apDb.e2TransInfo.transIdCounter == MAX_NUM_TRANSACTION)
59 duCb.e2apDb.e2TransInfo.transIdCounter = 0;
64 /*******************************************************************
66 * @brief Decode subscription ID
70 * Function : decodeSubscriptionId
72 * Functionality: Decode subscription id to get RAN function ID
75 * @params[in] Subscription ID
76 * RAN Function ID to be extracted
77 * RIC Request ID to be extracted
80 * ****************************************************************/
81 void decodeSubscriptionId(uint64_t subscriptionId, uint16_t *ranFuncId, RicRequestId *ricReqId)
83 /* Extract following from 64 bit subscription-ID :
84 * First 16 MSB is unused
85 * Next 16 MSB = RAN-Function-ID
86 * Next 16 MSB = Requestor-ID in RIC-Request-ID
87 * Last 16 LSB = Instance-ID in RIC-Request-ID
89 ricReqId->instanceId = subscriptionId & 0xFFFF;
90 ricReqId->requestorId = (subscriptionId >> 16) & 0xFFFF;
91 *ranFuncId = (subscriptionId >> 32) & 0xFFFF;
94 /*******************************************************************
96 * @brief Encode subscription ID
100 * Function : encodeSubscriptionId
102 * Functionality: Encode subscription id to get RAN function ID
105 * @params[in] Subscription ID to be encoded
110 * ****************************************************************/
111 void encodeSubscriptionId(uint64_t *subscriptionId, uint16_t ranFuncId, RicRequestId ricReqId)
113 /* Calculate 64 bit subscription-ID :
114 * First 16 MSB is unused
115 * Next 16 MSB = RAN-Function-ID
116 * Next 16 MSB = Requestor-ID in RIC-Request-ID
117 * Last 16 LSB = Instance-ID in RIC-Request-ID
119 *subscriptionId = ricReqId.instanceId;
120 *subscriptionId |= ((uint64_t)ricReqId.requestorId << 16);
121 *subscriptionId |= ((uint64_t)ranFuncId << 32);
124 /*******************************************************************
126 * @brief Fetch Action details
130 * Function : fetchActionInfoFromActionId
132 * Functionality: Fetch action details from RIC subscription DB
135 * @params[in] Action ID
136 * RIC Subscription DB
137 * @return Action Info DB
138 * NULL, in case of failure
140 * ****************************************************************/
141 ActionInfo *fetchActionInfoFromActionId(uint8_t actionId, RicSubscription *ricSubscriptionInfo)
143 ActionInfo *actionInfoDb = NULLP;
144 if(ricSubscriptionInfo->actionSequence[actionId-1].id == actionId)
146 actionInfoDb = &ricSubscriptionInfo->actionSequence[actionId-1];
150 DU_LOG("\nERROR --> DU_APP : fetchActionInfoFromActionId: Action Id [%d] not found in \
151 subscription info [Requestor id : %d] [Instance Id : %d]", actionId,\
152 ricSubscriptionInfo->requestId.requestorId, ricSubscriptionInfo->requestId.instanceId);
158 /*******************************************************************
160 * @brief Fetch subscripton DB
164 * Function : fetchSubsInfoFromRicReqId
166 * Functionality: Fetches subscription DB from RAN Function DB
167 * using RIC Request ID
169 * @params[in] RIC Request ID
171 * Pointer to RIC Subscription node to be searched
172 * @return RIC Subscription from RAN Function's subcription list
173 * NULL, in case of failure
175 * ****************************************************************/
176 RicSubscription *fetchSubsInfoFromRicReqId(RicRequestId ricReqId, RanFunction *ranFuncDb, CmLList **ricSubscriptionNode)
178 RicSubscription *ricSubscriptionInfo = NULLP;
180 /* Fetch subscription detail in RAN Function DB */
181 CM_LLIST_FIRST_NODE(&ranFuncDb->subscriptionList, *ricSubscriptionNode);
182 while(*ricSubscriptionNode)
184 ricSubscriptionInfo = (RicSubscription *)((*ricSubscriptionNode)->node);
185 if(ricSubscriptionInfo && (ricSubscriptionInfo->requestId.requestorId == ricReqId.requestorId) &&
186 (ricSubscriptionInfo->requestId.instanceId == ricReqId.instanceId))
190 *ricSubscriptionNode = (*ricSubscriptionNode)->next;
191 ricSubscriptionInfo = NULLP;
194 if(!ricSubscriptionInfo)
196 DU_LOG("\nERROR --> DU_APP : fetchSubsInfoFromRicReqId: Subscription not found for Requestor ID [%d] \
197 Instance ID [%d] in RAN Function ID [%d]", ricReqId.requestorId, ricReqId.instanceId, ranFuncDb->id);
200 return ricSubscriptionInfo;
203 /*******************************************************************
205 * @brief Fetches RAN Function DB
209 * Function : fetchRanFuncFromRanFuncId
211 * Functionality: Fetches RAN function DB from E2AP DB using
214 * @params[in] RAN Function ID
215 * @return RAN Function DB
216 * NULL, in case of failure
218 * ****************************************************************/
219 RanFunction *fetchRanFuncFromRanFuncId(uint16_t ranFuncId)
221 RanFunction *ranFuncDb = NULLP;
223 /* Fetch RAN Function DB */
224 if(duCb.e2apDb.ranFunction[ranFuncId-1].id == ranFuncId)
226 ranFuncDb = &duCb.e2apDb.ranFunction[ranFuncId-1];
230 DU_LOG("\nERROR --> DU_APP : fetchRanFuncFromRanFuncId: Invalid RAN Function ID[%d]", ranFuncId);
236 /*******************************************************************
238 * @brief Fetches subscription info
242 * Function : fetchSubsInfoFromSubsId
245 * 1. Firstly, RAN Function ID and RIC request ID is extracted
246 * from Subscription ID
247 * 2. Using RAN Function ID, RAN Function DB is searched
248 * 3. Using RIC Request ID, the subscription DB is searched in
251 * @params[in] Subscription ID
253 * RIC Subscription node from RAN Func's Subscription list
257 * ****************************************************************/
258 uint8_t fetchSubsInfoFromSubsId(uint64_t subscriptionId, RanFunction **ranFuncDb, CmLList **ricSubscriptionNode, \
259 RicSubscription **ricSubscriptionInfo)
261 uint16_t ranFuncId = 0;
262 RicRequestId ricReqId;
264 memset(&ricReqId, 0, sizeof(RicRequestId));
266 /* Decode subscription ID o get RIC Request ID and RAN Function ID */
267 decodeSubscriptionId(subscriptionId, &ranFuncId, &ricReqId);
269 /* Fetch RAN Function DB using RAN Function ID */
270 *ranFuncDb = fetchRanFuncFromRanFuncId(ranFuncId);
271 if((*ranFuncDb) == NULLP)
276 /* Fetch Sunscription DB from RAN Function using RIC Request ID */
277 *ricSubscriptionInfo = fetchSubsInfoFromRicReqId(ricReqId, *ranFuncDb, ricSubscriptionNode);
278 if((*ricSubscriptionInfo) == NULLP)
286 /*******************************************************************
288 * @brief Sends E2 msg over SCTP
292 * Function : SendE2APMsg
294 * Functionality: Sends E2 msg over SCTP
296 * @params[in] Region region
298 * @return ROK - success
301 * ****************************************************************/
303 uint8_t SendE2APMsg(Region region, Pool pool, char *encBuf, int encBufSize)
307 if(ODU_GET_MSG_BUF(region, pool, &mBuf) == ROK)
309 if(ODU_ADD_POST_MSG_MULT((Data *)encBuf, encBufSize, mBuf) == ROK)
311 ODU_PRINT_MSG(mBuf, 0,0);
313 if(sctpSend(mBuf, E2_INTERFACE) != ROK)
315 DU_LOG("\nERROR --> E2AP : SCTP Send for E2 failed");
316 ODU_PUT_MSG_BUF(mBuf);
322 DU_LOG("\nERROR --> E2AP : ODU_ADD_POST_MSG_MULT failed");
323 ODU_PUT_MSG_BUF(mBuf);
326 ODU_PUT_MSG_BUF(mBuf);
330 DU_LOG("\nERROR --> E2AP : Failed to allocate memory");
337 /*******************************************************************
343 * Function : ResetE2Request
345 * Functionality: This function resets E2.
346 * As per ORAN WG3 E2GAP v3.0 Spec, section 5.5.3
347 * If E2 node initates reset procedure then:
348 * a. Send reset request to RIC
349 * b. Delete any pre-established RIC subscriptions
350 * c. Gracefully terminates any ongoing RIC services
351 * If RIC initiates reset procedure then :
352 * a. Delete any pre-established RIC subscriptions
353 * b. Gracefully terminates any ongoing RIC services
354 * c. Send reset response to RIC
357 * @return ROK - success
360 * ****************************************************************/
361 uint8_t ResetE2Request(E2ProcedureDirection dir, E2FailureCause resetCause)
363 /* Send Reset Request to RIC if DU detects any abnormal failure */
364 if(dir == E2_NODE_INITIATED)
366 if(BuildAndSendE2ResetRequest(resetCause) != ROK)
368 DU_LOG("\nERROR --> E2AP : BuildAndSendE2ResetRequest failed");
373 /* TODO when RIC subscription service model is implemented
374 Process following steps of resetting E2
375 1. Deletes any pre-established RIC subscriptions
376 2. Gracefully terminates any ongoing RIC services
379 /* Send Reset Response if RIC initiated Reset request is received at DU */
380 if(dir == RIC_INITIATED)
382 //BuildAndSendE2ResetResponse();
387 /*******************************************************************
389 * @brief Fill RIC Subscription datils in MAC Statistics Request
393 * Function : fillRicSubsInMacStatsReq
395 * Functionality: Fill RIC Subscription datils in MAC Statistics
398 * @params[in] MAC Statistics Request to be filled
400 * RIC Subscription Info
402 * @return ROK - success
405 * ****************************************************************/
406 uint8_t fillRicSubsInMacStatsReq(MacStatsReq *macStatsReq, uint16_t ranFuncId, RicSubscription* ricSubscriptionInfo)
408 uint8_t actionIdx = 0, grpIdx = 0, statsIdx = 0;
409 uint64_t subscriptionId = 0;
410 ActionInfo *actionDb = NULLP;
411 ActionDefFormat1 *format1Action = NULLP;
413 /* Generate subscription ID using RIC Request ID and RAN Function ID */
414 encodeSubscriptionId(&subscriptionId, ranFuncId, ricSubscriptionInfo->requestId);
416 macStatsReq->subscriptionId = subscriptionId;
417 for(actionIdx = 0; actionIdx < ricSubscriptionInfo->numOfActions; actionIdx++)
419 if(ricSubscriptionInfo->actionSequence[actionIdx].action == CONFIG_ADD)
421 actionDb = &ricSubscriptionInfo->actionSequence[actionIdx];
422 macStatsReq->statsGrpList[grpIdx].groupId = actionDb->id;
423 switch(actionDb->definition.formatType)
427 format1Action = &actionDb->definition.choice.format1;
428 macStatsReq->statsGrpList[grpIdx].periodicity = format1Action->granularityPeriod;
430 CmLList *node = NULLP;
431 MeasurementInfo *measInfo = NULLP;
433 /* Update DL PRB Usage for all stats group which requested for DL Total PRB Usage */
434 node = cmLListFirst(&format1Action->measurementInfoList);
437 measInfo = (MeasurementInfo *)(node->node);
438 switch(measInfo->measurementTypeId)
442 macStatsReq->statsGrpList[grpIdx].statsList[statsIdx++] = MAC_DL_TOTAL_PRB_USAGE;
447 macStatsReq->statsGrpList[grpIdx].statsList[statsIdx++] = MAC_UL_TOTAL_PRB_USAGE;
452 DU_LOG("\nERROR --> DU_APP : Invalid measurement name");
458 macStatsReq->statsGrpList[grpIdx].numStats = statsIdx;
463 DU_LOG("\nERROR --> DU_APP : BuildAndSendStatsReqToMac: Only Action Definition Format 1 supported");
467 if(macStatsReq->statsGrpList[grpIdx].numStats)
472 macStatsReq->numStatsGroup = grpIdx;
473 if(macStatsReq->numStatsGroup)
480 /*******************************************************************
482 * @brief Rejects all actions received in a subscription request
486 * Function : duRejectAllStatsGroup
488 * Functionality: Rejects all actions received in a subscription
490 * a. Removing the subscription entry from RAN function
491 * b. Sending RIC Subscription Failure to RIC with appropriate
494 * @params[in] RAN Function DB
495 * Subscription entry in RAN Function subscription list
496 * Statistics Response from MAC
498 * @return ROK - success
501 * ****************************************************************/
502 uint8_t rejectAllStatsGroup(RanFunction *ranFuncDb, CmLList *ricSubscriptionNode, MacStatsRsp *statsRsp)
505 RicRequestId requestId;
506 E2FailureCause failureCause;
508 /* Delete subcription from RAN Function */
509 memcpy(&requestId, &((RicSubscription *)ricSubscriptionNode->node)->requestId, sizeof(RicRequestId));
510 cmLListDelFrm(&ranFuncDb->subscriptionList, ricSubscriptionNode);
511 DU_FREE(ricSubscriptionNode->node, sizeof(RicSubscription));
512 DU_FREE(ricSubscriptionNode, sizeof(CmLList));
514 convertDuCauseToE2Cause(statsRsp->statsGrpRejectedList[0].cause, &failureCause);
516 /* Send RIC subscription failure to RIC */
517 ret = BuildAndSendRicSubscriptionFailure(requestId, ranFuncDb->id, failureCause);
521 /*******************************************************************
523 * @brief Process statistics response from MAC
527 * Function : e2ProcStatsRsp
529 * Functionality: Processes statistics configuration response
530 * from MAC. If configuration is succsessful, DUAPP starts
531 * reporting period timer for this subscription request
536 * @return ROK - success
539 * ****************************************************************/
540 void e2ProcStatsRsp(MacStatsRsp *statsRsp)
543 uint8_t actionId = 0;
544 RanFunction *ranFuncDb = NULLP;
545 CmLList *ricSubscriptionNode = NULLP;
546 RicSubscription *ricSubscriptionInfo = NULLP;
547 ActionInfo *actionInfoDb = NULLP;
548 PendingSubsRspInfo *pendingSubsRsp = NULLP;
550 /* Fetch RAN Function and Subscription DB using subscription Id received in statistics response */
551 if(fetchSubsInfoFromSubsId(statsRsp->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK)
553 DU_LOG("\nERROR --> DU_APP : DuProcMacStatsRsp: Failed to fetch subscriprtion details");
557 /* Fetch pre-stored statistics response info by DU APP */
558 for(idx=0; idx<ranFuncDb->numPendingSubsRsp; idx++)
560 if((ranFuncDb->pendingSubsRspInfo[idx].requestId.requestorId == ricSubscriptionInfo->requestId.requestorId) &&
561 (ricSubscriptionInfo->requestId.instanceId == ricSubscriptionInfo->requestId.instanceId))
563 pendingSubsRsp = &ranFuncDb->pendingSubsRspInfo[idx];
568 /* If no action is accepted
569 * a. Remove subcription entry from RAN Function
570 * b. Send RIC subscription failure */
571 if(statsRsp->numGrpAccepted == 0)
573 rejectAllStatsGroup(ranFuncDb, ricSubscriptionNode, statsRsp);
577 /* If even 1 action is accepted :
579 * For accepted groups:
580 * Mark subscribed-action's -> action = CONFIG_UNKNOWN
581 * Add to accepted-action-list of subscription response
583 for(idx=0; idx<statsRsp->numGrpAccepted; idx++)
585 actionInfoDb = NULLP;
587 actionId = statsRsp->statsGrpAcceptedList[idx];
588 actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo);
589 if(actionInfoDb && (actionInfoDb->action == CONFIG_ADD))
591 actionInfoDb->action = CONFIG_UNKNOWN;
592 pendingSubsRsp->acceptedActionList[pendingSubsRsp->numOfAcceptedActions++] = actionId;
596 /* For rejected groups:
597 * Remove entry from DU's RAN Function->subscription->actionList
598 * Add to rejected-action-list in subscription response
600 for(idx=0; idx<statsRsp->numGrpRejected; idx++)
602 actionId = statsRsp->statsGrpRejectedList[idx].groupId;
603 if(ricSubscriptionInfo->actionSequence[actionId-1].id == actionId)
605 memset(&ricSubscriptionInfo->actionSequence[actionId-1], 0, sizeof(ActionInfo));
606 ricSubscriptionInfo->numOfActions--;
608 pendingSubsRsp->rejectedActionList[pendingSubsRsp->numOfRejectedActions].id = actionId;
609 convertDuCauseToE2Cause(statsRsp->statsGrpRejectedList[idx].cause, \
610 &pendingSubsRsp->rejectedActionList[pendingSubsRsp->numOfRejectedActions].failureCause);
611 pendingSubsRsp->numOfRejectedActions++;
615 /* Send subscription response with accepted and rejected action lists to RIC */
616 BuildAndSendRicSubscriptionRsp(pendingSubsRsp);
618 memset(pendingSubsRsp, 0, sizeof(PendingSubsRspInfo));
621 /*******************************************************************
623 * @brief Extract and store statistics received from DU layers
627 * Function : e2ProcStatsInd
629 * Functionality: Extract statistics received from DU layers
630 * and store in respective RAN function's subscription's
633 * @params[in] Statistics Indication message received from MAC
636 * ****************************************************************/
637 void e2ProcStatsInd(MacStatsInd *statsInd)
639 RanFunction *ranFuncDb = NULLP;
640 CmLList *ricSubscriptionNode = NULLP;
641 RicSubscription *ricSubscriptionInfo = NULLP;
643 /* TODO : When stats indication is received
644 * DU APP searches for the message type in E2AP RIC subscription
645 * database and stores in the value in the list of subscribed measurements
647 * This will be implemented in next gerrit.
650 /* Fetch RAN Function and Subscription DB using subscription Id received
651 * in statistics response */
652 if(fetchSubsInfoFromSubsId(statsInd->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK)
654 DU_LOG("\nERROR --> DU_APP : extractStatsMeasurement: Failed to fetch subscriprtion details");
659 /******************************************************************
661 * @brief Search E2 node component with the help of action type
665 * Function : fetchE2NodeComponentInfo
667 * Functionality: Search E2 node component with the help of action type
671 * Component action type
672 * Pointer to E2 component node to be searched
675 * ****************************************************************/
677 E2NodeComponent *fetchE2NodeComponentInfo(InterfaceType interfaceType, uint8_t componentActionType, CmLList **e2ComponentNode)
679 E2NodeComponent *e2NodeComponentInfo=NULLP;
681 if(duCb.e2apDb.e2NodeComponentList.count)
683 CM_LLIST_FIRST_NODE(&duCb.e2apDb.e2NodeComponentList, *e2ComponentNode);
684 while(*e2ComponentNode)
686 e2NodeComponentInfo = (E2NodeComponent*)((*e2ComponentNode)->node);
687 if((e2NodeComponentInfo->interfaceType == interfaceType) && (e2NodeComponentInfo->componentActionType == componentActionType))
693 *e2ComponentNode = (*e2ComponentNode)->next;
694 e2NodeComponentInfo = NULLP;
697 return e2NodeComponentInfo;
700 /*******************************************************************
702 * @brief add or modify E2NodeComponent list
706 * Function : addOrModifyE2NodeComponent
708 * Functionality: add or modify E2NodeComponent list
712 * Component action type
713 * boolean variable to check req or rsp msg type
714 * Size of buffer which needs to be store
715 * buffer string which needs to be store
716 * @return ROK - success
719 ******************************************************************/
721 uint8_t addOrModifyE2NodeComponent(InterfaceType interfaceType, uint8_t action, bool reqPart, uint8_t bufSize, char *bufString)
723 E2NodeComponent *e2NodeComponentInfo= NULL;
724 CmLList *node = NULLP;
728 DU_ALLOC(e2NodeComponentInfo, sizeof(E2NodeComponent));
729 if(!e2NodeComponentInfo)
731 DU_LOG("\nERROR --> E2AP : Memory allocation failed for e2NodeComponentInfo in %s",__func__);
734 e2NodeComponentInfo->interfaceType =interfaceType;
735 e2NodeComponentInfo->componentId=duCfgParam.duId;
736 e2NodeComponentInfo->componentActionType = action;
737 e2NodeComponentInfo->reqBufSize = bufSize;
739 DU_ALLOC(e2NodeComponentInfo->componentRequestPart, bufSize);
740 if(e2NodeComponentInfo->componentRequestPart == NULLP)
742 DU_LOG("\nERROR --> E2AP : Memory allocation failed for componentRequestPart");
743 DU_FREE(e2NodeComponentInfo, sizeof(E2NodeComponent));
746 memcpy(e2NodeComponentInfo->componentRequestPart, bufString, e2NodeComponentInfo->reqBufSize);
747 DU_ALLOC(node, sizeof(CmLList));
750 node->node = (PTR) e2NodeComponentInfo;
751 cmLListAdd2Tail(&duCb.e2apDb.e2NodeComponentList, node);
755 DU_LOG("\nERROR --> E2AP : Memory allocation failed for e2NodeComponentList node");
756 DU_FREE(e2NodeComponentInfo->componentRequestPart, bufSize);
757 DU_FREE(e2NodeComponentInfo, sizeof(E2NodeComponent));
763 if(duCb.e2apDb.e2NodeComponentList.count)
765 e2NodeComponentInfo = fetchE2NodeComponentInfo(interfaceType, action, &node);
766 if(e2NodeComponentInfo->componentRequestPart== NULLP)
768 DU_LOG("\nERROR --> E2AP : E2 node Component request part is not present");
772 e2NodeComponentInfo->rspBufSize = bufSize;
773 DU_ALLOC(e2NodeComponentInfo->componentResponsePart, bufSize);
774 if(e2NodeComponentInfo->componentResponsePart == NULLP)
776 DU_LOG("\nERROR --> E2AP : Memory allocation failed to store the encoding of rsp");
779 memcpy(e2NodeComponentInfo->componentResponsePart, bufString, e2NodeComponentInfo->rspBufSize);
784 DU_LOG("\nERROR --> E2AP : Unable to find the node");
791 /**********************************************************************
793 **********************************************************************/