[Epic-ID: ODUHIGH-406][Task-ID: ODUHIGH-422]F1AP Paging Message Handling at DUAPP
[o-du/l2.git] / src / du_app / du_cell_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
19 /* This file contains message handling functionality for DU cell management */
20 #include "common_def.h"
21 #include "lrg.h"
22 #include "legtp.h"
23 #include "lrg.x"
24 #include "lkw.x"
25 #include "rgr.h"
26 #include "rgr.x"
27 #include "du_app_mac_inf.h"
28 #include "du_app_rlc_inf.h"
29 #include "du_cfg.h"
30 #include "du_mgr.h"
31 #include "du_utils.h"
32 #include "du_cell_mgr.h"
33 #include "PCCH-Config.h"
34
35 #ifdef O1_ENABLE
36
37 #include "AlarmInterface.h"
38 #include "CmInterface.h"
39
40 #endif
41
42 DuMacCellDeleteReq packMacCellDeleteReqOpts[] =
43 {
44    packDuMacCellDeleteReq,       /* Loose coupling */
45    MacProcCellDeleteReq,         /* TIght coupling */
46    packDuMacCellDeleteReq        /* Light weight-loose coupling */
47 };
48
49 /*******************************************************************
50  *
51  * @brief Processes cells to be activated
52  *
53  * @details
54  *
55  *    Function : duProcCellsToBeActivated
56  *
57  *    Functionality:
58  *      - Processes cells to be activated list received in F1SetupRsp
59  *
60  * @params[in] void
61  * @return ROK     - success
62  *         RFAILED - failure
63  *
64  * ****************************************************************/
65 uint8_t duProcCellsToBeActivated(uint8_t *plmnStr, uint16_t nci, uint16_t nRPci)
66 {
67    uint8_t ret = ROK;
68    DuCellCb *cellCb = NULLP;
69    uint8_t cfgIdx, tmpPlmn[4];
70
71    for(cfgIdx=0; cfgIdx<duCb.numCfgCells; cfgIdx++)
72    {
73       memset(tmpPlmn, 0, 4);
74       buildPlmnId(duCb.cfgCellLst[cfgIdx]->cellInfo.nrEcgi.plmn, tmpPlmn);
75       if(duCb.cfgCellLst[cfgIdx]->cellInfo.nrEcgi.cellId == nci &&
76             (strcmp((const char*)tmpPlmn, (const char*)plmnStr) == 0))
77       {
78          cellCb = duCb.cfgCellLst[cfgIdx];
79          break;
80       }
81       else
82       {
83          DU_LOG("\nERROR  -->  DU APP : No Cell found for NCI %d", nci);
84          return RFAILED;
85       }
86    }
87
88    cellCb->cellStatus = ACTIVATION_IN_PROGRESS; 
89    cellCb->cellInfo.nrPci = nRPci;
90
91    if((cmHashListInit(&(cellCb->pagingInfoMap), MAX_SFN, sizeof(DuPagInfoList),\
92                 FALSE, CM_HASH_KEYTYPE_CONID, DU_APP_MEM_REGION, DU_POOL)) != ROK)
93    {
94       DU_LOG("ERROR  --> DU APP: Failed to Initialize the Paging Hash Map");
95       return RFAILED;             
96    }
97    duCb.actvCellLst[cellCb->cellId -1] = cellCb;
98    duCb.numActvCells++;
99
100    if(duBuildAndSendMacCellCfg(cellCb->cellId) != ROK)
101    {
102       DU_LOG("\nERROR  -->  DU APP : macCellCfg build and send failed");
103       /* Delete cell from actvCellList */
104       duCb.actvCellLst[cellCb->cellId -1] = NULLP;
105       --(duCb.numActvCells);
106       ret = RFAILED;
107    }
108    return ret;
109 }
110
111 /*******************************************************************
112  *
113  * @brief Handles DU F1Setup Rsp received in F1AP
114  *
115  * @details
116  *
117  *    Function : duProcF1SetupRsp
118  *
119  *    Functionality:
120  *      - Handles DU F1Setup Rsp received in F1AP
121  *
122  * @params[in] Pointer to F1SetupRsp 
123  * @return void
124  *
125  ******************************************************************/
126 void duProcF1SetupRsp()
127 {
128    DU_LOG("\nINFO   -->  DU_APP : F1 Setup Response received");
129    duCb.f1Status = TRUE; //Set F1 status as true
130 }
131
132 /*******************************************************************
133 *
134 * @brief Returns cellCb based on cell ID
135 *
136 * @details
137 *
138 *    Function : duGetCellCb
139 *
140 *    Functionality: Returns DU APP CellCb based on cell ID
141 *
142 * @params[in] F1AP_PDU_t ASN decoded F1AP message
143 * @return ROK     - success
144 *         RFAILED - failure
145 *
146 * ****************************************************************/
147 uint8_t duGetCellCb(uint16_t cellId, DuCellCb **cellCb)
148 {
149    uint8_t cellIdx = 0;
150
151    for(cellIdx=0; cellIdx < MAX_NUM_CELL; cellIdx++)
152    {
153       if(duCb.actvCellLst[cellIdx] && (duCb.actvCellLst[cellIdx]->cellId == cellId))
154       {
155          *cellCb = duCb.actvCellLst[cellIdx];
156               break;
157       }
158    }
159
160    if(!*cellCb)
161    {
162       DU_LOG("\nERROR  -->  DU APP : Cell Id %d not found in DU APP", cellId);
163       return RFAILED;
164    }
165
166    return ROK;
167 }
168
169 /*****************************************************************
170 * @brief Handles slot indication from MAC
171 *
172 * @details
173 *
174 *   Function : duHandleSlotInd
175 *
176 *   Functionality:
177 *       Handles  slot indication from MAC
178
179 *  @params[in] Post structure pointer
180 *              SlotTimingInfo *slotIndInfo
181 *  @return ROK     - success
182 *          RFAILED - failure
183
184
185 *****************************************************************/
186 uint8_t duHandleSlotInd(Pst *pst, SlotTimingInfo *slotIndInfo)
187 {
188    uint8_t cellIdx = 0, ret = ROK;
189    DuCellCb *duCellCb;
190
191    if(slotIndInfo)
192    {
193       GET_CELL_IDX(slotIndInfo->cellId, cellIdx);
194       duCellCb = duCb.actvCellLst[cellIdx];
195
196       if(duCellCb)
197       {
198          duCellCb->currSlotInfo.sfn = slotIndInfo->sfn;
199          duCellCb->currSlotInfo.slot = slotIndInfo->slot;
200       }
201       else
202       {
203          DU_LOG("\nERROR  -->  DU APP : CellId[%d] doesnot exist", slotIndInfo->cellId);
204          ret = RFAILED;
205       }
206       DU_FREE_SHRABL_BUF(pst->region, pst->pool, slotIndInfo, sizeof(SlotTimingInfo));
207    }
208    else
209    {
210       DU_LOG("\nERROR  -->  DU APP : Recevied null pointer from MAC");
211       ret = RFAILED;
212    }
213    return(ret);
214 }
215 /*******************************************************************
216  *
217  * @brief Handles cell up indication from MAC
218  *
219  * @details
220  *
221  *    Function : duHandleCellUpInd
222  *
223  *    Functionality:
224  *      Handles cell up indication from MAC
225  *
226  * @params[in] Post structure pointer
227  *             cell Up info
228  * @return ROK     - success
229  *         RFAILED - failure
230  *
231  * ****************************************************************/
232 uint8_t duHandleCellUpInd(Pst *pst, OduCellId *cellId)
233 {
234    DuCellCb *cellCb = NULLP; 
235
236    if(cellId->cellId <=0 || cellId->cellId > MAX_NUM_CELL)
237    {
238       DU_LOG("\nERROR  -->  DU APP : Invalid Cell Id %d in duHandleCellUpInd()", cellId->cellId);
239       return RFAILED;
240    }
241
242    if(duGetCellCb(cellId->cellId, &cellCb) != ROK)
243       return RFAILED;
244
245    if((cellCb != NULL) && (cellCb->cellStatus == ACTIVATION_IN_PROGRESS))
246    {
247       DU_LOG("\nINFO   -->  DU APP : 5G-NR Cell %d is UP", cellId->cellId);
248       cellCb->cellStatus = ACTIVATED;
249       gCellStatus = CELL_UP;
250
251       if(duCfgParam.tempSliceCfg.rrmPolicy)
252          BuildAndSendSliceConfigReq(duCfgParam.tempSliceCfg.rrmPolicy, duCfgParam.tempSliceCfg.totalRrmPolicy, duCfgParam.tempSliceCfg.totalSliceCount);
253 #ifdef O1_ENABLE
254       DU_LOG("\nINFO   -->  DU APP : Raise cell UP alarm for cell id=%d", cellId->cellId);
255       raiseCellAlrm(CELL_UP_ALARM_ID, cellId->cellId);
256       setCellOpState(cellId->cellId, ENABLED, ACTIVE);
257 #endif
258
259    }
260
261    if((pst->selector == ODU_SELECTOR_LWLC) || (pst->selector == ODU_SELECTOR_TC))
262       DU_FREE_SHRABL_BUF(pst->region, pst->pool, cellId, sizeof(OduCellId));
263    return ROK;
264 }
265
266 /*******************************************************************
267  *
268  * @brief Handle Cell delete response from MAC
269  *
270  * @details
271  *
272  *    Function : DuProcMacCellDeleteRsp
273  *
274  *    Functionality: Handle Cell delete response from MAC
275  *
276  * @params[in] Pointer to MacCellDeleteRsp and Pst
277  * @return ROK     - success
278  *         RFAILED - failure
279  *
280  * ****************************************************************/
281
282 uint8_t DuProcMacCellDeleteRsp(Pst *pst, MacCellDeleteRsp *deleteRsp)
283 {
284    uint8_t ret = ROK;
285    uint16_t cellIdx=0;
286    
287    if(deleteRsp)
288    {
289       if(deleteRsp->result == SUCCESSFUL_RSP)
290       {
291          GET_CELL_IDX(deleteRsp->cellId, cellIdx);
292          DU_LOG("\nINFO   -->  DU APP : MAC CELL Delete Response : SUCCESS [CELL IDX : %d]", deleteRsp->cellId);
293          if(duCb.actvCellLst[cellIdx] && (duCb.actvCellLst[cellIdx]->cellId == deleteRsp->cellId))
294          {
295             memset(duCb.actvCellLst[cellIdx], 0, sizeof(DuCellCb));
296             gCellStatus = CELL_DOWN;
297
298 #ifdef O1_ENABLE
299             DU_LOG("\nINFO   -->  DU APP : Raise cell down alarm for cell id=%d", deleteRsp->cellId);
300             raiseCellAlrm(CELL_DOWN_ALARM_ID, deleteRsp->cellId);
301             setCellOpState(deleteRsp->cellId, DISABLED, INACTIVE);
302 #endif
303
304             duCb.numActvCells--;
305             duCb.numCfgCells--;
306             DU_FREE(duCb.actvCellLst[cellIdx], sizeof(DuCellCb));
307
308          }
309          else
310          {
311             DU_LOG("\nERROR  -->  DU APP : DuProcMacCellDeleteRsp(): CellId [%d] doesnot exist", deleteRsp->cellId);
312             ret = RFAILED;
313          }
314       }
315       else
316       {
317          DU_LOG("\nERROR  -->  DU APP : DuProcMacCellDeleteRsp(): MAC CELL Delete Response : FAILED\
318          [CELL IDX : %d]", deleteRsp->cellId);
319          ret = RFAILED;
320       }
321       DU_FREE_SHRABL_BUF(pst->region, pst->pool, deleteRsp, sizeof(MacCellDeleteRsp));
322    }
323    else
324    {
325       DU_LOG("\nERROR  -->  DU APP : DuProcMacCellDeleteRsp(): Received MAC cell delete response is NULL");
326       ret = RFAILED;
327    }
328    return ret;
329 }
330
331 /*******************************************************************
332  *
333  * @brief Sending Cell Delete Req To Mac
334  *
335  * @details
336  *
337  *    Function : sendCellDeleteReqToMac
338  *
339  *    Functionality:
340  *     sending Cell Delete Req To Mac
341  *
342  *  @params[in]    uint16_t cellId
343  *  @return ROK     - success
344  *          RFAILED - failure
345  *
346  *
347  *****************************************************************/
348
349 uint8_t sendCellDeleteReqToMac(uint16_t cellId)
350 {
351    Pst pst;
352    uint8_t ret=ROK;
353    MacCellDelete *cellDelete = NULLP;
354    
355    DU_ALLOC_SHRABL_BUF(cellDelete, sizeof(MacCellDelete));
356    if(cellDelete)
357    {
358       cellDelete->cellId = cellId;
359       FILL_PST_DUAPP_TO_MAC(pst, EVENT_MAC_CELL_DELETE_REQ);
360
361       DU_LOG("\nINFO   -->  DU APP : Sending Cell Delete Request to MAC");  
362       /* Processing one Cell at a time to MAC */
363       ret = (*packMacCellDeleteReqOpts[pst.selector])(&pst, cellDelete);
364       if(ret == RFAILED)
365       {
366          DU_LOG("\nERROR  -->  DU APP : sendCellDeleteReqToMac(): Failed to send Cell delete Req to MAC");
367          DU_FREE_SHRABL_BUF(DU_APP_MEM_REGION, DU_POOL, cellDelete, sizeof(MacCellDelete));
368       }
369    }
370    else
371    {
372       DU_LOG("\nERROR  -->   DU APP : sendCellDeleteReqToMac(): Failed to allocate memory"); 
373       ret = RFAILED;
374    }
375    return ret;
376 }
377
378 /*******************************************************************
379  *
380  * @brief DU preocess Cell Delete Req to MAC 
381  *
382  * @details
383  *
384  *    Function : duSendCellDeletReq 
385  *
386  *    Functionality: DU process Cell Delete Req to MAC 
387  *
388  * @params[in] uint16_t cellId
389  * @return ROK     - success
390  *         RFAILED - failure
391  *
392  * ****************************************************************/
393
394 uint8_t duSendCellDeletReq(uint16_t cellId)
395 {
396    uint16_t cellIdx = 0;
397    DU_LOG("\nINFO   -->  DU APP : Processing Cell Delete Request ");
398    GET_CELL_IDX(cellId, cellIdx);
399
400    if(duCb.actvCellLst[cellIdx] == NULLP)
401    {
402       DU_LOG("\nERROR  -->  DU APP : duSendCellDeletReq(): CellId[%d] is not found", cellId);
403       return RFAILED;
404    }
405    
406    if(duCb.actvCellLst[cellIdx]->cellId != cellId)
407    {
408       DU_LOG("\nERROR  -->  DU APP : duSendCellDeletReq(): CellId[%d] is not found", cellId);
409       return RFAILED;
410
411    }  
412    
413    if(duCb.actvCellLst[cellIdx]->cellStatus != DELETION_IN_PROGRESS)
414    {
415       DU_LOG("\nERROR  -->  DU APP : duSendCellDeletReq(): CellStatus[%d] of cellId[%d] is not correct.\
416       Expected CellStatus is DELETION_IN_PROGRESS",duCb.actvCellLst[cellIdx]->cellStatus, cellId);
417       return RFAILED;  
418    }
419
420    if(duBuildAndSendMacCellStop(cellId) == RFAILED)
421    {
422       DU_LOG("\nERROR  -->  DU APP : duSendCellDeletReq(): Failed to build and send cell stop request to MAC for\
423             cellId[%d]",cellId);
424       return RFAILED;
425    }
426
427    return ROK;
428 }
429
430 /*******************************************************************
431  * @brief Find the PageInfo List from HashMap 
432  *
433  * @details
434  *
435  *    Function : findPagingInfoFromMap
436  *
437  *    Functionality: Search for the PageInfoList for a PF from HashMap
438  *
439  * @params[in] uint16_t pf, CmHashListCp *pagingInfoMap
440  *
441  * @return DuPagInfoList 
442  *
443  * ****************************************************************/
444 DuPagInfoList* findPagingInfoFromMap(uint16_t pf, CmHashListCp *pagingInfoMap)
445 {
446    DuPagInfoList *pagInfoLL = NULLP;
447
448    cmHashListFind(pagingInfoMap, (uint8_t *)&(pf), sizeof(uint16_t), 0, (PTR *)&pagInfoLL);
449    if(pagInfoLL == NULLP)
450    {
451       DU_LOG("\nDEBUG  --> DU APP: PF:%d doesnt exist in Map",pf);
452    }
453    return pagInfoLL;
454 }
455
456 /*******************************************************************
457  * @brief Handle the PageInfo List
458  *
459  * @details
460  *
461  *    Function : handlePageInfoLL
462  *
463  *    Functionality: Handling the (SEARCH,CREATE,DELETE) PageInfoList
464  *
465  * @params[in] uint8_t i_s, CmLListCp *pagInfoLL, ActionTypeLL action
466  *
467  * @return DuPagUeList 
468  *
469  * ****************************************************************/
470 DuPagUeList* handlePageInfoLL(uint8_t i_s, CmLListCp *pagInfoLL, ActionTypeLL action)
471 {
472    CmLList  *node = NULLP;
473    DuPagUeList *pagInfo = NULLP;
474    bool found = FALSE;
475
476    if(pagInfoLL == NULLP)
477    {
478       DU_LOG("\nERROR  -->  DU APP: PagInfo LL is empty");
479       return NULLP;
480    }
481    node = pagInfoLL->first;
482
483    while(node)
484    {
485       pagInfo = (DuPagUeList *)node->node;
486       if(pagInfo->i_s == i_s)
487       {
488          found = TRUE;
489          break;
490       }
491       node = node->next;
492    }
493
494    switch(action)
495    {
496       case SEARCH:
497          {
498             if(!found)
499             {
500                pagInfo = NULLP;
501             }
502             return pagInfo;
503          }
504
505       case CREATE:
506          {
507             if(node != NULLP)
508                return pagInfo;
509
510             /*Need to add a new node for this LC*/
511
512             /*List is empty; Initialize the LL ControlPointer*/
513             if(pagInfoLL->count == 0)
514             {
515                cmLListInit(pagInfoLL);
516             }
517
518             pagInfo = NULLP;
519             /*Allocate the List*/
520             DU_ALLOC(pagInfo, sizeof(DuPagUeList));
521             if(pagInfo)
522             {
523                pagInfo->i_s = i_s;
524             }
525             else
526             {
527                DU_LOG("\nERROR  -->  DU APP : Allocation of List failed,i_s:%d",i_s);
528                return NULLP;
529             }
530
531             if(duAddNodeToLList(pagInfoLL, pagInfo, NULLP) == RFAILED)
532             {
533                DU_LOG("\nERROR  -->  DU APP : failed to Add Node,i_s:%d",i_s);
534                DU_FREE(pagInfo, sizeof(DuPagUeList));
535                return NULLP;
536             }
537             return pagInfo;
538          }
539       case DELETE:
540          {
541             if(!found ||  pagInfo == NULLP)
542             {
543                DU_LOG("\nERROR  -->  DU APP: i_s:%d not found; thus Deletion unsuccessful",i_s);
544             }
545             else
546             {
547                if(duDelNodeFromLList(pagInfoLL, node) == ROK)
548                   DU_FREE(pagInfo, sizeof(DuPagUeList));
549
550                DU_LOG("\nDEBUG  -->  DU APP: i_s:%d Deleted successfully",i_s);
551             }
552             return NULLP;
553          }
554       default:
555          {
556             DU_LOG("\nERROR  -->  DU APP: Incorrect ActionType:%d on PageInfo List",action);
557          }
558    }
559    return NULLP;
560 }
561
562 /*******************************************************************
563  * @brief Handle the PageUe List
564  *
565  * @details
566  *
567  *    Function : handlePageUeLL
568  *
569  *    Functionality: Handling the (SEARCH,CREATE,DELETE) PageUeList
570  *
571  * @params[in] DuPagingMsg *pagingParam, CmLListCp *pageUeLL, ActionTypeLL
572  * action
573  *
574  * @return DuPagUeRecord 
575  *
576  * ****************************************************************/
577 DuPagUeRecord* handlePageUeLL(DuPagingMsg *pagingParam, CmLListCp *pageUeLL, ActionTypeLL action)
578 {
579    CmLList  *node = NULLP;
580    DuPagUeRecord *ueRecord = NULLP;
581    bool found = FALSE;
582
583    if(pageUeLL == NULLP)
584    {
585       DU_LOG("\nERROR  -->  DU APP: UE Page Record LL is empty");
586       return NULLP;
587    }
588    node = pageUeLL->first;
589
590    while(node)
591    {
592       ueRecord = (DuPagUeRecord *)node->node;
593       if(ueRecord && (ueRecord->pagUeId == pagingParam->pagUeId && 
594                ueRecord->sTmsi == pagingParam->sTmsi))
595       {
596          found = TRUE;
597          break;
598       }
599       node = node->next;
600    }
601
602    switch(action)
603    {
604       case SEARCH:
605          {
606             if(!found)
607             {
608                ueRecord = NULLP;
609             }
610             return ueRecord;
611          }
612
613       case CREATE:
614          {
615             if(node != NULLP)
616                return ueRecord;
617
618             /*Need to add a new node for this LC*/
619
620             /*List is empty; Initialize the LL ControlPointer*/
621             if(pageUeLL->count == 0)
622             {
623                cmLListInit(pageUeLL);
624             }
625
626             ueRecord = NULLP;
627             /*Allocate the List*/
628             DU_ALLOC(ueRecord, sizeof(DuPagUeRecord));
629             if(ueRecord)
630             {
631                ueRecord->pagUeId = pagingParam->pagUeId;
632                ueRecord->sTmsi = pagingParam->sTmsi;
633                ueRecord->pagPriority = pagingParam->pagPriority;
634             }
635             else
636             {
637                DU_LOG("\nERROR  -->  DU APP : Allocation of UE Record failed,ueId:%d",pagingParam->pagUeId);
638                return NULLP;
639             }
640
641             if(duAddNodeToLList(pageUeLL, ueRecord, NULLP) == RFAILED)
642             {
643                DU_LOG("\nERROR  -->  DU APP : failed to Add Ue Record Node,ueId:%d",pagingParam->pagUeId);
644                DU_FREE(ueRecord, sizeof(DuPagUeRecord));
645                return NULLP;
646             }
647             return ueRecord;
648          }
649       case DELETE:
650          {
651             if(!found ||  ueRecord == NULLP)
652             {
653                DU_LOG("\nERROR  -->  DU APP: UeId:%d not found; thus Deletion unsuccessful",pagingParam->pagUeId);
654             }
655             else
656             {
657                if(duDelNodeFromLList(pageUeLL, node) == ROK)
658                   DU_FREE(ueRecord, sizeof(DuPagUeRecord));
659
660                DU_LOG("\nDEBUG  -->  DU APP: UeId:%d Deleted successfully",pagingParam->pagUeId);
661             }
662             return NULLP;
663          }
664       default:
665          {
666             DU_LOG("\nERROR  -->  DU APP: Incorrect ActionType:%d on UeRecord",action);
667          }
668    }
669    return NULLP;
670 }
671
672 /*******************************************************************
673  * @brief Keeping the record of Paging having a particular SFN and index associated 
674  *
675  * @details
676  *
677  *    Function : insertPagingRecord 
678  *
679  *    Functionality:  Insert record of Paging assoc with particular SFN and index associated 
680  *
681  * @params[in] DuCellCb* cellCb, uint16_t iterations
682  *             DuPagingMsg  rcvdF1apPagingParam
683  *
684  * @return ROK     - success
685  *         RFAILED - failure
686  *
687  * ****************************************************************/
688 uint8_t insertPagingRecord(DuCellCb* cellCb, DuPagingMsg *rcvdF1apPagingParam, uint16_t iterations)
689 {
690    uint16_t maxIterations = 0; 
691    DuPagInfoList *pagInfoLLFromPF = NULLP;
692    DuPagUeList  *pageUeLL = NULLP;
693    DuPagUeRecord *ueRecord = NULLP;
694
695    //printPageList(&(cellCb->pagingInfoMap));
696
697    /*MAX Iteration : A UE can be paged at every T frames thus MAX determines
698     *how many Paging Frame(s) can be considered for Paging this UE*/
699    maxIterations = MAX_SFN/rcvdF1apPagingParam->T;
700    if(iterations >= maxIterations)
701    {
702       DU_LOG("\nERROR  --> DU APP: MAX Iterations reached for UEID:%d, thus Paging is dropped!", rcvdF1apPagingParam->pagUeId);
703       return RFAILED;
704    }
705
706    /*[Step1]: Extracting the PF from the HasMap between PF and PagingInfoList*/
707    pagInfoLLFromPF = findPagingInfoFromMap(rcvdF1apPagingParam->pagingFrame, &(cellCb->pagingInfoMap));
708    if(pagInfoLLFromPF != NULLP)
709    {
710       /*[Step2]: Extracting the PageInfo List for the Paging Indices(i_s)*/
711       pageUeLL = handlePageInfoLL(rcvdF1apPagingParam->i_s, &(pagInfoLLFromPF->pagInfoList), CREATE);
712
713       if(pageUeLL != NULLP)
714       {
715          /*[Step3]: Check whether MAX UE Record against this PF and i_s has reached*/
716          if(pageUeLL->pagUeList.count < MAX_PAGING_UE_RECORDS)
717          {
718             /*[Step4]: Insert the Paging Record to the end of the UE record List*/
719             ueRecord = handlePageUeLL(rcvdF1apPagingParam, &(pageUeLL->pagUeList), CREATE);
720
721             if(ueRecord == NULLP)
722             {
723                DU_LOG("\nERROR  --> DU APP: Unable to create UE Record in PagingList");
724                return RFAILED;
725             }
726             DU_LOG("\nDEBUG  --> DU APP: UE Record created successfully in PagingList");
727             return ROK;
728          }
729          else
730          {
731             /*Since MAX Page record has reached for this PF thus calculating and
732              *moving this UE to next Paging Cycle*/
733             DU_LOG("\nINFO   --> DU APP: Max Page Record reached for PagingFrame:%d",rcvdF1apPagingParam->pagingFrame);
734             rcvdF1apPagingParam->pagingFrame = ((rcvdF1apPagingParam->pagingFrame + rcvdF1apPagingParam->T) % MAX_SFN);
735             iterations++;
736
737             return insertPagingRecord(cellCb, rcvdF1apPagingParam, iterations);
738          }
739       }
740    }
741    /*Reaching here means that PF has no entry in the PageLists,
742     *Thus creating, Updating and inseritng the Paging Map, List and UE record.*/
743
744    DU_ALLOC(pagInfoLLFromPF, sizeof(DuPagInfoList));
745
746    if(pagInfoLLFromPF == NULLP)
747    {
748       DU_LOG("\nERROR  --> DU APP: PageInfo Map allocation failed.");
749       return RFAILED;
750    }
751    pagInfoLLFromPF->pf = rcvdF1apPagingParam->pagingFrame;
752    pageUeLL = handlePageInfoLL(rcvdF1apPagingParam->i_s, &(pagInfoLLFromPF->pagInfoList), CREATE);
753    ueRecord = handlePageUeLL(rcvdF1apPagingParam, &(pageUeLL->pagUeList), CREATE);
754    if(cmHashListInsert(&(cellCb->pagingInfoMap), (PTR)pagInfoLLFromPF, (uint8_t *)&(pagInfoLLFromPF->pf), sizeof(uint16_t)) == RFAILED)
755    {
756       DU_LOG("\nERROR  --> DU APP: Hash Map Insertion Failed for PF:%d.",rcvdF1apPagingParam->pagingFrame);
757    }
758
759    //printPageList(&(cellCb->pagingInfoMap));
760    return ROK;
761
762
763 }
764
765 /*******************************************************************
766  * @brief Calculate and fill paging information of a UE belongs to a particular cell
767  *
768  * @details
769  *
770  *    Function : calcAndFillPagingInfoInCellCb
771  *
772  *    Functionality: Calculate PO and i_s and 
773  *                   fill paging information of a UE in DuCellCb
774  *
775  * @params[in] DuCellCb* cellCb, uint8_t pagUeId, 
776  *             DuPagingMsg  rcvdF1apPagingParam
777  *
778  * @return ROK     - success
779  *         RFAILED - failure
780  *
781  * ****************************************************************/
782 uint8_t calcAndFillPagingInfoInCellCb(DuCellCb* cellCb, DuPagingMsg *rcvdF1apPagingParam)
783 {
784    uint8_t ns = 0;
785    uint16_t T=0, N=0, pagingFrame = 0, n = 0;
786    uint16_t currentSfn = 0, sfn = 0, newSfn = 0;
787    PcchCfg   duPcchCfg;
788
789    DU_LOG("\nINFO   --> DU APP : Start filling paging parameters in DuCellCb");
790    if(cellCb)
791    {
792       /* calculate paging frame and paging offset */
793       duPcchCfg = duCfgParam.sib1Params.srvCellCfgCommSib.dlCfg.pcchCfg;
794       rcvdF1apPagingParam->pagingFrameOffset = duPcchCfg.pageFrameOffset;
795       ns = duPcchCfg.ns;      
796
797       /*
798        * Fill the Value of T (DRX cycle of the UE)
799        * T = min(UE Specific DRX value allocated by upper layers, default DRX
800        * broadcast in System Information) */
801       if((rcvdF1apPagingParam->pagingDrxPres) && (duPcchCfg.dfltPagingCycle > rcvdF1apPagingParam->pagingDrx))
802       {
803          T = rcvdF1apPagingParam->pagingDrx;
804       } 
805       else
806       {
807          T = duPcchCfg.dfltPagingCycle;
808       }
809       rcvdF1apPagingParam->T = T;
810
811        /* N= number of total paging frames in T */
812
813       switch(duPcchCfg.nAndPagingFrmOffsetType)
814       {
815          case PCCH_Config__nAndPagingFrameOffset_PR_oneT:
816             N = T;
817             break;
818          case PCCH_Config__nAndPagingFrameOffset_PR_halfT:
819             N = T/2;
820             break;
821          case PCCH_Config__nAndPagingFrameOffset_PR_quarterT:
822             N = T/4;
823             break;
824          case PCCH_Config__nAndPagingFrameOffset_PR_oneEighthT:
825             N = T/8;
826             break;
827          case PCCH_Config__nAndPagingFrameOffset_PR_oneSixteenthT:
828             N = T/16;
829             break;
830          default:
831             N = T;
832             break;
833       }
834
835        /* calculate the Value of pagingFrame */
836       /*Refer: 38.304 Sec 7.1: (SFN + PF_offset) mod T = (T div N)*(UE_ID mod N)*/
837       //RHS of above formula
838       pagingFrame = (T / N) * ((rcvdF1apPagingParam->pagUeId) % N);
839
840       //LHS of above formula
841       if(pagingFrame)
842       {
843          pagingFrame = (pagingFrame - rcvdF1apPagingParam->pagingFrameOffset)%T;
844       }
845       else /*Paging Frame = 0 so thus PF will be calculated on Paging Cycle*/
846       {
847          pagingFrame = (T - rcvdF1apPagingParam->pagingFrameOffset)%T;
848       }
849
850       /*Paging Frame(SFN for Paging) has to be determined from current SFN. */
851       /*For eg: If T =128, PF(Calculated above) = 20; SFN can be 20,148,276,...
852        * If currSFN is running as 200 then (newSFN % T) == (T/N)*(UE_ID%N)
853        *Thus SFN at which paging has to be sent needs to be delayed and newSFN = 276*/
854
855       currentSfn = cellCb->currSlotInfo.sfn;
856
857       /*Multiplication Factor(x) to find the next best SFN to process paging*/
858
859       /*Below calculation will determine in which nth cycle of T (DRX cycle),new PF
860        * may fall(Delayed one)*/
861       if(currentSfn > pagingFrame)
862       {
863          n  = ((currentSfn - pagingFrame) / T) + 1;
864       }
865       else
866       {
867          n  = ((pagingFrame - currentSfn) / T) + 1;
868       }
869
870       newSfn = pagingFrame + T * n;
871
872       /*When pagingFrame is future from currSFN then pagingFrame will be used 
873        * else pagingFrame is delayed thus newSFN will be used.*/
874       if(currentSfn <= pagingFrame)
875       {
876          if(pagingFrame > currentSfn + PAGING_SCHED_DELTA)
877          {
878             sfn = pagingFrame;
879          }
880          else
881          {
882             sfn = newSfn;
883          }
884       }
885       else
886       {
887          
888          if(newSfn > currentSfn + PAGING_SCHED_DELTA)
889          {
890             sfn = newSfn;
891          }
892          else /*If newSFN is near to currSFN then delay it more by T*/
893          {
894             newSfn = newSfn + T;
895             sfn = newSfn;
896          }
897       }
898       rcvdF1apPagingParam->pagingFrame =  (sfn % MAX_SFN);
899       rcvdF1apPagingParam->i_s = ((uint32_t)(floor(rcvdF1apPagingParam->pagUeId / N)) % ns);
900
901       DU_LOG("\nINFO  --> DU APP : Successfully filled paging parameter in DuCellCb");
902       memcpy(&cellCb->tmpPagingInfoOfUe, rcvdF1apPagingParam, sizeof(DuPagingMsg));
903    }
904    else
905    {
906       DU_LOG("\nINFO  --> DU APP : calcAndFillPagingInfoInCellCb(): Received null pointer");
907       return RFAILED;
908    }
909    return ROK;
910 }
911
912 /*******************************************************************
913  * @brief Paging Processing on a particular cell 
914  *
915  * @details
916  *
917  *    Function : processPagingMsg
918  *
919  *    Functionality: Process Paging on a particular cell 
920  *
921  * @params[in] uint16_t cellId
922  *             DuPagingMsg  rcvdF1apPagingParam
923  *
924  * @return ROK     - success
925  *         RFAILED - failure
926  *
927  * ****************************************************************/
928 uint8_t processPagingMsg(uint16_t cellId, DuPagingMsg *rcvdF1apPagingParam)
929 {
930    uint16_t cellIdx = 0, iteration = 0;
931
932    GET_CELL_IDX(cellId, cellIdx);
933
934    if(duCb.actvCellLst[cellIdx] == NULLP || duCb.actvCellLst[cellIdx]->cellId != cellId)
935    {
936       DU_LOG("\nERROR  -->  DU APP : processPagingMsg(): CellId[%d] is not found", cellId);
937       return RFAILED;
938    }
939    
940    if(calcAndFillPagingInfoInCellCb(duCb.actvCellLst[cellIdx], rcvdF1apPagingParam) != ROK)
941    {
942       DU_LOG("\nERROR  --> DU APP : CellCb:%d not present to fill UE Paging Information",cellId);
943       return RFAILED;
944    }
945    if(insertPagingRecord(duCb.actvCellLst[cellIdx], rcvdF1apPagingParam, iteration) != ROK)
946    {
947       DU_LOG("\nERROR  --> DU APP : Insertion Failed ofUE Paging Information");
948       return RFAILED;
949    }
950    return ROK;
951
952 }
953 /**********************************************************************
954   End of file
955  **********************************************************************/