0c4b0b3b840143d8fec0da20a337c825063ee3e1
[o-du/l2.git] / src / du_app / du_e2ap_mgr.c
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2017-2019] [Radisys]                                        #
4 #                                                                              #
5 #   Licensed under the Apache License, Version 2.0 (the "License");            #
6 #   you may not use this file except in compliance with the License.           #
7 #   You may obtain a copy of the License at                                    #
8 #                                                                              #
9 #       http://www.apache.org/licenses/LICENSE-2.0                             #
10 #                                                                              #
11 #   Unless required by applicable law or agreed to in writing, software        #
12 #   distributed under the License is distributed on an "AS IS" BASIS,          #
13 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
14 #   See the License for the specific language governing permissions and        #
15 #   limitations under the License.                                             #
16 ################################################################################
17 *******************************************************************************/
18 #include "common_def.h"
19 #include <sys/time.h>
20 #include "du_tmr.h"
21 #include "lrg.h"
22 #include "lkw.x"
23 #include "lrg.x"
24 #include "legtp.h"
25 #include "du_app_mac_inf.h"
26 #include "du_app_rlc_inf.h"
27 #include "du_e2ap_mgr.h"
28 #include "du_e2_conversions.h"
29 #include "du_e2ap_msg_hdl.h"
30 #include "du_cfg.h"
31 #include "du_sctp.h"
32 #include "du_mgr.h"
33 #include "du_mgr_main.h"
34 #include "du_utils.h"
35
36 /*******************************************************************
37  *
38  * @brief Assigns new transaction id to DU initiated procedure
39  *
40  * @details
41  *
42  *    Function : assignTransactionId
43  *
44  *    Functionality: Assigns new transaction id to a DU initiated
45  *       procedure
46  *
47  * @params[in] Region region
48  *             Pool pool
49  * @return ROK     - success
50  *         RFAILED - failure
51  *
52  * ****************************************************************/
53 uint8_t assignTransactionId()
54 {
55    uint8_t currTransId = duCb.e2apDb.e2TransInfo.transIdCounter;
56
57    /* Update to next valid value */
58    duCb.e2apDb.e2TransInfo.transIdCounter++;
59    if(duCb.e2apDb.e2TransInfo.transIdCounter == MAX_NUM_TRANSACTION)
60       duCb.e2apDb.e2TransInfo.transIdCounter = 0;
61
62    return currTransId;
63 }
64
65 /*******************************************************************
66  *
67  * @brief Decode subscription ID
68  *
69  * @details
70  *
71  *    Function : decodeSubscriptionId
72  *
73  *    Functionality: Decode subscription id to get RAN function ID
74  *      and RIC Request ID
75  *
76  * @params[in] Subscription ID
77  *             RAN Function ID to be extracted
78  *             RIC Request ID to be extracted
79  * @return Void
80  *
81  * ****************************************************************/
82 void decodeSubscriptionId(uint64_t subscriptionId, uint16_t *ranFuncId, RicRequestId *ricReqId)
83 {
84    /* Extract following from 64 bit subscription-ID :
85     *  First 16 MSB is unused
86     *  Next 16 MSB = RAN-Function-ID
87     *  Next 16 MSB = Requestor-ID in RIC-Request-ID
88     *  Last 16 LSB = Instance-ID in RIC-Request-ID
89     */
90    ricReqId->instanceId = subscriptionId & 0xFFFF;
91    ricReqId->requestorId = (subscriptionId >> 16) & 0xFFFF;
92    *ranFuncId = (subscriptionId >> 32) & 0xFFFF;
93 }
94
95 /*******************************************************************
96  *
97  * @brief Encode subscription ID
98  *
99  * @details
100  *
101  *    Function : encodeSubscriptionId
102  *
103  *    Functionality: Encode subscription id to get RAN function ID
104  *      and RIC Request ID
105  *
106  * @params[in] Subscription ID to be encoded
107  *             RAN Function ID 
108  *             RIC Request ID
109  * @return Void
110  *
111  * ****************************************************************/
112 void encodeSubscriptionId(uint64_t *subscriptionId, uint16_t ranFuncId, RicRequestId ricReqId)
113 {
114    /* Calculate 64 bit subscription-ID :
115     *  First 16 MSB is unused
116     *  Next 16 MSB = RAN-Function-ID
117     *  Next 16 MSB = Requestor-ID in RIC-Request-ID
118     *  Last 16 LSB = Instance-ID in RIC-Request-ID
119     */
120    *subscriptionId = ricReqId.instanceId;
121    *subscriptionId |= ((uint64_t)ricReqId.requestorId << 16);
122    *subscriptionId |= ((uint64_t)ranFuncId << 32);
123 }
124
125 /*******************************************************************
126  *
127  * @brief Stores the current time at the start of reporting period
128  *
129  * @details
130  *
131  *    Function : storeReportStartTime
132  *
133  *    Functionality: Stores the current time at the start of 
134  *       reporting period
135  *
136  * @params[in] Start Timer to be stored
137  * @return Void
138  *
139  * ****************************************************************/
140 void storeReportStartTime(ReportStartTime *startTime)
141 {
142    struct timeval tv;
143
144    gettimeofday(&tv, NULL); 
145    startTime->timeInSec = tv.tv_sec;
146    startTime->timeInMilliSec = (tv.tv_usec/1000);
147 }
148
149
150 /*******************************************************************
151  *
152  * @brief Fetch Measurement Info using measurement type name
153  *
154  * @details
155  *
156  *    Function : fetchMeasInfoFromMeasTypeName
157  *
158  *    Functionality: Fetch Measurement Info using measurement type name
159  *
160  * @params[in] Measurement type name to search
161  *             Measurement Info list to search from
162  *             Measurement Info node found from list
163  * @return Measurement Info DB
164  *
165  * ****************************************************************/
166 MeasurementInfo *fetchMeasInfoFromMeasTypeName(char *e2MeasTypeName, CmLListCp *measInfoList, CmLList **measInfoNode)
167 {
168    MeasurementInfo *measInfo = NULLP;
169
170    /* Fetch subscription detail in RAN Function DB */
171    CM_LLIST_FIRST_NODE(measInfoList, *measInfoNode);
172    while(*measInfoNode)
173    {
174       measInfo = (MeasurementInfo *)((*measInfoNode)->node);
175       if(measInfo && !strcmp(e2MeasTypeName, measInfo->measurementTypeName))
176       {
177          break;
178       }
179       *measInfoNode = (*measInfoNode)->next;
180       measInfo = NULLP;
181    }
182
183    if(!measInfo)
184    {
185       DU_LOG("\nERROR  -->  E2AP : fetchMeasInfoFromMeasTypeName: Measurement [%s] not found", e2MeasTypeName);
186    }
187
188    return measInfo;
189 }
190
191 /*******************************************************************
192  *
193  * @brief Fetch Action details
194  *
195  * @details
196  *
197  *    Function : fetchActionInfoFromActionId
198  *
199  *    Functionality: Fetch action details from RIC subscription DB
200  *       using action ID
201  *
202  * @params[in] Action ID 
203  *             RIC Subscription DB
204  * @return Action Info DB
205  *         NULL, in case of failure
206  *
207  * ****************************************************************/
208 ActionInfo *fetchActionInfoFromActionId(uint8_t actionId, RicSubscription *ricSubscriptionInfo)
209 {
210    ActionInfo *actionInfoDb = NULLP;
211    if(ricSubscriptionInfo->actionSequence[actionId].actionId == actionId)
212    {
213       actionInfoDb = &ricSubscriptionInfo->actionSequence[actionId];
214    }
215    else
216    {
217       DU_LOG("\nERROR  -->  E2AP : fetchActionInfoFromActionId: Action Id [%d] not found in \
218          subscription info [Requestor id : %d] [Instance Id : %d]", actionId,\
219          ricSubscriptionInfo->requestId.requestorId, ricSubscriptionInfo->requestId.instanceId);
220
221    }
222    return actionInfoDb;
223 }
224
225 /*******************************************************************
226  *
227  * @brief Fetch subscripton DB 
228  *
229  * @details
230  *
231  *    Function : fetchSubsInfoFromRicReqId
232  *
233  *    Functionality: Fetches subscription DB from RAN Function DB
234  *       using RIC Request ID
235  *
236  * @params[in] RIC Request ID 
237  *             RAN Function DB
238  *             Pointer to RIC Subscription node to be searched
239  * @return RIC Subscription from RAN Function's subcription list
240  *         NULL, in case of failure
241  *
242  * ****************************************************************/
243 RicSubscription *fetchSubsInfoFromRicReqId(RicRequestId ricReqId, RanFunction *ranFuncDb, CmLList **ricSubscriptionNode)
244 {
245    RicSubscription *ricSubscriptionInfo = NULLP;
246
247    /* Fetch subscription detail in RAN Function DB */
248    CM_LLIST_FIRST_NODE(&ranFuncDb->subscriptionList, *ricSubscriptionNode);
249    while(*ricSubscriptionNode)
250    {
251       ricSubscriptionInfo = (RicSubscription *)((*ricSubscriptionNode)->node);
252       if(ricSubscriptionInfo && (ricSubscriptionInfo->requestId.requestorId == ricReqId.requestorId) &&
253             (ricSubscriptionInfo->requestId.instanceId == ricReqId.instanceId))
254       {
255          break;
256       }
257       *ricSubscriptionNode = (*ricSubscriptionNode)->next;
258       ricSubscriptionInfo = NULLP;
259    }
260
261    if(!ricSubscriptionInfo)
262    {
263       DU_LOG("\nERROR  -->  E2AP : fetchSubsInfoFromRicReqId: Subscription not found for Requestor ID [%d] \
264          Instance ID [%d] in RAN Function ID [%d]", ricReqId.requestorId, ricReqId.instanceId, ranFuncDb->id);
265    }
266
267    return ricSubscriptionInfo;
268 }
269
270 /*******************************************************************
271  *
272  * @brief Fetches RAN Function DB
273  *
274  * @details
275  *
276  *    Function : fetchRanFuncFromRanFuncId
277  *
278  *    Functionality: Fetches RAN function DB from E2AP DB using
279  *       RAN function ID 
280  *
281  * @params[in] RAN Function ID
282  * @return RAN Function DB
283  *         NULL, in case of failure
284  *
285  * ****************************************************************/
286 RanFunction *fetchRanFuncFromRanFuncId(uint16_t ranFuncId)
287 {
288    RanFunction *ranFuncDb = NULLP;
289
290    /* Fetch RAN Function DB */
291    if(duCb.e2apDb.ranFunction[ranFuncId-1].id == ranFuncId)
292    {
293       ranFuncDb = &duCb.e2apDb.ranFunction[ranFuncId-1];
294    }
295    else
296    {
297       DU_LOG("\nERROR  -->  E2AP : fetchRanFuncFromRanFuncId: Invalid RAN Function ID[%d]", ranFuncId);
298    }
299
300    return ranFuncDb;
301 }
302
303 /*******************************************************************
304  *
305  * @brief Fetches subscription info
306  *
307  * @details
308  *
309  *    Function : fetchSubsInfoFromSubsId
310  *
311  *    Functionality: 
312  *       1. Firstly, RAN Function ID and RIC request ID is extracted
313  *          from Subscription ID 
314  *       2. Using RAN Function ID, RAN Function DB is searched
315  *       3. Using RIC Request ID, the subscription DB is searched in
316  *          RAN Function DB
317  *
318  * @params[in] Subscription ID
319  *             RAN Function DB
320  *             RIC Subscription node from RAN Func's Subscription list
321  * @return ROK
322  *         RFAILED
323  *
324  * ****************************************************************/
325 uint8_t fetchSubsInfoFromSubsId(uint64_t subscriptionId, RanFunction **ranFuncDb, CmLList **ricSubscriptionNode, \
326    RicSubscription **ricSubscriptionInfo)
327 {
328    uint16_t ranFuncId = 0;
329    RicRequestId ricReqId;
330
331    memset(&ricReqId, 0, sizeof(RicRequestId));
332
333    /* Decode subscription ID o get RIC Request ID and RAN Function ID */
334    decodeSubscriptionId(subscriptionId, &ranFuncId, &ricReqId);
335
336    /* Fetch RAN Function DB using RAN Function ID */
337    *ranFuncDb = fetchRanFuncFromRanFuncId(ranFuncId);
338    if((*ranFuncDb) == NULLP)
339    {
340       return RFAILED;
341    }
342
343    /* Fetch Sunscription DB from RAN Function using RIC Request ID */
344    *ricSubscriptionInfo = fetchSubsInfoFromRicReqId(ricReqId, *ranFuncDb, ricSubscriptionNode);
345    if((*ricSubscriptionInfo) == NULLP)
346    {
347       return RFAILED;
348    }
349
350    return ROK;
351 }
352
353 /*******************************************************************
354  *
355  * @brief Sends E2 msg over SCTP
356  *
357  * @details
358  *
359  *    Function : SendE2APMsg
360  *
361  *    Functionality: Sends E2 msg over SCTP
362  *
363  * @params[in] Region region
364  *             Pool pool
365  * @return ROK     - success
366  *         RFAILED - failure
367  *
368  * ****************************************************************/
369
370 uint8_t SendE2APMsg(Region region, Pool pool, char *encBuf, int encBufSize)
371 {
372    Buffer *mBuf=NULLP;
373
374    if(ODU_GET_MSG_BUF(region, pool, &mBuf) == ROK)
375    {
376       if(ODU_ADD_POST_MSG_MULT((Data *)encBuf, encBufSize, mBuf) == ROK)
377       {
378          ODU_PRINT_MSG(mBuf, 0,0);
379
380          if(sctpSend(mBuf, E2_INTERFACE) != ROK)
381          {
382             DU_LOG("\nERROR  -->  E2AP : SCTP Send for E2  failed");
383             ODU_PUT_MSG_BUF(mBuf);
384             return RFAILED;
385          }
386       }
387       else
388       {
389          DU_LOG("\nERROR  -->  E2AP : ODU_ADD_POST_MSG_MULT failed");
390          ODU_PUT_MSG_BUF(mBuf);
391          return RFAILED;
392       }
393       ODU_PUT_MSG_BUF(mBuf);
394    }
395    else
396    {
397       DU_LOG("\nERROR  -->  E2AP : Failed to allocate memory");
398       return RFAILED;
399    }
400
401    return ROK;
402 } /* SendE2APMsg */
403
404 /*******************************************************************
405  *
406  * @brief Resets E2 
407  *
408  * @details
409  *
410  *    Function : ResetE2Request
411  *
412  *    Functionality: This function resets E2.
413  *       As per ORAN WG3 E2GAP v3.0 Spec, section 5.5.3
414  *       If E2 node initates reset procedure then:
415  *        a. Send reset request to RIC
416  *        b. Delete any pre-established RIC subscriptions
417  *        c. Gracefully terminates any ongoing RIC services
418  *       If RIC initiates reset procedure then :
419  *        a. Delete any pre-established RIC subscriptions
420  *        b. Gracefully terminates any ongoing RIC services
421  *        c. Send reset response to RIC
422  *
423  * @params[in]
424  * @return ROK     - success
425  *         RFAILED - failure
426  *
427  * ****************************************************************/
428 uint8_t ResetE2Request(E2ProcedureDirection dir, E2FailureCause resetCause)
429 {
430    /* Send Reset Request to RIC if DU detects any abnormal failure */
431    if(dir == E2_NODE_INITIATED)
432    {
433       if(BuildAndSendE2ResetRequest(resetCause) != ROK)
434       {
435          DU_LOG("\nERROR  -->  E2AP : BuildAndSendE2ResetRequest failed");
436          return RFAILED;
437       }
438    }
439
440    /* TODO when RIC subscription service model is implemented
441       Process following steps of resetting E2
442       1. Deletes any pre-established RIC subscriptions
443       2. Gracefully terminates any ongoing RIC services
444     */
445
446    /* Send Reset Response if RIC initiated Reset request is received at DU */
447    if(dir == RIC_INITIATED)
448    {
449       //BuildAndSendE2ResetResponse();
450    }   
451    return ROK;
452 }
453
454 /*******************************************************************
455  *
456  * @brief Fill RIC Subscription datils in MAC Statistics Request
457  *
458  * @details
459  *
460  *    Function : fillRicSubsInMacStatsReq
461  *
462  *    Functionality: Fill RIC Subscription datils in MAC Statistics 
463  *       Request
464  *
465  * @params[in] MAC Statistics Request to be filled
466  *             RIC Subscription Info
467  *
468  * @return ROK     - success
469  *         RFAILED - failure
470  *
471  * ****************************************************************/
472 uint8_t fillRicSubsInMacStatsReq(MacStatsReq *macStatsReq, RicSubscription* ricSubscriptionInfo)
473 {
474    uint8_t    actionIdx = 0, grpIdx = 0, statsIdx = 0;
475    uint64_t   subscriptionId = 0;
476    ActionInfo *actionDb = NULLP;
477    ActionDefFormat1 *format1Action = NULLP;
478
479    /* Generate subscription ID using RIC Request ID and RAN Function ID */
480    encodeSubscriptionId(&subscriptionId, ricSubscriptionInfo->ranFuncId, ricSubscriptionInfo->requestId);
481
482    macStatsReq->subscriptionId = subscriptionId;
483    for(actionIdx = 0; actionIdx < MAX_RIC_ACTION; actionIdx++)
484    {
485       if(ricSubscriptionInfo->actionSequence[actionIdx].action == CONFIG_ADD)
486       {
487          actionDb = &ricSubscriptionInfo->actionSequence[actionIdx];
488          macStatsReq->statsGrpList[grpIdx].groupId = actionDb->actionId;
489          switch(actionDb->definition.formatType)
490          {
491             case 1:
492                {
493                   format1Action = &actionDb->definition.choice.format1;
494                   macStatsReq->statsGrpList[grpIdx].periodicity = format1Action->granularityPeriod;
495
496                   CmLList *node = NULLP;
497                   MeasurementInfo *measInfo = NULLP;
498                   statsIdx = 0;
499                   /* Update DL PRB Usage for all stats group which requested for DL Total PRB Usage */
500                   node = cmLListFirst(&format1Action->measurementInfoList);
501                   while(node)
502                   {
503                      measInfo = (MeasurementInfo *)(node->node);
504                      switch(measInfo->measurementTypeId)
505                      {
506                         case 1:
507                            {
508                               macStatsReq->statsGrpList[grpIdx].statsList[statsIdx++] = MAC_DL_TOTAL_PRB_USAGE;
509                               break;
510                            }
511                         case 2:
512                            {
513                               macStatsReq->statsGrpList[grpIdx].statsList[statsIdx++] = MAC_UL_TOTAL_PRB_USAGE;
514                               break;
515                            }
516                         default:
517                            {
518                               DU_LOG("\nERROR  -->  E2AP : Invalid measurement name");
519                               break;
520                            }
521                      }
522                      node = node->next;
523                   }
524                   macStatsReq->statsGrpList[grpIdx].numStats = statsIdx;
525                   break;
526                }
527             default:
528                {
529                   DU_LOG("\nERROR  -->  E2AP : fillRicSubsInMacStatsReq: Only Action Definition Format 1 supported");
530                   break;
531                }
532          }
533          if(macStatsReq->statsGrpList[grpIdx].numStats)
534             grpIdx++;
535       }
536    }
537
538    macStatsReq->numStatsGroup = grpIdx;
539    if(macStatsReq->numStatsGroup)
540    {
541       return ROK;
542    }
543    return RFAILED;
544 }
545
546 /*******************************************************************
547  *
548  * @brief Rejects all actions received in a subscription request
549  *
550  * @details
551  *
552  *    Function : duRejectAllStatsGroup
553  *
554  *    Functionality: Rejects all actions received in a subscription
555  *       request by :
556  *       a. Removing the subscription entry from RAN function
557  *       b. Sending RIC Subscription Failure to RIC with appropriate
558  *          cause of failure
559  *
560  * @params[in] RAN Function DB
561  *             Subscription entry in RAN Function subscription list
562  *             Statistics Response from MAC
563  *
564  * @return ROK     - success
565  *         RFAILED - failure
566  *
567  * ****************************************************************/
568 uint8_t rejectAllStatsGroup(RanFunction *ranFuncDb, CmLList *ricSubscriptionNode, MacStatsRsp *statsRsp)
569 {
570    uint8_t ret = ROK;
571    RicRequestId  requestId;
572    E2FailureCause failureCause;
573
574    /* Delete subcription from RAN Function */
575    memcpy(&requestId, &((RicSubscription *)ricSubscriptionNode->node)->requestId, sizeof(RicRequestId));
576    cmLListDelFrm(&ranFuncDb->subscriptionList, ricSubscriptionNode);
577    deleteRicSubscriptionNode(ricSubscriptionNode);
578    ricSubscriptionNode = NULLP;
579    convertDuCauseToE2Cause(statsRsp->statsGrpRejectedList[0].cause, &failureCause);
580
581    /* Send RIC subscription failure to RIC */
582    ret = BuildAndSendRicSubscriptionFailure(requestId, ranFuncDb->id, failureCause);
583    return ret;
584 }
585
586 /*******************************************************************
587  *
588  * @brief Process statistics response from MAC
589  *
590  * @details
591  *
592  *    Function : e2ProcStatsRsp
593  *
594  *    Functionality: Processes statistics configuration response
595  *       from MAC. If configuration is succsessful, DUAPP starts
596  *       reporting period timer for this subscription request
597  *       from RIC
598  *
599  * @params[in] Statistics response received from MAC
600  *
601  * @return ROK     - success
602  *         RFAILED - failure
603  *
604  * ****************************************************************/
605 uint8_t e2ProcStatsRsp(MacStatsRsp *statsRsp)
606 {
607    uint8_t idx = 0;
608    uint8_t actionId = 0;
609    uint32_t reportingPeriod = 0;
610    RanFunction *ranFuncDb = NULLP;
611    CmLList *ricSubscriptionNode = NULLP;
612    RicSubscription *ricSubscriptionInfo = NULLP;
613    ActionInfo *actionInfoDb = NULLP;
614    PendingSubsRspInfo *pendingSubsRsp = NULLP;
615
616    /* Fetch RAN Function and Subscription DB using subscription Id received in statistics response */
617    if(fetchSubsInfoFromSubsId(statsRsp->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK)
618    {
619       DU_LOG("\nERROR  -->  E2AP : DuProcMacStatsRsp: Failed to fetch subscriprtion details");
620       return RFAILED;
621    }
622
623    /* Fetch pre-stored statistics response info by DU APP */
624    for(idx=0; idx<ranFuncDb->numPendingSubsRsp; idx++)
625    {
626       if((ranFuncDb->pendingSubsRspInfo[idx].requestId.requestorId == ricSubscriptionInfo->requestId.requestorId) &&
627             (ricSubscriptionInfo->requestId.instanceId == ricSubscriptionInfo->requestId.instanceId))
628       {
629          pendingSubsRsp = &ranFuncDb->pendingSubsRspInfo[idx];
630          break;
631       }
632    }
633
634    /* If no action is accepted
635     *  a. Remove subcription entry from RAN Function
636     *  b. Send RIC subscription failure */
637    if(statsRsp->numGrpAccepted == 0)
638    {
639       rejectAllStatsGroup(ranFuncDb, ricSubscriptionNode, statsRsp);
640    }
641    else
642    {
643       /* Once RIC subscription is successful, mark the config action as unknown */
644       ricSubscriptionInfo->action = CONFIG_UNKNOWN;
645
646       /* Start RIC Subscription reporting timer */
647       switch(ricSubscriptionInfo->eventTriggerDefinition.formatType)
648       {
649          case 1:
650             {
651                reportingPeriod = ricSubscriptionInfo->eventTriggerDefinition.choice.format1.reportingPeriod;
652
653                /* Save the start time of reporting period */
654                storeReportStartTime(&ricSubscriptionInfo->eventTriggerDefinition.choice.format1.startTime);
655                break;
656             }
657          default:
658          {
659             DU_LOG("\nERROR  -->  E2AP : Invalid event trigger format of RIC subscription");
660             return RFAILED;
661          }
662       }
663       if(duChkTmr((PTR)ricSubscriptionInfo, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR) != true)
664       {
665          duStartTmr((PTR)ricSubscriptionInfo, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR, reportingPeriod);
666       }
667       else
668       {
669          DU_LOG("\nERROR  -->  E2AP : RIC Subscription reporting timer already running for RIC Subscription");  
670          return RFAILED;
671       }
672
673
674       /* If even 1 action is accepted :
675        *
676        * For accepted groups:
677        *    Mark subscribed-action's -> action = CONFIG_UNKNOWN
678        *    Add to accepted-action-list of subscription response
679        */
680       for(idx=0; idx<statsRsp->numGrpAccepted; idx++)
681       {
682          actionInfoDb = NULLP;
683
684          actionId = statsRsp->statsGrpAcceptedList[idx];
685          actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo);
686          if(actionInfoDb && (actionInfoDb->action == CONFIG_ADD))
687          {
688             actionInfoDb->action = CONFIG_UNKNOWN;
689             pendingSubsRsp->acceptedActionList[pendingSubsRsp->numOfAcceptedActions++] = actionId;
690          }
691       }
692
693       /* For rejected groups:
694        *    Remove entry from DU's RAN Function->subscription->actionList
695        *    Add to rejected-action-list in subscription response
696        */
697       for(idx=0; idx<statsRsp->numGrpRejected; idx++)
698       {
699          actionId = statsRsp->statsGrpRejectedList[idx].groupId;
700          if(ricSubscriptionInfo->actionSequence[actionId].actionId == actionId)
701          {
702             memset(&ricSubscriptionInfo->actionSequence[actionId], 0, sizeof(ActionInfo));
703             ricSubscriptionInfo->numOfActions--;
704
705             pendingSubsRsp->rejectedActionList[pendingSubsRsp->numOfRejectedActions].id = actionId;
706             convertDuCauseToE2Cause(statsRsp->statsGrpRejectedList[idx].cause, \
707                   &pendingSubsRsp->rejectedActionList[pendingSubsRsp->numOfRejectedActions].failureCause);
708             pendingSubsRsp->numOfRejectedActions++;
709          }
710       }
711
712       /* Send subscription response with accepted and rejected action lists to RIC */
713       BuildAndSendRicSubscriptionRsp(pendingSubsRsp);
714    }
715    memset(pendingSubsRsp, 0, sizeof(PendingSubsRspInfo));
716    return ROK;
717 }
718
719 /*******************************************************************
720  *
721  * @brief Extract and store statistics received from DU layers
722  *
723  * @details
724  *
725  *    Function : e2ProcStatsInd
726  *
727  *    Functionality: Extract statistics received from DU layers
728  *       and store in respective RAN function's subscription's
729  *       action
730  *
731  * @params[in] Statistics Indication message received from MAC
732  * @return ROK-success
733  *         RFAILED-failure
734  *
735  * ****************************************************************/
736 uint8_t e2ProcStatsInd(MacStatsInd *statsInd)
737 {
738    uint8_t statsIdx = 0;
739    RanFunction *ranFuncDb = NULLP;
740    CmLList *ricSubscriptionNode = NULLP;
741    RicSubscription *ricSubscriptionInfo = NULLP;
742    ActionInfo *actionInfo = NULLP;
743    ActionDefFormat1 *actionFormat = NULLP;
744    char e2MeasTypeName[STRING_SIZE_150_BYTES] = "";
745    MeasurementInfo *measInfo = NULLP;
746    CmLList *measInfoNode = NULLP;
747    double *measValue = NULLP;
748    CmLList *measValueNode = NULLP;
749
750    /* TODO : When stats indication is received
751     * DU APP searches for the message type in E2AP RIC subscription
752     * database and stores in the value in the list of subscribed measurements
753     *
754     * This will be implemented in next gerrit.
755     */
756
757    /* Fetch RAN Function and Subscription DB using subscription Id received
758     * in statistics response */
759    if(fetchSubsInfoFromSubsId(statsInd->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK)
760    {
761       DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Failed to fetch subscriprtion details");
762       return RFAILED;
763    }
764
765    /* Fetch RIC subscription's action DB */
766    actionInfo = fetchActionInfoFromActionId(statsInd->groupId, ricSubscriptionInfo);
767    if(actionInfo == NULLP)
768    {
769       DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Failed to fetch action ID [%d]", statsInd->groupId);
770       return RFAILED;
771    }
772
773    /* Check Action format */
774    switch(actionInfo->definition.formatType)
775    {
776       case 1:
777          {
778             actionFormat = &actionInfo->definition.choice.format1;
779             break;
780          }
781       default:
782          {
783             DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Action Format [%d] is not supported", \
784                   actionInfo->definition.formatType);
785             return RFAILED;
786          }
787    }
788
789    /* Fetch each Measurement info from action info and store its reported value in DB */
790    for(statsIdx = 0; statsIdx < statsInd->numStats; statsIdx++)
791    {
792       memset(e2MeasTypeName, 0, STRING_SIZE_150_BYTES);
793       measInfo = NULLP;
794       measInfoNode = NULLP;
795
796       /* Convert Measurement type from MAC-supported format to E2-supported format */
797       if(convertMacMeasTypeToE2MeasType(statsInd->measuredStatsList[statsIdx].type, e2MeasTypeName) != ROK)
798       {
799          DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Failed to convert measurement type from MAC-supported\
800             MAC-supported format to E2-supported format");
801          continue;
802       }
803       
804       /* Fetch Measurement Info using E2-supported measurement type name */
805       measInfo = fetchMeasInfoFromMeasTypeName(e2MeasTypeName, &actionFormat->measurementInfoList, &measInfoNode); 
806       if(measInfo == NULLP)
807       {
808          DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Measurement Type Name [%s] not found", e2MeasTypeName); 
809          continue;
810       }
811       
812       /* Store the measurement value in the measurement info DB fetched */
813       DU_ALLOC(measValue, sizeof(double));
814       if(!measValue)
815       {
816          DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Memory allocation failed at line [%d]", __LINE__);
817          return RFAILED; 
818       }
819       *measValue = statsInd->measuredStatsList[statsIdx].value;
820
821       DU_ALLOC(measValueNode, sizeof(CmLList));
822       if(!measValueNode)
823       {
824          DU_LOG("\nERROR  -->  E2AP : extractStatsMeasurement: Memory allocation failed at line [%d]", __LINE__);
825          DU_FREE(measValue, sizeof(double));
826          return RFAILED; 
827       }
828       measValueNode->node = (PTR) measValue;
829       cmLListAdd2Tail(&measInfo->measuredValue, measValueNode);
830    }
831    return ROK;
832 }
833
834 /*******************************************************************
835  *
836  * @brief Handle RIC Subscription reporting timer expry
837  *
838  * @details
839  *
840  *    Function : E2apHdlRicSubsReportTmrExp
841  *
842  *    Functionality: On expiry of RIC subscription reporting
843  *       timer expiry, RIC indication is sent for all actions
844  *       in RIC subscription
845  *
846  * @params[in] RIC subscription DB
847  * @return void
848  *
849  * ****************************************************************/
850 void E2apHdlRicSubsReportTmrExp(RicSubscription *ricSubscription)
851 {
852    uint8_t actionIdx = 0;
853    uint32_t reportingPeriod = 0;
854
855    for(actionIdx = 0; actionIdx < MAX_RIC_ACTION; actionIdx++)
856    {
857       if(ricSubscription->actionSequence[actionIdx].actionId >= 0)
858       {
859          BuildAndSendRicIndication(ricSubscription, &ricSubscription->actionSequence[actionIdx]);  
860       }
861    }
862
863    /* Start RIC Subscription reporting timer again */
864    switch(ricSubscription->eventTriggerDefinition.formatType)
865    {
866       case 1:
867          {
868             reportingPeriod = ricSubscription->eventTriggerDefinition.choice.format1.reportingPeriod;
869             /* Save the start time of reporting period */
870             storeReportStartTime(&ricSubscription->eventTriggerDefinition.choice.format1.startTime);
871             break;
872          }
873       default:
874          return;
875    }
876    if(duChkTmr((PTR)ricSubscription, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR) != true)
877    {
878       duStartTmr((PTR)ricSubscription, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR, reportingPeriod);
879    }
880    else
881    {
882       DU_LOG("\nERROR  -->  E2AP : Failed in %s at line %d", __func__, __LINE__);
883       return;
884    }
885 }
886
887 /******************************************************************
888  *
889  * @brief Search E2 node component with the help of action type
890  *
891  * @details
892  *
893  *    Function : fetchE2NodeComponentInfo 
894  *
895  *    Functionality: Search E2 node component with the help of action type 
896  *
897  * @params[in] 
898  *       Type of interface 
899  *       Component Id
900  *       Pointer to E2 component node to be searched 
901  * @return CmLList
902  *
903  * ****************************************************************/
904
905 E2NodeComponent *fetchE2NodeComponentInfo(InterfaceType interfaceType, uint64_t componentId, CmLList **e2ComponentNode)
906 {
907    E2NodeComponent *e2NodeComponentInfo=NULLP;
908
909    if(duCb.e2apDb.e2NodeComponentList.count)
910    {
911       CM_LLIST_FIRST_NODE(&duCb.e2apDb.e2NodeComponentList, *e2ComponentNode);
912       while(*e2ComponentNode)
913       {
914          e2NodeComponentInfo = (E2NodeComponent*)((*e2ComponentNode)->node);
915          if((e2NodeComponentInfo->interfaceType == interfaceType) && (e2NodeComponentInfo->componentId == componentId))
916          {
917             break;
918          }
919          
920          *e2ComponentNode = (*e2ComponentNode)->next;
921          e2NodeComponentInfo = NULLP;
922       }
923    }
924    return e2NodeComponentInfo; 
925 }
926
927 /*******************************************************************
928  *
929  * @brief fill E2 node component rsp info
930  *
931  * @details
932  *
933  *    Function : fillE2NodeComponentRspInfo 
934  *
935  * Functionality: fill E2 Node Component rsp info 
936  *
937  * @parameter
938  *       Type of interface 
939  *       Component action type
940  *       Size of buffer which needs to be store
941  *       buffer string which needs to be store 
942  * @return ROK     - success
943  *         RFAILED - failure
944  *
945  * ****************************************************************/
946
947 uint8_t fillE2NodeComponentRspInfo(InterfaceType interfaceType, uint64_t componentId, uint8_t action, uint8_t bufSize, char *bufString)
948 {
949    E2NodeConfig *configInfo=NULLP;
950    E2NodeComponent *e2NodeComponentInfo= NULLP;
951    CmLList  *node = NULLP;
952
953    e2NodeComponentInfo = fetchE2NodeComponentInfo(interfaceType, componentId, &node);
954    if(!e2NodeComponentInfo) 
955    {
956       DU_LOG("\nERROR  -->  E2AP : Unable to find the node");
957       return RFAILED;
958    }
959
960    switch(action)
961    {
962       case E2_NODE_COMPONENT_ADD:
963          {
964             configInfo = e2NodeComponentInfo->addConfiguration;    
965             break;
966          }
967       case E2_NODE_COMPONENT_UPDATE: 
968          {
969             configInfo = e2NodeComponentInfo->updateConfiguration;
970             break;
971          }
972       default:
973          {
974             DU_LOG("\nERROR  -->  E2AP : Invalid action %d received",action);
975             return RFAILED;
976          }
977    }
978
979    if(configInfo->componentRequestPart== NULLP)
980    {
981       DU_LOG("\nERROR  -->  E2AP : E2 node Component request part is not present");
982       return RFAILED;
983    }
984
985    configInfo->rspBufSize = bufSize;
986    DU_ALLOC(configInfo->componentResponsePart, bufSize);
987    if(configInfo->componentResponsePart == NULLP)
988    {
989       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed to store the encoding of rsp");
990       return RFAILED;
991    }
992    memcpy(configInfo->componentResponsePart, bufString, configInfo->rspBufSize);
993    return ROK;
994 }
995
996 /*******************************************************************
997  *
998  * @brief add E2 node component req info
999  *
1000  * @details
1001  *
1002  *    Function : addE2NodeComponent 
1003  *
1004  * Functionality: add E2 node component req info 
1005  *
1006  * @parameter
1007  *       Type of interface 
1008  *       Component action type
1009  *       Size of buffer which needs to be store
1010  *       buffer string which needs to be store 
1011  * @return ROK     - success
1012  *         RFAILED - failure
1013  *
1014  ******************************************************************/
1015
1016 uint8_t addE2NodeComponent(InterfaceType interfaceType, uint64_t componentId,  uint8_t bufSize, char *bufString)
1017 {
1018    E2NodeComponent *e2NodeComponentInfo= NULLP;
1019    CmLList  *node = NULLP;
1020    
1021    DU_ALLOC(e2NodeComponentInfo, sizeof(E2NodeComponent));
1022    if(!e2NodeComponentInfo)
1023    {
1024       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed in %s at %d",__func__,__LINE__);
1025       return RFAILED;
1026    }
1027    e2NodeComponentInfo->interfaceType =interfaceType;
1028    e2NodeComponentInfo->componentId=componentId;
1029
1030    DU_ALLOC(e2NodeComponentInfo->addConfiguration, sizeof(E2NodeConfig));
1031    if(!e2NodeComponentInfo->addConfiguration)
1032    {
1033       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed in %s at %d",__func__,__LINE__);
1034       return RFAILED;
1035    }
1036
1037    e2NodeComponentInfo->addConfiguration->reqBufSize = bufSize;
1038
1039    DU_ALLOC(e2NodeComponentInfo->addConfiguration->componentRequestPart, bufSize);
1040    if(e2NodeComponentInfo->addConfiguration->componentRequestPart == NULLP)
1041    {
1042       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed in %s at %d",__func__,__LINE__);
1043       DU_FREE(e2NodeComponentInfo, sizeof(E2NodeComponent));
1044       return RFAILED;
1045    }
1046    memcpy(e2NodeComponentInfo->addConfiguration->componentRequestPart, bufString,\
1047    e2NodeComponentInfo->addConfiguration->reqBufSize);
1048
1049    DU_ALLOC(node, sizeof(CmLList));
1050    if(node)
1051    {
1052       node->node = (PTR) e2NodeComponentInfo;
1053       cmLListAdd2Tail(&duCb.e2apDb.e2NodeComponentList, node);
1054    }
1055    else
1056    {
1057       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed in %s at %d",__func__,__LINE__);
1058       DU_FREE(e2NodeComponentInfo->addConfiguration->componentRequestPart, bufSize);
1059       DU_FREE(e2NodeComponentInfo->addConfiguration, sizeof(E2NodeConfig));
1060       DU_FREE(e2NodeComponentInfo, sizeof(E2NodeComponent));
1061       return RFAILED;
1062    }
1063    return ROK;
1064 }
1065
1066 /*******************************************************************
1067  *
1068  * @brief update E2 node component req info
1069  *
1070  * @details
1071  *
1072  *    Function : updateE2NodeComponent 
1073  *
1074  * Functionality: update E2 node component req info 
1075  *
1076  * @parameter
1077  *       Type of interface 
1078  *       Size of buffer which needs to be store
1079  *       buffer string which needs to be store 
1080  * @return ROK     - success
1081  *         RFAILED - failure
1082  *
1083  ******************************************************************/
1084
1085 uint8_t updateE2NodeComponent(InterfaceType interfaceType, uint64_t componentId, uint8_t bufSize, char *bufString)
1086 {
1087    E2NodeComponent *e2NodeComponentInfo= NULLP;
1088    CmLList  *node = NULLP;
1089          
1090    e2NodeComponentInfo = fetchE2NodeComponentInfo(interfaceType, componentId, &node);
1091    if(!e2NodeComponentInfo)
1092    {
1093       DU_LOG("\nERROR  -->  E2AP : Received null information in %s",__func__);
1094       return RFAILED;
1095    }
1096    
1097    DU_ALLOC(e2NodeComponentInfo->updateConfiguration, sizeof(E2NodeConfig));
1098    if(!e2NodeComponentInfo->updateConfiguration)
1099    {
1100       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed in %s at %d",__func__,__LINE__);
1101       return RFAILED;
1102    }
1103
1104    e2NodeComponentInfo->updateConfiguration->reqBufSize = bufSize;
1105
1106    DU_ALLOC(e2NodeComponentInfo->updateConfiguration->componentRequestPart, bufSize);
1107    if(e2NodeComponentInfo->updateConfiguration->componentRequestPart == NULLP)
1108    {
1109       DU_LOG("\nERROR  -->  E2AP : Memory allocation failed in %s at %d",__func__,__LINE__);
1110       DU_FREE(e2NodeComponentInfo->updateConfiguration, sizeof(E2NodeConfig));
1111       return RFAILED;
1112    }
1113
1114    memcpy(e2NodeComponentInfo->updateConfiguration->componentRequestPart, bufString,\
1115    e2NodeComponentInfo->updateConfiguration->reqBufSize);
1116    return ROK;
1117
1118 }
1119
1120 /*******************************************************************
1121  *
1122  * @brief delete E2 node component req info
1123  *
1124  * @details
1125  *
1126  *    Function : deleteE2NodeComponent 
1127  *
1128  * Functionality: delete E2 node component req info 
1129  *
1130  * @parameter
1131  *       Type of interface 
1132  * @return ROK     - success
1133  *         RFAILED - failure
1134  *
1135  ******************************************************************/
1136
1137 uint8_t deleteE2NodeComponent(InterfaceType interfaceType, uint64_t componentId)
1138 {
1139    E2NodeComponent *e2NodeComponentInfo= NULLP;
1140    CmLList  *node = NULLP;
1141          
1142    e2NodeComponentInfo = fetchE2NodeComponentInfo(interfaceType, componentId, &node);
1143    if(!e2NodeComponentInfo)
1144    {
1145       DU_LOG("\nERROR  -->  E2AP : Received null information in %s",__func__);
1146       return RFAILED;
1147    }
1148    
1149    e2NodeComponentInfo->deleteConfiguration = true;
1150    return ROK;
1151 }
1152
1153 /*******************************************************************
1154  *
1155  * @brief fill E2 node component req info
1156  *
1157  * @details
1158  *
1159  *    Function : fillE2NodeComponentReqInfo 
1160  *
1161  * Functionality: fill E2 node component req info 
1162  *
1163  * @parameter
1164  *       Type of interface 
1165  *       Component action type
1166  *       Size of buffer which needs to be store
1167  *       buffer string which needs to be store 
1168  * @return ROK     - success
1169  *         RFAILED - failure
1170  *
1171  ******************************************************************/
1172
1173 uint8_t fillE2NodeComponentReqInfo(InterfaceType interfaceType, uint64_t componentId, uint8_t action, uint8_t bufSize, char *bufString)
1174 {
1175    switch(action)
1176    {
1177       case E2_NODE_COMPONENT_ADD:
1178          {
1179             if(addE2NodeComponent(interfaceType, componentId, bufSize, bufString) != ROK)
1180             {
1181                DU_LOG("\nERROR  -->  E2AP : Failed to add e2 node component");
1182                return RFAILED;
1183             }
1184             break;
1185          }
1186       case E2_NODE_COMPONENT_UPDATE: 
1187          {
1188             if(updateE2NodeComponent(interfaceType, componentId, bufSize, bufString) != ROK)
1189             {
1190                DU_LOG("\nERROR  -->  E2AP : Failed to update e2 node component");
1191                return RFAILED;
1192             }
1193             break;
1194          }
1195       case E2_NODE_COMPONENT_DEL:
1196          {
1197             if(deleteE2NodeComponent(interfaceType, componentId) != ROK)
1198             {
1199                DU_LOG("\nERROR  -->  E2AP : Failed to delete e2 node component");
1200                return RFAILED;
1201             }
1202             break;
1203          }
1204       default:
1205          {
1206             DU_LOG("\nERROR  -->  E2AP : Invalid action %d received",action);
1207             return RFAILED;
1208          }
1209    }
1210
1211    return ROK;
1212 }
1213
1214 /******************************************************************
1215  *
1216  * @brief Delete measured Value list
1217  *
1218  * @details
1219  *
1220  *    Function : deleteMeasuredValueList
1221  *
1222  *    Functionality: Delete measured Value list
1223  *
1224  * @params[in] List of measured Value
1225  *          
1226  * @return void 
1227  *
1228  * ****************************************************************/
1229 void deleteMeasuredValueList(CmLListCp *measuredValueList)
1230 {
1231    CmLList *measValNode = NULLP;
1232
1233    CM_LLIST_FIRST_NODE(measuredValueList, measValNode);
1234
1235    while(measValNode)
1236    {
1237       cmLListDelFrm(measuredValueList, measValNode);
1238       DU_FREE(measValNode->node, sizeof(double));
1239       DU_FREE(measValNode, sizeof(CmLList));
1240       CM_LLIST_FIRST_NODE(measuredValueList, measValNode);
1241    }
1242 }
1243
1244 /******************************************************************
1245  *
1246  * @brief Delete Measurement Info List 
1247  *
1248  * @details
1249  *
1250  *    Function : deleteMeasurementInfoList
1251  *
1252  *    Functionality: Delete Measurement Info List 
1253  *
1254  * @params[in] List of Measurement Info List
1255  *          
1256  * @return void 
1257  *
1258  * ****************************************************************/
1259 void deleteMeasurementInfoList(CmLListCp *measInfoList)
1260 {
1261    CmLList *measInfoNode = NULLP;
1262    MeasurementInfo *measInfo = NULLP;
1263
1264    CM_LLIST_FIRST_NODE(measInfoList, measInfoNode);
1265    while(measInfoNode)
1266    {
1267       measInfo = (MeasurementInfo *)measInfoNode->node;
1268       cmLListDelFrm(measInfoList, measInfoNode);
1269       deleteMeasuredValueList(&measInfo->measuredValue);
1270       DU_FREE(measInfo, sizeof(MeasurementInfo));
1271       DU_FREE(measInfoNode, sizeof(CmLList));
1272       CM_LLIST_FIRST_NODE(measInfoList, measInfoNode);
1273    }
1274 }
1275
1276 /******************************************************************
1277  *
1278  * @brief Delete Ric subscription action 
1279  *
1280  * @details
1281  *
1282  *    Function : deleteActionSequence
1283  *
1284  *    Functionality: Delete Ric subscription action 
1285  *
1286  * @params[in] Action info 
1287  *          
1288  * @return void 
1289  *
1290  * ****************************************************************/
1291 void deleteActionSequence(ActionInfo *action)
1292 {
1293    ActionDefinition *definition=NULLP;
1294    definition= &action->definition;       
1295    
1296    switch(definition->formatType)
1297    {
1298       case 1:
1299          {
1300             deleteMeasurementInfoList(&definition->choice.format1.measurementInfoList);
1301             break;
1302          }
1303
1304       case 2:
1305       case 3:
1306       case 4:
1307       case 5:
1308       default:
1309       {
1310          DU_LOG("\nERROR  -->  E2AP : Format %d does not supported", definition->formatType);
1311          break;
1312       }
1313    }
1314    memset(action, 0, sizeof(ActionInfo));
1315    action->actionId = -1;
1316 }
1317
1318 /******************************************************************
1319  *
1320  * @brief Delete Ric subscription node 
1321  *
1322  * @details
1323  *
1324  *    Function : deleteRicSubscriptionNode
1325  *
1326  *    Functionality: Delete Ric subscription node 
1327  *
1328  * @params[in] Ric subscription info 
1329  *          
1330  * @return void 
1331  *
1332  * ****************************************************************/
1333 void deleteRicSubscriptionNode(CmLList *subscriptionNode)
1334 {
1335    uint8_t actionIdx=0;
1336    RicSubscription *ricSubscriptionInfo = NULLP;
1337
1338    ricSubscriptionInfo = (RicSubscription*)subscriptionNode->node;    
1339
1340    for(actionIdx = 0; actionIdx < MAX_RIC_ACTION; actionIdx++)
1341    {
1342       if(ricSubscriptionInfo->actionSequence[actionIdx].actionId > -1)
1343       {
1344          deleteActionSequence(&ricSubscriptionInfo->actionSequence[actionIdx]);
1345       }
1346    }
1347
1348    if(duChkTmr((PTR)ricSubscriptionInfo, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR) == TRUE)
1349    {
1350       duStopTmr((PTR)ricSubscriptionInfo, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR);
1351    }
1352
1353    memset(ricSubscriptionInfo, 0, sizeof(RicSubscription));
1354    DU_FREE(subscriptionNode->node, sizeof(RicSubscription));
1355    DU_FREE(subscriptionNode, sizeof(CmLList));
1356 }
1357
1358 /******************************************************************
1359  *
1360  * @brief Delete ric subscription list from the database
1361  *
1362  * @details
1363  *
1364  *    Function : deleteRicSubscriptionList
1365  *
1366  *    Functionality: Delete ric subscription list 
1367  *
1368  * @params[in]
1369  *    Subscription List to be deleted 
1370
1371  * @return void 
1372  *
1373  * ****************************************************************/
1374 void deleteRicSubscriptionList(CmLListCp *subscriptionList)
1375 {
1376    CmLList *subscriptionNode=NULLP;
1377    
1378    CM_LLIST_FIRST_NODE(subscriptionList, subscriptionNode);
1379    while(subscriptionNode)
1380    {
1381       /* TODO - Remove subscription information from MAC and SCH as well */ 
1382       cmLListDelFrm(subscriptionList, subscriptionNode);
1383       deleteRicSubscriptionNode(subscriptionNode);
1384       CM_LLIST_FIRST_NODE(subscriptionList, subscriptionNode);
1385    }
1386 }
1387
1388 /*******************************************************************
1389  *
1390  * @brief Find all RIC subscriptions to be deleted in all RAN
1391  *    Functions
1392  *
1393  * @details
1394  *
1395  *    Function : fetchRicSubsToBeDeleted
1396  *
1397  * Functionality: Find all RIC subscriptions to be deleted in all
1398  *    RAN functions and store in a temporary list
1399  *
1400  * @parameter Temporary list to store subscriptions to be deleted
1401  * @return void
1402  *
1403  ******************************************************************/
1404 void fetchRicSubsToBeDeleted(CmLListCp *ricSubsToBeDelList)
1405 {
1406    uint16_t ranFuncIdx = 0;
1407    CmLList *subsNode = NULLP;
1408    CmLList *subsToDelNode = NULLP;
1409
1410    for(ranFuncIdx = 0; ranFuncIdx < MAX_RAN_FUNCTION; ranFuncIdx++)
1411    {
1412       if(duCb.e2apDb.ranFunction[ranFuncIdx].id > 0)
1413       {
1414          CM_LLIST_FIRST_NODE(&duCb.e2apDb.ranFunction[ranFuncIdx].subscriptionList, subsNode);
1415          while(subsNode)
1416          {
1417             if(((RicSubscription *)subsNode->node)->action == CONFIG_DEL)
1418             {
1419                DU_ALLOC(subsToDelNode, sizeof(CmLList));
1420                if(!subsToDelNode)
1421                {
1422                   DU_LOG("\nERROR  -->  E2AP : %s: Memory allocation failure at %d", __func__, __LINE__); 
1423                   return;
1424                }
1425                subsToDelNode->node = subsNode->node;
1426                cmLListAdd2Tail(ricSubsToBeDelList, subsToDelNode);
1427             }
1428             subsToDelNode = NULLP;
1429             subsNode = subsNode->next;
1430          }
1431       }
1432    }
1433 }
1434
1435 /******************************************************************
1436  *
1437  * @brief Delete e2 node information from the database
1438  *
1439  * @details
1440  *
1441  *    Function : removeE2NodeInformation 
1442  *
1443  *    Functionality: Delete e2 node information from the database 
1444  *
1445  * @params[in]
1446  *
1447  * @return void 
1448  *
1449 ******************************************************************/
1450 void removeE2NodeInformation()
1451 {
1452    uint16_t ranFuncIdx = 0;
1453    
1454    DU_LOG("\nINFO  -->  E2AP : Deleting all the E2 node configuration");
1455    for(ranFuncIdx=0; ranFuncIdx<MAX_RAN_FUNCTION; ranFuncIdx++)
1456    {
1457       if(duCb.e2apDb.ranFunction[ranFuncIdx].id >0)
1458       {
1459          deleteRicSubscriptionList(&(duCb.e2apDb.ranFunction[ranFuncIdx].subscriptionList));
1460          memset(&(duCb.e2apDb.ranFunction[ranFuncIdx].pendingSubsRspInfo), 0, MAX_PENDING_SUBSCRIPTION_RSP*sizeof(PendingSubsRspInfo));
1461       }
1462    }
1463    memset(&duCb.e2apDb.ricId, 0, sizeof(GlobalRicId));
1464    duCb.e2apDb.numOfTNLAssoc = 0;
1465    memset(&duCb.e2apDb.tnlAssoc, 0, MAX_TNL_ASSOCIATION*sizeof(TNLAssociation));
1466    cmInetClose(&ricParams.sockFd);
1467    memset(&ricParams, 0, sizeof(DuSctpDestCb));
1468 }
1469 /**********************************************************************
1470   End of file
1471  **********************************************************************/
1472