[Epic-ID: ODUHIGH-516][Task-ID: ODUHIGH-529] RIC Indication
[o-du/l2.git] / src / du_app / du_e2ap_mgr.c
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2017-2019] [Radisys]                                        #
4 #                                                                              #
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                                    #
8 #                                                                              #
9 #       http://www.apache.org/licenses/LICENSE-2.0                             #
10 #                                                                              #
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"
19 #include <sys/time.h>
20 #include "du_tmr.h"
21 #include "lrg.h"
22 #include "lkw.x"
23 #include "lrg.x"
24 #include "legtp.h"
25 #include "du_app_mac_inf.h"
26 #include "du_app_rlc_inf.h"
27 #include "du_e2ap_mgr.h"
28 #include "du_e2_conversions.h"
29 #include "du_e2ap_msg_hdl.h"
30 #include "du_cfg.h"
31 #include "du_sctp.h"
32 #include "du_mgr.h"
33 #include "du_mgr_main.h"
34 #include "du_utils.h"
35
36 /*******************************************************************
37  *
38  * @brief Assigns new transaction id to DU initiated procedure
39  *
40  * @details
41  *
42  *    Function : assignTransactionId
43  *
44  *    Functionality: Assigns new transaction id to a DU initiated
45  *       procedure
46  *
47  * @params[in] Region region
48  *             Pool pool
49  * @return ROK     - success
50  *         RFAILED - failure
51  *
52  * ****************************************************************/
53 uint8_t assignTransactionId()
54 {
55    uint8_t currTransId = duCb.e2apDb.e2TransInfo.transIdCounter;
56
57    /* Update to next valid value */
58    duCb.e2apDb.e2TransInfo.transIdCounter++;
59    if(duCb.e2apDb.e2TransInfo.transIdCounter == MAX_NUM_TRANSACTION)
60       duCb.e2apDb.e2TransInfo.transIdCounter = 0;
61
62    return currTransId;
63 }
64
65 /*******************************************************************
66  *
67  * @brief Decode subscription ID
68  *
69  * @details
70  *
71  *    Function : decodeSubscriptionId
72  *
73  *    Functionality: Decode subscription id to get RAN function ID
74  *      and RIC Request ID
75  *
76  * @params[in] Subscription ID
77  *             RAN Function ID to be extracted
78  *             RIC Request ID to be extracted
79  * @return Void
80  *
81  * ****************************************************************/
82 void decodeSubscriptionId(uint64_t subscriptionId, uint16_t *ranFuncId, RicRequestId *ricReqId)
83 {
84    /* Extract following from 64 bit subscription-ID :
85     *  First 16 MSB is unused
86     *  Next 16 MSB = RAN-Function-ID
87     *  Next 16 MSB = Requestor-ID in RIC-Request-ID
88     *  Last 16 LSB = Instance-ID in RIC-Request-ID
89     */
90    ricReqId->instanceId = subscriptionId & 0xFFFF;
91    ricReqId->requestorId = (subscriptionId >> 16) & 0xFFFF;
92    *ranFuncId = (subscriptionId >> 32) & 0xFFFF;
93 }
94
95 /*******************************************************************
96  *
97  * @brief Encode subscription ID
98  *
99  * @details
100  *
101  *    Function : encodeSubscriptionId
102  *
103  *    Functionality: Encode subscription id to get RAN function ID
104  *      and RIC Request ID
105  *
106  * @params[in] Subscription ID to be encoded
107  *             RAN Function ID 
108  *             RIC Request ID
109  * @return Void
110  *
111  * ****************************************************************/
112 void encodeSubscriptionId(uint64_t *subscriptionId, uint16_t ranFuncId, RicRequestId ricReqId)
113 {
114    /* Calculate 64 bit subscription-ID :
115     *  First 16 MSB is unused
116     *  Next 16 MSB = RAN-Function-ID
117     *  Next 16 MSB = Requestor-ID in RIC-Request-ID
118     *  Last 16 LSB = Instance-ID in RIC-Request-ID
119     */
120    *subscriptionId = ricReqId.instanceId;
121    *subscriptionId |= ((uint64_t)ricReqId.requestorId << 16);
122    *subscriptionId |= ((uint64_t)ranFuncId << 32);
123 }
124
125 /*******************************************************************
126  *
127  * @brief Stores the current time at the start of reporting period
128  *
129  * @details
130  *
131  *    Function : storeReportStartTime
132  *
133  *    Functionality: Stores the current time at the start of 
134  *       reporting period
135  *
136  * @params[in] Start Timer to be stored
137  * @return Void
138  *
139  * ****************************************************************/
140 void storeReportStartTime(ReportStartTime *startTime)
141 {
142    struct timeval tv;
143
144    gettimeofday(&tv, NULL); 
145    startTime->timeInSec = tv.tv_sec;
146    startTime->timeInMilliSec = (tv.tv_usec/1000);
147 }
148
149
150 /*******************************************************************
151  *
152  * @brief Fetch Measurement Info using measurement type name
153  *
154  * @details
155  *
156  *    Function : fetchMeasInfoFromMeasTypeName
157  *
158  *    Functionality: Fetch Measurement Info using measurement type name
159  *
160  * @params[in] Measurement type name to search
161  *             Measurement Info list to search from
162  *             Measurement Info node found from list
163  * @return Measurement Info DB
164  *
165  * ****************************************************************/
166 MeasurementInfo *fetchMeasInfoFromMeasTypeName(char *e2MeasTypeName, CmLListCp *measInfoList, CmLList **measInfoNode)
167 {
168    MeasurementInfo *measInfo = NULLP;
169
170    /* Fetch subscription detail in RAN Function DB */
171    CM_LLIST_FIRST_NODE(measInfoList, *measInfoNode);
172    while(*measInfoNode)
173    {
174       measInfo = (MeasurementInfo *)((*measInfoNode)->node);
175       if(measInfo && !strcmp(e2MeasTypeName, measInfo->measurementTypeName))
176       {
177          break;
178       }
179       *measInfoNode = (*measInfoNode)->next;
180       measInfo = NULLP;
181    }
182
183    if(!measInfo)
184    {
185       DU_LOG("\nERROR  -->  E2AP : fetchMeasInfoFromMeasTypeName: Measurement [%s] not found", e2MeasTypeName);
186    }
187
188    return measInfo;
189 }
190
191 /*******************************************************************
192  *
193  * @brief Fetch Action details
194  *
195  * @details
196  *
197  *    Function : fetchActionInfoFromActionId
198  *
199  *    Functionality: Fetch action details from RIC subscription DB
200  *       using action ID
201  *
202  * @params[in] Action ID 
203  *             RIC Subscription DB
204  * @return Action Info DB
205  *         NULL, in case of failure
206  *
207  * ****************************************************************/
208 ActionInfo *fetchActionInfoFromActionId(uint8_t actionId, RicSubscription *ricSubscriptionInfo)
209 {
210    ActionInfo *actionInfoDb = NULLP;
211    if(ricSubscriptionInfo->actionSequence[actionId].actionId == actionId)
212    {
213       actionInfoDb = &ricSubscriptionInfo->actionSequence[actionId];
214    }
215    else
216    {
217       DU_LOG("\nERROR  -->  E2AP : fetchActionInfoFromActionId: Action Id [%d] not found in \
218          subscription info [Requestor id : %d] [Instance Id : %d]", actionId,\
219          ricSubscriptionInfo->requestId.requestorId, ricSubscriptionInfo->requestId.instanceId);
220
221    }
222    return actionInfoDb;
223 }
224
225 /*******************************************************************
226  *
227  * @brief Fetch subscripton DB 
228  *
229  * @details
230  *
231  *    Function : fetchSubsInfoFromRicReqId
232  *
233  *    Functionality: Fetches subscription DB from RAN Function DB
234  *       using RIC Request ID
235  *
236  * @params[in] RIC Request ID 
237  *             RAN Function DB
238  *             Pointer to RIC Subscription node to be searched
239  * @return RIC Subscription from RAN Function's subcription list
240  *         NULL, in case of failure
241  *
242  * ****************************************************************/
243 RicSubscription *fetchSubsInfoFromRicReqId(RicRequestId ricReqId, RanFunction *ranFuncDb, CmLList **ricSubscriptionNode)
244 {
245    RicSubscription *ricSubscriptionInfo = NULLP;
246
247    /* Fetch subscription detail in RAN Function DB */
248    CM_LLIST_FIRST_NODE(&ranFuncDb->subscriptionList, *ricSubscriptionNode);
249    while(*ricSubscriptionNode)
250    {
251       ricSubscriptionInfo = (RicSubscription *)((*ricSubscriptionNode)->node);
252       if(ricSubscriptionInfo && (ricSubscriptionInfo->requestId.requestorId == ricReqId.requestorId) &&
253             (ricSubscriptionInfo->requestId.instanceId == ricReqId.instanceId))
254       {
255          break;
256       }
257       *ricSubscriptionNode = (*ricSubscriptionNode)->next;
258       ricSubscriptionInfo = NULLP;
259    }
260
261    if(!ricSubscriptionInfo)
262    {
263       DU_LOG("\nERROR  -->  E2AP : fetchSubsInfoFromRicReqId: Subscription not found for Requestor ID [%d] \
264          Instance ID [%d] in RAN Function ID [%d]", ricReqId.requestorId, ricReqId.instanceId, ranFuncDb->id);
265    }
266
267    return ricSubscriptionInfo;
268 }
269
270 /*******************************************************************
271  *
272  * @brief Fetches RAN Function DB
273  *
274  * @details
275  *
276  *    Function : fetchRanFuncFromRanFuncId
277  *
278  *    Functionality: Fetches RAN function DB from E2AP DB using
279  *       RAN function ID 
280  *
281  * @params[in] RAN Function ID
282  * @return RAN Function DB
283  *         NULL, in case of failure
284  *
285  * ****************************************************************/
286 RanFunction *fetchRanFuncFromRanFuncId(uint16_t ranFuncId)
287 {
288    RanFunction *ranFuncDb = NULLP;
289
290    /* Fetch RAN Function DB */
291    if(duCb.e2apDb.ranFunction[ranFuncId-1].id == ranFuncId)
292    {
293       ranFuncDb = &duCb.e2apDb.ranFunction[ranFuncId-1];
294    }
295    else
296    {
297       DU_LOG("\nERROR  -->  E2AP : fetchRanFuncFromRanFuncId: Invalid RAN Function ID[%d]", ranFuncId);
298    }
299
300    return ranFuncDb;
301 }
302
303 /*******************************************************************
304  *
305  * @brief Fetches subscription info
306  *
307  * @details
308  *
309  *    Function : fetchSubsInfoFromSubsId
310  *
311  *    Functionality: 
312  *       1. Firstly, RAN Function ID and RIC request ID is extracted
313  *          from Subscription ID 
314  *       2. Using RAN Function ID, RAN Function DB is searched
315  *       3. Using RIC Request ID, the subscription DB is searched in
316  *          RAN Function DB
317  *
318  * @params[in] Subscription ID
319  *             RAN Function DB
320  *             RIC Subscription node from RAN Func's Subscription list
321  * @return ROK
322  *         RFAILED
323  *
324  * ****************************************************************/
325 uint8_t fetchSubsInfoFromSubsId(uint64_t subscriptionId, RanFunction **ranFuncDb, CmLList **ricSubscriptionNode, \
326    RicSubscription **ricSubscriptionInfo)
327 {
328    uint16_t ranFuncId = 0;
329    RicRequestId ricReqId;
330
331    memset(&ricReqId, 0, sizeof(RicRequestId));
332
333    /* Decode subscription ID o get RIC Request ID and RAN Function ID */
334    decodeSubscriptionId(subscriptionId, &ranFuncId, &ricReqId);
335
336    /* Fetch RAN Function DB using RAN Function ID */
337    *ranFuncDb = fetchRanFuncFromRanFuncId(ranFuncId);
338    if((*ranFuncDb) == NULLP)
339    {
340       return RFAILED;
341    }
342
343    /* Fetch Sunscription DB from RAN Function using RIC Request ID */
344    *ricSubscriptionInfo = fetchSubsInfoFromRicReqId(ricReqId, *ranFuncDb, ricSubscriptionNode);
345    if((*ricSubscriptionInfo) == NULLP)
346    {
347       return RFAILED;
348    }
349
350    return ROK;
351 }
352
353 /*******************************************************************
354  *
355  * @brief Sends E2 msg over SCTP
356  *
357  * @details
358  *
359  *    Function : SendE2APMsg
360  *
361  *    Functionality: Sends E2 msg over SCTP
362  *
363  * @params[in] Region region
364  *             Pool pool
365  * @return ROK     - success
366  *         RFAILED - failure
367  *
368  * ****************************************************************/
369
370 uint8_t SendE2APMsg(Region region, Pool pool, char *encBuf, int encBufSize)
371 {
372    Buffer *mBuf=NULLP;
373
374    if(ODU_GET_MSG_BUF(region, pool, &mBuf) == ROK)
375    {
376       if(ODU_ADD_POST_MSG_MULT((Data *)encBuf, encBufSize, mBuf) == ROK)
377       {
378          ODU_PRINT_MSG(mBuf, 0,0);
379
380          if(sctpSend(mBuf, E2_INTERFACE) != ROK)
381          {
382             DU_LOG("\nERROR  -->  E2AP : SCTP Send for E2  failed");
383             ODU_PUT_MSG_BUF(mBuf);
384             return RFAILED;
385          }
386       }
387       else
388       {
389          DU_LOG("\nERROR  -->  E2AP : ODU_ADD_POST_MSG_MULT failed");
390          ODU_PUT_MSG_BUF(mBuf);
391          return RFAILED;
392       }
393       ODU_PUT_MSG_BUF(mBuf);
394    }
395    else
396    {
397       DU_LOG("\nERROR  -->  E2AP : Failed to allocate memory");
398       return RFAILED;
399    }
400
401    return ROK;
402 } /* SendE2APMsg */
403
404 /*******************************************************************
405  *
406  * @brief Resets E2 
407  *
408  * @details
409  *
410  *    Function : ResetE2Request
411  *
412  *    Functionality: This function resets E2.
413  *       As per ORAN WG3 E2GAP v3.0 Spec, section 5.5.3
414  *       If E2 node initates reset procedure then:
415  *        a. Send reset request to RIC
416  *        b. Delete any pre-established RIC subscriptions
417  *        c. Gracefully terminates any ongoing RIC services
418  *       If RIC initiates reset procedure then :
419  *        a. Delete any pre-established RIC subscriptions
420  *        b. Gracefully terminates any ongoing RIC services
421  *        c. Send reset response to RIC
422  *
423  * @params[in]
424  * @return ROK     - success
425  *         RFAILED - failure
426  *
427  * ****************************************************************/
428 uint8_t ResetE2Request(E2ProcedureDirection dir, E2FailureCause resetCause)
429 {
430    /* Send Reset Request to RIC if DU detects any abnormal failure */
431    if(dir == E2_NODE_INITIATED)
432    {
433       if(BuildAndSendE2ResetRequest(resetCause) != ROK)
434       {
435          DU_LOG("\nERROR  -->  E2AP : BuildAndSendE2ResetRequest failed");
436          return RFAILED;
437       }
438    }
439
440    /* TODO when RIC subscription service model is implemented
441       Process following steps of resetting E2
442       1. Deletes any pre-established RIC subscriptions
443       2. Gracefully terminates any ongoing RIC services
444     */
445
446    /* Send Reset Response if RIC initiated Reset request is received at DU */
447    if(dir == RIC_INITIATED)
448    {
449       //BuildAndSendE2ResetResponse();
450    }   
451    return ROK;
452 }
453
454 /*******************************************************************
455  *
456  * @brief Fill RIC Subscription datils in MAC Statistics Request
457  *
458  * @details
459  *
460  *    Function : fillRicSubsInMacStatsReq
461  *
462  *    Functionality: Fill RIC Subscription datils in MAC Statistics 
463  *       Request
464  *
465  * @params[in] MAC Statistics Request to be filled
466  *             RIC Subscription Info
467  *
468  * @return ROK     - success
469  *         RFAILED - failure
470  *
471  * ****************************************************************/
472 uint8_t fillRicSubsInMacStatsReq(MacStatsReq *macStatsReq, RicSubscription* ricSubscriptionInfo)
473 {
474    uint8_t    actionIdx = 0, grpIdx = 0, statsIdx = 0;
475    uint64_t   subscriptionId = 0;
476    ActionInfo *actionDb = NULLP;
477    ActionDefFormat1 *format1Action = NULLP;
478
479    /* Generate subscription ID using RIC Request ID and RAN Function ID */
480    encodeSubscriptionId(&subscriptionId, ricSubscriptionInfo->ranFuncId, ricSubscriptionInfo->requestId);
481
482    macStatsReq->subscriptionId = subscriptionId;
483    for(actionIdx = 0; actionIdx < MAX_RIC_ACTION; actionIdx++)
484    {
485       if(ricSubscriptionInfo->actionSequence[actionIdx].action == CONFIG_ADD)
486       {
487          actionDb = &ricSubscriptionInfo->actionSequence[actionIdx];
488          macStatsReq->statsGrpList[grpIdx].groupId = actionDb->actionId;
489          switch(actionDb->definition.formatType)
490          {
491             case 1:
492                {
493                   format1Action = &actionDb->definition.choice.format1;
494                   macStatsReq->statsGrpList[grpIdx].periodicity = format1Action->granularityPeriod;
495
496                   CmLList *node = NULLP;
497                   MeasurementInfo *measInfo = NULLP;
498                   statsIdx = 0;
499                   /* Update DL PRB Usage for all stats group which requested for DL Total PRB Usage */
500                   node = cmLListFirst(&format1Action->measurementInfoList);
501                   while(node)
502                   {
503                      measInfo = (MeasurementInfo *)(node->node);
504                      switch(measInfo->measurementTypeId)
505                      {
506                         case 1:
507                            {
508                               macStatsReq->statsGrpList[grpIdx].statsList[statsIdx++] = MAC_DL_TOTAL_PRB_USAGE;
509                               break;
510                            }
511                         case 2:
512                            {
513                               macStatsReq->statsGrpList[grpIdx].statsList[statsIdx++] = MAC_UL_TOTAL_PRB_USAGE;
514                               break;
515                            }
516                         default:
517                            {
518                               DU_LOG("\nERROR  -->  E2AP : Invalid measurement name");
519                               break;
520                            }
521                      }
522                      node = node->next;
523                   }
524                   macStatsReq->statsGrpList[grpIdx].numStats = statsIdx;
525                   break;
526                }
527             default:
528                {
529                   DU_LOG("\nERROR  -->  E2AP : fillRicSubsInMacStatsReq: Only Action Definition Format 1 supported");
530                   break;
531                }
532          }
533          if(macStatsReq->statsGrpList[grpIdx].numStats)
534             grpIdx++;
535       }
536    }
537
538    macStatsReq->numStatsGroup = grpIdx;
539    if(macStatsReq->numStatsGroup)
540    {
541       return ROK;
542    }
543    return RFAILED;
544 }
545
546 /*******************************************************************
547  *
548  * @brief Rejects all actions received in a subscription request
549  *
550  * @details
551  *
552  *    Function : duRejectAllStatsGroup
553  *
554  *    Functionality: Rejects all actions received in a subscription
555  *       request by :
556  *       a. Removing the subscription entry from RAN function
557  *       b. Sending RIC Subscription Failure to RIC with appropriate
558  *          cause of failure
559  *
560  * @params[in] RAN Function DB
561  *             Subscription entry in RAN Function subscription list
562  *             Statistics Response from MAC
563  *
564  * @return ROK     - success
565  *         RFAILED - failure
566  *
567  * ****************************************************************/
568 uint8_t rejectAllStatsGroup(RanFunction *ranFuncDb, CmLList *ricSubscriptionNode, MacStatsRsp *statsRsp)
569 {
570    uint8_t ret = ROK;
571    RicRequestId  requestId;
572    E2FailureCause failureCause;
573
574    /* Delete subcription from RAN Function */
575    memcpy(&requestId, &((RicSubscription *)ricSubscriptionNode->node)->requestId, sizeof(RicRequestId));
576    cmLListDelFrm(&ranFuncDb->subscriptionList, ricSubscriptionNode);
577    DU_FREE(ricSubscriptionNode->node, sizeof(RicSubscription));
578    DU_FREE(ricSubscriptionNode, sizeof(CmLList));
579
580    convertDuCauseToE2Cause(statsRsp->statsGrpRejectedList[0].cause, &failureCause);
581
582    /* Send RIC subscription failure to RIC */
583    ret = BuildAndSendRicSubscriptionFailure(requestId, ranFuncDb->id, failureCause);
584    return ret;
585 }
586
587 /*******************************************************************
588  *
589  * @brief Process statistics response from MAC
590  *
591  * @details
592  *
593  *    Function : e2ProcStatsRsp
594  *
595  *    Functionality: Processes statistics configuration response
596  *       from MAC. If configuration is succsessful, DUAPP starts
597  *       reporting period timer for this subscription request
598  *       from RIC
599  *
600  * @params[in] Statistics response received from MAC
601  *
602  * @return ROK     - success
603  *         RFAILED - failure
604  *
605  * ****************************************************************/
606 uint8_t e2ProcStatsRsp(MacStatsRsp *statsRsp)
607 {
608    uint8_t idx = 0;
609    uint8_t actionId = 0;
610    uint32_t reportingPeriod = 0;
611    RanFunction *ranFuncDb = NULLP;
612    CmLList *ricSubscriptionNode = NULLP;
613    RicSubscription *ricSubscriptionInfo = NULLP;
614    ActionInfo *actionInfoDb = NULLP;
615    PendingSubsRspInfo *pendingSubsRsp = NULLP;
616
617    /* Fetch RAN Function and Subscription DB using subscription Id received in statistics response */
618    if(fetchSubsInfoFromSubsId(statsRsp->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK)
619    {
620       DU_LOG("\nERROR  -->  E2AP : DuProcMacStatsRsp: Failed to fetch subscriprtion details");
621       return RFAILED;
622    }
623
624    /* Fetch pre-stored statistics response info by DU APP */
625    for(idx=0; idx<ranFuncDb->numPendingSubsRsp; idx++)
626    {
627       if((ranFuncDb->pendingSubsRspInfo[idx].requestId.requestorId == ricSubscriptionInfo->requestId.requestorId) &&
628             (ricSubscriptionInfo->requestId.instanceId == ricSubscriptionInfo->requestId.instanceId))
629       {
630          pendingSubsRsp = &ranFuncDb->pendingSubsRspInfo[idx];
631          break;
632       }
633    }
634
635    /* If no action is accepted
636     *  a. Remove subcription entry from RAN Function
637     *  b. Send RIC subscription failure */
638    if(statsRsp->numGrpAccepted == 0)
639    {
640       rejectAllStatsGroup(ranFuncDb, ricSubscriptionNode, statsRsp);
641    }
642    else
643    {
644       /* Start RIC Subscription reporting timer */
645       switch(ricSubscriptionInfo->eventTriggerDefinition.formatType)
646       {
647          case 1:
648             {
649                reportingPeriod = ricSubscriptionInfo->eventTriggerDefinition.choice.format1.reportingPeriod;
650
651                /* Save the start time of reporting period */
652                storeReportStartTime(&ricSubscriptionInfo->eventTriggerDefinition.choice.format1.startTime);
653                break;
654             }
655          default:
656          {
657             DU_LOG("\nERROR  -->  E2AP : Invalid event trigger format of RIC subscription");
658             return RFAILED;
659          }
660       }
661       if(duChkTmr((PTR)ricSubscriptionInfo, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR) != true)
662       {
663          duStartTmr((PTR)ricSubscriptionInfo, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR, reportingPeriod);
664       }
665       else
666       {
667          DU_LOG("\nERROR  -->  E2AP : RIC Subscription reporting timer already running for RIC Subscription");  
668          return RFAILED;
669       }
670
671
672       /* If even 1 action is accepted :
673        *
674        * For accepted groups:
675        *    Mark subscribed-action's -> action = CONFIG_UNKNOWN
676        *    Add to accepted-action-list of subscription response
677        */
678       for(idx=0; idx<statsRsp->numGrpAccepted; idx++)
679       {
680          actionInfoDb = NULLP;
681
682          actionId = statsRsp->statsGrpAcceptedList[idx];
683          actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo);
684          if(actionInfoDb && (actionInfoDb->action == CONFIG_ADD))
685          {
686             actionInfoDb->action = CONFIG_UNKNOWN;
687             pendingSubsRsp->acceptedActionList[pendingSubsRsp->numOfAcceptedActions++] = actionId;
688          }
689       }
690
691       /* For rejected groups:
692        *    Remove entry from DU's RAN Function->subscription->actionList
693        *    Add to rejected-action-list in subscription response
694        */
695       for(idx=0; idx<statsRsp->numGrpRejected; idx++)
696       {
697          actionId = statsRsp->statsGrpRejectedList[idx].groupId;
698          if(ricSubscriptionInfo->actionSequence[actionId].actionId == actionId)
699          {
700             memset(&ricSubscriptionInfo->actionSequence[actionId], 0, sizeof(ActionInfo));
701             ricSubscriptionInfo->numOfActions--;
702
703             pendingSubsRsp->rejectedActionList[pendingSubsRsp->numOfRejectedActions].id = actionId;
704             convertDuCauseToE2Cause(statsRsp->statsGrpRejectedList[idx].cause, \
705                   &pendingSubsRsp->rejectedActionList[pendingSubsRsp->numOfRejectedActions].failureCause);
706             pendingSubsRsp->numOfRejectedActions++;
707          }
708       }
709
710       /* Send subscription response with accepted and rejected action lists to RIC */
711       BuildAndSendRicSubscriptionRsp(pendingSubsRsp);
712    }
713    memset(pendingSubsRsp, 0, sizeof(PendingSubsRspInfo));
714    return ROK;
715 }
716
717 /*******************************************************************
718  *
719  * @brief Extract and store statistics received from DU layers
720  *
721  * @details
722  *
723  *    Function : e2ProcStatsInd
724  *
725  *    Functionality: Extract statistics received from DU layers
726  *       and store in respective RAN function's subscription's
727  *       action
728  *
729  * @params[in] Statistics Indication message received from MAC
730  * @return ROK-success
731  *         RFAILED-failure
732  *
733  * ****************************************************************/
734 uint8_t e2ProcStatsInd(MacStatsInd *statsInd)
735 {
736    uint8_t statsIdx = 0;
737    RanFunction *ranFuncDb = NULLP;
738    CmLList *ricSubscriptionNode = NULLP;
739    RicSubscription *ricSubscriptionInfo = NULLP;
740    ActionInfo *actionInfo = NULLP;
741    ActionDefFormat1 *actionFormat = NULLP;
742    char e2MeasTypeName[STRING_SIZE_150_BYTES] = "";
743    MeasurementInfo *measInfo = NULLP;
744    CmLList *measInfoNode = NULLP;
745    double *measValue = NULLP;
746    CmLList *measValueNode = NULLP;
747
748    /* TODO : When stats indication is received
749     * DU APP searches for the message type in E2AP RIC subscription
750     * database and stores in the value in the list of subscribed measurements
751     *
752     * This will be implemented in next gerrit.
753     */
754
755    /* Fetch RAN Function and Subscription DB using subscription Id received
756     * in statistics response */
757    if(fetchSubsInfoFromSubsId(statsInd->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK)
758    {
759       DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Failed to fetch subscriprtion details");
760       return RFAILED;
761    }
762
763    /* Fetch RIC subscription's action DB */
764    actionInfo = fetchActionInfoFromActionId(statsInd->groupId, ricSubscriptionInfo);
765    if(actionInfo == NULLP)
766    {
767       DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Failed to fetch action ID [%d]", statsInd->groupId);
768       return RFAILED;
769    }
770
771    /* Check Action format */
772    switch(actionInfo->definition.formatType)
773    {
774       case 1:
775          {
776             actionFormat = &actionInfo->definition.choice.format1;
777             break;
778          }
779       default:
780          {
781             DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Action Format [%d] is not supported", \
782                   actionInfo->definition.formatType);
783             return RFAILED;
784          }
785    }
786
787    /* Fetch each Measurement info from action info and store its reported value in DB */
788    for(statsIdx = 0; statsIdx < statsInd->numStats; statsIdx++)
789    {
790       memset(e2MeasTypeName, 0, STRING_SIZE_150_BYTES);
791       measInfo = NULLP;
792       measInfoNode = NULLP;
793
794       /* Convert Measurement type from MAC-supported format to E2-supported format */
795       if(convertMacMeasTypeToE2MeasType(statsInd->measuredStatsList[statsIdx].type, e2MeasTypeName) != ROK)
796       {
797          DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Failed to convert measurement type from MAC-supported\
798             MAC-supported format to E2-supported format");
799          continue;
800       }
801       
802       /* Fetch Measurement Info using E2-supported measurement type name */
803       measInfo = fetchMeasInfoFromMeasTypeName(e2MeasTypeName, &actionFormat->measurementInfoList, &measInfoNode); 
804       if(measInfo == NULLP)
805       {
806          DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Measurement Type Name [%s] not found", e2MeasTypeName); 
807          continue;
808       }
809       
810       /* Store the measurement value in the measurement info DB fetched */
811       DU_ALLOC(measValue, sizeof(double));
812       if(!measValue)
813       {
814          DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Memory allocation failed at line [%d]", __LINE__);
815          return RFAILED; 
816       }
817       *measValue = statsInd->measuredStatsList[statsIdx].value;
818
819       DU_ALLOC(measValueNode, sizeof(CmLList));
820       if(!measValueNode)
821       {
822          DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Memory allocation failed at line [%d]", __LINE__);
823          DU_FREE(measValue, sizeof(double));
824          return RFAILED; 
825       }
826       measValueNode->node = (PTR) measValue;
827       cmLListAdd2Tail(&measInfo->measuredValue, measValueNode);
828    }
829    return ROK;
830 }
831
832 /*******************************************************************
833  *
834  * @brief Handle RIC Subscription reporting timer expry
835  *
836  * @details
837  *
838  *    Function : E2apHdlRicSubsReportTmrExp
839  *
840  *    Functionality: On expiry of RIC subscription reporting
841  *       timer expiry, RIC indication is sent for all actions
842  *       in RIC subscription
843  *
844  * @params[in] RIC subscription DB
845  * @return void
846  *
847  * ****************************************************************/
848 void E2apHdlRicSubsReportTmrExp(RicSubscription *ricSubscription)
849 {
850    uint8_t actionIdx = 0;
851    uint32_t reportingPeriod = 0;
852
853    for(actionIdx = 0; actionIdx < MAX_RIC_ACTION; actionIdx++)
854    {
855       if(ricSubscription->actionSequence[actionIdx].actionId >= 0)
856       {
857          BuildAndSendRicIndication(ricSubscription, &ricSubscription->actionSequence[actionIdx]);  
858       }
859    }
860
861    /* Start RIC Subscription reporting timer again */
862    switch(ricSubscription->eventTriggerDefinition.formatType)
863    {
864       case 1:
865          {
866             reportingPeriod = ricSubscription->eventTriggerDefinition.choice.format1.reportingPeriod;
867             /* Save the start time of reporting period */
868             storeReportStartTime(&ricSubscription->eventTriggerDefinition.choice.format1.startTime);
869             break;
870          }
871       default:
872          return;
873    }
874    if(duChkTmr((PTR)ricSubscription, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR) != true)
875    {
876       duStartTmr((PTR)ricSubscription, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR, reportingPeriod);
877    }
878    else
879    {
880       DU_LOG("\nERROR  -->  E2AP : Failed in %s at line %d", __func__, __LINE__);
881       return;
882    }
883 }
884
885 /******************************************************************
886  *
887  * @brief Search E2 node component with the help of action type
888  *
889  * @details
890  *
891  *    Function : fetchE2NodeComponentInfo 
892  *
893  *    Functionality: Search E2 node component with the help of action type 
894  *
895  * @params[in] 
896  *       Type of interface 
897  *       Component action type
898  *       Pointer to E2 component node to be searched 
899  * @return CmLList
900  *
901  * ****************************************************************/
902
903 E2NodeComponent *fetchE2NodeComponentInfo(InterfaceType interfaceType, uint8_t componentActionType, CmLList **e2ComponentNode)
904 {
905    E2NodeComponent *e2NodeComponentInfo=NULLP;
906
907    if(duCb.e2apDb.e2NodeComponentList.count)
908    {
909       CM_LLIST_FIRST_NODE(&duCb.e2apDb.e2NodeComponentList, *e2ComponentNode);
910       while(*e2ComponentNode)
911       {
912          e2NodeComponentInfo = (E2NodeComponent*)((*e2ComponentNode)->node);
913          if((e2NodeComponentInfo->interfaceType == interfaceType) && (e2NodeComponentInfo->componentActionType == componentActionType))
914          {
915             
916             break;
917          }
918          
919          *e2ComponentNode = (*e2ComponentNode)->next;
920          e2NodeComponentInfo = NULLP;
921       }
922    }
923    return e2NodeComponentInfo; 
924 }
925
926 /*******************************************************************
927  *
928  * @brief add or modify E2NodeComponent list
929  *
930  * @details
931  *
932  *    Function : addOrModifyE2NodeComponent 
933  *
934  * Functionality: add or modify E2NodeComponent list 
935  *
936  * @parameter
937  *       Type of interface 
938  *       Component action type
939  *       boolean variable to check req or rsp msg type
940  *       Size of buffer which needs to be store
941  *       buffer string which needs to be store 
942  * @return ROK     - success
943  *         RFAILED - failure
944  *
945  ******************************************************************/
946
947 uint8_t addOrModifyE2NodeComponent(InterfaceType interfaceType, uint8_t action, bool reqPart, uint8_t bufSize, char *bufString)
948 {
949    E2NodeComponent *e2NodeComponentInfo= NULL;
950    CmLList  *node = NULLP;
951    
952    if(reqPart == true)
953    {
954       DU_ALLOC(e2NodeComponentInfo, sizeof(E2NodeComponent));
955       if(!e2NodeComponentInfo)
956       {
957          DU_LOG("\nERROR  -->  E2AP : Memory allocation failed for e2NodeComponentInfo in %s",__func__);
958          return RFAILED;
959       }
960       e2NodeComponentInfo->interfaceType =interfaceType;
961       e2NodeComponentInfo->componentId=duCfgParam.duId;
962       e2NodeComponentInfo->componentActionType = action;
963       e2NodeComponentInfo->reqBufSize = bufSize;
964
965       DU_ALLOC(e2NodeComponentInfo->componentRequestPart, bufSize);
966       if(e2NodeComponentInfo->componentRequestPart == NULLP)
967       {
968          DU_LOG("\nERROR  -->  E2AP : Memory allocation failed for componentRequestPart");
969          DU_FREE(e2NodeComponentInfo, sizeof(E2NodeComponent));
970          return RFAILED;
971       }
972       memcpy(e2NodeComponentInfo->componentRequestPart, bufString, e2NodeComponentInfo->reqBufSize);
973       DU_ALLOC(node, sizeof(CmLList));
974       if(node)
975       {
976          node->node = (PTR) e2NodeComponentInfo;
977          cmLListAdd2Tail(&duCb.e2apDb.e2NodeComponentList, node);
978       }
979       else
980       {
981          DU_LOG("\nERROR  -->  E2AP : Memory allocation failed for e2NodeComponentList node");
982          DU_FREE(e2NodeComponentInfo->componentRequestPart, bufSize);
983          DU_FREE(e2NodeComponentInfo, sizeof(E2NodeComponent));
984          return RFAILED;
985       }
986    }
987    else
988    {
989       if(duCb.e2apDb.e2NodeComponentList.count)
990       {
991          e2NodeComponentInfo = fetchE2NodeComponentInfo(interfaceType, action, &node);
992          if(e2NodeComponentInfo->componentRequestPart== NULLP)
993          {
994             DU_LOG("\nERROR  -->  E2AP : E2 node Component request part is not present");
995             return RFAILED;
996          }
997          
998          e2NodeComponentInfo->rspBufSize = bufSize;
999          DU_ALLOC(e2NodeComponentInfo->componentResponsePart, bufSize);
1000          if(e2NodeComponentInfo->componentResponsePart == NULLP)
1001          {
1002             DU_LOG("\nERROR  -->  E2AP : Memory allocation failed to store the encoding of rsp");
1003             return RFAILED;
1004          }
1005          memcpy(e2NodeComponentInfo->componentResponsePart, bufString, e2NodeComponentInfo->rspBufSize);
1006          return ROK;
1007       }
1008       else
1009       {
1010          DU_LOG("\nERROR  -->  E2AP : Unable to find the node");
1011          return RFAILED;
1012       }
1013    } 
1014    return ROK;
1015 }
1016
1017 /**********************************************************************
1018   End of file
1019  **********************************************************************/
1020