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