<[Epic-ID: ODUHIGH-406][Task-ID: ODUHIGH-421]Paging Message: CU_STUB Trigger and...
[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    duCb.actvCellLst[cellCb->cellId -1] = cellCb;
92    duCb.numActvCells++;
93
94    if(duBuildAndSendMacCellCfg(cellCb->cellId) != ROK)
95    {
96       DU_LOG("\nERROR  -->  DU APP : macCellCfg build and send failed");
97       /* Delete cell from actvCellList */
98       duCb.actvCellLst[cellCb->cellId -1] = NULLP;
99       --(duCb.numActvCells);
100       ret = RFAILED;
101    }
102    return ret;
103 }
104
105 /*******************************************************************
106  *
107  * @brief Handles DU F1Setup Rsp received in F1AP
108  *
109  * @details
110  *
111  *    Function : duProcF1SetupRsp
112  *
113  *    Functionality:
114  *      - Handles DU F1Setup Rsp received in F1AP
115  *
116  * @params[in] Pointer to F1SetupRsp 
117  * @return void
118  *
119  ******************************************************************/
120 void duProcF1SetupRsp()
121 {
122    DU_LOG("\nINFO   -->  DU_APP : F1 Setup Response received");
123    duCb.f1Status = TRUE; //Set F1 status as true
124 }
125
126 /*******************************************************************
127 *
128 * @brief Returns cellCb based on cell ID
129 *
130 * @details
131 *
132 *    Function : duGetCellCb
133 *
134 *    Functionality: Returns DU APP CellCb based on cell ID
135 *
136 * @params[in] F1AP_PDU_t ASN decoded F1AP message
137 * @return ROK     - success
138 *         RFAILED - failure
139 *
140 * ****************************************************************/
141 uint8_t duGetCellCb(uint16_t cellId, DuCellCb **cellCb)
142 {
143    uint8_t cellIdx = 0;
144
145    for(cellIdx=0; cellIdx < MAX_NUM_CELL; cellIdx++)
146    {
147       if(duCb.actvCellLst[cellIdx] && (duCb.actvCellLst[cellIdx]->cellId == cellId))
148       {
149          *cellCb = duCb.actvCellLst[cellIdx];
150               break;
151       }
152    }
153
154    if(!*cellCb)
155    {
156       DU_LOG("\nERROR  -->  DU APP : Cell Id %d not found in DU APP", cellId);
157       return RFAILED;
158    }
159
160    return ROK;
161 }
162
163 /*****************************************************************
164 * @brief Handles slot indication from MAC
165 *
166 * @details
167 *
168 *   Function : duHandleSlotInd
169 *
170 *   Functionality:
171 *       Handles  slot indication from MAC
172
173 *  @params[in] Post structure pointer
174 *              SlotTimingInfo *slotIndInfo
175 *  @return ROK     - success
176 *          RFAILED - failure
177
178
179 *****************************************************************/
180 uint8_t duHandleSlotInd(Pst *pst, SlotTimingInfo *slotIndInfo)
181 {
182    uint8_t cellIdx = 0, ret = ROK;
183    DuCellCb *duCellCb;
184
185    if(slotIndInfo)
186    {
187       GET_CELL_IDX(slotIndInfo->cellId, cellIdx);
188       duCellCb = duCb.actvCellLst[cellIdx];
189
190       if(duCellCb)
191       {
192          duCellCb->currSlotInfo.sfn = slotIndInfo->sfn;
193          duCellCb->currSlotInfo.slot = slotIndInfo->slot;
194       }
195       else
196       {
197          DU_LOG("\nERROR  -->  DU APP : CellId[%d] doesnot exist", slotIndInfo->cellId);
198          ret = RFAILED;
199       }
200       DU_FREE_SHRABL_BUF(pst->region, pst->pool, slotIndInfo, sizeof(SlotTimingInfo));
201    }
202    else
203    {
204       DU_LOG("\nERROR  -->  DU APP : Recevied null pointer from MAC");
205       ret = RFAILED;
206    }
207    return(ret);
208 }
209 /*******************************************************************
210  *
211  * @brief Handles cell up indication from MAC
212  *
213  * @details
214  *
215  *    Function : duHandleCellUpInd
216  *
217  *    Functionality:
218  *      Handles cell up indication from MAC
219  *
220  * @params[in] Post structure pointer
221  *             cell Up info
222  * @return ROK     - success
223  *         RFAILED - failure
224  *
225  * ****************************************************************/
226 uint8_t duHandleCellUpInd(Pst *pst, OduCellId *cellId)
227 {
228    DuCellCb *cellCb = NULLP; 
229
230    if(cellId->cellId <=0 || cellId->cellId > MAX_NUM_CELL)
231    {
232       DU_LOG("\nERROR  -->  DU APP : Invalid Cell Id %d in duHandleCellUpInd()", cellId->cellId);
233       return RFAILED;
234    }
235
236    if(duGetCellCb(cellId->cellId, &cellCb) != ROK)
237       return RFAILED;
238
239    if((cellCb != NULL) && (cellCb->cellStatus == ACTIVATION_IN_PROGRESS))
240    {
241       DU_LOG("\nINFO   -->  DU APP : 5G-NR Cell %d is UP", cellId->cellId);
242       cellCb->cellStatus = ACTIVATED;
243       gCellStatus = CELL_UP;
244
245       if(duCfgParam.tempSliceCfg.rrmPolicy)
246          BuildAndSendSliceConfigReq(duCfgParam.tempSliceCfg.rrmPolicy, duCfgParam.tempSliceCfg.totalRrmPolicy, duCfgParam.tempSliceCfg.totalSliceCount);
247 #ifdef O1_ENABLE
248       DU_LOG("\nINFO   -->  DU APP : Raise cell UP alarm for cell id=%d", cellId->cellId);
249       raiseCellAlrm(CELL_UP_ALARM_ID, cellId->cellId);
250       setCellOpState(cellId->cellId, ENABLED, ACTIVE);
251 #endif
252
253    }
254
255    if((pst->selector == ODU_SELECTOR_LWLC) || (pst->selector == ODU_SELECTOR_TC))
256       DU_FREE_SHRABL_BUF(pst->region, pst->pool, cellId, sizeof(OduCellId));
257    return ROK;
258 }
259
260 /*******************************************************************
261  *
262  * @brief Handle Cell delete response from MAC
263  *
264  * @details
265  *
266  *    Function : DuProcMacCellDeleteRsp
267  *
268  *    Functionality: Handle Cell delete response from MAC
269  *
270  * @params[in] Pointer to MacCellDeleteRsp and Pst
271  * @return ROK     - success
272  *         RFAILED - failure
273  *
274  * ****************************************************************/
275
276 uint8_t DuProcMacCellDeleteRsp(Pst *pst, MacCellDeleteRsp *deleteRsp)
277 {
278    uint8_t ret = ROK;
279    uint16_t cellIdx=0;
280    
281    if(deleteRsp)
282    {
283       if(deleteRsp->result == SUCCESSFUL_RSP)
284       {
285          GET_CELL_IDX(deleteRsp->cellId, cellIdx);
286          DU_LOG("\nINFO   -->  DU APP : MAC CELL Delete Response : SUCCESS [CELL IDX : %d]", deleteRsp->cellId);
287          if(duCb.actvCellLst[cellIdx] && (duCb.actvCellLst[cellIdx]->cellId == deleteRsp->cellId))
288          {
289             memset(duCb.actvCellLst[cellIdx], 0, sizeof(DuCellCb));
290             gCellStatus = CELL_DOWN;
291
292 #ifdef O1_ENABLE
293             DU_LOG("\nINFO   -->  DU APP : Raise cell down alarm for cell id=%d", deleteRsp->cellId);
294             raiseCellAlrm(CELL_DOWN_ALARM_ID, deleteRsp->cellId);
295             setCellOpState(deleteRsp->cellId, DISABLED, INACTIVE);
296 #endif
297
298             duCb.numActvCells--;
299             duCb.numCfgCells--;
300             DU_FREE(duCb.actvCellLst[cellIdx], sizeof(DuCellCb));
301
302          }
303          else
304          {
305             DU_LOG("\nERROR  -->  DU APP : DuProcMacCellDeleteRsp(): CellId [%d] doesnot exist", deleteRsp->cellId);
306             ret = RFAILED;
307          }
308       }
309       else
310       {
311          DU_LOG("\nERROR  -->  DU APP : DuProcMacCellDeleteRsp(): MAC CELL Delete Response : FAILED\
312          [CELL IDX : %d]", deleteRsp->cellId);
313          ret = RFAILED;
314       }
315       DU_FREE_SHRABL_BUF(pst->region, pst->pool, deleteRsp, sizeof(MacCellDeleteRsp));
316    }
317    else
318    {
319       DU_LOG("\nERROR  -->  DU APP : DuProcMacCellDeleteRsp(): Received MAC cell delete response is NULL");
320       ret = RFAILED;
321    }
322    return ret;
323 }
324
325 /*******************************************************************
326  *
327  * @brief Sending Cell Delete Req To Mac
328  *
329  * @details
330  *
331  *    Function : sendCellDeleteReqToMac
332  *
333  *    Functionality:
334  *     sending Cell Delete Req To Mac
335  *
336  *  @params[in]    uint16_t cellId
337  *  @return ROK     - success
338  *          RFAILED - failure
339  *
340  *
341  *****************************************************************/
342
343 uint8_t sendCellDeleteReqToMac(uint16_t cellId)
344 {
345    Pst pst;
346    uint8_t ret=ROK;
347    MacCellDelete *cellDelete = NULLP;
348    
349    DU_ALLOC_SHRABL_BUF(cellDelete, sizeof(MacCellDelete));
350    if(cellDelete)
351    {
352       cellDelete->cellId = cellId;
353       FILL_PST_DUAPP_TO_MAC(pst, EVENT_MAC_CELL_DELETE_REQ);
354
355       DU_LOG("\nINFO   -->  DU APP : Sending Cell Delete Request to MAC");  
356       /* Processing one Cell at a time to MAC */
357       ret = (*packMacCellDeleteReqOpts[pst.selector])(&pst, cellDelete);
358       if(ret == RFAILED)
359       {
360          DU_LOG("\nERROR  -->  DU APP : sendCellDeleteReqToMac(): Failed to send Cell delete Req to MAC");
361          DU_FREE_SHRABL_BUF(DU_APP_MEM_REGION, DU_POOL, cellDelete, sizeof(MacCellDelete));
362       }
363    }
364    else
365    {
366       DU_LOG("\nERROR  -->   DU APP : sendCellDeleteReqToMac(): Failed to allocate memory"); 
367       ret = RFAILED;
368    }
369    return ret;
370 }
371
372 /*******************************************************************
373  *
374  * @brief DU preocess Cell Delete Req to MAC 
375  *
376  * @details
377  *
378  *    Function : duSendCellDeletReq 
379  *
380  *    Functionality: DU process Cell Delete Req to MAC 
381  *
382  * @params[in] uint16_t cellId
383  * @return ROK     - success
384  *         RFAILED - failure
385  *
386  * ****************************************************************/
387
388 uint8_t duSendCellDeletReq(uint16_t cellId)
389 {
390    uint16_t cellIdx = 0;
391    DU_LOG("\nINFO   -->  DU APP : Processing Cell Delete Request ");
392    GET_CELL_IDX(cellId, cellIdx);
393
394    if(duCb.actvCellLst[cellIdx] == NULLP)
395    {
396       DU_LOG("\nERROR  -->  DU APP : duSendCellDeletReq(): CellId[%d] is not found", cellId);
397       return RFAILED;
398    }
399    
400    if(duCb.actvCellLst[cellIdx]->cellId != cellId)
401    {
402       DU_LOG("\nERROR  -->  DU APP : duSendCellDeletReq(): CellId[%d] is not found", cellId);
403       return RFAILED;
404
405    }  
406    
407    if(duCb.actvCellLst[cellIdx]->cellStatus != DELETION_IN_PROGRESS)
408    {
409       DU_LOG("\nERROR  -->  DU APP : duSendCellDeletReq(): CellStatus[%d] of cellId[%d] is not correct.\
410       Expected CellStatus is DELETION_IN_PROGRESS",duCb.actvCellLst[cellIdx]->cellStatus, cellId);
411       return RFAILED;  
412    }
413
414    if(duBuildAndSendMacCellStop(cellId) == RFAILED)
415    {
416       DU_LOG("\nERROR  -->  DU APP : duSendCellDeletReq(): Failed to build and send cell stop request to MAC for\
417             cellId[%d]",cellId);
418       return RFAILED;
419    }
420
421    return ROK;
422 }
423
424 /*******************************************************************
425  * @brief fill paging information of a UE belongs to a particular cell
426  *
427  * @details
428  *
429  *    Function : FillPagingInfoInCellCb
430  *
431  *    Functionality: fill paging information of a UE in DuCellCb
432  *
433  * @params[in] DuCellCb* cellCb, uint8_t ueId, 
434  *             DuPagingMsg  rcvdF1apPagingParam
435  *
436  * @return ROK     - success
437  *         RFAILED - failure
438  *
439  * ****************************************************************/
440 uint8_t FillPagingInfoInCellCb(DuCellCb* cellCb, DuPagingMsg *rcvdF1apPagingParam)
441 {
442    uint8_t ns = 0;
443    uint16_t T=0, N=0, pagingFrame = 0, n = 0;
444    uint16_t currentSfn = 0, sfn = 0, newSfn = 0;
445    PcchCfg   duPcchCfg;
446
447    DU_LOG("\nINFO   --> DU APP : Start filling paging parameters in DuCellCb");
448    if(cellCb)
449    {
450       /* calculate paging frame and paging offset */
451       duPcchCfg = duCfgParam.sib1Params.srvCellCfgCommSib.dlCfg.pcchCfg;
452       rcvdF1apPagingParam->pagingFrameOffset = duPcchCfg.pageFrameOffset;
453       ns = duPcchCfg.ns;      
454
455       /*
456        * Fill the Value of T (DRX cycle of the UE)
457        * T = min(UE Specific DRX value allocated by upper layers, default DRX
458        * broadcast in System Information) */
459       if((rcvdF1apPagingParam->pagingDrxPres) && (duPcchCfg.dfltPagingCycle > rcvdF1apPagingParam->pagingDrx))
460       {
461          T = rcvdF1apPagingParam->pagingDrx;
462       } 
463       else
464       {
465          T = duPcchCfg.dfltPagingCycle;
466       }
467       rcvdF1apPagingParam->T = T;
468
469        /* N= number of total paging frames in T */
470
471       switch(duPcchCfg.nAndPagingFrmOffsetType)
472       {
473          case PCCH_Config__nAndPagingFrameOffset_PR_oneT:
474             N = T;
475             break;
476          case PCCH_Config__nAndPagingFrameOffset_PR_halfT:
477             N = T/2;
478             break;
479          case PCCH_Config__nAndPagingFrameOffset_PR_quarterT:
480             N = T/4;
481             break;
482          case PCCH_Config__nAndPagingFrameOffset_PR_oneEighthT:
483             N = T/8;
484             break;
485          case PCCH_Config__nAndPagingFrameOffset_PR_oneSixteenthT:
486             N = T/16;
487             break;
488          default:
489             N = T;
490             break;
491       }
492
493        /* calculate the Value of pagingFrame */
494       /*Refer: 38.304 Sec 7.1: (SFN + PF_offset) mod T = (T div N)*(UE_ID mod N)*/
495       //RHS of above formula
496       pagingFrame = (T / N) * ((rcvdF1apPagingParam->ueId) % N);
497
498       //LHS of above formula
499       if(pagingFrame)
500       {
501          pagingFrame = (pagingFrame - rcvdF1apPagingParam->pagingFrameOffset)%T;
502       }
503       else /*Paging Frame = 0 so thus PF will be calculated on Paging Cycle*/
504       {
505          pagingFrame = (T - rcvdF1apPagingParam->pagingFrameOffset)%T;
506       }
507
508       /*Paging Frame(SFN for Paging) has to be determined from current SFN. */
509       /*For eg: If T =128, PF(Calculated above) = 20; SFN can be 20,148,276,...
510        * If currSFN is running as 200 then (newSFN % T) == (T/N)*(UE_ID%N)
511        *Thus SFN at which paging has to be sent needs to be delayed and newSFN = 276*/
512
513       currentSfn = cellCb->currSlotInfo.sfn;
514
515       /*Multiplication Factor(x) to find the next best SFN to process paging*/
516
517       /*Below calculation will determine in which nth cycle of T (DRX cycle),new PF
518        * may fall(Delayed one)*/
519       if(currentSfn > pagingFrame)
520       {
521          n  = ((currentSfn - pagingFrame) / T) + 1;
522       }
523       else
524       {
525          n  = ((pagingFrame - currentSfn) / T) + 1;
526       }
527
528       newSfn = pagingFrame + T * n;
529
530       /*When pagingFrame is future from currSFN then pagingFrame will be used 
531        * else pagingFrame is delayed thus newSFN will be used.*/
532       if(currentSfn <= pagingFrame)
533       {
534          if(pagingFrame > currentSfn + PAGING_SCHED_DELTA)
535          {
536             sfn = pagingFrame;
537          }
538          else
539          {
540             sfn = newSfn;
541          }
542       }
543       else
544       {
545          
546          if(newSfn > currentSfn + PAGING_SCHED_DELTA)
547          {
548             sfn = newSfn;
549          }
550          else /*If newSFN is near to currSFN then delay it more by T*/
551          {
552             newSfn = newSfn + T;
553             sfn = newSfn;
554          }
555       }
556       rcvdF1apPagingParam->pagingFrame =  (sfn % 1024);
557       rcvdF1apPagingParam->i_s = ((uint32_t)(floor(rcvdF1apPagingParam->ueId / N)) % ns);
558
559       DU_LOG("\nINFO  --> DU APP : Successfully filled paging parameter in DuCellCb");
560       memcpy(&cellCb->tmpPagingInfoOfUe, rcvdF1apPagingParam, sizeof(DuPagingMsg));
561    }
562    else
563    {
564       DU_LOG("\nINFO  --> DU APP : FillPagingInfoInCellCb(): Received null pointer");
565       return RFAILED;
566    }
567    return ROK;
568 }
569
570
571 /**********************************************************************
572   End of file
573  **********************************************************************/