Merge "RAR and MSG3 scheduling in TDD [Issue-ID: ODUHIGH-342]"
[o-du/l2.git] / src / 5gnrrlc / rlc_utl_ul.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:     NR RLC Layer 
22   
23      Type:     C file
24   
25      Desc:     Source code for RLC Utility Module
26                This file contains following functions
27
28                   --rlcUtlSendToMac
29                   --rlcUtlRcvFrmMac
30                   --rlcUtlEmptySduQ
31                   --rlcUtlSendUlDataToDu 
32                   --kwUtlShutDown
33
34      File:     rlc_utl_ul.c
35
36 **********************************************************************/
37
38 /** @file rlc_utl_ul.c
39 @brief RLC Utility Module 
40 */
41
42 /* header (.h) include files */
43 #include "common_def.h"
44 /* kw005.201 added support for L2 Measurement */
45 #ifdef LTE_L2_MEAS
46 #include <sys/time.h>
47 #endif
48
49 #include "ckw.h"           /* CKW defines */
50 #include "kwu.h"           /* KWU defines */
51 #include "lkw.h"           /* LKW defines */
52 #include "rgu.h"           /* RGU defines */
53 #include "rlc_env.h"        /* RLC environment options */
54 #include "rlc_err.h"        /* Error defines */
55
56
57 /* extern (.x) include files */
58 #include "ckw.x"           /* CKW includes */
59 #include "kwu.x"           /* KWU includes */
60 #include "lkw.x"           /* LKW includes */
61 #include "rgu.x"           /* RGU includes */
62
63 #include "rlc_utils.h"            /* RLC defines */
64 #include "rlc_ul.h"         /* RLC Uplink defines */
65 #include "du_app_rlc_inf.h"
66 #include "rlc_upr_inf_api.h"
67
68 #ifdef SS_RBUF
69 S16 SMrkUlPkt(Buffer *mbuf);
70 #endif
71 RlcAmRecBuf* rlcUtlGetRecBuf(CmLListCp *recBufLst, RlcSn sn);
72 #define RLC_MODULE (RLC_DBGMASK_DUT | RLC_DBGMASK_UL) /* for debugging purpose */
73
74
75 /**
76  *
77  * @brief 
78  *        Handler for receiving data for multiple logical channels from MAC.
79  *
80  * @details
81  *        This function receives the data sent by MAC for one or more 
82  *        logical channels.It calls the UMM or AMM functions to process
83  *        the PDUs and send them to the uppper layer.  
84  *
85  * @param[in] gCb          - RLC instance control block 
86  * @param[in] datIndInfo   - Data Indication Information containing the PDU(s)
87  *                            for one or more logical channels  
88  *
89  * @return  S16
90  *      -# ROK 
91  *      -# RFAILED
92  *
93  */
94 uint8_t rlcUtlRcvFrmMac(RlcCb *gCb, KwDatIndInfo  *datIndInfo)
95 {
96    uint32_t    count;      /* Loop Counter */
97    KwPduInfo   *pduInfo;   /* PDU Information */
98    RlcUlRbCb    *rbCb;      /* RB Control Block */
99    RlcUlUeCb    *ueCb;      /* UE Control Block */
100
101    ueCb = NULLP;
102    
103    /* fetch UeCb  */
104    if( ROK != rlcDbmFetchUlUeCb(gCb,datIndInfo->rnti,datIndInfo->cellId,&(ueCb)))
105    {
106       /* Fetch UeCb failed */
107       DU_LOG("\nERROR  -->  RLC_UL : rlcUtlRcvFrmMac : UEID:%d UeCb not found",
108                datIndInfo->rnti);
109       /* free the buffers inside the datIndInfo */
110       uint32_t i,j;
111       for(i = 0; i< datIndInfo->numLch; i++)
112       {
113          for(j = 0; j < datIndInfo->lchData[i].pdu.numPdu; j++)
114          {
115             if(datIndInfo->lchData[i].pdu.mBuf[j])
116             {
117                ODU_PUT_MSG_BUF(datIndInfo->lchData[i].pdu.mBuf[j]);
118             }
119          }
120       }
121       
122       return RFAILED;
123    }
124
125 #ifdef LTE_L2_MEAS
126
127    if (RGU_L2M_UL_BURST_START == datIndInfo->burstInd)
128    {
129       ueCb->isUlBurstActive = TRUE;
130    }
131    else
132    {
133       ueCb->firstPacketTTI = 0;
134       ueCb->isUlBurstActive = FALSE;
135    }
136 #endif
137    for ( count = 0;count < datIndInfo->numLch; count++ )
138    {
139       rbCb = ueCb->lCh[datIndInfo->lchData[count].lcId - 1].ulRbCb;
140       /* kw002.201 Removed allocation of pduInfo */ 
141       pduInfo = &(datIndInfo->lchData[count].pdu);
142       /* Fix for CR ccpu00138374,sometimes rbCb is NULL in UL path,
143        * So inorder to avoid the crash, added this preventive check
144        */
145       if(rbCb == NULLP)
146       {
147          uint32_t j;
148          for(j = 0; j < pduInfo->numPdu; j++)
149          {
150             if(pduInfo->mBuf[j])
151             {
152                ODU_PUT_MSG_BUF(pduInfo->mBuf[j]);
153             }
154          }
155          continue;
156       }
157
158 #ifdef SS_RBUF
159       SMrkUlPkt(pduInfo->mBuf[0]);
160 #endif
161       if ( rbCb->mode == RLC_MODE_UM )
162       {
163 /* kw005.201 added support for L2 Measurement */
164 #ifdef LTE_L2_MEAS
165          rlcUmmProcessPdus(gCb,rbCb, pduInfo, datIndInfo->ttiCnt);
166 #else
167          rlcUmmProcessPdus(gCb,rbCb,pduInfo);
168 #endif
169       }
170       else if (rbCb->mode == RLC_MODE_AM )
171       {
172 /* kw005.201 added support for L2 Measurement */
173 #ifdef LTE_L2_MEAS
174          rlcAmmProcessPdus(gCb,rbCb,  pduInfo, datIndInfo->ttiCnt);
175 #else
176          rlcAmmProcessPdus(gCb,rbCb,pduInfo);
177 #endif
178       }
179    }
180    return ROK;
181 }
182
183 /**
184  *
185  * @brief 
186  *    Handler for sending Data Indication to the upper layer. 
187  * 
188  * @Details
189  *    This function is used to send re-assembled SDU to the upper layer.
190  *
191  * @param[in]  gCb    - RLC instance Control Block 
192  * @param[in]  rbCb   - RB Control Block 
193  * @param[in]  sdu    - SDU to be sent to upper layer 
194  *
195  * @return  S16
196  *      -# ROK 
197  */
198 uint8_t rlcUtlSendUlDataToDu(RlcCb *gCb, RlcUlRbCb *rbCb, Buffer *sdu)
199 {
200 #ifndef KW_PDCP
201    KwuDatIndInfo   *datIndInfo = NULLP;   /* Data Indication Information */
202    KwuDatIndInfo datIndInfoTmp;
203 #endif
204    RlcUlRrcMsgInfo  *ulRrcMsgInfo = NULLP;
205    RlcUlUserDatInfo *ulUserDatInfo = NULLP;
206    uint16_t        msgLen = 0, copyLen = 0;
207    Pst             pst;
208
209 #ifndef KW_PDCP
210    /* Creating static memory for KwuDatIndInfo. #else will be 
211     * removed once the testing is done on all platforms */
212    datIndInfo = &datIndInfoTmp;
213    if (datIndInfo == NULLP)
214    {
215       DU_LOG("\nERROR  -->  RLC_UL: rlcUtlSendUlDataToDu: Memory allocation failed UEID:%d \
216          CELLID:%d", rbCb->rlcId.ueId, rbCb->rlcId.cellId);
217       ODU_PUT_MSG_BUF(sdu);
218       return RFAILED;
219    }
220
221    RLC_MEM_CPY(&(datIndInfo->rlcId),&(rbCb->rlcId),sizeof(CmLteRlcId));
222    /* Set the "isOutofSeq" flag for each packet 
223     * If packets are in-sequence set flag as TRUE else FALSE */
224    datIndInfo->isOutOfSeq = rbCb->m.amUl.isOutOfSeq; 
225 #endif /* KW_PDCP */
226    
227    if(rbCb->rlcId.rbType == RB_TYPE_SRB)
228    {
229       /* Filling UL RRC Message Info if UL msg is not received on SRBs*/
230       RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL,
231             ulRrcMsgInfo, sizeof(RlcUlRrcMsgInfo));
232       if (ulRrcMsgInfo)
233       {
234               ulRrcMsgInfo->cellId = rbCb->rlcId.cellId;
235               ulRrcMsgInfo->ueIdx = rbCb->rlcId.ueId;
236               ulRrcMsgInfo->lcId = rbCb->lch.lChId;
237               ODU_GET_MSG_LEN(sdu, (MsgLen *)&msgLen);
238               RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL,
239                      ulRrcMsgInfo->rrcMsg, msgLen);
240               if (ulRrcMsgInfo->rrcMsg)
241               {
242                 ODU_COPY_MSG_TO_FIX_BUF(sdu, 0, msgLen, ulRrcMsgInfo->rrcMsg, (MsgLen *)&copyLen);
243                 ulRrcMsgInfo->msgLen = msgLen;
244
245                 /* Sending UL RRC Message transfeer to DU APP */
246                 memset(&pst, 0, sizeof(Pst));
247                 FILL_PST_RLC_TO_DUAPP(pst, RLC_UL_INST, EVENT_UL_RRC_MSG_TRANS_TO_DU);
248                 rlcSendUlRrcMsgToDu(&pst, ulRrcMsgInfo);
249              }
250              else
251              {
252                DU_LOG("\nERROR  -->  RLC_UL: rlcUtlSendUlDataToDu: Memory allocation failed for rrcMsg");
253                RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL, ulRrcMsgInfo, sizeof(RlcUlRrcMsgInfo));
254                return RFAILED;
255              }
256       }
257       else
258       {
259          DU_LOG("\nERROR  -->  RLC_UL: rlcUtlSendUlDataToDu: Memory allocation failed for ulRrcMsgInfo");
260          return RFAILED;
261       }
262    }
263    else if(rbCb->rlcId.rbType == RB_TYPE_DRB)
264    {
265       /* Filling UL User Data Info if UL msg is received on a DRB */
266       RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL, ulUserDatInfo, sizeof(RlcUlUserDatInfo));
267       if (ulUserDatInfo)
268       {
269          ulUserDatInfo->cellId = rbCb->rlcId.cellId;
270               ulUserDatInfo->ueIdx = rbCb->rlcId.ueId;
271          ulUserDatInfo->rbId = rbCb->rlcId.rbId;
272               ODU_GET_MSG_LEN(sdu, (MsgLen *)&msgLen);
273               RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL, ulUserDatInfo->userData, msgLen);
274               if (ulUserDatInfo->userData)
275               {
276                 ODU_COPY_MSG_TO_FIX_BUF(sdu, 0, msgLen, ulUserDatInfo->userData, (MsgLen *)&copyLen);
277                 ulUserDatInfo->msgLen = msgLen;
278                
279             DU_LOG("\nDEBUG  -->  RLC_UL -> DUAPP : UL DATA [DRB ID:%d]", ulUserDatInfo->rbId);
280
281                /* Sending UL RRC Message transfeer to DU APP */
282                memset(&pst, 0, sizeof(Pst));
283                FILL_PST_RLC_TO_DUAPP(pst, RLC_UL_INST, EVENT_UL_USER_DATA_TRANS_TO_DU);
284                rlcSendUlUserDataToDu(&pst, ulUserDatInfo);
285              }
286              else
287              {
288                 DU_LOG("\nERROR  -->  RLC_UL: rlcUtlSendUlDataToDu: Memory allocation failed for user data");
289                 RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL, ulUserDatInfo, sizeof(RlcUlUserDatInfo));
290                 return RFAILED;
291              }
292      }
293      else
294      {
295              DU_LOG("\nERROR  -->  RLC_UL: rlcUtlSendUlDataToDu: Memory allocation failed for ulUserDatInfo");
296              return RFAILED;
297      }
298    }
299    return ROK;
300 } /* rlcUtlSendUlDataToDu */
301
302
303 static Void dumpRLCUlRbInformation(RlcUlRbCb* ulRbCb)
304 {
305    if(ulRbCb->mode == RLC_MODE_UM)
306    {
307       uint32_t i;
308       uint32_t pdusInReceptionBuffer = 0;
309       uint32_t totalSegs = 0;
310
311       for(i = 0; i< RLC_RCV_BUF_BIN_SIZE; i++)
312       {
313          RlcUmRecBuf *recBuf = rlcUtlGetUmRecBuf(ulRbCb->m.umUl.recBufLst, i);
314          if(recBuf != NULLP)
315          {
316              pdusInReceptionBuffer++;
317              totalSegs += (recBuf->segLst.count);
318          }
319       }
320       
321       DU_LOG("\nDEBUG  -->  RLC_UL: UM UL UEID:%d CELLID:%d Reception Buffer size = %d Total segs = %d", 
322          ulRbCb->rlcId.ueId, ulRbCb->rlcId.cellId, pdusInReceptionBuffer, totalSegs);
323    }
324    else if(ulRbCb->mode == RLC_MODE_AM)
325    {
326       uint32_t i;
327       uint32_t pdusInReceptionBuffer = 0;
328       uint32_t totalSegs = 0;
329       uint32_t windSz  = RLC_AM_GET_WIN_SZ(ulRbCb->m.amUl.snLen) << 1;
330       
331       for(i = 0; i< windSz; i++)
332       {
333          RlcAmRecBuf *recBuf = rlcUtlGetRecBuf(ulRbCb->m.amUl.recBufLst, i);
334          if(recBuf != NULLP)
335          {
336             pdusInReceptionBuffer++;
337             totalSegs += (recBuf->segLst.count);
338          }
339       }
340
341       DU_LOG("\nDEBUG  -->  RLC_UL: AM UL UEID:%d CELLID:%d Reception Buf size = %d total segs = %d", 
342          ulRbCb->rlcId.ueId, ulRbCb->rlcId.cellId, pdusInReceptionBuffer, totalSegs);
343    }
344 }
345
346 Void DumpRLCUlDebugInformation(Void)
347 {
348    RlcCb* ulInst = rlcCb[0]; /* TODO : Check whether UL is 0 or 1 */
349    RlcUlCb* ulCb = ulInst->u.ulCb;
350    RlcUlUeCb *ueCb = NULLP; 
351
352    /* Until no more ueCb is ueLstCp hash list get and delete ueCb */
353    while (ROK == cmHashListGetNext(&ulCb->ueLstCp, 
354                                    (PTR) ueCb, 
355                                    (PTR *)&ueCb))
356    {
357       uint32_t i;
358       for(i = 0; i< RLC_MAX_SRB_PER_UE; i++)
359       {
360          RlcUlRbCb* ulRbCb = ueCb->srbCb[i]; 
361          if(ulRbCb != NULLP)
362          {
363             dumpRLCUlRbInformation(ulRbCb);
364          }
365       }
366       for(i = 0; i< RLC_MAX_DRB_PER_UE; i++)
367       {
368          RlcUlRbCb* ulRbCb = ueCb->drbCb[i]; 
369          if(ulRbCb != NULLP)
370          {
371             dumpRLCUlRbInformation(ulRbCb);
372          }
373       }
374    }
375 }
376
377
378 /*
379  * kwUtlFreeUlRbCb() function is split into two functions 
380  *  -  rlcAmmFreeUlRbCb() ---> gp_amm_ul.c 
381  *  -  rlcUmmFreeUlRbCb() ---> gp_umm_ul.c
382  * and placed in respective files mentioned above
383  */
384
385
386
387 /* kw005.201 added support for L2 Measurement */
388 #ifdef LTE_L2_MEAS
389
390 /**
391  *
392  * @brief 
393  *    Handler for initialisation of measurement 
394  * 
395  * @param[in]  gCb    - RLC instance Control Block 
396  *
397  * @return  S16
398  *      -# ROK 
399  */
400 S16 rlcUtlL2MeasUlInit(RlcCb *gCb)
401 {
402    uint16_t             cntr;
403
404    gCb->u.ulCb->rlcL2Cb.rlcNumMeas=0;
405    for(cntr = 0; cntr < LKW_MAX_L2MEAS; cntr++)
406    {
407       memset(&(gCb->u.ulCb->rlcL2Cb.rlcL2EvtCb[cntr]), 0, sizeof(RlcL2MeasEvtCb));
408    }
409    gCb->u.ulCb->rlcL2Cb.rlcL2EvtCb[RLC_L2MEAS_UL_IP].measCb.measType = LKW_L2MEAS_UL_IP;
410    return ROK;
411 }
412 /**
413  *
414  * @brief
415  *
416  *        Handler to calculate the Ul Ip throughput for a LCH
417  *
418  * @b Description:
419  *
420  *
421  * @param[in] rbCb         RB control block
422  * @param[in] pdu          Pdu of LCH
423  *
424  *  @return  Void
425  *
426  */
427 Void rlcUtlCalUlIpThrPutIncTTI(RlcCb *gCb,RlcUlRbCb *rbCb,uint32_t ttiCnt)
428 {
429    volatile uint32_t     startTime = 0;
430
431       /*starting Task*/
432       SStartTask(&startTime, PID_RLC_IP_TPT_INCTTI);
433 #ifndef ALIGN_64BIT
434    DU_LOG("\nDEBUG  -->  RLC_UL : Log for ul ip throughput:"
435          "RB_MeasOn:%d ttiCnt :%ld UEID:%d CELLID:%d", 
436          rbCb->rbL2Cb.measOn,ttiCnt,
437          rbCb->rlcId.ueId,
438          rbCb->rlcId.cellId);
439 #else
440    DU_LOG("\nDEBUG  -->  RLC_UL : Log for ul ip throughput:"
441          "RB_MeasOn:%d ttiCnt :%d UEID:%d CELLID:%d", 
442          rbCb->rbL2Cb.measOn,ttiCnt,
443          rbCb->rlcId.ueId,
444          rbCb->rlcId.cellId);
445 #endif
446
447    /*Check if UL IP throughput measurement is ON for this RB or not*/
448    if(RLC_MEAS_IS_UL_IP_MEAS_ON_FOR_RB(gCb,rbCb))              
449    {
450       if (TRUE  == rbCb->ueCb->isUlBurstActive)
451       {
452          if (ttiCnt < rbCb->l2MeasIpThruput.prevTtiCnt)
453          {
454             /*Removed Error Print*/
455          }
456          if (rbCb->l2MeasIpThruput.prevTtiCnt != 0)
457          {
458             rbCb->rbL2Cb.l2Sts[RLC_L2MEAS_UL_IP]->ulIpThruput.timeSummation += 
459                (ttiCnt - rbCb->l2MeasIpThruput.prevTtiCnt);
460          }
461          else
462          {
463             rbCb->ueCb->firstPacketTTI = ttiCnt;
464          }
465          rbCb->l2MeasIpThruput.prevTtiCnt = ttiCnt;
466       }
467       else
468       {
469          rbCb->l2MeasIpThruput.prevTtiCnt = 0;
470       }
471    }   
472
473    /*stopping Task*/
474    SStopTask(startTime, PID_RLC_IP_TPT_INCTTI);
475 } /* rlcUtlCalUlIpThrPutIncTTI */
476
477
478 /**
479  *
480  * @brief
481  *
482  *        Handler to calculate the Ul Ip throughput for a LCH
483  *
484  * @b Description:
485  *
486  *
487  * @param[in] rbCb         RB control block
488  * @param[in] pdu          Pdu of LCH
489  *
490  *  @return  Void
491  *
492  */
493 Void rlcUtlCalUlIpThrPut
494 (
495 RlcCb        *gCb,
496 RlcUlRbCb    *rbCb,
497 Buffer       *pdu,
498 uint32_t     ttiCnt
499 )
500 {
501    MsgLen        rlcSduSz = 0;  /*Holds length of Rlc Sdu*/
502    volatile uint32_t     startTime = 0;
503
504    /*starting Task*/
505    SStartTask(&startTime, PID_RLC_IP_TPT_INCVOL);
506
507    /*Check if UL IP throughput measurement is ON for this RB or not*/
508    if(RLC_MEAS_IS_UL_IP_MEAS_ON_FOR_RB(gCb, rbCb) &&              
509          (TRUE  == rbCb->ueCb->isUlBurstActive) &&
510          (rbCb->ueCb->firstPacketTTI) &&
511          (ttiCnt != rbCb->ueCb->firstPacketTTI))
512    {
513       SFndLenMsg(pdu, &rlcSduSz);
514
515       rbCb->rbL2Cb.l2Sts[RLC_L2MEAS_UL_IP]->ulIpThruput.volSummation += rlcSduSz;
516
517    }
518    /*stopping Task*/
519    SStopTask(startTime, PID_RLC_IP_TPT_INCVOL);
520 } /* rlcUtlCalUlIpThrPut */
521
522 \f
523 /**
524  *
525  * @brief Handler for L2 Measurement timer expiry.
526  *
527  *
528  * @b Description
529  *        This function is called when the l2 measurement timer expires. 
530  *        This function sends a consolidates the mesaurements taken during
531  *        this time and sends the confirm .
532  *
533  *  @param[in] measEvtCb    Measurement Event Control Block.
534  *
535  *
536  *  @return  S16
537  *      -# ROK
538  */
539
540 S16 rlcUtlHdlL2TmrExp(RlcCb *gCb,RlcL2MeasEvtCb *measEvtCb)
541 {
542
543 #ifdef LTE_L2_MEAS_RLC
544    uint16_t             qciIdx;
545    RlcL2MeasCb     *measCb;
546    
547    /* Clean up the RB data structures */
548    if((measEvtCb->measCb.measType & LKW_L2MEAS_ACT_UE) &&
549       (measEvtCb->measCb.val.nonIpThMeas.numSamples))
550    {
551       measCb = &measEvtCb->measCb;
552
553       for(qciIdx = 0; qciIdx < measCb->val.nonIpThMeas.numQci;qciIdx++)
554       {
555          measCb->val.nonIpThMeas.measData[measCb->val.nonIpThMeas.qci[qciIdx]].actUe.numActvUe   +=   
556                      rlcCb.rlcL2Cb.numActUe[measCb->val.nonIpThMeas.qci[qciIdx]];
557          measCb->val.nonIpThMeas.measData[measCb->val.nonIpThMeas.qci[qciIdx]].actUe.sampOc++;
558       }
559       measEvtCb->val.nonIpThMeas.measCb.numSamples--;
560       rlcStartTmr(gCb, (PTR)measEvtCb, EVENT_RLC_L2_TMR); 
561       return (ROK);
562    }
563 #endif
564
565    rlcUtlSndUlL2MeasCfm(gCb, measEvtCb);
566
567    return (ROK);
568 } /* rlcUtlHdlL2TmrExp */
569 /**
570  *
571  * @brief Handler for Sending L2 Measurement confirm.
572  *
573  *
574  * @b Description
575  *        This function sends a consolidates the mesaurements taken during
576  *        this time and sends the confirm .
577  *
578  *  @param[in] measEvtCb    Measurement Event Control Block.
579  *
580  *
581  *  @return  S16
582  *      -# ROK
583  */
584
585 S16 rlcUtlSndUlL2MeasCfm(RlcCb *gCb,RlcL2MeasEvtCb  *measEvtCb)
586 {
587    uint32_t            qciIdx;
588    RlcL2MeasCb         *measCb;
589    RlcL2MeasCfmEvt     measCfmEvt;
590    uint64_t            ulDataVol;
591    uint64_t            ulTime;
592    uint16_t            cntr;
593    /* Discard new changes starts */
594    uint8_t             qci = 0;
595    uint32_t            cfmIdx =0;
596    /* Discard new changes ends */
597
598    /* kw006.201 ccpu00120058 emoved 64 bit compilation warning */
599 #ifndef ALIGN_64BIT
600    DU_LOG("\nDEBUG  -->  RLC_UL : rlcUtlSndUlL2MeasCfm(transId(%ld))", measEvtCb->transId);
601 #else
602    DU_LOG("\nDEBUG  -->  RLC_UL : rlcUtlSndUlL2MeasCfm(transId(%d))", measEvtCb->transId);
603 #endif
604
605    /* Clean up the RB data structures */
606    measCb = &measEvtCb->measCb;
607    
608    memset(&measCfmEvt, 0, sizeof(RlcL2MeasCfmEvt));
609    measCfmEvt.transId = measEvtCb->transId;
610
611    measCfmEvt.measType = measCb->measType;
612    measCfmEvt.status.status = LCM_PRIM_OK;
613    measCfmEvt.status.reason = LCM_REASON_NOT_APPL;
614    
615    if( measCb->measType & LKW_L2MEAS_UL_IP)
616    {
617       RlcL2MeasCbUeMeasInfo *pUeInfoLstCb  = measCb->val.ipThMeas.ueInfoLst;
618       RlcL2MeasCfmUeInfoLst *pUeInfoLstCfm = measCfmEvt.val.ipThMeas.ueInfoLst;
619       for(cntr = 0;(cntr < measCb->val.ipThMeas.numUes) && (cntr < gCb->genCfg.maxUe);cntr++)        
620       {
621          pUeInfoLstCfm[cfmIdx].numCfm = 0;
622          if (pUeInfoLstCb[cntr].isValid == TRUE)
623          {
624             pUeInfoLstCfm[cfmIdx].ueId = pUeInfoLstCb[cntr].ueId;
625             pUeInfoLstCfm[cfmIdx].cellId = pUeInfoLstCb[cntr].cellId;
626
627             for(qciIdx = 0; qciIdx < pUeInfoLstCb[cntr].numQci; qciIdx++)
628             {
629                qci = pUeInfoLstCb[cntr].qci[qciIdx];
630                pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].qci = qci;
631
632                if(measCb->measType & LKW_L2MEAS_UL_IP)
633                {
634                   ulDataVol = pUeInfoLstCb[cntr].measData[qci].ulIpThruput.volSummation;
635                   ulTime = pUeInfoLstCb[cntr].measData[qci].ulIpThruput.timeSummation;
636                   if(0 == ulTime)
637                   {
638                      pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.ulIpThPut = 0;
639                   }
640                   else
641                   {
642                      pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.ulIpThPut = (ulDataVol / ulTime);
643
644                      /* Converting it to kbps */
645                      pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.ulIpThPut *= 8;
646
647                   }
648                   /* Reset the values after reporting to Application */
649                   pUeInfoLstCb[cntr].measData[qci].ulIpThruput.volSummation = 0;
650                   pUeInfoLstCb[cntr].measData[qci].ulIpThruput.timeSummation = 0;
651                }
652                pUeInfoLstCfm[cfmIdx].numCfm++;
653             }
654             cfmIdx++;
655          }
656       }
657       measCfmEvt.val.ipThMeas.numUes = cfmIdx; 
658    }
659    RlcMiLkwL2MeasCfm(&gCb->genCfg.lmPst, &measCfmEvt);
660    return (ROK);
661 } /* rlcUtlSndUlL2MeasCfm */
662 /**
663  *
664  * @brief Handler for Sending Negative confirm .
665  *
666  *
667   @b Description
668  *        This function is called when the l2 measurement cannot be started
669  *        This function sends  negative confirm for all the requests
670  *
671  * @param[in] gCb - RLC instance control block
672  * @param[in] measReqEvt    Measurement Req Structure
673  * @param[in] measCfmEvt  Confirmation to be sent to layer manager
674  *
675  *
676  *  @return  S16
677  *      -# ROK
678  */
679
680 S16 rlcUtlSndUlL2MeasNCfm(RlcCb *gCb,RlcL2MeasReqEvt *measReqEvt,RlcL2MeasCfmEvt *measCfmEvt)
681 {
682
683    RlcMiLkwL2MeasCfm(&gCb->genCfg.lmPst, measCfmEvt);
684    return ROK;
685 } /* kwUtlSndL2MeasNCfm */
686
687 #ifdef LTE_L2_MEAS_RLC
688 /**
689  * @brief  Validates the measurement request parameters. 
690  *
691  * @details
692  *
693  *     Function :rlcUtlValidateL2Meas 
694  *
695  *  @param[in]  measReqEvt L2 measurement request received from layer manager.
696  *  @param[out] measCfmEvt L2 measurement confirm to be prepared.
697  *  @param[out] lChId      List of LCh for the given Ue corresponding to QCIs
698                            given in measurement request.
699  *  @param[out] numLCh     Number of LCh in array lChId.
700  **/
701
702 S16 rlcUtlValidateL2Meas
703 (
704 RlcL2MeasReqEvt *measReqEvt,
705 RlcL2MeasCfmEvt *measCfmEvt,
706 CmLteLcId       *lChId,
707 uint8_t         *numLCh
708 )
709 {
710    uint8_t    measType;
711    S16        ret;
712    uint8_t    qciIdx;
713    uint8_t    qci;
714    uint8_t    idx;
715    uint8_t    *qciVal;
716    uint8_t    numQci;
717    RlcUlRbCb  *rbCb;
718    RlcUlUeCb  *ueCb;
719    RbCb       **rbCbLst;
720    uint8_t    rbIdx;
721    uint8_t    lsbNibble = 0;
722    uint8_t    msbNibble = 0;
723    uint8_t    numFaild = 0;
724
725    idx = 0;
726    rbCb = NULLP;
727    ret = ROK;
728    measType = measReqEvt->measReq.measType;
729    /* Check for the range of measType */
730    /* LKW_L2MEAS_DL_IP+ LKW_L2MEAS_UL_IP = 0x0030*/
731    if((measType == 0x00) ||
732        measType > 0x30)
733    {
734       measCfmEvt->transId = measReqEvt->transId;
735       measCfmEvt->measType = measType;
736       measCfmEvt->status.status = LCM_PRIM_NOK;
737       measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
738       return RFAILED;
739    }
740    /*User can either request for Active UE,*
741     *Dl delay, Dl discard, Uu Loss OR Dl ip throughput, Ul ip throughput. */
742    lsbNibble = measType & 0x0F;
743    msbNibble = measType & 0xF0;
744
745    if( (lsbNibble != 0) && (msbNibble != 0) )
746    {
747       measCfmEvt->transId = measReqEvt->transId;
748       measCfmEvt->measType = measType;
749       measCfmEvt->status.status = LCM_PRIM_NOK;
750       measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
751       return RFAILED;
752    }
753
754    /* Check for total maximum number of Measurement Control Block */
755    if(rlcCb.rlcL2Cb.rlcNumMeas >= LKW_MAX_L2MEAS )
756    {
757       measCfmEvt->transId = measReqEvt->transId;
758       measCfmEvt->measType = measType;
759       measCfmEvt->status.status = LCM_PRIM_NOK;
760       measCfmEvt->status.reason = LKW_CAUSE_EXCEED_NUMMEAS;
761       return RFAILED;
762    }
763
764    /* Check that number of samples should be a non-zero value */
765    if(((measType & LKW_L2MEAS_ACT_UE) &&
766       (measReqEvt->measReq.val.nonIpThMeas.numSamples == 0)))
767    {
768       measCfmEvt->transId = measReqEvt->transId;
769       measCfmEvt->measType = measType;
770       measCfmEvt->status.status = LCM_PRIM_NOK;
771       measCfmEvt->status.reason = LKW_CAUSE_ZERO_NUMSAM;
772       return RFAILED;
773    }
774    /* Check that measurement period  should be completely divisible *
775     * number of sample.                                             */
776    if(((measType & LKW_L2MEAS_ACT_UE) &&
777       ((measReqEvt->measPeriod % 
778         measReqEvt->measReq.val.nonIpThMeas.numSamples) != 0)))
779    {
780       measCfmEvt->transId = measReqEvt->transId;
781       measCfmEvt->measType = measType;
782       measCfmEvt->status.status = LCM_PRIM_NOK;
783       measCfmEvt->status.reason = LKW_CAUSE_INVALID_NUMSAM;
784       return RFAILED;
785    }
786    {
787       numQci = measReqEvt->measReq.val.nonIpThMeas.numQci;
788       qciVal = measReqEvt->measReq.val.nonIpThMeas.qci;
789    }
790    /* Check whether qci is configured or not */
791    for(qciIdx = 0; qciIdx < numQci; qciIdx++)
792    {
793       qci = qciVal[qciIdx];
794       ret = cmHashListFind(&(rlcCb.rlcL2Cb.qciHlCp), 
795             (uint8_t *)&qci, (uint16_t)sizeof(qci), 0, (PTR *)&rbCb);
796       if(ret != ROK)
797       {
798          measCfmEvt->val.nonIpThMeas.measCfm[measCfmEvt->val.nonIpThMeas.numCfm].qci = qci;
799          measCfmEvt->val.nonIpThMeas.numCfm++;
800
801       }
802    }
803    if(measCfmEvt->val.nonIpThMeas.numCfm > 0)
804    {
805       measCfmEvt->status.status = LCM_PRIM_NOK;
806       measCfmEvt->status.reason = LKW_CAUSE_INVALID_QCI;
807       measCfmEvt->measType = measType;
808       measCfmEvt->transId = measReqEvt->transId;
809       return RFAILED;
810    }
811    {
812       for(qciIdx = 0; qciIdx < numQci; qciIdx++)
813       {
814          if(rlcCb.rlcL2Cb.measOn[qci] & measReqEvt->measReq.measType)
815          {
816             /* measurement is already ongoing */
817             measCfmEvt->status.status = LCM_PRIM_NOK;
818             measCfmEvt->status.reason = LKW_CAUSE_MEAS_ALREADY_ENA;
819             measCfmEvt->val.nonIpThMeas.measCfm[measCfmEvt->val.nonIpThMeas.numCfm].qci = qci;
820             measCfmEvt->measType = measType;
821             measCfmEvt->val.nonIpThMeas.numCfm++;
822          }
823       }
824    }
825    if(measCfmEvt->val.nonIpThMeas.numCfm > 0)
826    {
827       measCfmEvt->transId = measReqEvt->transId;
828       return RFAILED;
829    }
830
831    return (ROK);
832 }/* rlcUtlValidateL2Meas */
833 #endif
834
835 S16 rlcUtlValidateIpThL2Meas(RlcL2MeasReqEvt *measReqEvt,RlcL2MeasCfmEvt *measCfmEvt)
836 {
837    uint8_t      measType;
838    uint8_t         lsbNibble = 0;
839    uint8_t         msbNibble = 0;
840
841    measType = measReqEvt->measReq.measType;
842    /* Check for the range of measType */
843    /* LKW_L2MEAS_DL_IP+ LKW_L2MEAS_UL_IP = 0x0030*/
844    if((measType == 0x00) ||
845        measType > 0x30)
846    {
847       measCfmEvt->transId = measReqEvt->transId;
848       measCfmEvt->measType = measType;
849       measCfmEvt->status.status = LCM_PRIM_NOK;
850       measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
851       return RFAILED;
852    }
853    /*User can either request for Active UE,*
854     *Dl delay, Dl discard, Uu Loss OR Dl ip throughput, Ul ip throughput. */
855    lsbNibble = measType & 0x0F;
856    msbNibble = measType & 0xF0;
857
858    if( (lsbNibble != 0) && (msbNibble != 0) )
859    {
860       measCfmEvt->transId = measReqEvt->transId;
861       measCfmEvt->measType = measType;
862       measCfmEvt->status.status = LCM_PRIM_NOK;
863       measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
864       return RFAILED;
865    }
866    return (ROK);
867 }/* rlcUtlValidateL2Meas */
868
869 /**
870  *
871  * @brief Handler for resetting the RB data structures
872  *
873  *
874  * @b Description
875  *        This function resets the RB data structure after the expiry of 
876  *        measurement timer.
877  *
878  *  @param[in] measCb    Measurement Control Block.
879  *
880  *
881  *  @return  Void
882  */
883
884 Void rlcUtlResetUlL2MeasInRlcRb(RlcCb *gCb,RlcL2MeasCb *measCb,uint8_t measType)
885 {
886    uint32_t           rbIdx;
887    uint32_t           ueIdx;
888    uint32_t           qciIdx;
889    RlcUlUeCb         *ueCb = NULL;
890
891
892
893    if (measCb->measType & LKW_L2MEAS_UL_IP)
894    {
895       for(ueIdx = 0; ueIdx < measCb->val.ipThMeas.numUes; ueIdx++)
896       {           
897          if (measCb->val.ipThMeas.ueInfoLst[ueIdx].isValid == TRUE)
898          {
899             for (qciIdx =0; qciIdx < measCb->val.ipThMeas.ueInfoLst[ueIdx].numQci; qciIdx++)
900             {
901                if (measType & LKW_L2MEAS_UL_IP)
902                {
903                   measCb->val.ipThMeas.ueInfoLst[ueIdx].measData[qciIdx].ulIpThruput.volSummation = 0;
904                   measCb->val.ipThMeas.ueInfoLst[ueIdx].measData[qciIdx].ulIpThruput.timeSummation = 0;
905                }
906             }
907
908             if(ROK  != rlcDbmFetchUlUeCb(gCb, measCb->val.ipThMeas.ueInfoLst[ueIdx].ueId,
909                      measCb->val.ipThMeas.ueInfoLst[ueIdx].cellId, &ueCb))
910             {
911                continue;
912             }
913
914             for (rbIdx = 0; rbIdx < RLC_MAX_DRB_PER_UE; rbIdx++)
915             {
916                if (ueCb->drbCb[rbIdx])
917                {
918                   ueCb->drbCb[rbIdx]->rbL2Cb.measOn &= ~measType;
919                }
920             }
921          }
922       }
923    }
924 } /* rlcUtlResetUlL2MeasInRlcRb */
925
926 /**
927  *
928  * @brief Handler for storing address of MeasData in rbCb at right index
929  *
930  *
931  * @b Description
932  *        This function is called when LM sends measReq message to RLC.
933  *
934  *  @param[in] 
935  *  @param[out] 
936  *  @param[in] 
937  *
938  *
939  *  @return  S16
940  *      -# ROK
941  */
942 Void rlcUtlPlcMeasDatInL2Sts(RlcL2Cntr *measData,RlcL2MeasRbCb *rbL2Cb,uint8_t measType)
943 {
944    /* We should check the number of measType in the request. This can be done 
945     * by looking at each bit in the measType. Also store the measData in the 
946     * correct index of l2Sts in RbCb.
947     * */
948
949     if(measType & LKW_L2MEAS_ACT_UE)
950     {
951          rbL2Cb->l2Sts[RLC_L2MEAS_ACT_UE] = measData;
952     }
953     if(measType & LKW_L2MEAS_UU_LOSS)
954     {
955          rbL2Cb->l2Sts[RLC_L2MEAS_UU_LOSS] = measData;
956     }
957     if(measType & LKW_L2MEAS_DL_IP )
958     {
959          rbL2Cb->l2Sts[RLC_L2MEAS_DL_IP] = measData;
960     }
961     if(measType & LKW_L2MEAS_UL_IP)
962     {
963          rbL2Cb->l2Sts[RLC_L2MEAS_UL_IP] = measData;
964     }
965     if(measType & LKW_L2MEAS_DL_DISC)
966     {
967          rbL2Cb->l2Sts[RLC_L2MEAS_DL_DISC] = measData;
968     }
969     if(measType & LKW_L2MEAS_DL_DELAY)
970     {
971          rbL2Cb->l2Sts[RLC_L2MEAS_DL_DELAY] = measData;
972     }
973 }/* End of rlcUtlPlcMeasDatInL2Sts */
974 #endif /* LTE_L2_MEAS */
975
976 /**
977  *
978  * @brief Store the UL buffer in hashList  
979  *
980  *
981  * @b Description
982  *
983  *   Use the SN % binSize as key and store the received UL buffer
984  *  @param[in] recBufLst       List CP array
985  *  @param[in] recBuf          received buffer
986  *  @param[in] sn              sn of the received buffer 
987  *
988  *
989  *  @return  Void
990  */
991 void rlcUtlStoreRecBuf(CmLListCp *recBufLst, RlcAmRecBuf *recBuf, RlcSn sn)
992 {
993    uint32_t    hashKey; 
994    
995    hashKey = (sn % RLC_RCV_BUF_BIN_SIZE ); 
996    recBuf->lnk.node = (PTR)recBuf;
997    cmLListAdd2Tail(&(recBufLst[hashKey]), &recBuf->lnk);
998
999    return;
1000 } /* rlcUtlStoreRecBuf */
1001
1002 /**
1003  *
1004  * @brief Retrieve the UL buffer from the list
1005  *
1006  *
1007  * @Description
1008  *
1009  *   Use the SN % binSize as key and retrieve the UL buffer
1010  *  @param[in] recBufLst       List CP array
1011  *  @param[in] sn              sn of the received buffer 
1012  *
1013  *
1014  *  @return  Void
1015  */
1016 RlcAmRecBuf* rlcUtlGetRecBuf(CmLListCp *recBufLst, RlcSn sn)
1017 {
1018    uint32_t            hashKey; 
1019    CmLListCp           *recBufLstCp;
1020    RlcAmRecBuf         *recBuf;
1021    CmLList             *node = NULLP;
1022
1023    hashKey = (sn % RLC_RCV_BUF_BIN_SIZE ); 
1024  
1025    recBufLstCp = &recBufLst[hashKey];
1026    CM_LLIST_FIRST_NODE(recBufLstCp, node);
1027    while(node)
1028    {
1029       recBuf = (RlcAmRecBuf *) node->node;
1030       if(recBuf->amHdr.sn == sn)
1031       {
1032          return recBuf;
1033       }
1034       CM_LLIST_NEXT_NODE(recBufLstCp, node);
1035    }
1036    return NULLP;
1037 } /* rlcUtlGetRecBuf */
1038 /**
1039  *
1040  * @brief Delete the UL buffer from the list
1041  *
1042  *
1043  * @Description
1044  *
1045  *   Use the SN % binSize as key and retrieve the UL buffer
1046  *  @param[in] recBufLst       List CP array
1047  *  @param[in] sn              sn of the received buffer 
1048  *
1049  *
1050  *  @return  Void
1051  */
1052 void rlcUtlDelRecBuf(CmLListCp *recBufLst, RlcAmRecBuf *recBuf, RlcCb *gCb)
1053 {
1054    uint32_t            hashKey; 
1055    CmLListCp           *recBufLstCp;
1056
1057    hashKey = (recBuf->amHdr.sn % RLC_RCV_BUF_BIN_SIZE ); 
1058  
1059    recBufLstCp = &recBufLst[hashKey];
1060    cmLListDelFrm(recBufLstCp, &recBuf->lnk);
1061    RLC_FREE(gCb, recBuf, sizeof(RlcAmRecBuf));
1062
1063    return;
1064 } /* rlcUtlDelRecBuf */
1065
1066 /**
1067  *
1068  * @brief Store the UL buffer in hashList  
1069  *
1070  * @b Description
1071  *
1072  *  Use the SN % binSize as key and store the received UL buffer
1073  *  @param[in] recBufLst       List CP array
1074  *  @param[in] recBuf          received buffer
1075  *  @param[in] sn              sn of the received buffer 
1076  *
1077  *  @return  Void
1078  */
1079 void rlcUtlStoreUmRecBuf(CmLListCp *recBufLst, RlcUmRecBuf *recBuf, RlcSn sn)
1080 {
1081    uint32_t    hashKey; 
1082    
1083    hashKey = (sn % RLC_RCV_BUF_BIN_SIZE ); 
1084    recBuf->lnk.node = (PTR)recBuf;
1085    cmLListAdd2Tail(&(recBufLst[hashKey]), &recBuf->lnk);
1086
1087    return;
1088 } /* rlcUtlStoreUmRecBuf */
1089
1090 /**
1091  *
1092  * @brief Retrieve the UL buffer from the list
1093  *
1094  * @Description
1095  *
1096  *   Use the SN % binSize as key and retrieve the UL buffer
1097  *  @param[in] recBufLst       List CP array
1098  *  @param[in] sn              sn of the received buffer 
1099  *
1100  *  @return  Void
1101  */
1102 RlcUmRecBuf* rlcUtlGetUmRecBuf(CmLListCp *recBufLst, RlcSn sn)
1103 {
1104    uint32_t            hashKey; 
1105    CmLListCp           *recBufLstCp;
1106    RlcUmRecBuf         *recBuf;
1107    CmLList             *node = NULLP;
1108
1109    hashKey = (sn % RLC_RCV_BUF_BIN_SIZE ); 
1110  
1111    recBufLstCp = &recBufLst[hashKey];
1112    CM_LLIST_FIRST_NODE(recBufLstCp, node);
1113    while(node)
1114    {
1115       recBuf = (RlcUmRecBuf *) node->node;
1116       if(recBuf->umHdr.sn == sn)
1117       {
1118          return recBuf;
1119       }
1120       CM_LLIST_NEXT_NODE(recBufLstCp, node);
1121    }
1122    return NULLP;
1123 } /* rlcUtlGetUmRecBuf */
1124
1125 /**
1126  *
1127  * @brief Delete the UM Mode UL buffer from the list
1128  *
1129  *
1130  * @details
1131  *   Use the SN % binSize as key and retrieve the UL buffer
1132  *
1133  *  @param[in] *recBufLst       List CP array
1134  *  @param[in] *recBuf          Received buffer
1135  *
1136  *  @return  Void
1137  */
1138 void rlcUtlDelUmRecBuf(RlcCb *gCb, CmLListCp *recBufLst, RlcUmRecBuf  *recBuf)
1139 {
1140    uint32_t   hashKey;
1141    CmLListCp  *recBufLstCp;
1142
1143    hashKey = (recBuf->sn % RLC_RCV_BUF_BIN_SIZE );
1144    recBufLstCp = &recBufLst[hashKey];
1145    cmLListDelFrm(recBufLstCp, &recBuf->lnk);
1146    RLC_FREE(gCb, recBuf, sizeof(RlcUmRecBuf));
1147
1148    return;
1149 } /* rlcUtlDelUmRecBuf */
1150
1151 /********************************************************************30**
1152          End of file
1153 **********************************************************************/