[Epic-ID: ODUHIGH-516][Task-ID: ODUHIGH-530] Processing of RIC Subscription Modificat...
[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  *             Config Type
206  * @return Action Info DB
207  *         NULL, in case of failure
208  *
209  * ****************************************************************/
210 ActionInfo *fetchActionInfoFromActionId(uint8_t actionId, RicSubscription *ricSubscriptionInfo, CmLList ** actionNode, ConfigType cfgType)
211 {
212    ActionInfo *actionInfoDb = NULLP;
213
214    CM_LLIST_FIRST_NODE(&ricSubscriptionInfo->actionSequence, *actionNode);
215    while(*actionNode)
216    {
217       actionInfoDb = (ActionInfo*)((*actionNode)->node);
218       if(actionInfoDb && (actionInfoDb->actionId == actionId) && (actionInfoDb->action == cfgType))
219       {
220          break;
221       }
222       *actionNode= (*actionNode)->next;
223       actionInfoDb = NULLP;
224    }
225    
226    if(!actionInfoDb) 
227    {
228       DU_LOG("\nERROR  -->  E2AP : fetchActionInfoFromActionId: Action Id [%d] not found in \
229             subscription info [Requestor id : %d] [Instance Id : %d]", actionId,\
230             ricSubscriptionInfo->requestId.requestorId, ricSubscriptionInfo->requestId.instanceId);
231
232    }
233    return actionInfoDb;
234 }
235
236 /*******************************************************************
237  *
238  * @brief Fetch subscripton DB 
239  *
240  * @details
241  *
242  *    Function : fetchSubsInfoFromRicReqId
243  *
244  *    Functionality: Fetches subscription DB from RAN Function DB
245  *       using RIC Request ID
246  *
247  * @params[in] RIC Request ID 
248  *             RAN Function DB
249  *             Pointer to RIC Subscription node to be searched
250  * @return RIC Subscription from RAN Function's subcription list
251  *         NULL, in case of failure
252  *
253  * ****************************************************************/
254 RicSubscription *fetchSubsInfoFromRicReqId(RicRequestId ricReqId, RanFunction *ranFuncDb, CmLList **ricSubscriptionNode)
255 {
256    RicSubscription *ricSubscriptionInfo = NULLP;
257
258    /* Fetch subscription detail in RAN Function DB */
259    CM_LLIST_FIRST_NODE(&ranFuncDb->subscriptionList, *ricSubscriptionNode);
260    while(*ricSubscriptionNode)
261    {
262       ricSubscriptionInfo = (RicSubscription *)((*ricSubscriptionNode)->node);
263       if(ricSubscriptionInfo && (ricSubscriptionInfo->requestId.requestorId == ricReqId.requestorId) &&
264             (ricSubscriptionInfo->requestId.instanceId == ricReqId.instanceId))
265       {
266          break;
267       }
268       *ricSubscriptionNode = (*ricSubscriptionNode)->next;
269       ricSubscriptionInfo = NULLP;
270    }
271
272    if(!ricSubscriptionInfo)
273    {
274       DU_LOG("\nERROR  -->  E2AP : fetchSubsInfoFromRicReqId: Subscription not found for Requestor ID [%d] \
275          Instance ID [%d] in RAN Function ID [%d]", ricReqId.requestorId, ricReqId.instanceId, ranFuncDb->id);
276    }
277
278    return ricSubscriptionInfo;
279 }
280
281 /*******************************************************************
282  *
283  * @brief Fetches RAN Function DB
284  *
285  * @details
286  *
287  *    Function : fetchRanFuncFromRanFuncId
288  *
289  *    Functionality: Fetches RAN function DB from E2AP DB using
290  *       RAN function ID 
291  *
292  * @params[in] RAN Function ID
293  * @return RAN Function DB
294  *         NULL, in case of failure
295  *
296  * ****************************************************************/
297 RanFunction *fetchRanFuncFromRanFuncId(uint16_t ranFuncId)
298 {
299    RanFunction *ranFuncDb = NULLP;
300
301    /* Fetch RAN Function DB */
302    if(duCb.e2apDb.ranFunction[ranFuncId-1].id == ranFuncId)
303    {
304       ranFuncDb = &duCb.e2apDb.ranFunction[ranFuncId-1];
305    }
306    else
307    {
308       DU_LOG("\nERROR  -->  E2AP : fetchRanFuncFromRanFuncId: Invalid RAN Function ID[%d]", ranFuncId);
309    }
310
311    return ranFuncDb;
312 }
313
314 /*******************************************************************
315  *
316  * @brief Fetches subscription info
317  *
318  * @details
319  *
320  *    Function : fetchSubsInfoFromSubsId
321  *
322  *    Functionality: 
323  *       1. Firstly, RAN Function ID and RIC request ID is extracted
324  *          from Subscription ID 
325  *       2. Using RAN Function ID, RAN Function DB is searched
326  *       3. Using RIC Request ID, the subscription DB is searched in
327  *          RAN Function DB
328  *
329  * @params[in] Subscription ID
330  *             RAN Function DB
331  *             RIC Subscription node from RAN Func's Subscription list
332  * @return ROK
333  *         RFAILED
334  *
335  * ****************************************************************/
336 uint8_t fetchSubsInfoFromSubsId(uint64_t subscriptionId, RanFunction **ranFuncDb, CmLList **ricSubscriptionNode, \
337    RicSubscription **ricSubscriptionInfo)
338 {
339    uint16_t ranFuncId = 0;
340    RicRequestId ricReqId;
341
342    memset(&ricReqId, 0, sizeof(RicRequestId));
343
344    /* Decode subscription ID o get RIC Request ID and RAN Function ID */
345    decodeSubscriptionId(subscriptionId, &ranFuncId, &ricReqId);
346
347    /* Fetch RAN Function DB using RAN Function ID */
348    *ranFuncDb = fetchRanFuncFromRanFuncId(ranFuncId);
349    if((*ranFuncDb) == NULLP)
350    {
351       return RFAILED;
352    }
353
354    /* Fetch Sunscription DB from RAN Function using RIC Request ID */
355    *ricSubscriptionInfo = fetchSubsInfoFromRicReqId(ricReqId, *ranFuncDb, ricSubscriptionNode);
356    if((*ricSubscriptionInfo) == NULLP)
357    {
358       return RFAILED;
359    }
360
361    return ROK;
362 }
363
364 /*******************************************************************
365  *
366  * @brief Sends E2 msg over SCTP
367  *
368  * @details
369  *
370  *    Function : SendE2APMsg
371  *
372  *    Functionality: Sends E2 msg over SCTP
373  *
374  * @params[in] Region region
375  *             Pool pool
376  * @return ROK     - success
377  *         RFAILED - failure
378  *
379  * ****************************************************************/
380
381 uint8_t SendE2APMsg(Region region, Pool pool, char *encBuf, int encBufSize)
382 {
383    Buffer *mBuf=NULLP;
384
385    if(ODU_GET_MSG_BUF(region, pool, &mBuf) == ROK)
386    {
387       if(ODU_ADD_POST_MSG_MULT((Data *)encBuf, encBufSize, mBuf) == ROK)
388       {
389          ODU_PRINT_MSG(mBuf, 0,0);
390
391          if(sctpSend(mBuf, E2_INTERFACE) != ROK)
392          {
393             DU_LOG("\nERROR  -->  E2AP : SCTP Send for E2  failed");
394             ODU_PUT_MSG_BUF(mBuf);
395             return RFAILED;
396          }
397       }
398       else
399       {
400          DU_LOG("\nERROR  -->  E2AP : ODU_ADD_POST_MSG_MULT failed");
401          ODU_PUT_MSG_BUF(mBuf);
402          return RFAILED;
403       }
404       ODU_PUT_MSG_BUF(mBuf);
405    }
406    else
407    {
408       DU_LOG("\nERROR  -->  E2AP : Failed to allocate memory");
409       return RFAILED;
410    }
411
412    return ROK;
413 } /* SendE2APMsg */
414
415 /*******************************************************************
416  *
417  * @brief Resets E2 
418  *
419  * @details
420  *
421  *    Function : ResetE2Request
422  *
423  *    Functionality: This function resets E2.
424  *       As per ORAN WG3 E2GAP v3.0 Spec, section 5.5.3
425  *       If E2 node initates reset procedure then:
426  *        a. Send reset request to RIC
427  *        b. Delete any pre-established RIC subscriptions
428  *        c. Gracefully terminates any ongoing RIC services
429  *       If RIC initiates reset procedure then :
430  *        a. Delete any pre-established RIC subscriptions
431  *        b. Gracefully terminates any ongoing RIC services
432  *        c. Send reset response to RIC
433  *
434  * @params[in]
435  * @return ROK     - success
436  *         RFAILED - failure
437  *
438  * ****************************************************************/
439 uint8_t ResetE2Request(E2ProcedureDirection dir, E2FailureCause resetCause)
440 {
441    /* Send Reset Request to RIC if DU detects any abnormal failure */
442    if(dir == E2_NODE_INITIATED)
443    {
444       if(BuildAndSendE2ResetRequest(resetCause) != ROK)
445       {
446          DU_LOG("\nERROR  -->  E2AP : BuildAndSendE2ResetRequest failed");
447          return RFAILED;
448       }
449    }
450
451    /* TODO when RIC subscription service model is implemented
452       Process following steps of resetting E2
453       1. Deletes any pre-established RIC subscriptions
454       2. Gracefully terminates any ongoing RIC services
455     */
456
457    /* Send Reset Response if RIC initiated Reset request is received at DU */
458    if(dir == RIC_INITIATED)
459    {
460       //BuildAndSendE2ResetResponse();
461    }   
462    return ROK;
463 }
464
465 /*******************************************************************
466  *
467  * @brief Fill RIC Subscription datils in MAC Statistics Request
468  *
469  * @details
470  *
471  *    Function : fillRicSubsInMacStatsReq
472  *
473  *    Functionality: Fill RIC Subscription datils in MAC Statistics 
474  *       Request
475  *
476  * @params[in] MAC Statistics Request to be filled
477  *             RIC Subscription Info
478  *
479  * @return ROK     - success
480  *         RFAILED - failure
481  *
482  * ****************************************************************/
483 uint8_t fillRicSubsInMacStatsReq(MacStatsReq *macStatsReq, RicSubscription* ricSubscriptionInfo)
484 {
485    uint8_t    grpIdx = 0, statsIdx = 0;
486    uint64_t   subscriptionId = 0;
487    ActionInfo *actionDb = NULLP;
488    CmLList *actionNode = NULLP;
489    ActionDefFormat1 *format1Action = NULLP;
490
491    /* Generate subscription ID using RIC Request ID and RAN Function ID */
492    encodeSubscriptionId(&subscriptionId, ricSubscriptionInfo->ranFuncId, ricSubscriptionInfo->requestId);
493
494    macStatsReq->subscriptionId = subscriptionId;
495    CM_LLIST_FIRST_NODE(&ricSubscriptionInfo->actionSequence, actionNode);
496    while(actionNode)
497    {
498       actionDb = (ActionInfo*)(actionNode->node);
499       if(actionDb->action == CONFIG_ADD)
500       {
501          macStatsReq->statsGrpList[grpIdx].groupId = actionDb->actionId;
502          switch(actionDb->definition.formatType)
503          {
504             case 1:
505                {
506                   format1Action = &actionDb->definition.choice.format1;
507                   macStatsReq->statsGrpList[grpIdx].periodicity = format1Action->granularityPeriod;
508
509                   CmLList *node = NULLP;
510                   MeasurementInfo *measInfo = NULLP;
511                   statsIdx = 0;
512                   /* Update DL PRB Usage for all stats group which requested for DL Total PRB Usage */
513                   node = cmLListFirst(&format1Action->measurementInfoList);
514                   while(node)
515                   {
516                      measInfo = (MeasurementInfo *)(node->node);
517                      switch(measInfo->measurementTypeId)
518                      {
519                         case 1:
520                            {
521                               macStatsReq->statsGrpList[grpIdx].statsList[statsIdx++] = MAC_DL_TOTAL_PRB_USAGE;
522                               break;
523                            }
524                         case 2:
525                            {
526                               macStatsReq->statsGrpList[grpIdx].statsList[statsIdx++] = MAC_UL_TOTAL_PRB_USAGE;
527                               break;
528                            }
529                         default:
530                            {
531                               DU_LOG("\nERROR  -->  E2AP : Invalid measurement name");
532                               break;
533                            }
534                      }
535                      node = node->next;
536                   }
537                   macStatsReq->statsGrpList[grpIdx].numStats = statsIdx;
538                   break;
539                }
540             default:
541                {
542                   DU_LOG("\nERROR  -->  E2AP : fillRicSubsInMacStatsReq: Only Action Definition Format 1 supported");
543                   break;
544                }
545          }
546          if(macStatsReq->statsGrpList[grpIdx].numStats)
547             grpIdx++;
548       }
549       actionNode = actionNode->next;
550    }
551
552    macStatsReq->numStatsGroup = grpIdx;
553    if(macStatsReq->numStatsGroup)
554    {
555       return ROK;
556    }
557    return RFAILED;
558 }
559
560 /*******************************************************************
561  *
562  * @brief Rejects all actions received in a subscription request
563  *
564  * @details
565  *
566  *    Function : duRejectAllStatsGroup
567  *
568  *    Functionality: Rejects all actions received in a subscription
569  *       request by :
570  *       a. Removing the subscription entry from RAN function
571  *       b. Sending RIC Subscription Failure to RIC with appropriate
572  *          cause of failure
573  *
574  * @params[in] RAN Function DB
575  *             Subscription entry in RAN Function subscription list
576  *             Statistics Response from MAC
577  *
578  * @return ROK     - success
579  *         RFAILED - failure
580  *
581  * ****************************************************************/
582 uint8_t rejectAllStatsGroup(RanFunction *ranFuncDb, CmLList *ricSubscriptionNode, MacStatsRsp *statsRsp)
583 {
584    uint8_t ret = ROK;
585    RicRequestId  requestId;
586    E2FailureCause failureCause;
587
588    /* Delete subcription from RAN Function */
589    memcpy(&requestId, &((RicSubscription *)ricSubscriptionNode->node)->requestId, sizeof(RicRequestId));
590    cmLListDelFrm(&ranFuncDb->subscriptionList, ricSubscriptionNode);
591    deleteRicSubscriptionNode(ricSubscriptionNode);
592    ricSubscriptionNode = NULLP;
593    convertDuCauseToE2Cause(statsRsp->statsGrpRejectedList[0].cause, &failureCause);
594
595    /* Send RIC subscription failure to RIC */
596    ret = BuildAndSendRicSubscriptionFailure(requestId, ranFuncDb->id, failureCause);
597    return ret;
598 }
599
600 /*******************************************************************
601  *
602  * @brief Process statistics response received for subscription 
603  * modification req and send the ric subscription response msg
604  *
605  * @details
606  *
607  *    Function : procStatsRspForSubsModReq
608  *
609  *    Functionality: Processes statistics configuration response
610  *     received for subscription modification req. 
611  *     [Step 1] - Fetch pendingSubsModRsp list from ran func db 
612  *     based on RIC request info.
613  *     [Step 2] - Traverse each index of accepted list received in
614  *     stats response.
615  *          [Step 2.1] - Added each action related info in pending 
616  *          rsp's accepted list and mark action status CONFIG_UNKNOWN.
617  *     [Step 3] - Traverse each index of rejected list received in
618  *     stats response.
619  *          [Step 3.1] - Added each action related info in pending 
620  *          rsp's rejected list and delete the action info from Db.
621  *     [Step 4] - Set addActionCompleted true, and  process the Pending
622  *          Subscription modification rsp list.
623  *
624  * @params[in]
625  *             Mac Stats Rsp
626  *             Ran Function info
627  *             Ric subscription info
628  *
629  * @return ROK     - success
630  *         RFAILED - failure
631  *
632  * ****************************************************************/
633 uint8_t procStatsRspForSubsModReq(MacStatsRsp *statsRsp, RanFunction *ranFuncDb, RicSubscription *ricSubscriptionInfo)
634 {
635    uint8_t idx = 0;
636    uint8_t actionId = 0;
637    CmLList *actionNode = NULLP;
638    ActionInfo *actionInfoDb = NULLP;
639    PendingSubsModRspInfo *pendingSubsModRsp = NULLP;
640    
641    /* Step - 1 */
642    for(idx=0; idx<ranFuncDb->numPendingSubsModRsp; idx++)
643    {
644       if((ranFuncDb->pendingSubsModRspInfo[idx].requestId.requestorId == ricSubscriptionInfo->requestId.requestorId) &&
645             (ricSubscriptionInfo->requestId.instanceId == ricSubscriptionInfo->requestId.instanceId))
646       {
647          pendingSubsModRsp = &ranFuncDb->pendingSubsModRspInfo[idx];
648          break;
649       }
650    }
651    
652    if(pendingSubsModRsp == NULLP)
653    {
654       DU_LOG("\nERROR  -->  E2AP : failed in function %s at line %d",__func__,__LINE__);
655       return RFAILED;
656    }
657
658    /* Step - 2 */
659    for(idx=0; idx<statsRsp->numGrpAccepted; idx++)
660    {
661       actionInfoDb = NULLP;
662
663       actionId = statsRsp->statsGrpAcceptedList[idx];
664       actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo, &actionNode, CONFIG_ADD);
665       if(actionInfoDb)
666       {
667          /* Step - 2.1 */
668          actionInfoDb->action = CONFIG_UNKNOWN;
669          pendingSubsModRsp->addActionStatus.acceptedActionList[pendingSubsModRsp->addActionStatus.numOfAcceptedActions++] = actionId;
670       }
671    }
672
673    /* Step - 3 */
674    for(idx=0; idx<statsRsp->numGrpRejected; idx++)
675    {
676       actionInfoDb = NULLP;
677       actionId = statsRsp->statsGrpRejectedList[idx].groupId;
678       actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo, &actionNode, CONFIG_ADD);
679       if(actionInfoDb)
680       {
681          /* Step - 3.1 */
682          cmLListDelFrm(&ricSubscriptionInfo->actionSequence, actionNode);
683          deleteActionSequence(actionNode);
684          pendingSubsModRsp->addActionStatus.rejectedActionList[pendingSubsModRsp->addActionStatus.numOfRejectedActions].id = actionId;
685          convertDuCauseToE2Cause(statsRsp->statsGrpRejectedList[idx].cause, \
686                &pendingSubsModRsp->addActionStatus.rejectedActionList[pendingSubsModRsp->addActionStatus.numOfRejectedActions].failureCause);
687          pendingSubsModRsp->addActionStatus.numOfRejectedActions++;
688       }
689    }
690    
691    /* Step - 4 */
692    pendingSubsModRsp->addActionCompleted =true; 
693    if(duProcPendingSubsModRsp(pendingSubsModRsp) != ROK)
694    {
695       DU_LOG("\nERROR  -->  E2AP : failed in function %s at line %d",__func__,__LINE__);
696       return RFAILED;
697    }
698    return ROK;
699 }
700
701 /*******************************************************************
702  *
703  * @brief Process statistics response for subscription req and 
704  * send the ric subscription response msg
705  *
706  * @details
707  *
708  *    Function : procStatsRspForSubsReq
709  *
710  *    Functionality: Processes statistics configuration response
711  *     received for subscription req.  
712  *     [Step 1] - Fetch PendingSubsRspInfo list from ran func db 
713  *     based on RIC request info.
714  *     [Step 2] - If all stats group got rejected then send delete
715  *     ric subs action info from db and send ric subscription delete
716  *     message to ric
717  *     [Step 3] - Store and start RIC Subscription reporting timer.
718  *     [Step 4] - Traverse each index of accepted list received in
719  *     stats response.
720  *          [Step 4.1] - Added each action related info in pending 
721  *          rsp's accepted list and mark action status CONFIG_UNKNOWN.
722  *     [Step 5] - Traverse each index of rejected list received in
723  *     stats response.
724  *          [Step 5.1] - Added each action related info in pending 
725  *          rsp's rejected list and delete the action info from Db.
726  *     [Step 6] - Send subscription response with accepted and rejected 
727  *     action lists to RIC.
728  *
729  * @params[in] 
730  *             Mac Stats Rsp
731  *             Ran Function info
732  *             Ric subscription node
733  *             Ric subscription info
734  *
735  * @return ROK     - success
736  *         RFAILED - failure
737  *
738  * ****************************************************************/
739 uint8_t procStatsRspForSubsReq(MacStatsRsp *statsRsp, RanFunction *ranFuncDb,  CmLList *ricSubscriptionNode, RicSubscription *ricSubscriptionInfo)
740 {
741    uint8_t idx = 0;
742    uint8_t actionId = 0;
743    uint32_t reportingPeriod = 0;
744    CmLList *actionNode = NULLP;
745    ActionInfo *actionInfoDb = NULLP;
746    PendingSubsRspInfo *pendingSubsRsp = NULLP;
747
748    /* [Step 1]  */
749    for(idx=0; idx<ranFuncDb->numPendingSubsRsp; idx++)
750    {
751       if((ranFuncDb->pendingSubsRspInfo[idx].requestId.requestorId == ricSubscriptionInfo->requestId.requestorId) &&
752             (ricSubscriptionInfo->requestId.instanceId == ricSubscriptionInfo->requestId.instanceId))
753       {
754          pendingSubsRsp = &ranFuncDb->pendingSubsRspInfo[idx];
755          break;
756       }
757    }
758    
759    if(pendingSubsRsp == NULLP)
760    {
761       DU_LOG("\nERROR  -->  E2AP : failed in function %s at line %d",__func__,__LINE__);
762       return RFAILED;
763    }
764    
765    if(statsRsp->numGrpAccepted == 0)
766    {
767       /* [Step 2 ]  */
768       rejectAllStatsGroup(ranFuncDb, ricSubscriptionNode, statsRsp);
769    }
770    else
771    {
772       /* [Step 3 ]  */
773       switch(ricSubscriptionInfo->eventTriggerDefinition.formatType)
774       {
775          case 1:
776             {
777                reportingPeriod = ricSubscriptionInfo->eventTriggerDefinition.choice.format1.reportingPeriod;
778                storeReportStartTime(&ricSubscriptionInfo->eventTriggerDefinition.choice.format1.startTime);
779                break;
780             }
781          default:
782             {
783                DU_LOG("\nERROR  -->  E2AP : Invalid event trigger format of RIC subscription");
784                return RFAILED;
785             }
786       }
787       if(duChkTmr((PTR)ricSubscriptionInfo, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR) != true)
788       {
789          duStartTmr((PTR)ricSubscriptionInfo, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR, reportingPeriod);
790       }
791       else
792       {
793          DU_LOG("\nERROR  -->  E2AP : RIC Subscription reporting timer already running for RIC Subscription");
794          return RFAILED;
795       }
796
797
798       /* [ Step 4 ]  */
799       for(idx=0; idx<statsRsp->numGrpAccepted; idx++)
800       {
801          actionInfoDb = NULLP;
802
803          actionId = statsRsp->statsGrpAcceptedList[idx];
804          actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo, &actionNode, CONFIG_ADD);
805          if(actionInfoDb)
806          {
807             /* [ Step 4.1 ]  */
808             actionInfoDb->action = CONFIG_UNKNOWN;
809             pendingSubsRsp->acceptedActionList[pendingSubsRsp->numOfAcceptedActions++] = actionId;
810          }
811       }
812
813       /* [ Step 5 ]  */
814       for(idx=0; idx<statsRsp->numGrpRejected; idx++)
815       {
816          actionInfoDb = NULLP;
817          actionId = statsRsp->statsGrpRejectedList[idx].groupId;
818          actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo, &actionNode, CONFIG_ADD);
819          if(actionInfoDb)
820          {
821             /* [ Step 5.1 ]  */
822             cmLListDelFrm(&ricSubscriptionInfo->actionSequence, actionNode);
823             deleteActionSequence(actionNode);
824             pendingSubsRsp->rejectedActionList[pendingSubsRsp->numOfRejectedActions].id = actionId;
825             convertDuCauseToE2Cause(statsRsp->statsGrpRejectedList[idx].cause, \
826                   &pendingSubsRsp->rejectedActionList[pendingSubsRsp->numOfRejectedActions].failureCause);
827             pendingSubsRsp->numOfRejectedActions++;
828          }
829       }
830
831       /* [ Step 6]  */
832       if(BuildAndSendRicSubscriptionRsp(pendingSubsRsp) != ROK)
833       {
834          DU_LOG("\nERROR  -->  E2AP : Failed to build and send RIC Subscription rsp");
835          return RFAILED;
836       }
837    }
838    memset(pendingSubsRsp, 0, sizeof(PendingSubsRspInfo));
839    ricSubscriptionInfo->action = CONFIG_UNKNOWN;
840    return ROK;
841 }
842
843 /*******************************************************************
844  *
845  * @brief Process statistics response from MAC
846  *
847  * @details
848  *
849  *    Function : e2ProcStatsRsp
850  *
851  *    Functionality: Processes statistics configuration response
852  *       from MAC.
853  *       [Step -1]Fetch RAN Function and Subscription DB using 
854  *       subscription Id received in statistics response
855  *       [Step -2]check ricSubscriptionInfo's action
856  *          [Step 2.1]if action == CONFIG_ADD, if no group 
857  *          accepted then reject all stats group and send ric
858  *          subscription failure. Else process stats rsp for 
859  *          RIC subscription response.
860  *          [Step 2.1]if action == CONFIG_MOD, process stats rsp 
861  *          for RIC subscription modification response.
862  *
863  * @params[in] Statistics response received from MAC
864  *
865  * @return ROK     - success
866  *         RFAILED - failure
867  *
868  * ****************************************************************/
869 uint8_t e2ProcStatsRsp(MacStatsRsp *statsRsp)
870 {
871    RanFunction *ranFuncDb = NULLP;
872    CmLList *ricSubscriptionNode = NULLP;
873    RicSubscription *ricSubscriptionInfo = NULLP;
874
875    /*  [Step -1] */
876    if(fetchSubsInfoFromSubsId(statsRsp->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK)
877    {
878       DU_LOG("\nERROR  -->  E2AP : failed in function %s at line %d",__func__,__LINE__);
879       return RFAILED;
880    }
881    
882    /*  [Step -2] */
883    if(ricSubscriptionInfo->action == CONFIG_ADD)
884    {
885       /*  [Step -2.1] */
886       if(procStatsRspForSubsReq(statsRsp, ranFuncDb, ricSubscriptionNode, ricSubscriptionInfo) != ROK)
887       {
888          rejectAllStatsGroup(ranFuncDb, ricSubscriptionNode, statsRsp);
889          DU_LOG("\nERROR  -->  E2AP : Failed to build and send RIC Subscription rsp");
890          return RFAILED;
891       }
892    }
893    else if(ricSubscriptionInfo->action == CONFIG_MOD)
894    {
895       /*  [Step -2.2] */
896       if(procStatsRspForSubsModReq(statsRsp, ranFuncDb, ricSubscriptionInfo) != ROK)
897       {
898          DU_LOG("\nERROR  -->  E2AP : Failed to build and send RIC Subscription rsp");
899          return RFAILED;
900       }
901    }
902    return ROK;
903 }
904
905 /*******************************************************************
906  *
907  * @brief Extract and store statistics received from DU layers
908  *
909  * @details
910  *
911  *    Function : e2ProcStatsInd
912  *
913  *    Functionality: Extract statistics received from DU layers
914  *       and store in respective RAN function's subscription's
915  *       action
916  *
917  * @params[in] Statistics Indication message received from MAC
918  * @return ROK-success
919  *         RFAILED-failure
920  *
921  * ****************************************************************/
922 uint8_t e2ProcStatsInd(MacStatsInd *statsInd)
923 {
924    uint8_t statsIdx = 0;
925    RanFunction *ranFuncDb = NULLP;
926    CmLList *ricSubscriptionNode = NULLP;
927    CmLList *actionNode = NULLP;
928    RicSubscription *ricSubscriptionInfo = NULLP;
929    ActionInfo *actionInfo = NULLP;
930    ActionDefFormat1 *actionFormat = NULLP;
931    char e2MeasTypeName[STRING_SIZE_150_BYTES] = "";
932    MeasurementInfo *measInfo = NULLP;
933    CmLList *measInfoNode = NULLP;
934    double *measValue = NULLP;
935    CmLList *measValueNode = NULLP;
936
937    /* TODO : When stats indication is received
938     * DU APP searches for the message type in E2AP RIC subscription
939     * database and stores in the value in the list of subscribed measurements
940     *
941     * This will be implemented in next gerrit.
942     */
943
944    /* Fetch RAN Function and Subscription DB using subscription Id received
945     * in statistics response */
946    if(fetchSubsInfoFromSubsId(statsInd->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK)
947    {
948       DU_LOG("\nERROR  -->  E2AP : %s : Failed to fetch subscriprtion details",__func__);
949       return RFAILED;
950    }
951
952    /* Fetch RIC subscription's action DB */
953    actionInfo = fetchActionInfoFromActionId(statsInd->groupId, ricSubscriptionInfo, &actionNode, CONFIG_UNKNOWN);
954    if(actionInfo == NULLP)
955    {
956       DU_LOG("\nERROR  -->  E2AP : %s: Failed to fetch action ID [%d]",__func__, statsInd->groupId);
957       return RFAILED;
958    }
959
960    /* Check Action format */
961    switch(actionInfo->definition.formatType)
962    {
963       case 1:
964          {
965             actionFormat = &actionInfo->definition.choice.format1;
966             break;
967          }
968       default:
969          {
970             DU_LOG("\nERROR  -->  E2AP : %s: Action Format [%d] is not supported", __func__,\
971                   actionInfo->definition.formatType);
972             return RFAILED;
973          }
974    }
975
976    /* Fetch each Measurement info from action info and store its reported value in DB */
977    for(statsIdx = 0; statsIdx < statsInd->numStats; statsIdx++)
978    {
979       memset(e2MeasTypeName, 0, STRING_SIZE_150_BYTES);
980       measInfo = NULLP;
981       measInfoNode = NULLP;
982
983       /* Convert Measurement type from MAC-supported format to E2-supported format */
984       if(convertMacMeasTypeToE2MeasType(statsInd->measuredStatsList[statsIdx].type, e2MeasTypeName) != ROK)
985       {
986          DU_LOG("\nERROR  -->  E2AP : %s: Failed to convert measurement type from MAC-supported\
987             MAC-supported format to E2-supported format",__func__);
988          continue;
989       }
990       
991       /* Fetch Measurement Info using E2-supported measurement type name */
992       measInfo = fetchMeasInfoFromMeasTypeName(e2MeasTypeName, &actionFormat->measurementInfoList, &measInfoNode); 
993       if(measInfo == NULLP)
994       {
995          DU_LOG("\nERROR  -->  E2AP : %s: Measurement Type Name [%s] not found", __func__,e2MeasTypeName); 
996          continue;
997       }
998       
999       /* Store the measurement value in the measurement info DB fetched */
1000       DU_ALLOC(measValue, sizeof(double));
1001       if(!measValue)
1002       {
1003          DU_LOG("\nERROR  -->  E2AP : %s: Memory allocation failed at line [%d]",__func__, __LINE__);
1004          return RFAILED; 
1005       }
1006       *measValue = statsInd->measuredStatsList[statsIdx].value;
1007
1008       DU_ALLOC(measValueNode, sizeof(CmLList));
1009       if(!measValueNode)
1010       {
1011          DU_LOG("\nERROR  -->  E2AP : %s : Memory allocation failed at line [%d]",__func__, __LINE__);
1012          DU_FREE(measValue, sizeof(double));
1013          return RFAILED; 
1014       }
1015       measValueNode->node = (PTR) measValue;
1016       cmLListAdd2Tail(&measInfo->measuredValue, measValueNode);
1017    }
1018    return ROK;
1019 }
1020
1021 /*******************************************************************
1022  *
1023  * @brief Handle RIC Subscription reporting timer expry
1024  *
1025  * @details
1026  *
1027  *    Function : E2apHdlRicSubsReportTmrExp
1028  *
1029  *    Functionality: On expiry of RIC subscription reporting
1030  *       timer expiry, RIC indication is sent for all actions
1031  *       in RIC subscription
1032  *
1033  * @params[in] RIC subscription DB
1034  * @return void
1035  *
1036  * ****************************************************************/
1037 void E2apHdlRicSubsReportTmrExp(RicSubscription *ricSubscription)
1038 {
1039    uint32_t reportingPeriod = 0;
1040    ActionInfo *action=NULLP;
1041    CmLList *actionNode=NULLP;
1042
1043    CM_LLIST_FIRST_NODE(&ricSubscription->actionSequence, actionNode);
1044    while(actionNode)
1045    {
1046       action = (ActionInfo*)actionNode->node;
1047       BuildAndSendRicIndication(ricSubscription, action);
1048       actionNode = actionNode->next;
1049    }
1050
1051    /* Start RIC Subscription reporting timer again */
1052    switch(ricSubscription->eventTriggerDefinition.formatType)
1053    {
1054       case 1:
1055          {
1056             reportingPeriod = ricSubscription->eventTriggerDefinition.choice.format1.reportingPeriod;
1057             /* Save the start time of reporting period */
1058             storeReportStartTime(&ricSubscription->eventTriggerDefinition.choice.format1.startTime);
1059             break;
1060          }
1061       default:
1062          return;
1063    }
1064    if(duChkTmr((PTR)ricSubscription, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR) != true)
1065    {
1066       duStartTmr((PTR)ricSubscription, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR, reportingPeriod);
1067    }
1068    else
1069    {
1070       DU_LOG("\nERROR  -->  E2AP : Failed in %s at line %d", __func__, __LINE__);
1071       return;
1072    }
1073 }
1074
1075 /******************************************************************
1076  *
1077  * @brief Search E2 node component with the help of action type
1078  *
1079  * @details
1080  *
1081  *    Function : fetchE2NodeComponentInfo 
1082  *
1083  *    Functionality: Search E2 node component with the help of action type 
1084  *
1085  * @params[in] 
1086  *       Type of interface 
1087  *       Component Id
1088  *       Pointer to E2 component node to be searched 
1089  * @return CmLList
1090  *
1091  * ****************************************************************/
1092
1093 E2NodeComponent *fetchE2NodeComponentInfo(InterfaceType interfaceType, uint64_t componentId, CmLList **e2ComponentNode)
1094 {
1095    E2NodeComponent *e2NodeComponentInfo=NULLP;
1096
1097    if(duCb.e2apDb.e2NodeComponentList.count)
1098    {
1099       CM_LLIST_FIRST_NODE(&duCb.e2apDb.e2NodeComponentList, *e2ComponentNode);
1100       while(*e2ComponentNode)
1101       {
1102          e2NodeComponentInfo = (E2NodeComponent*)((*e2ComponentNode)->node);
1103          if((e2NodeComponentInfo->interfaceType == interfaceType) && (e2NodeComponentInfo->componentId == componentId))
1104          {
1105             break;
1106          }
1107          
1108          *e2ComponentNode = (*e2ComponentNode)->next;
1109          e2NodeComponentInfo = NULLP;
1110       }
1111    }
1112    return e2NodeComponentInfo; 
1113 }
1114
1115 /*******************************************************************
1116  *
1117  * @brief fill E2 node component rsp info
1118  *
1119  * @details
1120  *
1121  *    Function : fillE2NodeComponentRspInfo 
1122  *
1123  * Functionality: fill E2 Node Component rsp info 
1124  *
1125  * @parameter
1126  *       Type of interface 
1127  *       Component action type
1128  *       Size of buffer which needs to be store
1129  *       buffer string which needs to be store 
1130  * @return ROK     - success
1131  *         RFAILED - failure
1132  *
1133  * ****************************************************************/
1134
1135 uint8_t fillE2NodeComponentRspInfo(InterfaceType interfaceType, uint64_t componentId, uint8_t action, uint8_t bufSize, char *bufString)
1136 {
1137    E2NodeConfig *configInfo=NULLP;
1138    E2NodeComponent *e2NodeComponentInfo= NULLP;
1139    CmLList  *node = NULLP;
1140
1141    e2NodeComponentInfo = fetchE2NodeComponentInfo(interfaceType, componentId, &node);
1142    if(!e2NodeComponentInfo) 
1143    {
1144       DU_LOG("\nERROR  -->  E2AP : Unable to find the node");
1145       return RFAILED;
1146    }
1147
1148    switch(action)
1149    {
1150       case E2_NODE_COMPONENT_ADD:
1151          {
1152             configInfo = e2NodeComponentInfo->addConfiguration;    
1153             break;
1154          }
1155       case E2_NODE_COMPONENT_UPDATE: 
1156          {
1157             configInfo = e2NodeComponentInfo->updateConfiguration;
1158             break;
1159          }
1160       default:
1161          {
1162             DU_LOG("\nERROR  -->  E2AP : Invalid action %d received",action);
1163             return RFAILED;
1164          }
1165    }
1166
1167    if(configInfo->componentRequestPart== NULLP)
1168    {
1169       DU_LOG("\nERROR  -->  E2AP : E2 node Component request part is not present");
1170       return RFAILED;
1171    }
1172
1173    configInfo->rspBufSize = bufSize;
1174    DU_ALLOC(configInfo->componentResponsePart, bufSize);
1175    if(configInfo->componentResponsePart == NULLP)
1176    {
1177       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed to store the encoding of rsp");
1178       return RFAILED;
1179    }
1180    memcpy(configInfo->componentResponsePart, bufString, configInfo->rspBufSize);
1181    return ROK;
1182 }
1183
1184 /*******************************************************************
1185  *
1186  * @brief add E2 node component req info
1187  *
1188  * @details
1189  *
1190  *    Function : addE2NodeComponent 
1191  *
1192  * Functionality: add E2 node component req info 
1193  *
1194  * @parameter
1195  *       Type of interface 
1196  *       Component action type
1197  *       Size of buffer which needs to be store
1198  *       buffer string which needs to be store 
1199  * @return ROK     - success
1200  *         RFAILED - failure
1201  *
1202  ******************************************************************/
1203
1204 uint8_t addE2NodeComponent(InterfaceType interfaceType, uint64_t componentId,  uint8_t bufSize, char *bufString)
1205 {
1206    E2NodeComponent *e2NodeComponentInfo= NULLP;
1207    CmLList  *node = NULLP;
1208    
1209    DU_ALLOC(e2NodeComponentInfo, sizeof(E2NodeComponent));
1210    if(!e2NodeComponentInfo)
1211    {
1212       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed in %s at %d",__func__,__LINE__);
1213       return RFAILED;
1214    }
1215    e2NodeComponentInfo->interfaceType =interfaceType;
1216    e2NodeComponentInfo->componentId=componentId;
1217
1218    DU_ALLOC(e2NodeComponentInfo->addConfiguration, sizeof(E2NodeConfig));
1219    if(!e2NodeComponentInfo->addConfiguration)
1220    {
1221       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed in %s at %d",__func__,__LINE__);
1222       return RFAILED;
1223    }
1224
1225    e2NodeComponentInfo->addConfiguration->reqBufSize = bufSize;
1226
1227    DU_ALLOC(e2NodeComponentInfo->addConfiguration->componentRequestPart, bufSize);
1228    if(e2NodeComponentInfo->addConfiguration->componentRequestPart == NULLP)
1229    {
1230       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed in %s at %d",__func__,__LINE__);
1231       DU_FREE(e2NodeComponentInfo, sizeof(E2NodeComponent));
1232       return RFAILED;
1233    }
1234    memcpy(e2NodeComponentInfo->addConfiguration->componentRequestPart, bufString,\
1235    e2NodeComponentInfo->addConfiguration->reqBufSize);
1236
1237    DU_ALLOC(node, sizeof(CmLList));
1238    if(node)
1239    {
1240       node->node = (PTR) e2NodeComponentInfo;
1241       cmLListAdd2Tail(&duCb.e2apDb.e2NodeComponentList, node);
1242    }
1243    else
1244    {
1245       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed in %s at %d",__func__,__LINE__);
1246       DU_FREE(e2NodeComponentInfo->addConfiguration->componentRequestPart, bufSize);
1247       DU_FREE(e2NodeComponentInfo->addConfiguration, sizeof(E2NodeConfig));
1248       DU_FREE(e2NodeComponentInfo, sizeof(E2NodeComponent));
1249       return RFAILED;
1250    }
1251    return ROK;
1252 }
1253
1254 /*******************************************************************
1255  *
1256  * @brief update E2 node component req info
1257  *
1258  * @details
1259  *
1260  *    Function : updateE2NodeComponent 
1261  *
1262  * Functionality: update E2 node component req info 
1263  *
1264  * @parameter
1265  *       Type of interface 
1266  *       Size of buffer which needs to be store
1267  *       buffer string which needs to be store 
1268  * @return ROK     - success
1269  *         RFAILED - failure
1270  *
1271  ******************************************************************/
1272
1273 uint8_t updateE2NodeComponent(InterfaceType interfaceType, uint64_t componentId, uint8_t bufSize, char *bufString)
1274 {
1275    E2NodeComponent *e2NodeComponentInfo= NULLP;
1276    CmLList  *node = NULLP;
1277          
1278    e2NodeComponentInfo = fetchE2NodeComponentInfo(interfaceType, componentId, &node);
1279    if(!e2NodeComponentInfo)
1280    {
1281       DU_LOG("\nERROR  -->  E2AP : Received null information in %s",__func__);
1282       return RFAILED;
1283    }
1284    
1285    DU_ALLOC(e2NodeComponentInfo->updateConfiguration, sizeof(E2NodeConfig));
1286    if(!e2NodeComponentInfo->updateConfiguration)
1287    {
1288       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed in %s at %d",__func__,__LINE__);
1289       return RFAILED;
1290    }
1291
1292    e2NodeComponentInfo->updateConfiguration->reqBufSize = bufSize;
1293
1294    DU_ALLOC(e2NodeComponentInfo->updateConfiguration->componentRequestPart, bufSize);
1295    if(e2NodeComponentInfo->updateConfiguration->componentRequestPart == NULLP)
1296    {
1297       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed in %s at %d",__func__,__LINE__);
1298       DU_FREE(e2NodeComponentInfo->updateConfiguration, sizeof(E2NodeConfig));
1299       return RFAILED;
1300    }
1301
1302    memcpy(e2NodeComponentInfo->updateConfiguration->componentRequestPart, bufString,\
1303    e2NodeComponentInfo->updateConfiguration->reqBufSize);
1304    return ROK;
1305
1306 }
1307
1308 /*******************************************************************
1309  *
1310  * @brief delete E2 node component req info
1311  *
1312  * @details
1313  *
1314  *    Function : deleteE2NodeComponent 
1315  *
1316  * Functionality: delete E2 node component req info 
1317  *
1318  * @parameter
1319  *       Type of interface 
1320  * @return ROK     - success
1321  *         RFAILED - failure
1322  *
1323  ******************************************************************/
1324
1325 uint8_t deleteE2NodeComponent(InterfaceType interfaceType, uint64_t componentId)
1326 {
1327    E2NodeComponent *e2NodeComponentInfo= NULLP;
1328    CmLList  *node = NULLP;
1329          
1330    e2NodeComponentInfo = fetchE2NodeComponentInfo(interfaceType, componentId, &node);
1331    if(!e2NodeComponentInfo)
1332    {
1333       DU_LOG("\nERROR  -->  E2AP : Received null information in %s",__func__);
1334       return RFAILED;
1335    }
1336    
1337    e2NodeComponentInfo->deleteConfiguration = true;
1338    return ROK;
1339 }
1340
1341 /*******************************************************************
1342  *
1343  * @brief fill E2 node component req info
1344  *
1345  * @details
1346  *
1347  *    Function : fillE2NodeComponentReqInfo 
1348  *
1349  * Functionality: fill E2 node component req info 
1350  *
1351  * @parameter
1352  *       Type of interface 
1353  *       Component action type
1354  *       Size of buffer which needs to be store
1355  *       buffer string which needs to be store 
1356  * @return ROK     - success
1357  *         RFAILED - failure
1358  *
1359  ******************************************************************/
1360
1361 uint8_t fillE2NodeComponentReqInfo(InterfaceType interfaceType, uint64_t componentId, uint8_t action, uint8_t bufSize, char *bufString)
1362 {
1363    switch(action)
1364    {
1365       case E2_NODE_COMPONENT_ADD:
1366          {
1367             if(addE2NodeComponent(interfaceType, componentId, bufSize, bufString) != ROK)
1368             {
1369                DU_LOG("\nERROR  -->  E2AP : Failed to add e2 node component");
1370                return RFAILED;
1371             }
1372             break;
1373          }
1374       case E2_NODE_COMPONENT_UPDATE: 
1375          {
1376             if(updateE2NodeComponent(interfaceType, componentId, bufSize, bufString) != ROK)
1377             {
1378                DU_LOG("\nERROR  -->  E2AP : Failed to update e2 node component");
1379                return RFAILED;
1380             }
1381             break;
1382          }
1383       case E2_NODE_COMPONENT_DEL:
1384          {
1385             if(deleteE2NodeComponent(interfaceType, componentId) != ROK)
1386             {
1387                DU_LOG("\nERROR  -->  E2AP : Failed to delete e2 node component");
1388                return RFAILED;
1389             }
1390             break;
1391          }
1392       default:
1393          {
1394             DU_LOG("\nERROR  -->  E2AP : Invalid action %d received",action);
1395             return RFAILED;
1396          }
1397    }
1398
1399    return ROK;
1400 }
1401
1402 /******************************************************************
1403  *
1404  * @brief Delete measured Value list
1405  *
1406  * @details
1407  *
1408  *    Function : deleteMeasuredValueList
1409  *
1410  *    Functionality: Delete measured Value list
1411  *
1412  * @params[in] List of measured Value
1413  *          
1414  * @return void 
1415  *
1416  * ****************************************************************/
1417 void deleteMeasuredValueList(CmLListCp *measuredValueList)
1418 {
1419    CmLList *measValNode = NULLP;
1420
1421    CM_LLIST_FIRST_NODE(measuredValueList, measValNode);
1422
1423    while(measValNode)
1424    {
1425       cmLListDelFrm(measuredValueList, measValNode);
1426       DU_FREE(measValNode->node, sizeof(double));
1427       DU_FREE(measValNode, sizeof(CmLList));
1428       CM_LLIST_FIRST_NODE(measuredValueList, measValNode);
1429    }
1430 }
1431
1432 /******************************************************************
1433  *
1434  * @brief Delete Measurement Info List 
1435  *
1436  * @details
1437  *
1438  *    Function : deleteMeasurementInfoList
1439  *
1440  *    Functionality: Delete Measurement Info List 
1441  *
1442  * @params[in] List of Measurement Info List
1443  *          
1444  * @return void 
1445  *
1446  * ****************************************************************/
1447 void deleteMeasurementInfoList(CmLListCp *measInfoList)
1448 {
1449    CmLList *measInfoNode = NULLP;
1450    MeasurementInfo *measInfo = NULLP;
1451
1452    CM_LLIST_FIRST_NODE(measInfoList, measInfoNode);
1453    while(measInfoNode)
1454    {
1455       measInfo = (MeasurementInfo *)measInfoNode->node;
1456       cmLListDelFrm(measInfoList, measInfoNode);
1457       deleteMeasuredValueList(&measInfo->measuredValue);
1458       DU_FREE(measInfo, sizeof(MeasurementInfo));
1459       DU_FREE(measInfoNode, sizeof(CmLList));
1460       CM_LLIST_FIRST_NODE(measInfoList, measInfoNode);
1461    }
1462 }
1463
1464 /******************************************************************
1465  *
1466  * @brief Delete Ric subscription action 
1467  *
1468  * @details
1469  *
1470  *    Function : deleteActionSequence
1471  *
1472  *    Functionality: Delete Ric subscription action 
1473  *
1474  * @params[in] Action info 
1475  *          
1476  * @return void 
1477  *
1478  * ****************************************************************/
1479 void deleteActionSequence(CmLList *actionNode)
1480 {
1481    ActionInfo *action = NULLP;
1482    ActionDefinition *definition=NULLP;
1483    
1484    if(actionNode)
1485    {
1486       action = (ActionInfo*)actionNode->node;
1487       definition= &action->definition;       
1488
1489       switch(definition->formatType)
1490       {
1491          case 1:
1492             {
1493                deleteMeasurementInfoList(&definition->choice.format1.measurementInfoList);
1494                break;
1495             }
1496
1497          case 2:
1498          case 3:
1499          case 4:
1500          case 5:
1501          default:
1502             {
1503                DU_LOG("\nERROR  -->  E2AP : Format %d does not supported", definition->formatType);
1504                break;
1505             }
1506       }
1507       memset(action, 0, sizeof(ActionInfo));
1508       DU_FREE(actionNode->node, sizeof(ActionInfo));
1509       DU_FREE(actionNode, sizeof(CmLList));
1510    }
1511 }
1512
1513 /******************************************************************
1514  *
1515  * @brief Delete Ric subscription action list
1516  *
1517  * @details
1518  *
1519  *    Function : deleteActionSequenceList
1520  *
1521  *    Functionality: Delete Ric subscription action list
1522  *
1523  * @params[in] Action info list
1524  *
1525  * @return void
1526  *
1527  * ****************************************************************/
1528 void deleteActionSequenceList(CmLListCp *actionList)
1529 {
1530    CmLList *actionNode=NULLP;
1531
1532    CM_LLIST_FIRST_NODE(actionList, actionNode);
1533    while(actionNode)
1534    {
1535       cmLListDelFrm(actionList, actionNode);
1536       deleteActionSequence(actionNode);
1537       CM_LLIST_FIRST_NODE(actionList, actionNode);
1538    }
1539 }
1540
1541 /******************************************************************
1542  *
1543  * @brief Delete Ric subscription node 
1544  *
1545  * @details
1546  *
1547  *    Function : deleteRicSubscriptionNode
1548  *
1549  *    Functionality: Delete Ric subscription node 
1550  *
1551  * @params[in] Ric subscription info 
1552  *          
1553  * @return void 
1554  *
1555  * ****************************************************************/
1556 void deleteRicSubscriptionNode(CmLList *subscriptionNode)
1557 {
1558    RicSubscription *ricSubscriptionInfo = NULLP;
1559
1560    ricSubscriptionInfo = (RicSubscription*)subscriptionNode->node;    
1561
1562    deleteActionSequenceList(&ricSubscriptionInfo->actionSequence);
1563    if(duChkTmr((PTR)ricSubscriptionInfo, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR) == TRUE)
1564    {
1565       duStopTmr((PTR)ricSubscriptionInfo, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR);
1566    }
1567
1568    memset(ricSubscriptionInfo, 0, sizeof(RicSubscription));
1569    DU_FREE(subscriptionNode->node, sizeof(RicSubscription));
1570    DU_FREE(subscriptionNode, sizeof(CmLList));
1571 }
1572
1573 /******************************************************************
1574  *
1575  * @brief Delete ric subscription list from the database
1576  *
1577  * @details
1578  *
1579  *    Function : deleteRicSubscriptionList
1580  *
1581  *    Functionality: Delete ric subscription list 
1582  *
1583  * @params[in]
1584  *    Subscription List to be deleted 
1585
1586  * @return void 
1587  *
1588  * ****************************************************************/
1589 void deleteRicSubscriptionList(CmLListCp *subscriptionList)
1590 {
1591    CmLList *subscriptionNode=NULLP;
1592    
1593    CM_LLIST_FIRST_NODE(subscriptionList, subscriptionNode);
1594    while(subscriptionNode)
1595    {
1596       /* TODO - Remove subscription information from MAC and SCH as well */ 
1597       cmLListDelFrm(subscriptionList, subscriptionNode);
1598       deleteRicSubscriptionNode(subscriptionNode);
1599       CM_LLIST_FIRST_NODE(subscriptionList, subscriptionNode);
1600    }
1601 }
1602
1603 /*******************************************************************
1604  *
1605  * @brief Find all RIC subscriptions to be deleted in all RAN
1606  *    Functions
1607  *
1608  * @details
1609  *
1610  *    Function : fetchRicSubsToBeDeleted
1611  *
1612  * Functionality: Find all RIC subscriptions to be deleted in all
1613  *    RAN functions and store in a temporary list
1614  *
1615  * @parameter Temporary list to store subscriptions to be deleted
1616  * @return void
1617  *
1618  ******************************************************************/
1619 void fetchRicSubsToBeDeleted(CmLListCp *ricSubsToBeDelList)
1620 {
1621    uint16_t ranFuncIdx = 0;
1622    CmLList *subsNode = NULLP;
1623    CmLList *subsToDelNode = NULLP;
1624
1625    for(ranFuncIdx = 0; ranFuncIdx < MAX_RAN_FUNCTION; ranFuncIdx++)
1626    {
1627       if(duCb.e2apDb.ranFunction[ranFuncIdx].id > 0)
1628       {
1629          CM_LLIST_FIRST_NODE(&duCb.e2apDb.ranFunction[ranFuncIdx].subscriptionList, subsNode);
1630          while(subsNode)
1631          {
1632             if(((RicSubscription *)subsNode->node)->action == CONFIG_DEL)
1633             {
1634                DU_ALLOC(subsToDelNode, sizeof(CmLList));
1635                if(!subsToDelNode)
1636                {
1637                   DU_LOG("\nERROR  -->  E2AP : %s: Memory allocation failure at %d", __func__, __LINE__); 
1638                   return;
1639                }
1640                subsToDelNode->node = subsNode->node;
1641                cmLListAdd2Tail(ricSubsToBeDelList, subsToDelNode);
1642             }
1643             subsToDelNode = NULLP;
1644             subsNode = subsNode->next;
1645          }
1646       }
1647    }
1648 }
1649
1650 /******************************************************************
1651  *
1652  * @brief Delete e2 node information from the database
1653  *
1654  * @details
1655  *
1656  *    Function : removeE2NodeInformation 
1657  *
1658  *    Functionality: Delete e2 node information from the database 
1659  *
1660  * @params[in]
1661  *
1662  * @return void 
1663  *
1664 ******************************************************************/
1665 void removeE2NodeInformation()
1666 {
1667    uint16_t ranFuncIdx = 0;
1668    
1669    DU_LOG("\nINFO  -->  E2AP : Deleting all the E2 node configuration");
1670    for(ranFuncIdx=0; ranFuncIdx<MAX_RAN_FUNCTION; ranFuncIdx++)
1671    {
1672       if(duCb.e2apDb.ranFunction[ranFuncIdx].id >0)
1673       {
1674          deleteRicSubscriptionList(&(duCb.e2apDb.ranFunction[ranFuncIdx].subscriptionList));
1675          memset(&(duCb.e2apDb.ranFunction[ranFuncIdx].pendingSubsRspInfo), 0, MAX_PENDING_SUBSCRIPTION_RSP*sizeof(PendingSubsRspInfo));
1676       }
1677    }
1678    memset(&duCb.e2apDb.ricId, 0, sizeof(GlobalRicId));
1679    duCb.e2apDb.numOfTNLAssoc = 0;
1680    memset(&duCb.e2apDb.tnlAssoc, 0, MAX_TNL_ASSOCIATION*sizeof(TNLAssociation));
1681    memset(&ricParams, 0, sizeof(DuSctpDestCb));
1682 }
1683
1684 /*******************************************************************
1685  *
1686  * @brief Extract statistics received from DU layers and delete
1687  * Ric subscription info
1688  *
1689  * @details
1690  *
1691  *    Function :e2ProcStatsDeleteRsp 
1692  *
1693  *    Functionality: Extract statistics received from DU layers
1694  *       and delete ric subscription iformation form db
1695  *
1696  * @params[in] Statistics delete rsp from MAC
1697  * @return ROK-success
1698  *         RFAILED-failure
1699  *
1700  * ****************************************************************/
1701 uint8_t e2ProcStatsDeleteRsp(MacStatsDeleteRsp *statsDeleteRsp)
1702 {
1703    RicRequestId    requestId;
1704    uint16_t        ranFuncId;
1705    RanFunction *ranFuncDb = NULLP;
1706    CmLList *ricSubscriptionNode = NULLP;
1707    RicSubscription *ricSubscriptionInfo = NULLP;
1708    E2FailureCause failureCause;
1709
1710    /* Fetch RAN Function and Subscription DB using subscription Id received
1711     * in statistics delete response */
1712    if(fetchSubsInfoFromSubsId(statsDeleteRsp->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK)
1713    {
1714       DU_LOG("\nERROR  -->  E2AP : e2ProcStatsDeleteRsp: Failed to fetch subscriprtion details");
1715       return RFAILED;
1716    }
1717    ranFuncId = ricSubscriptionInfo->ranFuncId;
1718    memcpy(&requestId, &ricSubscriptionInfo->requestId, sizeof(RicRequestId));
1719
1720    deleteRicSubscriptionNode(ricSubscriptionNode);
1721    
1722    if(statsDeleteRsp->subsDelRsp == MAC_DU_APP_RSP_NOK)
1723    {
1724       if(statsDeleteRsp->subsDelCause == STATS_ID_NOT_FOUND)
1725       {
1726          failureCause.causeType =E2_RIC_REQUEST;
1727          failureCause.cause = E2_REQUEST_INFORMATION_UNAVAILABLE;
1728       }
1729       else
1730       {
1731          failureCause.causeType = E2_MISCELLANEOUS;
1732          failureCause.cause = E2_MISCELLANEOUS_CAUSE_UNSPECIFIED;
1733       }
1734
1735       if(BuildAndSendRicSubscriptionDeleteFailure(ranFuncId, requestId, failureCause) != ROK)
1736       {
1737          DU_LOG("\nERROR  -->  E2AP : e2ProcStatsDeleteRsp: failed to build and send ric subs delete failure");
1738          return RFAILED;
1739       }
1740    }
1741    else
1742    {
1743       if(BuildAndSendRicSubscriptionDeleteResponse(ranFuncId, requestId) != ROK)
1744       {
1745          DU_LOG("\nERROR  -->  E2AP : e2ProcStatsDeleteRsp: failed to build and send ric subs delete rsp");
1746          return RFAILED;
1747       }
1748    }
1749    
1750    return ROK;
1751 }
1752
1753 /*******************************************************************
1754  *
1755  * @brief Extract statistics received from DU layers and delete
1756  * Ric subscription's action info
1757  *
1758  * @details
1759  *
1760  *    Function : e2ProcActionDeleteRsp
1761  *
1762  *    Functionality: 
1763  *       [Step-1] Fetch RAN Function and Subscription DB using 
1764  *       subscription Id received in statistics delete response.
1765  *       [Step-2] Fetch pending ric subs modification rsp info
1766  *       from ran func db based on ric request information.
1767  *       [Step 3] - Traverse each index of stats group delete list 
1768  *       received in stats delete response.
1769  *         [Step 3.1] - If action deleted successfully, delete the 
1770  *         node from DB and fill the action info in the pending ric 
1771  *         subs modification rsp's accepted list.
1772  *         [Step 3.1] - Else fill the action info in the pending ric 
1773  *         subs modification rsp's rejected list.
1774  *       [Step 4] - Set removeActionCompleted true and process the 
1775  *       Pending Subscription modification rsp list.
1776  *
1777  *
1778  * @params[in] Statistics delete rsp 
1779  * @return ROK-success
1780  *         RFAILED-failure
1781  *
1782  * ****************************************************************/
1783 uint8_t e2ProcActionDeleteRsp(MacStatsDeleteRsp *statsDeleteRsp)
1784 {
1785    uint8_t idx = 0;
1786    uint8_t actionId = 0;
1787    uint8_t tmpIndex = 0;
1788    CmLList *actionNode = NULLP;
1789    ActionInfo *actionInfoDb = NULLP;
1790    PendingSubsModRspInfo *pendingSubsModRsp = NULLP;
1791    RanFunction *ranFuncDb = NULLP;
1792    CmLList *ricSubscriptionNode = NULLP;
1793    RicSubscription *ricSubscriptionInfo = NULLP;
1794
1795    /* [Step-1]  */
1796    if(fetchSubsInfoFromSubsId(statsDeleteRsp->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK)
1797    {
1798       DU_LOG("\nERROR  -->  E2AP : failed in function %s at line %d",__func__,__LINE__);
1799       return RFAILED;
1800    }
1801    
1802    /* [Step-2]  */
1803    for(idx=0; idx<ranFuncDb->numPendingSubsModRsp; idx++)
1804    {
1805       if((ranFuncDb->pendingSubsModRspInfo[idx].requestId.requestorId == ricSubscriptionInfo->requestId.requestorId) &&
1806             (ricSubscriptionInfo->requestId.instanceId == ricSubscriptionInfo->requestId.instanceId))
1807       {
1808          pendingSubsModRsp = &ranFuncDb->pendingSubsModRspInfo[idx];
1809          break;
1810       }
1811    }
1812
1813    if(pendingSubsModRsp == NULLP)
1814    {
1815       DU_LOG("\nERROR  -->  E2AP : failed in function %s at line %d",__func__,__LINE__);
1816       return RFAILED;
1817    }
1818
1819    /* [Step-3]  */
1820    for(idx=0; idx<statsDeleteRsp->numStatsGroupDeleted; idx++)
1821    {
1822       actionInfoDb = NULLP;
1823       actionId = statsDeleteRsp->statsGrpDelInfo[idx].groupId;
1824       actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo, &actionNode, CONFIG_DEL);
1825       if(actionInfoDb)
1826       {
1827          if(statsDeleteRsp->statsGrpDelInfo[idx].statsGrpDelRsp == MAC_DU_APP_RSP_OK)
1828          {
1829             /* [Step-3.1]  */
1830             tmpIndex = pendingSubsModRsp->removeActionStatus.numOfAcceptedActions;
1831             actionInfoDb->action = CONFIG_UNKNOWN;
1832             cmLListDelFrm(&ricSubscriptionInfo->actionSequence, actionNode);
1833             deleteActionSequence(actionNode);
1834             pendingSubsModRsp->removeActionStatus.acceptedActionList[tmpIndex] = actionId;
1835             pendingSubsModRsp->removeActionStatus.numOfAcceptedActions++;
1836          }
1837          else
1838          {
1839             /* [Step-3.2]  */
1840             tmpIndex = pendingSubsModRsp->removeActionStatus.numOfRejectedActions;
1841             pendingSubsModRsp->removeActionStatus.rejectedActionList[tmpIndex].id = actionId;
1842             convertDuCauseToE2Cause(statsDeleteRsp->statsGrpDelInfo[idx].statsGrpDelCause,\
1843             &pendingSubsModRsp->removeActionStatus.rejectedActionList[tmpIndex].failureCause);
1844             pendingSubsModRsp->removeActionStatus.numOfRejectedActions++;
1845          }
1846       }
1847    }
1848    
1849    /* [Step-4]  */
1850    pendingSubsModRsp->removeActionCompleted = true;
1851    if(duProcPendingSubsModRsp(pendingSubsModRsp) != ROK)
1852    {
1853       DU_LOG("\nERROR  -->  E2AP : failed to process subscription modification rsp");
1854       return RFAILED;
1855    }
1856    return ROK;
1857 }
1858
1859 /*******************************************************************
1860  *
1861  * @brief du process pending ric subscription modification rsp 
1862  * recieved from the layers
1863  *
1864  * @details
1865  *
1866  *    Function : duProcPendingSubsModRsp 
1867  *
1868  *    Functionality: Process pending subscription modification response 
1869  *                If processing of add, mod and remove action completes 
1870  *                then send the ric sub modification rsp
1871  *
1872  * @params[in] Pending Subs modification rsp
1873  *
1874  * @return ROK     - success
1875  *         RFAILED - failure
1876  *
1877  * ****************************************************************/
1878 uint8_t duProcPendingSubsModRsp( PendingSubsModRspInfo *pendingSubsModRsp)
1879 {
1880    if(pendingSubsModRsp->addActionCompleted && pendingSubsModRsp->removeActionCompleted && pendingSubsModRsp->modActionCompleted)
1881    {
1882 #if 0
1883        BuildAndSendRicSubsModRsp(pendingSubsModRsp);
1884 #endif
1885        memset(pendingSubsModRsp, 0, sizeof(PendingSubsModRspInfo));
1886        DU_LOG("\nProcessing of RIC subscription modification completed");
1887    }
1888    return ROK;
1889 }
1890 /*******************************************************************
1891  *
1892  * @brief Process statistics modification response from MAC
1893  *
1894  * @details
1895  *
1896  *    Function : e2ProcStatsModificationRsp
1897  *
1898  *    Functionality: Processes statistics modification configuration 
1899  *     response from MAC.
1900  *     [Step-1] Fetch RAN Function and Subscription DB using subs Id
1901  *     received in statistics modification response.
1902  *     [Step-2] Fetch pre-stored statistics mod response info by DUAPP.
1903  *     [Step 3] - Traverse each index of accepted list received in
1904  *     stats modification response.
1905  *          [Step 3.1] - fetch action info from databse which is set
1906  *          as CONFIG_UNKNOWN and then delete the node.
1907  *          [Step 3.1] - Again fetch action info from databse which is 
1908  *          set as CONFIG_MOD. Change the action status as CONFIG_UNKNOWN.
1909  *          fill the action in pending subscription modification rsp's 
1910  *          accepted list.
1911  *     [Step 4] - Traverse each index of rejected list received in
1912  *     stats modification response.
1913  *          [Step 4.1] - fetch action info from databse and delete 
1914  *          the action node which is set as CONFIG_MOD. and then 
1915  *          fill the action in pending subscription modification rsp's 
1916  *          rejected list.
1917  *     [Step 5] - Send subscription response with accepted and rejected 
1918  * @params[in] Statistics modification response received from MAC
1919  *
1920  * @return ROK     - success
1921  *         RFAILED - failure
1922  *
1923  * ****************************************************************/
1924 uint8_t e2ProcStatsModificationRsp(MacStatsModificationRsp *statsModificationRsp)
1925 {
1926    uint8_t idx = 0;
1927    uint8_t actionId = 0;
1928    uint8_t tempCount = 0;
1929    RanFunction *ranFuncDb = NULLP;
1930    CmLList *actionNode = NULLP;
1931    ActionInfo *actionInfoDb = NULLP;
1932    CmLList *ricSubscriptionNode = NULLP;
1933    RicSubscription *ricSubscriptionInfo = NULLP;
1934    PendingSubsModRspInfo *pendingSubsModRsp = NULLP;
1935
1936
1937    /* [Step-1] */
1938    if(fetchSubsInfoFromSubsId(statsModificationRsp->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK)
1939    {
1940       DU_LOG("\nERROR  -->  E2AP : failed in function %s at line %d",__func__,__LINE__);
1941       return RFAILED;
1942    }
1943
1944    /* [Step-2] */
1945    for(idx=0; idx<ranFuncDb->numPendingSubsModRsp; idx++)
1946    {
1947       if((ranFuncDb->pendingSubsModRspInfo[idx].requestId.requestorId == ricSubscriptionInfo->requestId.requestorId) &&
1948             (ricSubscriptionInfo->requestId.instanceId == ricSubscriptionInfo->requestId.instanceId))
1949       {
1950          pendingSubsModRsp = &ranFuncDb->pendingSubsModRspInfo[idx];
1951          break;
1952       }
1953    }
1954    if(pendingSubsModRsp == NULLP)
1955    {
1956       DU_LOG("\nERROR  -->  E2AP : failed in function %s at line %d",__func__,__LINE__);
1957       return RFAILED;
1958    }
1959
1960    /* [Step-3] */
1961    for(idx=0; idx<statsModificationRsp->numGrpAccepted; idx++)
1962    {
1963       actionInfoDb = NULLP;
1964       actionId = statsModificationRsp->statsGrpAcceptedList[idx];
1965       
1966       /* [Step-3.1] */
1967       actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo, &actionNode,CONFIG_UNKNOWN);
1968       if(actionInfoDb)
1969       {
1970          cmLListDelFrm(&ricSubscriptionInfo->actionSequence, actionNode);
1971          deleteActionSequence(actionNode);
1972       }
1973       
1974       /* [Step-3.2] */
1975       actionNode=NULLP;
1976       actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo, &actionNode,CONFIG_MOD);
1977       if(actionInfoDb)
1978       {
1979          actionInfoDb->action = CONFIG_UNKNOWN;
1980       }
1981       pendingSubsModRsp->modActionStatus.acceptedActionList[pendingSubsModRsp->modActionStatus.numOfAcceptedActions++] = actionId;
1982    }
1983
1984    /* [Step-4] */
1985    for(idx=0; idx<statsModificationRsp->numGrpRejected; idx++)
1986    {
1987       actionInfoDb = NULLP;
1988       actionId = statsModificationRsp->statsGrpRejectedList[idx].groupId;
1989
1990       /* [Step-4.1] */
1991       actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo, &actionNode, CONFIG_MOD);
1992       if(actionInfoDb)
1993       {
1994          cmLListDelFrm(&ricSubscriptionInfo->actionSequence, actionNode);
1995          deleteActionSequence(actionNode);
1996          tempCount = pendingSubsModRsp->modActionStatus.numOfRejectedActions;
1997          pendingSubsModRsp->modActionStatus.rejectedActionList[tempCount].id = actionId;
1998          convertDuCauseToE2Cause(statsModificationRsp->statsGrpRejectedList[idx].cause, \
1999          &pendingSubsModRsp->modActionStatus.rejectedActionList[tempCount].failureCause);
2000          pendingSubsModRsp->modActionStatus.numOfRejectedActions++;
2001       }
2002    }
2003    
2004    /* [Step-5] */
2005    pendingSubsModRsp->modActionCompleted = true;
2006    if(duProcPendingSubsModRsp(pendingSubsModRsp) != ROK)
2007    {
2008       DU_LOG("\nERROR  -->  E2AP : failed to process subscription modification rsp");
2009       return RFAILED;
2010    }
2011    return ROK;
2012 }
2013
2014 /*******************************************************************
2015  *
2016  * @brief Fill RIC Subscription datils in MAC Statistics 
2017  * ModificationRequest
2018  *
2019  * @details
2020  *
2021  *    Function : fillRicSubsInMacStatsModificationReq
2022  *
2023  *    Functionality: Fill RIC Subscription datils in MAC 
2024  *    Modification Statistics Request
2025  *    [Step -1] Generate subscription ID using RIC Request ID and 
2026  *    RAN Function ID
2027  *    [Step -2] Check all the action staus of each action present
2028  *    in the ric subscription. If action is CONFIG_MOD then fill
2029  *    the information in stats group list.
2030  *    [Step -3] Fill group related information in stats modification 
2031  *    req's in stats group list
2032  *    [Step -4] fill measurement information in stats group list
2033  *    [Step -5] If the number of stats which needs to modify is 
2034  *    greater then zero then return ROK else return RFAILED
2035  *
2036  * @params[in] MAC Statistics Modification Request to be filled
2037  *             RIC Subscription Info
2038  *
2039  * @return ROK     - success
2040  *         RFAILED - failure
2041  *
2042  * ****************************************************************/
2043 uint8_t fillRicSubsInMacStatsModificationReq(MacStatsModificationReq *macStatsModificationReq, RicSubscription* ricSubscriptionInfo)
2044 {
2045    uint8_t    grpIdx = 0;
2046    uint8_t statsModifyReqIdx = 0;
2047    uint64_t   subscriptionId = 0;
2048    CmLList *node = NULLP;
2049    ActionInfo *actionDb = NULLP;
2050    CmLList *actionNode = NULLP;
2051    MeasurementInfo *measInfo = NULLP;
2052    ActionDefFormat1 *format1Action = NULLP;
2053
2054    /* [Step -1] */
2055    encodeSubscriptionId(&subscriptionId, ricSubscriptionInfo->ranFuncId, ricSubscriptionInfo->requestId);
2056
2057    macStatsModificationReq->subscriptionId = subscriptionId;
2058    CM_LLIST_FIRST_NODE(&ricSubscriptionInfo->actionSequence, actionNode);
2059    while(actionNode)
2060    {
2061       actionDb = (ActionInfo*)(actionNode->node);
2062       /* [Step -2] */
2063       if(actionDb->action == CONFIG_MOD)
2064       {
2065          /* [Step -3] */
2066          macStatsModificationReq->statsGrpList[grpIdx].groupId = actionDb->actionId;
2067          switch(actionDb->definition.formatType)
2068          {
2069             case 1:
2070                {
2071                   format1Action = &actionDb->definition.choice.format1;
2072                   macStatsModificationReq->statsGrpList[grpIdx].periodicity = format1Action->granularityPeriod;
2073
2074                   statsModifyReqIdx = 0;
2075                   node = cmLListFirst(&format1Action->measurementInfoList);
2076                   while(node)
2077                   {
2078                      /* [Step -4] */
2079                      measInfo = (MeasurementInfo *)(node->node);
2080                      switch(measInfo->measurementTypeId)
2081                      {
2082                         case 1:
2083                            {
2084                               macStatsModificationReq->statsGrpList[grpIdx].statsList[statsModifyReqIdx++] = MAC_DL_TOTAL_PRB_USAGE;
2085                               break;
2086                            }
2087                         case 2:
2088                            {
2089                               macStatsModificationReq->statsGrpList[grpIdx].statsList[statsModifyReqIdx++] = MAC_UL_TOTAL_PRB_USAGE;
2090                               break;
2091                            }
2092                         default:
2093                            {
2094                               DU_LOG("\nERROR  -->  E2AP : Invalid measurement name");
2095                               break;
2096                            }
2097                      }
2098                      node = node->next;
2099                   }
2100                   macStatsModificationReq->statsGrpList[grpIdx].numStats = statsModifyReqIdx;
2101                   break;
2102                }
2103             default:
2104                {
2105                   DU_LOG("\nERROR  -->  E2AP : fillRicSubsInMacStatsModificationReq: Only Action Definition Format 1 supported");
2106                   break;
2107                }
2108          }
2109          if(macStatsModificationReq->statsGrpList[grpIdx].numStats)
2110             grpIdx++;
2111       }
2112       actionNode = actionNode->next;
2113    }
2114
2115    /* [Step -5] */
2116    macStatsModificationReq->numStatsGroup = grpIdx;
2117    if(macStatsModificationReq->numStatsGroup)
2118    {
2119       return ROK;
2120    }
2121    return RFAILED;
2122 }
2123
2124 /**********************************************************************
2125   End of file
2126  **********************************************************************/
2127