644a5eb35272aa1af01b1d59c2c9a103fb65ca1d
[o-du/l2.git] / src / 5gnrmac / rg_l2m.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 /************************************************************************
20  
21      Name:     LTE-MAC layer
22   
23      Type:     C source file
24   
25      Desc:     C source code for  L2 Measurements in MAC
26   
27      File:     rg_l2m.c
28   
29 **********************************************************************/
30
31 /** @file rg_l2m.c
32 @brief This file implements the schedulers main access to MAC layer code.
33 */
34
35 /* header include files -- defines (.h) */
36 #include "common_def.h"
37 #include "lrg.h"
38 #include "crg.h"        
39 #include "rgr.h"
40 #include "rgu.h"           
41 #include "tfu.h"
42 #include "rg_env.h"
43 #include "rg_err.h"
44 #include "rg_sch_inf.h"
45 #include "rg.h"
46
47 /* header/extern include files (.x) */
48 #include "rgu.x"           /* RGU types */
49 #include "tfu.x"           /* TFU types */
50 #include "lrg.x"           /* layer management typedefs for MAC */
51 #include "rgr.x"           /* layer management typedefs for MAC */
52 #include "crg.x"           /* layer management typedefs for MAC */
53 #include "rg_sch_inf.x"    /* typedefs for Scheduler */
54 #include "rg_prg.x"        /* typedefs for PRG interface */
55 #include "du_app_mac_inf.h"
56 #include "rg.x"            /* MAC types */
57
58
59 /* local defines */
60 #ifdef LTE_L2_MEAS
61 static S16 rgL2mInsertMeasCb ARGS((
62          RgCellCb       *cell,
63          RgL2MeasCb     *measCb,
64          RgInfL2MeasReq *measInfo ));
65
66 static RgL2MeasCb * rgL2mAllocMeasCb ARGS((
67          RgCellCb       *cell,
68          RgInfL2MeasReq *measInfo,
69          RgErrInfo      *err));
70
71 /* Function definitions */
72
73 /** @brief This function creates the measCb
74  *
75  * @details
76  *
77  *     Function: rgL2mCreateMeasCb
78  *         Processing steps:
79  *         - Check the measType
80  *         - Create measCb for every qci
81  *
82  * @param  [in] RgCellCb       *cell
83  * @param  [in] RgInfL2MeasReq *measInfo
84  * @param  [in] uint8_t             measType
85  * @param  [out] RgErrInfo      *err
86  * @return  S16
87  *      -# ROK 
88  *      -# RFAILED 
89  *
90  */
91 S16 rgL2mCreateMeasCb 
92 (
93 RgCellCb       *cell,
94 RgInfL2MeasReq *measInfo, 
95 uint8_t        measType,
96 RgErrInfo      *err
97 )
98 {
99   // Inst    inst = cell->macInst - RG_INST_START;
100    uint32_t     idx;
101    RgL2MeasCb   *measCb = NULLP;
102    uint8_t      qciVal = 0;
103
104    UNUSED(measType);
105    UNUSED(err);
106
107    if ((measCb = rgL2mAllocMeasCb(cell, measInfo, err)) == NULLP)
108    {
109       DU_LOG("\nERROR  -->  MAC : Allocation of RgL2MeasCb failed");
110       return RFAILED;
111    }
112    //Memcpy is already done in rgL2mAllocMeasCb
113    /*memcpy(&measCb->measReq, (const uint8_t *)measInfo,\
114      sizeof(RgInfL2MeasReq));*/
115    rgL2mInsertMeasCb(cell, measCb, measInfo);
116    measCb->measReq.timePrd = measInfo->timePrd;
117
118    if(measInfo->timePrd == 0)
119    {
120       cell->sndL2Meas = FALSE;
121    }
122
123    for(idx = 0; idx < measInfo->t.prbReq.numQci; idx++)
124    {
125       if(measInfo->timePrd == 0)
126       {
127          qciVal = measInfo->t.prbReq.qci[idx];
128          cell->qciArray[qciVal].qci = qciVal;
129       }
130       cell->qciArray[measInfo->t.prbReq.qci[idx]].mask = TRUE;
131    }
132    return ROK;
133 } /* rgL2mCreateMeasCb */
134
135
136 /**
137  * @brief Layer Manager Measurement request handler. 
138  *
139  * @details
140  *
141  *     Function : rgL2mMeasReq
142  *     
143  *     This function handles  measurement request received at MAC
144  *     from the Scheduler.
145  *     -# Measurement request will be stored in the list in descending order of
146  *     there time period.
147  *     
148  *  @param[in]  Pst *pst, the post structure     
149  *  @param[in]  RgInfL2MeasReq *measInfo, the measurement request structure
150  *  @param[out] RgErrInfo   *err, error information
151  *  @return  S16
152  *      -# ROK
153  **/
154 S16 rgL2mMeasReq 
155 (
156 RgCellCb       *cell,
157 RgInfL2MeasReq *measInfo,
158 RgErrInfo      *err
159 )
160 {
161    S16  ret=RFAILED;
162
163    /* Creaet MeasCb Insert in cell->l2mList and return*/
164    if ( (ret = rgL2mCreateMeasCb(cell, measInfo,
165                LRG_L2MEAS_AVG_PRB_PER_QCI_UL, err)) != ROK)
166    {
167       /* Clear Downlink MeasCb created Above If exists*/
168       return (ret);
169    }
170    return ROK;
171 } /* rgL2mMeasReq */
172 /** @brief This function sends the measurement confirm
173  *  from mac to scheduler
174  *
175  * @details
176  *
177  *     Function: rgSndL2MeasCfm
178  *
179  * @param  [in] RgCellCb          *cell
180  * @param  [in] RgInfL2MeasCfm    *measCfm
181  */
182 static Void rgSndL2MeasCfm(RgCellCb *cell, RgInfL2MeasCfm *measCfm)
183 {
184    Pst             pst;
185    Inst            macInst = cell->macInst - RG_INST_START;
186
187    memset(&pst, 0, sizeof(Pst));
188    rgGetPstToInst(&pst,macInst, cell->schInstMap.schInst);
189    RgMacSchL2Meas(&pst, measCfm);
190
191    return;
192 }/* rgSndL2MeasCfm */
193
194 /** @brief This function sends the measurement stop confirm
195  *  from mac to scheduler
196  *
197  * @details
198  *
199  *     Function: rgSndL2MeasStopCfm
200  *
201  * @param  [in] RgCellCb          *cell
202  * @param  [in] RgInfL2MeasCfm    *measCfm
203  */
204 static Void rgSndL2MeasStopCfm(RgCellCb *cell,RgInfL2MeasCfm *measCfm)
205 {
206    Pst             pst;
207    Inst            macInst = cell->macInst - RG_INST_START;
208
209    memset(&pst, 0, sizeof(Pst));
210    rgGetPstToInst(&pst,macInst, cell->schInstMap.schInst);
211    RgMacSchL2MeasStop(&pst, measCfm);
212
213    return;
214 }/* rgSndL2MeasStopCfm */
215
216 /**
217  * @brief  L2 Measurement request handler.This function shall be called by
218  *  scheduler to calculate average PRB usage Per Qci in Uplink
219  *
220  * @details
221  *
222  *     Function : RgSchMacL2MeasReq
223  *     
224  *  @param[in]  Pst *pst, the post structure     
225  *  @param[in]  RgInfL2MeasReq *measInfo, L2 Measurement req structure
226  *  @return  S16
227  *      -# ROK
228  *      -# RFAILED
229  **/
230 S16 RgSchMacL2MeasReq
231 (
232 Pst               *pst,          /* post structure  */
233 RgInfL2MeasReq    *measInfo      /* Meas Req Info */
234 )
235 {
236    Inst            inst;
237    RgCellCb        *cellCb = NULLP;
238    RgErrInfo       err;
239    S16             ret = ROK;
240    RgInfL2MeasCfm   measCfm;
241
242    RG_IS_INST_VALID(pst->dstInst);
243    inst   = pst->dstInst - RG_INST_START;
244    cellCb = rgCb[inst].cell;
245    /* Get the  cell using cellId */
246    if ((cellCb == NULLP) ||
247        (cellCb->cellId != measInfo->cellId))
248    {
249       DU_LOG("\nERROR  -->  MAC : unable to get the cellCb");
250       return RFAILED;
251    }
252    /* Call L2M Function to store Meas req */
253    ret = rgL2mMeasReq(cellCb, measInfo, &err);
254    if (ret != ROK)
255    {
256       memset(&measCfm, 0, sizeof(RgInfL2MeasCfm));
257       measCfm.transId     = measInfo->transId;
258       measCfm.cellId      = measInfo->cellId;
259       measCfm.measType    = measInfo->measType;
260       measCfm.cfm.reason   = LCM_REASON_INVALID_PAR_VAL;
261       measCfm.cfm.status  = LCM_PRIM_NOK;
262       rgSndL2MeasCfm(cellCb, &measCfm);
263       DU_LOG("\nERROR  -->  MAC : Meas req Failed  errType(%d) errCause(%d)",
264                err.errType, err.errCause);
265       return RFAILED;
266    }
267    return (ret);
268 } /* -- RgSchMacL2MeasReq-- */
269
270 /**
271  * @brief  L2 Measurement request handler.This function shall be called by
272  *         sch to to stop l2 measurement in MAC,
273  *
274  * @details
275  *
276  *     Function : RgSchMacL2MeasStopReq
277  *     
278  *  @param[in]  Pst *pst, the post structure     
279  *  @param[in]  RgInfL2MeasReq *measInfo, L2 Measurement req structure
280  *  @return  S16
281  *      -# ROK
282  *      -# RFAILED
283  **/
284 S16 RgSchMacL2MeasStopReq
285 (
286 Pst               *pst,          /* post structure  */
287 RgInfL2MeasStopReq *measInfo      /* Meas Req Info */
288 )
289 {
290    S16            ret = ROK;   
291    CmLList        *node   = NULLP;
292    RgL2MeasCb     *measCb = NULLP;
293    uint8_t        idx;
294    uint8_t        qciVal;
295    Inst           inst;
296    RgCellCb       *cellCb = NULLP;
297    RgInfL2MeasCfm  measCfm;
298
299    RG_IS_INST_VALID(pst->dstInst);
300    inst   = pst->dstInst - RG_INST_START;
301    cellCb = rgCb[inst].cell;
302       /* Get the  cell using cellId */
303    if ((cellCb == NULLP) ||
304        (cellCb->cellId != measInfo->cellId))
305    {
306       
307       DU_LOG("\nERROR  -->  MAC : Unable to get the cellCb");
308       return RFAILED;
309    }
310    node = cellCb->l2mList.first; 
311    while(node != NULLP)
312    {
313       measCb = (RgL2MeasCb *)(node)->node;
314       node = (node)->next;
315       /*L2 Meas off for qci in cell */
316       for(idx = 0; idx < measCb->measReq.t.prbReq.numQci; idx++)
317       {
318          qciVal = measCb->measReq.t.prbReq.qci[idx];
319          cellCb->qciArray[qciVal].mask = FALSE;
320       }
321       cmLListDelFrm(&cellCb->l2mList, &measCb->measLnk);
322       rgFreeSBuf(inst,(Data**)&measCb, sizeof(RgL2MeasCb));
323    }
324    memset(&measCfm, 0, sizeof(RgInfL2MeasCfm));
325    measCfm.transId     = measInfo->transId;
326    measCfm.cellId      = measInfo->cellId;
327    measCfm.measType    = measInfo->measType;
328    measCfm.cfm.status  = LCM_PRIM_OK;
329    rgSndL2MeasStopCfm(cellCb, &measCfm);
330    return (ret);
331 } /* -- RgSchMacL2MeasStopReq-- */
332
333 /**
334  * @brief  L2 Measurement request handler.This function shall be called by
335  *  scheduler for  sending L2 meas 
336  *
337  * @details
338  *
339  *     Function : RgSchMacL2MeasSendReq
340  *     
341  *  @param[in]  Pst *pst, the post structure     
342  *  @param[in]  RgInfL2MeasReq *measInfo, L2 Measurement req structure
343  *  @return  S16
344  *      -# ROK
345  *      -# RFAILED
346  **/
347 S16 RgSchMacL2MeasSendReq
348 (
349 Pst               *pst,          /* post structure  */
350 RgInfL2MeasSndReq *measInfo      /* Meas Req Info */
351 )
352 {
353    Inst            inst;
354    RgCellCb       *cellCb = NULLP;
355    S16             ret    = ROK;
356
357    RG_IS_INST_VALID(pst->dstInst);
358    inst   = pst->dstInst - RG_INST_START;
359    cellCb = rgCb[inst].cell;
360       /* Get the  cell using cellId */
361    if ((cellCb == NULLP) ||
362        (cellCb->cellId != measInfo->cellId))
363    {
364       
365       DU_LOG("\nERROR  -->  MAC : Unable to get the cellCb");
366       return RFAILED;
367    }
368    /*set sndL2Meas as applicatoin sent l2 meas info request*/
369    cellCb->sndL2Meas = TRUE;
370
371    return (ret);
372 }/*RgSchMacL2MeasSendReq*/ 
373
374 /** @brief This function inserts the MeasCb in to data base
375  *
376  * @details
377  *
378  *     Function: rgL2mInsertMeasCb
379  *
380  * @param  [in] RgCellCb       *cell
381  * @param  [in] RgL2MeasCb     *measCb
382  * @param  [in] RgInfMeasReq   *measInfo
383  * @return  S16
384  *      -# ROK 
385  *      -# RFAILED 
386  */
387 static S16 rgL2mInsertMeasCb
388 (
389 RgCellCb       *cell,
390 RgL2MeasCb     *measCb,
391 RgInfL2MeasReq *measInfo
392 )
393 {
394    CmLList    *lnk, *node;
395    RgL2MeasCb *oldMeasCb;
396    uint16_t   diffTime;
397
398       /* 
399        * 1. Check if l2mList has any entries.
400        * 2. If yes 
401        *       1. Take the first entrie's time period and find the diff with
402        *       cell->crntTime.
403        *       2. If the diff is > measInfo->timePeriod then insert before this
404        *       entry.
405        *       3. Else take the next entry in list
406        *       4. If reached without adding to list . Append at the end of list.
407        * 3. If no entries in l2mList add at the first.
408        */
409       lnk = cell->l2mList.first;
410
411    node = &measCb->measLnk;
412    node->node = (PTR)measCb;
413    while(lnk != NULLP )
414    {
415       oldMeasCb = (RgL2MeasCb *)lnk->node;
416       diffTime = (oldMeasCb->measReq.timePrd - 
417             (RG_CALC_SF_DIFF(cell->crntTime, oldMeasCb->startTime)));
418       if (diffTime > measInfo->timePrd)
419       {
420          cell->l2mList.crnt = lnk;
421          cmLListInsCrnt(&(cell->l2mList), node);
422          return ROK;
423       }
424       else
425       {
426          lnk = lnk->next;
427       }
428    }  /* End of While */
429
430    cmLListAdd2Tail(&(cell->l2mList), node);
431    return ROK;
432 } /* rgL2mInsertMeasCb */
433
434 /** @brief This function allocates memory from the heap
435  *
436  * @details
437  *
438  *     Function: rgL2mAllocMeasCb
439  *
440  * @param  [in] RgCellCb       *cell
441  * @param  [in] RgInfL2MeasReq *measInfo
442  * @param  [out] RgErrInfo      *err
443  * @return  RgSchL2MeasCb *
444  */
445 static RgL2MeasCb * rgL2mAllocMeasCb
446 (
447 RgCellCb       *cell,
448 RgInfL2MeasReq *measInfo,
449 RgErrInfo      *err
450 )
451 {
452    RgL2MeasCb       *measCb = NULLP;
453    Inst             inst = cell->macInst - RG_INST_START;
454
455
456       if((rgAllocSBuf(inst,(Data **)&(measCb),
457                   sizeof(RgL2MeasCb))) == RFAILED)
458       {
459          DU_LOG("\nERROR  -->  MAC : Allocation of RgL2MeasCb failed");
460          err->errType  = RGERR_L2M_MEASREQ;
461          err->errCause = RGERR_RAM_MEM_EXHAUST;
462          return (NULLP);
463       }
464    memcpy(&measCb->measReq, measInfo, sizeof(RgInfL2MeasReq));
465    RGCPYTIMEINFO(cell->crntTime, measCb->startTime);
466
467    return (measCb);
468 } /* rgL2mAllocMeasCb */
469
470
471 /**
472  * @brief This function calculates the measurement for measType 
473  * LRG_L2MEAS_AVG_PRB_PER_QCI_UL and send the end result to the 
474  * MAC Scheduler.
475  *
476  * @details
477  *
478  *  Function : rgL2Meas
479  *     
480  *  @param[in] RgCellCb  *cell
481  *  @return  S16
482  *      -# ROK
483  *      -# RFAILED
484  **/
485 S16 rgL2Meas(RgCellCb  *cell)
486 {
487    CmLList         *node   = NULLP;
488    RgL2MeasCb      *measCb = NULLP;
489    RgInfL2MeasCfm   measCfm;
490    uint8_t          idx = 0;
491    uint8_t          qciVal = 0;
492    uint32_t         measPrd; /*LTE_L2_MEAS_PHASE2*/
493    CmLteTimingInfo  crntTime;
494    Inst             inst = cell->macInst - RG_INST_START;
495    
496    node = cell->l2mList.first;
497
498    while(node != NULLP)
499    {
500       measCb = (RgL2MeasCb *)node->node;
501       node = node->next;
502       crntTime = cell->crntTime;
503
504       if(cell->crntTime.sfn == 0 && (cell->crntTime.slot % RG_NUM_SUB_FRAMES) == 0)
505       {
506          measCb->sfnCycle++;
507       }
508
509       measPrd = RG_CALC_SFN_SF_DIFF(cell->crntTime, 
510                         measCb->sfnCycle, measCb->startTime);
511       
512       /*LTE_L2_MEAS_PHASE2*/
513       if (cell->sndL2Meas || measPrd == measCb->measReq.timePrd)
514       {
515          memset(&measCfm, 0, sizeof(RgInfL2MeasCfm));
516          for(idx = 0; idx < measCb->measReq.t.prbReq.numQci; idx++)
517          {
518             qciVal = measCb->measReq.t.prbReq.qci[idx];
519             measCfm.u.prbCfm.prbUsage[idx].qciValue = qciVal;
520
521             measCfm.transId  = measCb->measReq.transId;
522             measCfm.measType = measCb->measReq.measType;
523             measCfm.cellId    = measCb->measReq.cellId;
524
525             measCfm.u.prbCfm.prbUsage[idx].prbUsage = 
526                cell->qciArray[qciVal].prbCount;
527
528             cell->qciArray[qciVal].prbCount = 0;
529             measCfm.u.prbCfm.numQci++;
530             if(measCb->measReq.timePrd > 0)
531             {
532                cell->qciArray[qciVal].mask = FALSE;
533             }
534          }
535          rgSndL2MeasCfm(cell, &measCfm);
536
537          if(measCb->measReq.timePrd > 0) 
538          {
539             cmLListDelFrm(&cell->l2mList, &measCb->measLnk);
540             rgFreeSBuf(inst,(Data**)&measCb, sizeof(RgL2MeasCb));
541          }
542          else /*if meas period is 0 then do not delette meascb , just reset l2 cntrs value to 0*/
543          { 
544             measCb->startTime = crntTime;
545             measCb->measReq.timePrd = 0;
546             cell->sndL2Meas = FALSE;
547          }
548          continue;
549       } 
550    }
551    return ROK;
552 } /* rgL2MEas */
553
554 #endif /* LTE_L2_MEAS */
555 /**********************************************************************
556  
557          End of file
558 **********************************************************************/