b1b350ad3b6275798e659ce16c504fada993bd60
[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  *             Ric Action Node
205  * @return Action Info DB
206  *         NULL, in case of failure
207  *
208  * ****************************************************************/
209 ActionInfo *fetchActionInfoFromActionId(uint8_t actionId, RicSubscription *ricSubscriptionInfo, CmLList ** actionNode)
210 {
211    ActionInfo *actionInfoDb = NULLP;
212
213    CM_LLIST_FIRST_NODE(&ricSubscriptionInfo->actionSequence, *actionNode);
214    while(*actionNode)
215    {
216       actionInfoDb = (ActionInfo*)((*actionNode)->node);
217       if(actionInfoDb && actionInfoDb->actionId == actionId)
218       {
219          break;
220       }
221       *actionNode= (*actionNode)->next;
222       actionInfoDb = NULLP;
223    }
224    
225    if(!actionInfoDb) 
226    {
227       DU_LOG("\nERROR  -->  E2AP : fetchActionInfoFromActionId: Action Id [%d] not found in \
228             subscription info [Requestor id : %d] [Instance Id : %d]", actionId,\
229             ricSubscriptionInfo->requestId.requestorId, ricSubscriptionInfo->requestId.instanceId);
230
231    }
232    return actionInfoDb;
233 }
234
235 /*******************************************************************
236  *
237  * @brief Fetch subscripton DB 
238  *
239  * @details
240  *
241  *    Function : fetchSubsInfoFromRicReqId
242  *
243  *    Functionality: Fetches subscription DB from RAN Function DB
244  *       using RIC Request ID
245  *
246  * @params[in] RIC Request ID 
247  *             RAN Function DB
248  *             Pointer to RIC Subscription node to be searched
249  * @return RIC Subscription from RAN Function's subcription list
250  *         NULL, in case of failure
251  *
252  * ****************************************************************/
253 RicSubscription *fetchSubsInfoFromRicReqId(RicRequestId ricReqId, RanFunction *ranFuncDb, CmLList **ricSubscriptionNode)
254 {
255    RicSubscription *ricSubscriptionInfo = NULLP;
256
257    /* Fetch subscription detail in RAN Function DB */
258    CM_LLIST_FIRST_NODE(&ranFuncDb->subscriptionList, *ricSubscriptionNode);
259    while(*ricSubscriptionNode)
260    {
261       ricSubscriptionInfo = (RicSubscription *)((*ricSubscriptionNode)->node);
262       if(ricSubscriptionInfo && (ricSubscriptionInfo->requestId.requestorId == ricReqId.requestorId) &&
263             (ricSubscriptionInfo->requestId.instanceId == ricReqId.instanceId))
264       {
265          break;
266       }
267       *ricSubscriptionNode = (*ricSubscriptionNode)->next;
268       ricSubscriptionInfo = NULLP;
269    }
270
271    if(!ricSubscriptionInfo)
272    {
273       DU_LOG("\nERROR  -->  E2AP : fetchSubsInfoFromRicReqId: Subscription not found for Requestor ID [%d] \
274          Instance ID [%d] in RAN Function ID [%d]", ricReqId.requestorId, ricReqId.instanceId, ranFuncDb->id);
275    }
276
277    return ricSubscriptionInfo;
278 }
279
280 /*******************************************************************
281  *
282  * @brief Fetches RAN Function DB
283  *
284  * @details
285  *
286  *    Function : fetchRanFuncFromRanFuncId
287  *
288  *    Functionality: Fetches RAN function DB from E2AP DB using
289  *       RAN function ID 
290  *
291  * @params[in] RAN Function ID
292  * @return RAN Function DB
293  *         NULL, in case of failure
294  *
295  * ****************************************************************/
296 RanFunction *fetchRanFuncFromRanFuncId(uint16_t ranFuncId)
297 {
298    RanFunction *ranFuncDb = NULLP;
299
300    /* Fetch RAN Function DB */
301    if(duCb.e2apDb.ranFunction[ranFuncId-1].id == ranFuncId)
302    {
303       ranFuncDb = &duCb.e2apDb.ranFunction[ranFuncId-1];
304    }
305    else
306    {
307       DU_LOG("\nERROR  -->  E2AP : fetchRanFuncFromRanFuncId: Invalid RAN Function ID[%d]", ranFuncId);
308    }
309
310    return ranFuncDb;
311 }
312
313 /*******************************************************************
314  *
315  * @brief Fetches subscription info
316  *
317  * @details
318  *
319  *    Function : fetchSubsInfoFromSubsId
320  *
321  *    Functionality: 
322  *       1. Firstly, RAN Function ID and RIC request ID is extracted
323  *          from Subscription ID 
324  *       2. Using RAN Function ID, RAN Function DB is searched
325  *       3. Using RIC Request ID, the subscription DB is searched in
326  *          RAN Function DB
327  *
328  * @params[in] Subscription ID
329  *             RAN Function DB
330  *             RIC Subscription node from RAN Func's Subscription list
331  * @return ROK
332  *         RFAILED
333  *
334  * ****************************************************************/
335 uint8_t fetchSubsInfoFromSubsId(uint64_t subscriptionId, RanFunction **ranFuncDb, CmLList **ricSubscriptionNode, \
336    RicSubscription **ricSubscriptionInfo)
337 {
338    uint16_t ranFuncId = 0;
339    RicRequestId ricReqId;
340
341    memset(&ricReqId, 0, sizeof(RicRequestId));
342
343    /* Decode subscription ID o get RIC Request ID and RAN Function ID */
344    decodeSubscriptionId(subscriptionId, &ranFuncId, &ricReqId);
345
346    /* Fetch RAN Function DB using RAN Function ID */
347    *ranFuncDb = fetchRanFuncFromRanFuncId(ranFuncId);
348    if((*ranFuncDb) == NULLP)
349    {
350       return RFAILED;
351    }
352
353    /* Fetch Sunscription DB from RAN Function using RIC Request ID */
354    *ricSubscriptionInfo = fetchSubsInfoFromRicReqId(ricReqId, *ranFuncDb, ricSubscriptionNode);
355    if((*ricSubscriptionInfo) == NULLP)
356    {
357       return RFAILED;
358    }
359
360    return ROK;
361 }
362
363 /*******************************************************************
364  *
365  * @brief Sends E2 msg over SCTP
366  *
367  * @details
368  *
369  *    Function : SendE2APMsg
370  *
371  *    Functionality: Sends E2 msg over SCTP
372  *
373  * @params[in] Region region
374  *             Pool pool
375  * @return ROK     - success
376  *         RFAILED - failure
377  *
378  * ****************************************************************/
379
380 uint8_t SendE2APMsg(Region region, Pool pool, char *encBuf, int encBufSize)
381 {
382    Buffer *mBuf=NULLP;
383
384    if(ODU_GET_MSG_BUF(region, pool, &mBuf) == ROK)
385    {
386       if(ODU_ADD_POST_MSG_MULT((Data *)encBuf, encBufSize, mBuf) == ROK)
387       {
388          ODU_PRINT_MSG(mBuf, 0,0);
389
390          if(sctpSend(mBuf, E2_INTERFACE) != ROK)
391          {
392             DU_LOG("\nERROR  -->  E2AP : SCTP Send for E2  failed");
393             ODU_PUT_MSG_BUF(mBuf);
394             return RFAILED;
395          }
396       }
397       else
398       {
399          DU_LOG("\nERROR  -->  E2AP : ODU_ADD_POST_MSG_MULT failed");
400          ODU_PUT_MSG_BUF(mBuf);
401          return RFAILED;
402       }
403       ODU_PUT_MSG_BUF(mBuf);
404    }
405    else
406    {
407       DU_LOG("\nERROR  -->  E2AP : Failed to allocate memory");
408       return RFAILED;
409    }
410
411    return ROK;
412 } /* SendE2APMsg */
413
414 /*******************************************************************
415  *
416  * @brief Resets E2 
417  *
418  * @details
419  *
420  *    Function : ResetE2Request
421  *
422  *    Functionality: This function resets E2.
423  *       As per ORAN WG3 E2GAP v3.0 Spec, section 5.5.3
424  *       If E2 node initates reset procedure then:
425  *        a. Send reset request to RIC
426  *        b. Delete any pre-established RIC subscriptions
427  *        c. Gracefully terminates any ongoing RIC services
428  *       If RIC initiates reset procedure then :
429  *        a. Delete any pre-established RIC subscriptions
430  *        b. Gracefully terminates any ongoing RIC services
431  *        c. Send reset response to RIC
432  *
433  * @params[in]
434  * @return ROK     - success
435  *         RFAILED - failure
436  *
437  * ****************************************************************/
438 uint8_t ResetE2Request(E2ProcedureDirection dir, E2FailureCause resetCause)
439 {
440    /* Send Reset Request to RIC if DU detects any abnormal failure */
441    if(dir == E2_NODE_INITIATED)
442    {
443       if(BuildAndSendE2ResetRequest(resetCause) != ROK)
444       {
445          DU_LOG("\nERROR  -->  E2AP : BuildAndSendE2ResetRequest failed");
446          return RFAILED;
447       }
448    }
449
450    /* TODO when RIC subscription service model is implemented
451       Process following steps of resetting E2
452       1. Deletes any pre-established RIC subscriptions
453       2. Gracefully terminates any ongoing RIC services
454     */
455
456    /* Send Reset Response if RIC initiated Reset request is received at DU */
457    if(dir == RIC_INITIATED)
458    {
459       //BuildAndSendE2ResetResponse();
460    }   
461    return ROK;
462 }
463
464 /*******************************************************************
465  *
466  * @brief Fill RIC Subscription datils in MAC Statistics Request
467  *
468  * @details
469  *
470  *    Function : fillRicSubsInMacStatsReq
471  *
472  *    Functionality: Fill RIC Subscription datils in MAC Statistics 
473  *       Request
474  *
475  * @params[in] MAC Statistics Request to be filled
476  *             RIC Subscription Info
477  *
478  * @return ROK     - success
479  *         RFAILED - failure
480  *
481  * ****************************************************************/
482 uint8_t fillRicSubsInMacStatsReq(MacStatsReq *macStatsReq, RicSubscription* ricSubscriptionInfo)
483 {
484    uint8_t    actionIdx = 0, grpIdx = 0, statsIdx = 0;
485    uint64_t   subscriptionId = 0;
486    ActionInfo *actionDb = NULLP;
487    CmLList *actionNode = NULLP;
488    ActionDefFormat1 *format1Action = NULLP;
489
490    /* Generate subscription ID using RIC Request ID and RAN Function ID */
491    encodeSubscriptionId(&subscriptionId, ricSubscriptionInfo->ranFuncId, ricSubscriptionInfo->requestId);
492
493    macStatsReq->subscriptionId = subscriptionId;
494    CM_LLIST_FIRST_NODE(&ricSubscriptionInfo->actionSequence, actionNode);
495    while(actionNode)
496    {
497       actionDb = (ActionInfo*)(actionNode->node);
498       if(actionDb->action == CONFIG_ADD)
499       {
500          macStatsReq->statsGrpList[grpIdx].groupId = actionDb->actionId;
501          switch(actionDb->definition.formatType)
502          {
503             case 1:
504                {
505                   format1Action = &actionDb->definition.choice.format1;
506                   macStatsReq->statsGrpList[grpIdx].periodicity = format1Action->granularityPeriod;
507
508                   CmLList *node = NULLP;
509                   MeasurementInfo *measInfo = NULLP;
510                   statsIdx = 0;
511                   /* Update DL PRB Usage for all stats group which requested for DL Total PRB Usage */
512                   node = cmLListFirst(&format1Action->measurementInfoList);
513                   while(node)
514                   {
515                      measInfo = (MeasurementInfo *)(node->node);
516                      switch(measInfo->measurementTypeId)
517                      {
518                         case 1:
519                            {
520                               macStatsReq->statsGrpList[grpIdx].statsList[statsIdx++] = MAC_DL_TOTAL_PRB_USAGE;
521                               break;
522                            }
523                         case 2:
524                            {
525                               macStatsReq->statsGrpList[grpIdx].statsList[statsIdx++] = MAC_UL_TOTAL_PRB_USAGE;
526                               break;
527                            }
528                         default:
529                            {
530                               DU_LOG("\nERROR  -->  E2AP : Invalid measurement name");
531                               break;
532                            }
533                      }
534                      node = node->next;
535                   }
536                   macStatsReq->statsGrpList[grpIdx].numStats = statsIdx;
537                   break;
538                }
539             default:
540                {
541                   DU_LOG("\nERROR  -->  E2AP : fillRicSubsInMacStatsReq: Only Action Definition Format 1 supported");
542                   break;
543                }
544          }
545          if(macStatsReq->statsGrpList[grpIdx].numStats)
546             grpIdx++;
547       }
548       actionNode = actionNode->next;
549    }
550
551    macStatsReq->numStatsGroup = grpIdx;
552    if(macStatsReq->numStatsGroup)
553    {
554       return ROK;
555    }
556    return RFAILED;
557 }
558
559 /*******************************************************************
560  *
561  * @brief Rejects all actions received in a subscription request
562  *
563  * @details
564  *
565  *    Function : duRejectAllStatsGroup
566  *
567  *    Functionality: Rejects all actions received in a subscription
568  *       request by :
569  *       a. Removing the subscription entry from RAN function
570  *       b. Sending RIC Subscription Failure to RIC with appropriate
571  *          cause of failure
572  *
573  * @params[in] RAN Function DB
574  *             Subscription entry in RAN Function subscription list
575  *             Statistics Response from MAC
576  *
577  * @return ROK     - success
578  *         RFAILED - failure
579  *
580  * ****************************************************************/
581 uint8_t rejectAllStatsGroup(RanFunction *ranFuncDb, CmLList *ricSubscriptionNode, MacStatsRsp *statsRsp)
582 {
583    uint8_t ret = ROK;
584    RicRequestId  requestId;
585    E2FailureCause failureCause;
586
587    /* Delete subcription from RAN Function */
588    memcpy(&requestId, &((RicSubscription *)ricSubscriptionNode->node)->requestId, sizeof(RicRequestId));
589    cmLListDelFrm(&ranFuncDb->subscriptionList, ricSubscriptionNode);
590    deleteRicSubscriptionNode(ricSubscriptionNode);
591    ricSubscriptionNode = NULLP;
592    convertDuCauseToE2Cause(statsRsp->statsGrpRejectedList[0].cause, &failureCause);
593
594    /* Send RIC subscription failure to RIC */
595    ret = BuildAndSendRicSubscriptionFailure(requestId, ranFuncDb->id, failureCause);
596    return ret;
597 }
598
599 /*******************************************************************
600  *
601  * @brief Process statistics response from MAC
602  *
603  * @details
604  *
605  *    Function : e2ProcStatsRsp
606  *
607  *    Functionality: Processes statistics configuration response
608  *       from MAC. If configuration is succsessful, DUAPP starts
609  *       reporting period timer for this subscription request
610  *       from RIC
611  *
612  * @params[in] Statistics response received from MAC
613  *
614  * @return ROK     - success
615  *         RFAILED - failure
616  *
617  * ****************************************************************/
618 uint8_t e2ProcStatsRsp(MacStatsRsp *statsRsp)
619 {
620    uint8_t idx = 0;
621    uint8_t actionId = 0;
622    uint32_t reportingPeriod = 0;
623    RanFunction *ranFuncDb = NULLP;
624    CmLList *ricSubscriptionNode = NULLP;
625    CmLList *actionNode = NULLP;
626    RicSubscription *ricSubscriptionInfo = NULLP;
627    ActionInfo *actionInfoDb = NULLP;
628    PendingSubsRspInfo *pendingSubsRsp = NULLP;
629
630    /* Fetch RAN Function and Subscription DB using subscription Id received in statistics response */
631    if(fetchSubsInfoFromSubsId(statsRsp->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK)
632    {
633       DU_LOG("\nERROR  -->  E2AP : DuProcMacStatsRsp: Failed to fetch subscriprtion details");
634       return RFAILED;
635    }
636
637    /* Fetch pre-stored statistics response info by DU APP */
638    for(idx=0; idx<ranFuncDb->numPendingSubsRsp; idx++)
639    {
640       if((ranFuncDb->pendingSubsRspInfo[idx].requestId.requestorId == ricSubscriptionInfo->requestId.requestorId) &&
641             (ricSubscriptionInfo->requestId.instanceId == ricSubscriptionInfo->requestId.instanceId))
642       {
643          pendingSubsRsp = &ranFuncDb->pendingSubsRspInfo[idx];
644          break;
645       }
646    }
647
648    /* If no action is accepted
649     *  a. Remove subcription entry from RAN Function
650     *  b. Send RIC subscription failure */
651    if(statsRsp->numGrpAccepted == 0)
652    {
653       rejectAllStatsGroup(ranFuncDb, ricSubscriptionNode, statsRsp);
654    }
655    else
656    {
657       /* Once RIC subscription is successful, mark the config action as unknown */
658       ricSubscriptionInfo->action = CONFIG_UNKNOWN;
659
660       /* Start RIC Subscription reporting timer */
661       switch(ricSubscriptionInfo->eventTriggerDefinition.formatType)
662       {
663          case 1:
664             {
665                reportingPeriod = ricSubscriptionInfo->eventTriggerDefinition.choice.format1.reportingPeriod;
666
667                /* Save the start time of reporting period */
668                storeReportStartTime(&ricSubscriptionInfo->eventTriggerDefinition.choice.format1.startTime);
669                break;
670             }
671          default:
672          {
673             DU_LOG("\nERROR  -->  E2AP : Invalid event trigger format of RIC subscription");
674             return RFAILED;
675          }
676       }
677       if(duChkTmr((PTR)ricSubscriptionInfo, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR) != true)
678       {
679          duStartTmr((PTR)ricSubscriptionInfo, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR, reportingPeriod);
680       }
681       else
682       {
683          DU_LOG("\nERROR  -->  E2AP : RIC Subscription reporting timer already running for RIC Subscription");  
684          return RFAILED;
685       }
686
687
688       /* If even 1 action is accepted :
689        *
690        * For accepted groups:
691        *    Mark subscribed-action's -> action = CONFIG_UNKNOWN
692        *    Add to accepted-action-list of subscription response
693        */
694       for(idx=0; idx<statsRsp->numGrpAccepted; idx++)
695       {
696          actionInfoDb = NULLP;
697
698          actionId = statsRsp->statsGrpAcceptedList[idx];
699          actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo, &actionNode);
700          if(actionInfoDb && (actionInfoDb->action == CONFIG_ADD))
701          {
702             actionInfoDb->action = CONFIG_UNKNOWN;
703             pendingSubsRsp->acceptedActionList[pendingSubsRsp->numOfAcceptedActions++] = actionId;
704          }
705       }
706
707       /* For rejected groups:
708        *    Remove entry from DU's RAN Function->subscription->actionList
709        *    Add to rejected-action-list in subscription response
710        */
711       for(idx=0; idx<statsRsp->numGrpRejected; idx++)
712       {
713          actionInfoDb = NULLP;
714          actionId = statsRsp->statsGrpRejectedList[idx].groupId;
715          actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo, &actionNode);
716          if(actionInfoDb->actionId == actionId)
717          {
718             deleteActionSequence(actionNode);
719             pendingSubsRsp->rejectedActionList[pendingSubsRsp->numOfRejectedActions].id = actionId;
720             convertDuCauseToE2Cause(statsRsp->statsGrpRejectedList[idx].cause, \
721                   &pendingSubsRsp->rejectedActionList[pendingSubsRsp->numOfRejectedActions].failureCause);
722             pendingSubsRsp->numOfRejectedActions++;
723          }
724       }
725
726       /* Send subscription response with accepted and rejected action lists to RIC */
727       BuildAndSendRicSubscriptionRsp(pendingSubsRsp);
728    }
729    memset(pendingSubsRsp, 0, sizeof(PendingSubsRspInfo));
730    return ROK;
731 }
732
733 /*******************************************************************
734  *
735  * @brief Extract and store statistics received from DU layers
736  *
737  * @details
738  *
739  *    Function : e2ProcStatsInd
740  *
741  *    Functionality: Extract statistics received from DU layers
742  *       and store in respective RAN function's subscription's
743  *       action
744  *
745  * @params[in] Statistics Indication message received from MAC
746  * @return ROK-success
747  *         RFAILED-failure
748  *
749  * ****************************************************************/
750 uint8_t e2ProcStatsInd(MacStatsInd *statsInd)
751 {
752    uint8_t statsIdx = 0;
753    RanFunction *ranFuncDb = NULLP;
754    CmLList *ricSubscriptionNode = NULLP;
755    CmLList *actionNode = NULLP;
756    RicSubscription *ricSubscriptionInfo = NULLP;
757    ActionInfo *actionInfo = NULLP;
758    ActionDefFormat1 *actionFormat = NULLP;
759    char e2MeasTypeName[STRING_SIZE_150_BYTES] = "";
760    MeasurementInfo *measInfo = NULLP;
761    CmLList *measInfoNode = NULLP;
762    double *measValue = NULLP;
763    CmLList *measValueNode = NULLP;
764
765    /* TODO : When stats indication is received
766     * DU APP searches for the message type in E2AP RIC subscription
767     * database and stores in the value in the list of subscribed measurements
768     *
769     * This will be implemented in next gerrit.
770     */
771
772    /* Fetch RAN Function and Subscription DB using subscription Id received
773     * in statistics response */
774    if(fetchSubsInfoFromSubsId(statsInd->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK)
775    {
776       DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Failed to fetch subscriprtion details");
777       return RFAILED;
778    }
779
780    /* Fetch RIC subscription's action DB */
781    actionInfo = fetchActionInfoFromActionId(statsInd->groupId, ricSubscriptionInfo, &actionNode);
782    if(actionInfo == NULLP)
783    {
784       DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Failed to fetch action ID [%d]", statsInd->groupId);
785       return RFAILED;
786    }
787
788    /* Check Action format */
789    switch(actionInfo->definition.formatType)
790    {
791       case 1:
792          {
793             actionFormat = &actionInfo->definition.choice.format1;
794             break;
795          }
796       default:
797          {
798             DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Action Format [%d] is not supported", \
799                   actionInfo->definition.formatType);
800             return RFAILED;
801          }
802    }
803
804    /* Fetch each Measurement info from action info and store its reported value in DB */
805    for(statsIdx = 0; statsIdx < statsInd->numStats; statsIdx++)
806    {
807       memset(e2MeasTypeName, 0, STRING_SIZE_150_BYTES);
808       measInfo = NULLP;
809       measInfoNode = NULLP;
810
811       /* Convert Measurement type from MAC-supported format to E2-supported format */
812       if(convertMacMeasTypeToE2MeasType(statsInd->measuredStatsList[statsIdx].type, e2MeasTypeName) != ROK)
813       {
814          DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Failed to convert measurement type from MAC-supported\
815             MAC-supported format to E2-supported format");
816          continue;
817       }
818       
819       /* Fetch Measurement Info using E2-supported measurement type name */
820       measInfo = fetchMeasInfoFromMeasTypeName(e2MeasTypeName, &actionFormat->measurementInfoList, &measInfoNode); 
821       if(measInfo == NULLP)
822       {
823          DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Measurement Type Name [%s] not found", e2MeasTypeName); 
824          continue;
825       }
826       
827       /* Store the measurement value in the measurement info DB fetched */
828       DU_ALLOC(measValue, sizeof(double));
829       if(!measValue)
830       {
831          DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Memory allocation failed at line [%d]", __LINE__);
832          return RFAILED; 
833       }
834       *measValue = statsInd->measuredStatsList[statsIdx].value;
835
836       DU_ALLOC(measValueNode, sizeof(CmLList));
837       if(!measValueNode)
838       {
839          DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Memory allocation failed at line [%d]", __LINE__);
840          DU_FREE(measValue, sizeof(double));
841          return RFAILED; 
842       }
843       measValueNode->node = (PTR) measValue;
844       cmLListAdd2Tail(&measInfo->measuredValue, measValueNode);
845    }
846    return ROK;
847 }
848
849 /*******************************************************************
850  *
851  * @brief Handle RIC Subscription reporting timer expry
852  *
853  * @details
854  *
855  *    Function : E2apHdlRicSubsReportTmrExp
856  *
857  *    Functionality: On expiry of RIC subscription reporting
858  *       timer expiry, RIC indication is sent for all actions
859  *       in RIC subscription
860  *
861  * @params[in] RIC subscription DB
862  * @return void
863  *
864  * ****************************************************************/
865 void E2apHdlRicSubsReportTmrExp(RicSubscription *ricSubscription)
866 {
867    uint8_t actionIdx = 0;
868    uint32_t reportingPeriod = 0;
869    ActionInfo *action=NULLP;
870    CmLList *actionNode=NULLP;
871
872    CM_LLIST_FIRST_NODE(&ricSubscription->actionSequence, actionNode);
873    while(actionNode)
874    {
875       action = (ActionInfo*)actionNode->node;
876       BuildAndSendRicIndication(ricSubscription, action);
877       actionNode = actionNode->next;
878    }
879
880    /* Start RIC Subscription reporting timer again */
881    switch(ricSubscription->eventTriggerDefinition.formatType)
882    {
883       case 1:
884          {
885             reportingPeriod = ricSubscription->eventTriggerDefinition.choice.format1.reportingPeriod;
886             /* Save the start time of reporting period */
887             storeReportStartTime(&ricSubscription->eventTriggerDefinition.choice.format1.startTime);
888             break;
889          }
890       default:
891          return;
892    }
893    if(duChkTmr((PTR)ricSubscription, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR) != true)
894    {
895       duStartTmr((PTR)ricSubscription, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR, reportingPeriod);
896    }
897    else
898    {
899       DU_LOG("\nERROR  -->  E2AP : Failed in %s at line %d", __func__, __LINE__);
900       return;
901    }
902 }
903
904 /******************************************************************
905  *
906  * @brief Search E2 node component with the help of action type
907  *
908  * @details
909  *
910  *    Function : fetchE2NodeComponentInfo 
911  *
912  *    Functionality: Search E2 node component with the help of action type 
913  *
914  * @params[in] 
915  *       Type of interface 
916  *       Component Id
917  *       Pointer to E2 component node to be searched 
918  * @return CmLList
919  *
920  * ****************************************************************/
921
922 E2NodeComponent *fetchE2NodeComponentInfo(InterfaceType interfaceType, uint64_t componentId, CmLList **e2ComponentNode)
923 {
924    E2NodeComponent *e2NodeComponentInfo=NULLP;
925
926    if(duCb.e2apDb.e2NodeComponentList.count)
927    {
928       CM_LLIST_FIRST_NODE(&duCb.e2apDb.e2NodeComponentList, *e2ComponentNode);
929       while(*e2ComponentNode)
930       {
931          e2NodeComponentInfo = (E2NodeComponent*)((*e2ComponentNode)->node);
932          if((e2NodeComponentInfo->interfaceType == interfaceType) && (e2NodeComponentInfo->componentId == componentId))
933          {
934             break;
935          }
936          
937          *e2ComponentNode = (*e2ComponentNode)->next;
938          e2NodeComponentInfo = NULLP;
939       }
940    }
941    return e2NodeComponentInfo; 
942 }
943
944 /*******************************************************************
945  *
946  * @brief fill E2 node component rsp info
947  *
948  * @details
949  *
950  *    Function : fillE2NodeComponentRspInfo 
951  *
952  * Functionality: fill E2 Node Component rsp info 
953  *
954  * @parameter
955  *       Type of interface 
956  *       Component action type
957  *       Size of buffer which needs to be store
958  *       buffer string which needs to be store 
959  * @return ROK     - success
960  *         RFAILED - failure
961  *
962  * ****************************************************************/
963
964 uint8_t fillE2NodeComponentRspInfo(InterfaceType interfaceType, uint64_t componentId, uint8_t action, uint8_t bufSize, char *bufString)
965 {
966    E2NodeConfig *configInfo=NULLP;
967    E2NodeComponent *e2NodeComponentInfo= NULLP;
968    CmLList  *node = NULLP;
969
970    e2NodeComponentInfo = fetchE2NodeComponentInfo(interfaceType, componentId, &node);
971    if(!e2NodeComponentInfo) 
972    {
973       DU_LOG("\nERROR  -->  E2AP : Unable to find the node");
974       return RFAILED;
975    }
976
977    switch(action)
978    {
979       case E2_NODE_COMPONENT_ADD:
980          {
981             configInfo = e2NodeComponentInfo->addConfiguration;    
982             break;
983          }
984       case E2_NODE_COMPONENT_UPDATE: 
985          {
986             configInfo = e2NodeComponentInfo->updateConfiguration;
987             break;
988          }
989       default:
990          {
991             DU_LOG("\nERROR  -->  E2AP : Invalid action %d received",action);
992             return RFAILED;
993          }
994    }
995
996    if(configInfo->componentRequestPart== NULLP)
997    {
998       DU_LOG("\nERROR  -->  E2AP : E2 node Component request part is not present");
999       return RFAILED;
1000    }
1001
1002    configInfo->rspBufSize = bufSize;
1003    DU_ALLOC(configInfo->componentResponsePart, bufSize);
1004    if(configInfo->componentResponsePart == NULLP)
1005    {
1006       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed to store the encoding of rsp");
1007       return RFAILED;
1008    }
1009    memcpy(configInfo->componentResponsePart, bufString, configInfo->rspBufSize);
1010    return ROK;
1011 }
1012
1013 /*******************************************************************
1014  *
1015  * @brief add E2 node component req info
1016  *
1017  * @details
1018  *
1019  *    Function : addE2NodeComponent 
1020  *
1021  * Functionality: add E2 node component req info 
1022  *
1023  * @parameter
1024  *       Type of interface 
1025  *       Component action type
1026  *       Size of buffer which needs to be store
1027  *       buffer string which needs to be store 
1028  * @return ROK     - success
1029  *         RFAILED - failure
1030  *
1031  ******************************************************************/
1032
1033 uint8_t addE2NodeComponent(InterfaceType interfaceType, uint64_t componentId,  uint8_t bufSize, char *bufString)
1034 {
1035    E2NodeComponent *e2NodeComponentInfo= NULLP;
1036    CmLList  *node = NULLP;
1037    
1038    DU_ALLOC(e2NodeComponentInfo, sizeof(E2NodeComponent));
1039    if(!e2NodeComponentInfo)
1040    {
1041       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed in %s at %d",__func__,__LINE__);
1042       return RFAILED;
1043    }
1044    e2NodeComponentInfo->interfaceType =interfaceType;
1045    e2NodeComponentInfo->componentId=componentId;
1046
1047    DU_ALLOC(e2NodeComponentInfo->addConfiguration, sizeof(E2NodeConfig));
1048    if(!e2NodeComponentInfo->addConfiguration)
1049    {
1050       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed in %s at %d",__func__,__LINE__);
1051       return RFAILED;
1052    }
1053
1054    e2NodeComponentInfo->addConfiguration->reqBufSize = bufSize;
1055
1056    DU_ALLOC(e2NodeComponentInfo->addConfiguration->componentRequestPart, bufSize);
1057    if(e2NodeComponentInfo->addConfiguration->componentRequestPart == NULLP)
1058    {
1059       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed in %s at %d",__func__,__LINE__);
1060       DU_FREE(e2NodeComponentInfo, sizeof(E2NodeComponent));
1061       return RFAILED;
1062    }
1063    memcpy(e2NodeComponentInfo->addConfiguration->componentRequestPart, bufString,\
1064    e2NodeComponentInfo->addConfiguration->reqBufSize);
1065
1066    DU_ALLOC(node, sizeof(CmLList));
1067    if(node)
1068    {
1069       node->node = (PTR) e2NodeComponentInfo;
1070       cmLListAdd2Tail(&duCb.e2apDb.e2NodeComponentList, node);
1071    }
1072    else
1073    {
1074       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed in %s at %d",__func__,__LINE__);
1075       DU_FREE(e2NodeComponentInfo->addConfiguration->componentRequestPart, bufSize);
1076       DU_FREE(e2NodeComponentInfo->addConfiguration, sizeof(E2NodeConfig));
1077       DU_FREE(e2NodeComponentInfo, sizeof(E2NodeComponent));
1078       return RFAILED;
1079    }
1080    return ROK;
1081 }
1082
1083 /*******************************************************************
1084  *
1085  * @brief update E2 node component req info
1086  *
1087  * @details
1088  *
1089  *    Function : updateE2NodeComponent 
1090  *
1091  * Functionality: update E2 node component req info 
1092  *
1093  * @parameter
1094  *       Type of interface 
1095  *       Size of buffer which needs to be store
1096  *       buffer string which needs to be store 
1097  * @return ROK     - success
1098  *         RFAILED - failure
1099  *
1100  ******************************************************************/
1101
1102 uint8_t updateE2NodeComponent(InterfaceType interfaceType, uint64_t componentId, uint8_t bufSize, char *bufString)
1103 {
1104    E2NodeComponent *e2NodeComponentInfo= NULLP;
1105    CmLList  *node = NULLP;
1106          
1107    e2NodeComponentInfo = fetchE2NodeComponentInfo(interfaceType, componentId, &node);
1108    if(!e2NodeComponentInfo)
1109    {
1110       DU_LOG("\nERROR  -->  E2AP : Received null information in %s",__func__);
1111       return RFAILED;
1112    }
1113    
1114    DU_ALLOC(e2NodeComponentInfo->updateConfiguration, sizeof(E2NodeConfig));
1115    if(!e2NodeComponentInfo->updateConfiguration)
1116    {
1117       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed in %s at %d",__func__,__LINE__);
1118       return RFAILED;
1119    }
1120
1121    e2NodeComponentInfo->updateConfiguration->reqBufSize = bufSize;
1122
1123    DU_ALLOC(e2NodeComponentInfo->updateConfiguration->componentRequestPart, bufSize);
1124    if(e2NodeComponentInfo->updateConfiguration->componentRequestPart == NULLP)
1125    {
1126       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed in %s at %d",__func__,__LINE__);
1127       DU_FREE(e2NodeComponentInfo->updateConfiguration, sizeof(E2NodeConfig));
1128       return RFAILED;
1129    }
1130
1131    memcpy(e2NodeComponentInfo->updateConfiguration->componentRequestPart, bufString,\
1132    e2NodeComponentInfo->updateConfiguration->reqBufSize);
1133    return ROK;
1134
1135 }
1136
1137 /*******************************************************************
1138  *
1139  * @brief delete E2 node component req info
1140  *
1141  * @details
1142  *
1143  *    Function : deleteE2NodeComponent 
1144  *
1145  * Functionality: delete E2 node component req info 
1146  *
1147  * @parameter
1148  *       Type of interface 
1149  * @return ROK     - success
1150  *         RFAILED - failure
1151  *
1152  ******************************************************************/
1153
1154 uint8_t deleteE2NodeComponent(InterfaceType interfaceType, uint64_t componentId)
1155 {
1156    E2NodeComponent *e2NodeComponentInfo= NULLP;
1157    CmLList  *node = NULLP;
1158          
1159    e2NodeComponentInfo = fetchE2NodeComponentInfo(interfaceType, componentId, &node);
1160    if(!e2NodeComponentInfo)
1161    {
1162       DU_LOG("\nERROR  -->  E2AP : Received null information in %s",__func__);
1163       return RFAILED;
1164    }
1165    
1166    e2NodeComponentInfo->deleteConfiguration = true;
1167    return ROK;
1168 }
1169
1170 /*******************************************************************
1171  *
1172  * @brief fill E2 node component req info
1173  *
1174  * @details
1175  *
1176  *    Function : fillE2NodeComponentReqInfo 
1177  *
1178  * Functionality: fill E2 node component req info 
1179  *
1180  * @parameter
1181  *       Type of interface 
1182  *       Component action type
1183  *       Size of buffer which needs to be store
1184  *       buffer string which needs to be store 
1185  * @return ROK     - success
1186  *         RFAILED - failure
1187  *
1188  ******************************************************************/
1189
1190 uint8_t fillE2NodeComponentReqInfo(InterfaceType interfaceType, uint64_t componentId, uint8_t action, uint8_t bufSize, char *bufString)
1191 {
1192    switch(action)
1193    {
1194       case E2_NODE_COMPONENT_ADD:
1195          {
1196             if(addE2NodeComponent(interfaceType, componentId, bufSize, bufString) != ROK)
1197             {
1198                DU_LOG("\nERROR  -->  E2AP : Failed to add e2 node component");
1199                return RFAILED;
1200             }
1201             break;
1202          }
1203       case E2_NODE_COMPONENT_UPDATE: 
1204          {
1205             if(updateE2NodeComponent(interfaceType, componentId, bufSize, bufString) != ROK)
1206             {
1207                DU_LOG("\nERROR  -->  E2AP : Failed to update e2 node component");
1208                return RFAILED;
1209             }
1210             break;
1211          }
1212       case E2_NODE_COMPONENT_DEL:
1213          {
1214             if(deleteE2NodeComponent(interfaceType, componentId) != ROK)
1215             {
1216                DU_LOG("\nERROR  -->  E2AP : Failed to delete e2 node component");
1217                return RFAILED;
1218             }
1219             break;
1220          }
1221       default:
1222          {
1223             DU_LOG("\nERROR  -->  E2AP : Invalid action %d received",action);
1224             return RFAILED;
1225          }
1226    }
1227
1228    return ROK;
1229 }
1230
1231 /******************************************************************
1232  *
1233  * @brief Delete measured Value list
1234  *
1235  * @details
1236  *
1237  *    Function : deleteMeasuredValueList
1238  *
1239  *    Functionality: Delete measured Value list
1240  *
1241  * @params[in] List of measured Value
1242  *          
1243  * @return void 
1244  *
1245  * ****************************************************************/
1246 void deleteMeasuredValueList(CmLListCp *measuredValueList)
1247 {
1248    CmLList *measValNode = NULLP;
1249
1250    CM_LLIST_FIRST_NODE(measuredValueList, measValNode);
1251
1252    while(measValNode)
1253    {
1254       cmLListDelFrm(measuredValueList, measValNode);
1255       DU_FREE(measValNode->node, sizeof(double));
1256       DU_FREE(measValNode, sizeof(CmLList));
1257       CM_LLIST_FIRST_NODE(measuredValueList, measValNode);
1258    }
1259 }
1260
1261 /******************************************************************
1262  *
1263  * @brief Delete Measurement Info List 
1264  *
1265  * @details
1266  *
1267  *    Function : deleteMeasurementInfoList
1268  *
1269  *    Functionality: Delete Measurement Info List 
1270  *
1271  * @params[in] List of Measurement Info List
1272  *          
1273  * @return void 
1274  *
1275  * ****************************************************************/
1276 void deleteMeasurementInfoList(CmLListCp *measInfoList)
1277 {
1278    CmLList *measInfoNode = NULLP;
1279    MeasurementInfo *measInfo = NULLP;
1280
1281    CM_LLIST_FIRST_NODE(measInfoList, measInfoNode);
1282    while(measInfoNode)
1283    {
1284       measInfo = (MeasurementInfo *)measInfoNode->node;
1285       cmLListDelFrm(measInfoList, measInfoNode);
1286       deleteMeasuredValueList(&measInfo->measuredValue);
1287       DU_FREE(measInfo, sizeof(MeasurementInfo));
1288       DU_FREE(measInfoNode, sizeof(CmLList));
1289       CM_LLIST_FIRST_NODE(measInfoList, measInfoNode);
1290    }
1291 }
1292
1293 /******************************************************************
1294  *
1295  * @brief Delete Ric subscription action 
1296  *
1297  * @details
1298  *
1299  *    Function : deleteActionSequence
1300  *
1301  *    Functionality: Delete Ric subscription action 
1302  *
1303  * @params[in] Action info 
1304  *          
1305  * @return void 
1306  *
1307  * ****************************************************************/
1308 void deleteActionSequence(CmLList *actionNode)
1309 {
1310    ActionInfo *action = NULLP;
1311    ActionDefinition *definition=NULLP;
1312    
1313    if(actionNode)
1314    {
1315       action = (ActionInfo*)actionNode->node;
1316       definition= &action->definition;       
1317
1318       switch(definition->formatType)
1319       {
1320          case 1:
1321             {
1322                deleteMeasurementInfoList(&definition->choice.format1.measurementInfoList);
1323                break;
1324             }
1325
1326          case 2:
1327          case 3:
1328          case 4:
1329          case 5:
1330          default:
1331             {
1332                DU_LOG("\nERROR  -->  E2AP : Format %d does not supported", definition->formatType);
1333                break;
1334             }
1335       }
1336       memset(action, 0, sizeof(ActionInfo));
1337       DU_FREE(actionNode->node, sizeof(ActionInfo));
1338       DU_FREE(actionNode, sizeof(CmLList));
1339    }
1340 }
1341
1342 /******************************************************************
1343  *
1344  * @brief Delete Ric subscription action list
1345  *
1346  * @details
1347  *
1348  *    Function : deleteActionSequenceList
1349  *
1350  *    Functionality: Delete Ric subscription action list
1351  *
1352  * @params[in] Action info list
1353  *
1354  * @return void
1355  *
1356  * ****************************************************************/
1357 void deleteActionSequenceList(CmLListCp *actionList)
1358 {
1359    CmLList *actionNode=NULLP;
1360
1361    CM_LLIST_FIRST_NODE(actionList, actionNode);
1362    while(actionNode)
1363    {
1364       cmLListDelFrm(actionList, actionNode);
1365       deleteActionSequence(actionNode);
1366       CM_LLIST_FIRST_NODE(actionList, actionNode);
1367    }
1368 }
1369
1370 /******************************************************************
1371  *
1372  * @brief Delete Ric subscription node 
1373  *
1374  * @details
1375  *
1376  *    Function : deleteRicSubscriptionNode
1377  *
1378  *    Functionality: Delete Ric subscription node 
1379  *
1380  * @params[in] Ric subscription info 
1381  *          
1382  * @return void 
1383  *
1384  * ****************************************************************/
1385 void deleteRicSubscriptionNode(CmLList *subscriptionNode)
1386 {
1387    RicSubscription *ricSubscriptionInfo = NULLP;
1388
1389    ricSubscriptionInfo = (RicSubscription*)subscriptionNode->node;    
1390
1391    deleteActionSequenceList(&ricSubscriptionInfo->actionSequence);
1392    if(duChkTmr((PTR)ricSubscriptionInfo, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR) == TRUE)
1393    {
1394       duStopTmr((PTR)ricSubscriptionInfo, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR);
1395    }
1396
1397    memset(ricSubscriptionInfo, 0, sizeof(RicSubscription));
1398    DU_FREE(subscriptionNode->node, sizeof(RicSubscription));
1399    DU_FREE(subscriptionNode, sizeof(CmLList));
1400 }
1401
1402 /******************************************************************
1403  *
1404  * @brief Delete ric subscription list from the database
1405  *
1406  * @details
1407  *
1408  *    Function : deleteRicSubscriptionList
1409  *
1410  *    Functionality: Delete ric subscription list 
1411  *
1412  * @params[in]
1413  *    Subscription List to be deleted 
1414
1415  * @return void 
1416  *
1417  * ****************************************************************/
1418 void deleteRicSubscriptionList(CmLListCp *subscriptionList)
1419 {
1420    CmLList *subscriptionNode=NULLP;
1421    
1422    CM_LLIST_FIRST_NODE(subscriptionList, subscriptionNode);
1423    while(subscriptionNode)
1424    {
1425       /* TODO - Remove subscription information from MAC and SCH as well */ 
1426       cmLListDelFrm(subscriptionList, subscriptionNode);
1427       deleteRicSubscriptionNode(subscriptionNode);
1428       CM_LLIST_FIRST_NODE(subscriptionList, subscriptionNode);
1429    }
1430 }
1431
1432 /*******************************************************************
1433  *
1434  * @brief Find all RIC subscriptions to be deleted in all RAN
1435  *    Functions
1436  *
1437  * @details
1438  *
1439  *    Function : fetchRicSubsToBeDeleted
1440  *
1441  * Functionality: Find all RIC subscriptions to be deleted in all
1442  *    RAN functions and store in a temporary list
1443  *
1444  * @parameter Temporary list to store subscriptions to be deleted
1445  * @return void
1446  *
1447  ******************************************************************/
1448 void fetchRicSubsToBeDeleted(CmLListCp *ricSubsToBeDelList)
1449 {
1450    uint16_t ranFuncIdx = 0;
1451    CmLList *subsNode = NULLP;
1452    CmLList *subsToDelNode = NULLP;
1453
1454    for(ranFuncIdx = 0; ranFuncIdx < MAX_RAN_FUNCTION; ranFuncIdx++)
1455    {
1456       if(duCb.e2apDb.ranFunction[ranFuncIdx].id > 0)
1457       {
1458          CM_LLIST_FIRST_NODE(&duCb.e2apDb.ranFunction[ranFuncIdx].subscriptionList, subsNode);
1459          while(subsNode)
1460          {
1461             if(((RicSubscription *)subsNode->node)->action == CONFIG_DEL)
1462             {
1463                DU_ALLOC(subsToDelNode, sizeof(CmLList));
1464                if(!subsToDelNode)
1465                {
1466                   DU_LOG("\nERROR  -->  E2AP : %s: Memory allocation failure at %d", __func__, __LINE__); 
1467                   return;
1468                }
1469                subsToDelNode->node = subsNode->node;
1470                cmLListAdd2Tail(ricSubsToBeDelList, subsToDelNode);
1471             }
1472             subsToDelNode = NULLP;
1473             subsNode = subsNode->next;
1474          }
1475       }
1476    }
1477 }
1478
1479 /******************************************************************
1480  *
1481  * @brief Delete e2 node information from the database
1482  *
1483  * @details
1484  *
1485  *    Function : removeE2NodeInformation 
1486  *
1487  *    Functionality: Delete e2 node information from the database 
1488  *
1489  * @params[in]
1490  *
1491  * @return void 
1492  *
1493 ******************************************************************/
1494 void removeE2NodeInformation()
1495 {
1496    uint16_t ranFuncIdx = 0;
1497    
1498    DU_LOG("\nINFO  -->  E2AP : Deleting all the E2 node configuration");
1499    for(ranFuncIdx=0; ranFuncIdx<MAX_RAN_FUNCTION; ranFuncIdx++)
1500    {
1501       if(duCb.e2apDb.ranFunction[ranFuncIdx].id >0)
1502       {
1503          deleteRicSubscriptionList(&(duCb.e2apDb.ranFunction[ranFuncIdx].subscriptionList));
1504          memset(&(duCb.e2apDb.ranFunction[ranFuncIdx].pendingSubsRspInfo), 0, MAX_PENDING_SUBSCRIPTION_RSP*sizeof(PendingSubsRspInfo));
1505       }
1506    }
1507    memset(&duCb.e2apDb.ricId, 0, sizeof(GlobalRicId));
1508    duCb.e2apDb.numOfTNLAssoc = 0;
1509    memset(&duCb.e2apDb.tnlAssoc, 0, MAX_TNL_ASSOCIATION*sizeof(TNLAssociation));
1510    memset(&ricParams, 0, sizeof(DuSctpDestCb));
1511 }
1512
1513 /*******************************************************************
1514  *
1515  * @brief Extract statistics received from DU layers and delete
1516  * Ric subscription info
1517  *
1518  * @details
1519  *
1520  *    Function :e2ProcStatsDeleteRsp 
1521  *
1522  *    Functionality: Extract statistics received from DU layers
1523  *       and delete ric subscription iformation form db
1524  *
1525  * @params[in] Statistics delete rsp from MAC
1526  * @return ROK-success
1527  *         RFAILED-failure
1528  *
1529  * ****************************************************************/
1530 uint8_t e2ProcStatsDeleteRsp(MacStatsDeleteRsp *statsDeleteRsp)
1531 {
1532    RicRequestId    requestId;
1533    uint16_t        ranFuncId;
1534    RanFunction *ranFuncDb = NULLP;
1535    CmLList *ricSubscriptionNode = NULLP;
1536    RicSubscription *ricSubscriptionInfo = NULLP;
1537    E2FailureCause failureCause;
1538
1539    /* Fetch RAN Function and Subscription DB using subscription Id received
1540     * in statistics delete response */
1541    if(fetchSubsInfoFromSubsId(statsDeleteRsp->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK)
1542    {
1543       DU_LOG("\nERROR  -->  E2AP : e2ProcStatsDeleteRsp: Failed to fetch subscriprtion details");
1544       return RFAILED;
1545    }
1546    ranFuncId = ricSubscriptionInfo->ranFuncId;
1547    memcpy(&requestId, &ricSubscriptionInfo->requestId, sizeof(RicRequestId));
1548
1549    deleteRicSubscriptionNode(ricSubscriptionNode);
1550    
1551    if(statsDeleteRsp->subsDelRsp == MAC_DU_APP_RSP_NOK)
1552    {
1553       if(statsDeleteRsp->subsDelCause == STATS_ID_NOT_FOUND)
1554       {
1555          failureCause.causeType =E2_RIC_REQUEST;
1556          failureCause.cause = E2_REQUEST_INFORMATION_UNAVAILABLE;
1557       }
1558       else
1559       {
1560          failureCause.causeType = E2_MISCELLANEOUS;
1561          failureCause.cause = E2_MISCELLANEOUS_CAUSE_UNSPECIFIED;
1562       }
1563
1564       if(BuildAndSendRicSubscriptionDeleteFailure(ranFuncId, requestId, failureCause) != ROK)
1565       {
1566          DU_LOG("\nERROR  -->  E2AP : e2ProcStatsDeleteRsp: failed to build and send ric subs delete failure");
1567          return RFAILED;
1568       }
1569    }
1570    else
1571    {
1572       if(BuildAndSendRicSubscriptionDeleteResponse(ranFuncId, requestId) != ROK)
1573       {
1574          DU_LOG("\nERROR  -->  E2AP : e2ProcStatsDeleteRsp: failed to build and send ric subs delete rsp");
1575          return RFAILED;
1576       }
1577    }
1578    
1579    return ROK;
1580 }
1581
1582 /*******************************************************************
1583  *
1584  * @brief Fill RIC Subscription datils in MAC Statistics 
1585  * ModificationRequest
1586  *
1587  * @details
1588  *
1589  *    Function : fillRicSubsInMacStatsModificationReq
1590  *
1591  *    Functionality: Fill RIC Subscription datils in MAC 
1592  * Modification Statistics Request
1593  *    [Step -1] Generate subscription ID using RIC Request ID and 
1594  *    RAN Function ID
1595  *    [Step -2] Check all the action staus of each action present
1596  *    in the ric subscription. If action is CONFIG_MOD then fill
1597  *    the information in stats group list.
1598  *    [Step -3] Fill group related information in stats modification 
1599  *    req's in stats group list
1600  *    [Step -4] fill measurement information in stats group list
1601  *    [Step -5] If the number of stats which needs to modify is 
1602  *    greater then zero then return ROK else return RFAILED
1603  *
1604  * @params[in] MAC Statistics Modification Request to be filled
1605  *             RIC Subscription Info
1606  *
1607  * @return ROK     - success
1608  *         RFAILED - failure
1609  *
1610  * ****************************************************************/
1611 uint8_t fillRicSubsInMacStatsModificationReq(MacStatsModificationReq *macStatsModificationReq, RicSubscription* ricSubscriptionInfo)
1612 {
1613    uint8_t    grpIdx = 0;
1614    uint8_t statsModifyReqIdx = 0;
1615    uint64_t   subscriptionId = 0;
1616    CmLList *node = NULLP;
1617    ActionInfo *actionDb = NULLP;
1618    CmLList *actionNode = NULLP;
1619    MeasurementInfo *measInfo = NULLP;
1620    ActionDefFormat1 *format1Action = NULLP;
1621
1622    /* [Step -1] */
1623    encodeSubscriptionId(&subscriptionId, ricSubscriptionInfo->ranFuncId, ricSubscriptionInfo->requestId);
1624
1625    macStatsModificationReq->subscriptionId = subscriptionId;
1626    CM_LLIST_FIRST_NODE(&ricSubscriptionInfo->actionSequence, actionNode);
1627    while(actionNode)
1628    {
1629       actionDb = (ActionInfo*)(actionNode->node);
1630       /* [Step -2] */
1631       if(actionDb->action == CONFIG_MOD)
1632       {
1633          /* [Step -3] */
1634          macStatsModificationReq->statsGrpList[grpIdx].groupId = actionDb->actionId;
1635          switch(actionDb->definition.formatType)
1636          {
1637             case 1:
1638                {
1639                   format1Action = &actionDb->definition.choice.format1;
1640                   macStatsModificationReq->statsGrpList[grpIdx].periodicity = format1Action->granularityPeriod;
1641
1642                   statsModifyReqIdx = 0;
1643                   node = cmLListFirst(&format1Action->measurementInfoList);
1644                   while(node)
1645                   {
1646                      /* [Step -4] */
1647                      measInfo = (MeasurementInfo *)(node->node);
1648                      switch(measInfo->measurementTypeId)
1649                      {
1650                         case 1:
1651                            {
1652                               macStatsModificationReq->statsGrpList[grpIdx].statsList[statsModifyReqIdx++] = MAC_DL_TOTAL_PRB_USAGE;
1653                               break;
1654                            }
1655                         case 2:
1656                            {
1657                               macStatsModificationReq->statsGrpList[grpIdx].statsList[statsModifyReqIdx++] = MAC_UL_TOTAL_PRB_USAGE;
1658                               break;
1659                            }
1660                         default:
1661                            {
1662                               DU_LOG("\nERROR  -->  E2AP : Invalid measurement name");
1663                               break;
1664                            }
1665                      }
1666                      node = node->next;
1667                   }
1668                   macStatsModificationReq->statsGrpList[grpIdx].numStats = statsModifyReqIdx;
1669                   break;
1670                }
1671             default:
1672                {
1673                   DU_LOG("\nERROR  -->  E2AP : fillRicSubsInMacStatsModificationReq: Only Action Definition Format 1 supported");
1674                   break;
1675                }
1676          }
1677          if(macStatsModificationReq->statsGrpList[grpIdx].numStats)
1678             grpIdx++;
1679       }
1680       actionNode = actionNode->next;
1681    }
1682
1683    /* [Step -5] */
1684    macStatsModificationReq->numStatsGroup = grpIdx;
1685    if(macStatsModificationReq->numStatsGroup)
1686    {
1687       return ROK;
1688    }
1689    return RFAILED;
1690 }
1691
1692 /**********************************************************************
1693   End of file
1694  **********************************************************************/
1695