4604f19f28868b49f3bcba54ff9b913dd200967c
[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;   /* Data Indication Information */
202    KwuDatIndInfo datIndInfoTmp;
203 #endif
204    RlcUlRrcMsgInfo  *ulRrcMsgInfo;
205    RlcUlUserDatInfo *ulUserDatInfo;
206    uint16_t        msgLen, copyLen;
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          RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL,
238                ulRrcMsgInfo->rrcMsg, msgLen);
239          if (ulRrcMsgInfo->rrcMsg)
240          {
241             ODU_GET_MSG_LEN(sdu, (MsgLen *)&msgLen);
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          RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL, ulUserDatInfo->userData, msgLen);
273          if (ulUserDatInfo->userData)
274          {
275             ODU_GET_MSG_LEN(sdu, (MsgLen *)&msgLen);
276             ODU_COPY_MSG_TO_FIX_BUF(sdu, 0, msgLen, ulUserDatInfo->userData, (MsgLen *)&copyLen);
277             ulUserDatInfo->msgLen = msgLen;
278
279             /* Sending UL RRC Message transfeer to DU APP */
280             memset(&pst, 0, sizeof(Pst));
281             FILL_PST_RLC_TO_DUAPP(pst, RLC_UL_INST, EVENT_UL_USER_DATA_TRANS_TO_DU);
282             rlcSendUlUserDataToDu(&pst, ulUserDatInfo);
283          }
284          else
285          {
286             DU_LOG("\nERROR  -->  RLC_UL: rlcUtlSendUlDataToDu: Memory allocation failed for user data");
287             RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL, ulUserDatInfo, sizeof(RlcUlUserDatInfo));
288             return RFAILED;
289          }
290       }
291       else
292       {
293          DU_LOG("\nERROR  -->  RLC_UL: rlcUtlSendUlDataToDu: Memory allocation failed for ulUserDatInfo");
294          return RFAILED;
295       }
296    }
297    return ROK;
298 } /* rlcUtlSendUlDataToDu */
299
300
301 static Void dumpRLCUlRbInformation(RlcUlRbCb* ulRbCb)
302 {
303    if(ulRbCb->mode == RLC_MODE_UM)
304    {
305       uint32_t i;
306       uint32_t pdusInReceptionBuffer = 0;
307       uint32_t totalSegs = 0;
308
309       for(i = 0; i< RLC_RCV_BUF_BIN_SIZE; i++)
310       {
311          RlcUmRecBuf *recBuf = rlcUtlGetUmRecBuf(ulRbCb->m.umUl.recBufLst, i);
312          if(recBuf != NULLP)
313          {
314              pdusInReceptionBuffer++;
315              totalSegs += (recBuf->segLst.count);
316          }
317       }
318       
319       DU_LOG("\nDEBUG  -->  RLC_UL: UM UL UEID:%d CELLID:%d Reception Buffer size = %d Total segs = %d", 
320          ulRbCb->rlcId.ueId, ulRbCb->rlcId.cellId, pdusInReceptionBuffer, totalSegs);
321    }
322    else if(ulRbCb->mode == RLC_MODE_AM)
323    {
324       uint32_t i;
325       uint32_t pdusInReceptionBuffer = 0;
326       uint32_t totalSegs = 0;
327       uint32_t windSz  = RLC_AM_GET_WIN_SZ(ulRbCb->m.amUl.snLen) << 1;
328       
329       for(i = 0; i< windSz; i++)
330       {
331          RlcAmRecBuf *recBuf = rlcUtlGetRecBuf(ulRbCb->m.amUl.recBufLst, i);
332          if(recBuf != NULLP)
333          {
334             pdusInReceptionBuffer++;
335             totalSegs += (recBuf->segLst.count);
336          }
337       }
338
339       DU_LOG("\nDEBUG  -->  RLC_UL: AM UL UEID:%d CELLID:%d Reception Buf size = %d total segs = %d", 
340          ulRbCb->rlcId.ueId, ulRbCb->rlcId.cellId, pdusInReceptionBuffer, totalSegs);
341    }
342 }
343
344 Void DumpRLCUlDebugInformation(Void)
345 {
346    RlcCb* ulInst = rlcCb[0]; /* TODO : Check whether UL is 0 or 1 */
347    RlcUlCb* ulCb = ulInst->u.ulCb;
348    RlcUlUeCb *ueCb = NULLP; 
349
350    /* Until no more ueCb is ueLstCp hash list get and delete ueCb */
351    while (ROK == cmHashListGetNext(&ulCb->ueLstCp, 
352                                    (PTR) ueCb, 
353                                    (PTR *)&ueCb))
354    {
355       uint32_t i;
356       for(i = 0; i< RLC_MAX_SRB_PER_UE; i++)
357       {
358          RlcUlRbCb* ulRbCb = ueCb->srbCb[i]; 
359          if(ulRbCb != NULLP)
360          {
361             dumpRLCUlRbInformation(ulRbCb);
362          }
363       }
364       for(i = 0; i< RLC_MAX_DRB_PER_UE; i++)
365       {
366          RlcUlRbCb* ulRbCb = ueCb->drbCb[i]; 
367          if(ulRbCb != NULLP)
368          {
369             dumpRLCUlRbInformation(ulRbCb);
370          }
371       }
372    }
373 }
374
375
376 /*
377  * kwUtlFreeUlRbCb() function is split into two functions 
378  *  -  rlcAmmFreeUlRbCb() ---> gp_amm_ul.c 
379  *  -  rlcUmmFreeUlRbCb() ---> gp_umm_ul.c
380  * and placed in respective files mentioned above
381  */
382
383
384
385 /* kw005.201 added support for L2 Measurement */
386 #ifdef LTE_L2_MEAS
387
388 /**
389  *
390  * @brief 
391  *    Handler for initialisation of measurement 
392  * 
393  * @param[in]  gCb    - RLC instance Control Block 
394  *
395  * @return  S16
396  *      -# ROK 
397  */
398 S16 rlcUtlL2MeasUlInit(RlcCb *gCb)
399 {
400    uint16_t             cntr;
401
402    gCb->u.ulCb->rlcL2Cb.rlcNumMeas=0;
403    for(cntr = 0; cntr < LKW_MAX_L2MEAS; cntr++)
404    {
405       memset(&(gCb->u.ulCb->rlcL2Cb.rlcL2EvtCb[cntr]), 0, sizeof(RlcL2MeasEvtCb));
406    }
407    gCb->u.ulCb->rlcL2Cb.rlcL2EvtCb[RLC_L2MEAS_UL_IP].measCb.measType = LKW_L2MEAS_UL_IP;
408    return ROK;
409 }
410 /**
411  *
412  * @brief
413  *
414  *        Handler to calculate the Ul Ip throughput for a LCH
415  *
416  * @b Description:
417  *
418  *
419  * @param[in] rbCb         RB control block
420  * @param[in] pdu          Pdu of LCH
421  *
422  *  @return  Void
423  *
424  */
425 Void rlcUtlCalUlIpThrPutIncTTI(RlcCb *gCb,RlcUlRbCb *rbCb,uint32_t ttiCnt)
426 {
427    volatile uint32_t     startTime = 0;
428
429       /*starting Task*/
430       SStartTask(&startTime, PID_RLC_IP_TPT_INCTTI);
431 #ifndef ALIGN_64BIT
432    DU_LOG("\nDEBUG  -->  RLC_UL : Log for ul ip throughput:"
433          "RB_MeasOn:%d ttiCnt :%ld UEID:%d CELLID:%d", 
434          rbCb->rbL2Cb.measOn,ttiCnt,
435          rbCb->rlcId.ueId,
436          rbCb->rlcId.cellId);
437 #else
438    DU_LOG("\nDEBUG  -->  RLC_UL : Log for ul ip throughput:"
439          "RB_MeasOn:%d ttiCnt :%d UEID:%d CELLID:%d", 
440          rbCb->rbL2Cb.measOn,ttiCnt,
441          rbCb->rlcId.ueId,
442          rbCb->rlcId.cellId);
443 #endif
444
445    /*Check if UL IP throughput measurement is ON for this RB or not*/
446    if(RLC_MEAS_IS_UL_IP_MEAS_ON_FOR_RB(gCb,rbCb))              
447    {
448       if (TRUE  == rbCb->ueCb->isUlBurstActive)
449       {
450          if (ttiCnt < rbCb->l2MeasIpThruput.prevTtiCnt)
451          {
452             /*Removed Error Print*/
453          }
454          if (rbCb->l2MeasIpThruput.prevTtiCnt != 0)
455          {
456             rbCb->rbL2Cb.l2Sts[RLC_L2MEAS_UL_IP]->ulIpThruput.timeSummation += 
457                (ttiCnt - rbCb->l2MeasIpThruput.prevTtiCnt);
458          }
459          else
460          {
461             rbCb->ueCb->firstPacketTTI = ttiCnt;
462          }
463          rbCb->l2MeasIpThruput.prevTtiCnt = ttiCnt;
464       }
465       else
466       {
467          rbCb->l2MeasIpThruput.prevTtiCnt = 0;
468       }
469    }   
470
471    /*stopping Task*/
472    SStopTask(startTime, PID_RLC_IP_TPT_INCTTI);
473 } /* rlcUtlCalUlIpThrPutIncTTI */
474
475
476 /**
477  *
478  * @brief
479  *
480  *        Handler to calculate the Ul Ip throughput for a LCH
481  *
482  * @b Description:
483  *
484  *
485  * @param[in] rbCb         RB control block
486  * @param[in] pdu          Pdu of LCH
487  *
488  *  @return  Void
489  *
490  */
491 Void rlcUtlCalUlIpThrPut
492 (
493 RlcCb        *gCb,
494 RlcUlRbCb    *rbCb,
495 Buffer       *pdu,
496 uint32_t     ttiCnt
497 )
498 {
499    MsgLen        rlcSduSz = 0;  /*Holds length of Rlc Sdu*/
500    volatile uint32_t     startTime = 0;
501
502    /*starting Task*/
503    SStartTask(&startTime, PID_RLC_IP_TPT_INCVOL);
504
505    /*Check if UL IP throughput measurement is ON for this RB or not*/
506    if(RLC_MEAS_IS_UL_IP_MEAS_ON_FOR_RB(gCb, rbCb) &&              
507          (TRUE  == rbCb->ueCb->isUlBurstActive) &&
508          (rbCb->ueCb->firstPacketTTI) &&
509          (ttiCnt != rbCb->ueCb->firstPacketTTI))
510    {
511       SFndLenMsg(pdu, &rlcSduSz);
512
513       rbCb->rbL2Cb.l2Sts[RLC_L2MEAS_UL_IP]->ulIpThruput.volSummation += rlcSduSz;
514
515    }
516    /*stopping Task*/
517    SStopTask(startTime, PID_RLC_IP_TPT_INCVOL);
518 } /* rlcUtlCalUlIpThrPut */
519
520 \f
521 /**
522  *
523  * @brief Handler for L2 Measurement timer expiry.
524  *
525  *
526  * @b Description
527  *        This function is called when the l2 measurement timer expires. 
528  *        This function sends a consolidates the mesaurements taken during
529  *        this time and sends the confirm .
530  *
531  *  @param[in] measEvtCb    Measurement Event Control Block.
532  *
533  *
534  *  @return  S16
535  *      -# ROK
536  */
537
538 S16 rlcUtlHdlL2TmrExp(RlcCb *gCb,RlcL2MeasEvtCb *measEvtCb)
539 {
540
541 #ifdef LTE_L2_MEAS_RLC
542    uint16_t             qciIdx;
543    RlcL2MeasCb     *measCb;
544    
545    /* Clean up the RB data structures */
546    if((measEvtCb->measCb.measType & LKW_L2MEAS_ACT_UE) &&
547       (measEvtCb->measCb.val.nonIpThMeas.numSamples))
548    {
549       measCb = &measEvtCb->measCb;
550
551       for(qciIdx = 0; qciIdx < measCb->val.nonIpThMeas.numQci;qciIdx++)
552       {
553          measCb->val.nonIpThMeas.measData[measCb->val.nonIpThMeas.qci[qciIdx]].actUe.numActvUe   +=   
554                      rlcCb.rlcL2Cb.numActUe[measCb->val.nonIpThMeas.qci[qciIdx]];
555          measCb->val.nonIpThMeas.measData[measCb->val.nonIpThMeas.qci[qciIdx]].actUe.sampOc++;
556       }
557       measEvtCb->val.nonIpThMeas.measCb.numSamples--;
558       rlcStartTmr(gCb, (PTR)measEvtCb, EVENT_RLC_L2_TMR); 
559       return (ROK);
560    }
561 #endif
562
563    rlcUtlSndUlL2MeasCfm(gCb, measEvtCb);
564
565    return (ROK);
566 } /* rlcUtlHdlL2TmrExp */
567 /**
568  *
569  * @brief Handler for Sending L2 Measurement confirm.
570  *
571  *
572  * @b Description
573  *        This function sends a consolidates the mesaurements taken during
574  *        this time and sends the confirm .
575  *
576  *  @param[in] measEvtCb    Measurement Event Control Block.
577  *
578  *
579  *  @return  S16
580  *      -# ROK
581  */
582
583 S16 rlcUtlSndUlL2MeasCfm(RlcCb *gCb,RlcL2MeasEvtCb  *measEvtCb)
584 {
585    uint32_t            qciIdx;
586    RlcL2MeasCb         *measCb;
587    RlcL2MeasCfmEvt     measCfmEvt;
588    uint64_t            ulDataVol;
589    uint64_t            ulTime;
590    uint16_t            cntr;
591    /* Discard new changes starts */
592    uint8_t             qci = 0;
593    uint32_t            cfmIdx =0;
594    /* Discard new changes ends */
595
596    /* kw006.201 ccpu00120058 emoved 64 bit compilation warning */
597 #ifndef ALIGN_64BIT
598    DU_LOG("\nDEBUG  -->  RLC_UL : rlcUtlSndUlL2MeasCfm(transId(%ld))", measEvtCb->transId);
599 #else
600    DU_LOG("\nDEBUG  -->  RLC_UL : rlcUtlSndUlL2MeasCfm(transId(%d))", measEvtCb->transId);
601 #endif
602
603    /* Clean up the RB data structures */
604    measCb = &measEvtCb->measCb;
605    
606    memset(&measCfmEvt, 0, sizeof(RlcL2MeasCfmEvt));
607    measCfmEvt.transId = measEvtCb->transId;
608
609    measCfmEvt.measType = measCb->measType;
610    measCfmEvt.status.status = LCM_PRIM_OK;
611    measCfmEvt.status.reason = LCM_REASON_NOT_APPL;
612    
613    if( measCb->measType & LKW_L2MEAS_UL_IP)
614    {
615       RlcL2MeasCbUeMeasInfo *pUeInfoLstCb  = measCb->val.ipThMeas.ueInfoLst;
616       RlcL2MeasCfmUeInfoLst *pUeInfoLstCfm = measCfmEvt.val.ipThMeas.ueInfoLst;
617       for(cntr = 0;(cntr < measCb->val.ipThMeas.numUes) && (cntr < gCb->genCfg.maxUe);cntr++)        
618       {
619          pUeInfoLstCfm[cfmIdx].numCfm = 0;
620          if (pUeInfoLstCb[cntr].isValid == TRUE)
621          {
622             pUeInfoLstCfm[cfmIdx].ueId = pUeInfoLstCb[cntr].ueId;
623             pUeInfoLstCfm[cfmIdx].cellId = pUeInfoLstCb[cntr].cellId;
624
625             for(qciIdx = 0; qciIdx < pUeInfoLstCb[cntr].numQci; qciIdx++)
626             {
627                qci = pUeInfoLstCb[cntr].qci[qciIdx];
628                pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].qci = qci;
629
630                if(measCb->measType & LKW_L2MEAS_UL_IP)
631                {
632                   ulDataVol = pUeInfoLstCb[cntr].measData[qci].ulIpThruput.volSummation;
633                   ulTime = pUeInfoLstCb[cntr].measData[qci].ulIpThruput.timeSummation;
634                   if(0 == ulTime)
635                   {
636                      pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.ulIpThPut = 0;
637                   }
638                   else
639                   {
640                      pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.ulIpThPut = (ulDataVol / ulTime);
641
642                      /* Converting it to kbps */
643                      pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.ulIpThPut *= 8;
644
645                   }
646                   /* Reset the values after reporting to Application */
647                   pUeInfoLstCb[cntr].measData[qci].ulIpThruput.volSummation = 0;
648                   pUeInfoLstCb[cntr].measData[qci].ulIpThruput.timeSummation = 0;
649                }
650                pUeInfoLstCfm[cfmIdx].numCfm++;
651             }
652             cfmIdx++;
653          }
654       }
655       measCfmEvt.val.ipThMeas.numUes = cfmIdx; 
656    }
657    RlcMiLkwL2MeasCfm(&gCb->genCfg.lmPst, &measCfmEvt);
658    return (ROK);
659 } /* rlcUtlSndUlL2MeasCfm */
660 /**
661  *
662  * @brief Handler for Sending Negative confirm .
663  *
664  *
665   @b Description
666  *        This function is called when the l2 measurement cannot be started
667  *        This function sends  negative confirm for all the requests
668  *
669  * @param[in] gCb - RLC instance control block
670  * @param[in] measReqEvt    Measurement Req Structure
671  * @param[in] measCfmEvt  Confirmation to be sent to layer manager
672  *
673  *
674  *  @return  S16
675  *      -# ROK
676  */
677
678 S16 rlcUtlSndUlL2MeasNCfm(RlcCb *gCb,RlcL2MeasReqEvt *measReqEvt,RlcL2MeasCfmEvt *measCfmEvt)
679 {
680
681    RlcMiLkwL2MeasCfm(&gCb->genCfg.lmPst, measCfmEvt);
682    return ROK;
683 } /* kwUtlSndL2MeasNCfm */
684
685 #ifdef LTE_L2_MEAS_RLC
686 /**
687  * @brief  Validates the measurement request parameters. 
688  *
689  * @details
690  *
691  *     Function :rlcUtlValidateL2Meas 
692  *
693  *  @param[in]  measReqEvt L2 measurement request received from layer manager.
694  *  @param[out] measCfmEvt L2 measurement confirm to be prepared.
695  *  @param[out] lChId      List of LCh for the given Ue corresponding to QCIs
696                            given in measurement request.
697  *  @param[out] numLCh     Number of LCh in array lChId.
698  **/
699
700 S16 rlcUtlValidateL2Meas
701 (
702 RlcL2MeasReqEvt *measReqEvt,
703 RlcL2MeasCfmEvt *measCfmEvt,
704 CmLteLcId       *lChId,
705 uint8_t         *numLCh
706 )
707 {
708    uint8_t    measType;
709    S16        ret;
710    uint8_t    qciIdx;
711    uint8_t    qci;
712    uint8_t    idx;
713    uint8_t    *qciVal;
714    uint8_t    numQci;
715    RlcUlRbCb  *rbCb;
716    RlcUlUeCb  *ueCb;
717    RbCb       **rbCbLst;
718    uint8_t    rbIdx;
719    uint8_t    lsbNibble = 0;
720    uint8_t    msbNibble = 0;
721    uint8_t    numFaild = 0;
722
723    idx = 0;
724    rbCb = NULLP;
725    ret = ROK;
726    measType = measReqEvt->measReq.measType;
727    /* Check for the range of measType */
728    /* LKW_L2MEAS_DL_IP+ LKW_L2MEAS_UL_IP = 0x0030*/
729    if((measType == 0x00) ||
730        measType > 0x30)
731    {
732       measCfmEvt->transId = measReqEvt->transId;
733       measCfmEvt->measType = measType;
734       measCfmEvt->status.status = LCM_PRIM_NOK;
735       measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
736       return RFAILED;
737    }
738    /*User can either request for Active UE,*
739     *Dl delay, Dl discard, Uu Loss OR Dl ip throughput, Ul ip throughput. */
740    lsbNibble = measType & 0x0F;
741    msbNibble = measType & 0xF0;
742
743    if( (lsbNibble != 0) && (msbNibble != 0) )
744    {
745       measCfmEvt->transId = measReqEvt->transId;
746       measCfmEvt->measType = measType;
747       measCfmEvt->status.status = LCM_PRIM_NOK;
748       measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
749       return RFAILED;
750    }
751
752    /* Check for total maximum number of Measurement Control Block */
753    if(rlcCb.rlcL2Cb.rlcNumMeas >= LKW_MAX_L2MEAS )
754    {
755       measCfmEvt->transId = measReqEvt->transId;
756       measCfmEvt->measType = measType;
757       measCfmEvt->status.status = LCM_PRIM_NOK;
758       measCfmEvt->status.reason = LKW_CAUSE_EXCEED_NUMMEAS;
759       return RFAILED;
760    }
761
762    /* Check that number of samples should be a non-zero value */
763    if(((measType & LKW_L2MEAS_ACT_UE) &&
764       (measReqEvt->measReq.val.nonIpThMeas.numSamples == 0)))
765    {
766       measCfmEvt->transId = measReqEvt->transId;
767       measCfmEvt->measType = measType;
768       measCfmEvt->status.status = LCM_PRIM_NOK;
769       measCfmEvt->status.reason = LKW_CAUSE_ZERO_NUMSAM;
770       return RFAILED;
771    }
772    /* Check that measurement period  should be completely divisible *
773     * number of sample.                                             */
774    if(((measType & LKW_L2MEAS_ACT_UE) &&
775       ((measReqEvt->measPeriod % 
776         measReqEvt->measReq.val.nonIpThMeas.numSamples) != 0)))
777    {
778       measCfmEvt->transId = measReqEvt->transId;
779       measCfmEvt->measType = measType;
780       measCfmEvt->status.status = LCM_PRIM_NOK;
781       measCfmEvt->status.reason = LKW_CAUSE_INVALID_NUMSAM;
782       return RFAILED;
783    }
784    {
785       numQci = measReqEvt->measReq.val.nonIpThMeas.numQci;
786       qciVal = measReqEvt->measReq.val.nonIpThMeas.qci;
787    }
788    /* Check whether qci is configured or not */
789    for(qciIdx = 0; qciIdx < numQci; qciIdx++)
790    {
791       qci = qciVal[qciIdx];
792       ret = cmHashListFind(&(rlcCb.rlcL2Cb.qciHlCp), 
793             (uint8_t *)&qci, (uint16_t)sizeof(qci), 0, (PTR *)&rbCb);
794       if(ret != ROK)
795       {
796          measCfmEvt->val.nonIpThMeas.measCfm[measCfmEvt->val.nonIpThMeas.numCfm].qci = qci;
797          measCfmEvt->val.nonIpThMeas.numCfm++;
798
799       }
800    }
801    if(measCfmEvt->val.nonIpThMeas.numCfm > 0)
802    {
803       measCfmEvt->status.status = LCM_PRIM_NOK;
804       measCfmEvt->status.reason = LKW_CAUSE_INVALID_QCI;
805       measCfmEvt->measType = measType;
806       measCfmEvt->transId = measReqEvt->transId;
807       return RFAILED;
808    }
809    {
810       for(qciIdx = 0; qciIdx < numQci; qciIdx++)
811       {
812          if(rlcCb.rlcL2Cb.measOn[qci] & measReqEvt->measReq.measType)
813          {
814             /* measurement is already ongoing */
815             measCfmEvt->status.status = LCM_PRIM_NOK;
816             measCfmEvt->status.reason = LKW_CAUSE_MEAS_ALREADY_ENA;
817             measCfmEvt->val.nonIpThMeas.measCfm[measCfmEvt->val.nonIpThMeas.numCfm].qci = qci;
818             measCfmEvt->measType = measType;
819             measCfmEvt->val.nonIpThMeas.numCfm++;
820          }
821       }
822    }
823    if(measCfmEvt->val.nonIpThMeas.numCfm > 0)
824    {
825       measCfmEvt->transId = measReqEvt->transId;
826       return RFAILED;
827    }
828
829    return (ROK);
830 }/* rlcUtlValidateL2Meas */
831 #endif
832
833 S16 rlcUtlValidateIpThL2Meas(RlcL2MeasReqEvt *measReqEvt,RlcL2MeasCfmEvt *measCfmEvt)
834 {
835    uint8_t      measType;
836    uint8_t         lsbNibble = 0;
837    uint8_t         msbNibble = 0;
838
839    measType = measReqEvt->measReq.measType;
840    /* Check for the range of measType */
841    /* LKW_L2MEAS_DL_IP+ LKW_L2MEAS_UL_IP = 0x0030*/
842    if((measType == 0x00) ||
843        measType > 0x30)
844    {
845       measCfmEvt->transId = measReqEvt->transId;
846       measCfmEvt->measType = measType;
847       measCfmEvt->status.status = LCM_PRIM_NOK;
848       measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
849       return RFAILED;
850    }
851    /*User can either request for Active UE,*
852     *Dl delay, Dl discard, Uu Loss OR Dl ip throughput, Ul ip throughput. */
853    lsbNibble = measType & 0x0F;
854    msbNibble = measType & 0xF0;
855
856    if( (lsbNibble != 0) && (msbNibble != 0) )
857    {
858       measCfmEvt->transId = measReqEvt->transId;
859       measCfmEvt->measType = measType;
860       measCfmEvt->status.status = LCM_PRIM_NOK;
861       measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
862       return RFAILED;
863    }
864    return (ROK);
865 }/* rlcUtlValidateL2Meas */
866
867 /**
868  *
869  * @brief Handler for resetting the RB data structures
870  *
871  *
872  * @b Description
873  *        This function resets the RB data structure after the expiry of 
874  *        measurement timer.
875  *
876  *  @param[in] measCb    Measurement Control Block.
877  *
878  *
879  *  @return  Void
880  */
881
882 Void rlcUtlResetUlL2MeasInRlcRb(RlcCb *gCb,RlcL2MeasCb *measCb,uint8_t measType)
883 {
884    uint32_t           rbIdx;
885    uint32_t           ueIdx;
886    uint32_t           qciIdx;
887    RlcUlUeCb         *ueCb = NULL;
888
889
890
891    if (measCb->measType & LKW_L2MEAS_UL_IP)
892    {
893       for(ueIdx = 0; ueIdx < measCb->val.ipThMeas.numUes; ueIdx++)
894       {           
895          if (measCb->val.ipThMeas.ueInfoLst[ueIdx].isValid == TRUE)
896          {
897             for (qciIdx =0; qciIdx < measCb->val.ipThMeas.ueInfoLst[ueIdx].numQci; qciIdx++)
898             {
899                if (measType & LKW_L2MEAS_UL_IP)
900                {
901                   measCb->val.ipThMeas.ueInfoLst[ueIdx].measData[qciIdx].ulIpThruput.volSummation = 0;
902                   measCb->val.ipThMeas.ueInfoLst[ueIdx].measData[qciIdx].ulIpThruput.timeSummation = 0;
903                }
904             }
905
906             if(ROK  != rlcDbmFetchUlUeCb(gCb, measCb->val.ipThMeas.ueInfoLst[ueIdx].ueId,
907                      measCb->val.ipThMeas.ueInfoLst[ueIdx].cellId, &ueCb))
908             {
909                continue;
910             }
911
912             for (rbIdx = 0; rbIdx < RLC_MAX_DRB_PER_UE; rbIdx++)
913             {
914                if (ueCb->drbCb[rbIdx])
915                {
916                   ueCb->drbCb[rbIdx]->rbL2Cb.measOn &= ~measType;
917                }
918             }
919          }
920       }
921    }
922 } /* rlcUtlResetUlL2MeasInRlcRb */
923
924 /**
925  *
926  * @brief Handler for storing address of MeasData in rbCb at right index
927  *
928  *
929  * @b Description
930  *        This function is called when LM sends measReq message to RLC.
931  *
932  *  @param[in] 
933  *  @param[out] 
934  *  @param[in] 
935  *
936  *
937  *  @return  S16
938  *      -# ROK
939  */
940 Void rlcUtlPlcMeasDatInL2Sts(RlcL2Cntr *measData,RlcL2MeasRbCb *rbL2Cb,uint8_t measType)
941 {
942    /* We should check the number of measType in the request. This can be done 
943     * by looking at each bit in the measType. Also store the measData in the 
944     * correct index of l2Sts in RbCb.
945     * */
946
947     if(measType & LKW_L2MEAS_ACT_UE)
948     {
949          rbL2Cb->l2Sts[RLC_L2MEAS_ACT_UE] = measData;
950     }
951     if(measType & LKW_L2MEAS_UU_LOSS)
952     {
953          rbL2Cb->l2Sts[RLC_L2MEAS_UU_LOSS] = measData;
954     }
955     if(measType & LKW_L2MEAS_DL_IP )
956     {
957          rbL2Cb->l2Sts[RLC_L2MEAS_DL_IP] = measData;
958     }
959     if(measType & LKW_L2MEAS_UL_IP)
960     {
961          rbL2Cb->l2Sts[RLC_L2MEAS_UL_IP] = measData;
962     }
963     if(measType & LKW_L2MEAS_DL_DISC)
964     {
965          rbL2Cb->l2Sts[RLC_L2MEAS_DL_DISC] = measData;
966     }
967     if(measType & LKW_L2MEAS_DL_DELAY)
968     {
969          rbL2Cb->l2Sts[RLC_L2MEAS_DL_DELAY] = measData;
970     }
971 }/* End of rlcUtlPlcMeasDatInL2Sts */
972 #endif /* LTE_L2_MEAS */
973
974 /**
975  *
976  * @brief Store the UL buffer in hashList  
977  *
978  *
979  * @b Description
980  *
981  *   Use the SN % binSize as key and store the received UL buffer
982  *  @param[in] recBufLst       List CP array
983  *  @param[in] recBuf          received buffer
984  *  @param[in] sn              sn of the received buffer 
985  *
986  *
987  *  @return  Void
988  */
989 void rlcUtlStoreRecBuf(CmLListCp *recBufLst, RlcAmRecBuf *recBuf, RlcSn sn)
990 {
991    uint32_t    hashKey; 
992    
993    hashKey = (sn % RLC_RCV_BUF_BIN_SIZE ); 
994    recBuf->lnk.node = (PTR)recBuf;
995    cmLListAdd2Tail(&(recBufLst[hashKey]), &recBuf->lnk);
996
997    return;
998 } /* rlcUtlStoreRecBuf */
999
1000 /**
1001  *
1002  * @brief Retrieve the UL buffer from the list
1003  *
1004  *
1005  * @Description
1006  *
1007  *   Use the SN % binSize as key and retrieve the UL buffer
1008  *  @param[in] recBufLst       List CP array
1009  *  @param[in] sn              sn of the received buffer 
1010  *
1011  *
1012  *  @return  Void
1013  */
1014 RlcAmRecBuf* rlcUtlGetRecBuf(CmLListCp *recBufLst, RlcSn sn)
1015 {
1016    uint32_t            hashKey; 
1017    CmLListCp           *recBufLstCp;
1018    RlcAmRecBuf         *recBuf;
1019    CmLList             *node = NULLP;
1020
1021    hashKey = (sn % RLC_RCV_BUF_BIN_SIZE ); 
1022  
1023    recBufLstCp = &recBufLst[hashKey];
1024    CM_LLIST_FIRST_NODE(recBufLstCp, node);
1025    while(node)
1026    {
1027       recBuf = (RlcAmRecBuf *) node->node;
1028       if(recBuf->amHdr.sn == sn)
1029       {
1030          return recBuf;
1031       }
1032       CM_LLIST_NEXT_NODE(recBufLstCp, node);
1033    }
1034    return NULLP;
1035 } /* rlcUtlGetRecBuf */
1036 /**
1037  *
1038  * @brief Delete the UL buffer from the list
1039  *
1040  *
1041  * @Description
1042  *
1043  *   Use the SN % binSize as key and retrieve the UL buffer
1044  *  @param[in] recBufLst       List CP array
1045  *  @param[in] sn              sn of the received buffer 
1046  *
1047  *
1048  *  @return  Void
1049  */
1050 void rlcUtlDelRecBuf(CmLListCp *recBufLst, RlcAmRecBuf *recBuf, RlcCb *gCb)
1051 {
1052    uint32_t            hashKey; 
1053    CmLListCp           *recBufLstCp;
1054
1055    hashKey = (recBuf->amHdr.sn % RLC_RCV_BUF_BIN_SIZE ); 
1056  
1057    recBufLstCp = &recBufLst[hashKey];
1058    cmLListDelFrm(recBufLstCp, &recBuf->lnk);
1059    RLC_FREE(gCb, recBuf, sizeof(RlcAmRecBuf));
1060
1061    return;
1062 } /* rlcUtlDelRecBuf */
1063
1064 /**
1065  *
1066  * @brief Store the UL buffer in hashList  
1067  *
1068  * @b Description
1069  *
1070  *  Use the SN % binSize as key and store the received UL buffer
1071  *  @param[in] recBufLst       List CP array
1072  *  @param[in] recBuf          received buffer
1073  *  @param[in] sn              sn of the received buffer 
1074  *
1075  *  @return  Void
1076  */
1077 void rlcUtlStoreUmRecBuf(CmLListCp *recBufLst, RlcUmRecBuf *recBuf, RlcSn sn)
1078 {
1079    uint32_t    hashKey; 
1080    
1081    hashKey = (sn % RLC_RCV_BUF_BIN_SIZE ); 
1082    recBuf->lnk.node = (PTR)recBuf;
1083    cmLListAdd2Tail(&(recBufLst[hashKey]), &recBuf->lnk);
1084
1085    return;
1086 } /* rlcUtlStoreUmRecBuf */
1087
1088 /**
1089  *
1090  * @brief Retrieve the UL buffer from the list
1091  *
1092  * @Description
1093  *
1094  *   Use the SN % binSize as key and retrieve the UL buffer
1095  *  @param[in] recBufLst       List CP array
1096  *  @param[in] sn              sn of the received buffer 
1097  *
1098  *  @return  Void
1099  */
1100 RlcUmRecBuf* rlcUtlGetUmRecBuf(CmLListCp *recBufLst, RlcSn sn)
1101 {
1102    uint32_t            hashKey; 
1103    CmLListCp           *recBufLstCp;
1104    RlcUmRecBuf         *recBuf;
1105    CmLList             *node = NULLP;
1106
1107    hashKey = (sn % RLC_RCV_BUF_BIN_SIZE ); 
1108  
1109    recBufLstCp = &recBufLst[hashKey];
1110    CM_LLIST_FIRST_NODE(recBufLstCp, node);
1111    while(node)
1112    {
1113       recBuf = (RlcUmRecBuf *) node->node;
1114       if(recBuf->umHdr.sn == sn)
1115       {
1116          return recBuf;
1117       }
1118       CM_LLIST_NEXT_NODE(recBufLstCp, node);
1119    }
1120    return NULLP;
1121 } /* rlcUtlGetUmRecBuf */
1122
1123 /**
1124  *
1125  * @brief Delete the UM Mode UL buffer from the list
1126  *
1127  *
1128  * @details
1129  *   Use the SN % binSize as key and retrieve the UL buffer
1130  *
1131  *  @param[in] *recBufLst       List CP array
1132  *  @param[in] *recBuf          Received buffer
1133  *
1134  *  @return  Void
1135  */
1136 void rlcUtlDelUmRecBuf(RlcCb *gCb, CmLListCp *recBufLst, RlcUmRecBuf  *recBuf)
1137 {
1138    uint32_t   hashKey;
1139    CmLListCp  *recBufLstCp;
1140
1141    hashKey = (recBuf->sn % RLC_RCV_BUF_BIN_SIZE );
1142    recBufLstCp = &recBufLst[hashKey];
1143    cmLListDelFrm(recBufLstCp, &recBuf->lnk);
1144    RLC_FREE(gCb, recBuf, sizeof(RlcUmRecBuf));
1145
1146    return;
1147 } /* rlcUtlDelUmRecBuf */
1148
1149 /********************************************************************30**
1150          End of file
1151 **********************************************************************/