Initial commit
[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                   --kwUtlSndToLi
29                   --kwUtlRcvFrmLi
30                   --kwUtlEmptySduQ
31                   --kwUtlSndDatInd 
32                   --kwUtlShutDown
33
34      File:     kw_utl_ul.c
35
36 **********************************************************************/
37 static const char* RLOG_MODULE_NAME="UTL";
38 static int RLOG_MODULE_ID=2048;
39 static int RLOG_FILE_ID=210;
40
41 /** @file kw_utl_ul.c
42 @brief RLC Utility Module 
43 */
44
45 /* header (.h) include files */
46 #include "envopt.h"        /* environment options */
47 #include "envdep.h"        /* environment dependent */
48 #include "envind.h"        /* environment independent */
49 /* kw005.201 added support for L2 Measurement */
50 #ifdef LTE_L2_MEAS
51 #include <sys/time.h>
52 #endif
53
54 #include "gen.h"           /* general */
55 #include "ssi.h"           /* system services */
56 #include "cm5.h"           /* common timer defines */
57 #include "cm_tkns.h"       /* common tokens defines */
58 #include "cm_mblk.h"       /* common memory allocation library defines */
59 #include "cm_llist.h"      /* common link list  defines  */
60 #include "cm_hash.h"       /* common hash list  defines */
61 #include "cm_lte.h"        /* common LTE defines */
62 #include "ckw.h"           /* CKW defines */
63 #include "kwu.h"           /* KWU defines */
64 #include "lkw.h"           /* LKW defines */
65 #include "rgu.h"           /* RGU defines */
66
67 #include "kw_env.h"        /* RLC environment options */
68 #include "kw.h"            /* RLC defines */
69 #include "kw_err.h"        /* Error defines */
70 #include "kw_ul.h"         /* RLC Uplink defines */
71
72 /* extern (.x) include files */
73 #include "gen.x"           /* general */
74 #include "ssi.x"           /* system services */
75
76 #include "cm5.x"           /* common timer library */
77 #include "cm_tkns.x"       /* common tokens */
78 #include "cm_mblk.x"       /* common memory allocation */
79 #include "cm_llist.x"      /* common link list */
80 #include "cm_hash.x"       /* common hash list */
81 #include "cm_lte.x"        /* common LTE includes */
82 #include "cm_lib.x"        /* common memory allocation library */
83 #include "ckw.x"           /* CKW includes */
84 #include "kwu.x"           /* KWU includes */
85 #include "lkw.x"           /* LKW includes */
86 #include "rgu.x"           /* RGU includes */
87
88 #include "kw.x"            /* RLC inlcudes */
89 #include "kw_ul.x"         /* RLC uplink includes */
90 #include "ss_rbuf.h"
91 #include "ss_rbuf.x"
92 #ifdef SS_RBUF
93 PUBLIC S16 SMrkUlPkt(Buffer *mbuf);
94 #endif
95 PUBLIC KwAmRecBuf* kwUtlGetRecBuf(CmLListCp *recBufLst, KwSn sn);
96 #define KW_MODULE (KW_DBGMASK_DUT | KW_DBGMASK_UL) /* for debugging purpose */
97
98
99 /**
100  *
101  * @brief 
102  *        Handler for receiving data for multiple logical channels from MAC.
103  *
104  * @details
105  *        This function receives the data sent by MAC for one or more 
106  *        logical channels.It calls the UMM or AMM functions to process
107  *        the PDUs and send them to the uppper layer.  
108  *
109  * @param[in] gCb          - RLC instance control block 
110  * @param[in] datIndInfo   - Data Indication Information containing the PDU(s)
111  *                            for one or more logical channels  
112  *
113  * @return  S16
114  *      -# ROK 
115  *      -# RFAILED
116  *
117  */
118 #ifdef ANSI
119 PUBLIC S16 kwUtlRcvFrmLi
120 (
121 KwCb           *gCb,                              
122 KwDatIndInfo   *datIndInfo                       
123 )
124 #else
125 PUBLIC S16 kwUtlRcvFrmLi(gCb,datIndInfo)  
126 KwCb           *gCb;                     
127 KwDatIndInfo   *datIndInfo;             
128 #endif
129 {
130    U32         count;      /* Loop Counter */
131    KwPduInfo   *pduInfo;   /* PDU Information */
132    KwUlRbCb    *rbCb;      /* RB Control Block */
133    KwUlUeCb    *ueCb;      /* UE Control Block */
134 /* kw005.201 added support for L2 Measurement */
135
136    TRC2(kwUtlRcvFrmLi)
137
138
139    ueCb = NULLP;
140    
141    /* fetch UeCb  */
142    if( ROK != kwDbmFetchUlUeCb(gCb,datIndInfo->rnti,datIndInfo->cellId,&(ueCb)))
143    {
144       /* Fetch UeCb failed */
145       RLOG_ARG1(L_ERROR,DBG_CELLID,datIndInfo->cellId,
146                "UEID:%d UeCb not found",
147                datIndInfo->rnti);
148       /* free the buffers inside the datIndInfo */
149       U32 i,j;
150       for(i = 0; i< datIndInfo->numLch; i++)
151       {
152          for(j = 0; j < datIndInfo->lchData[i].pdu.numPdu; j++)
153          {
154             if(datIndInfo->lchData[i].pdu.mBuf[j])
155             {
156                KW_FREE_BUF_WC(datIndInfo->lchData[i].pdu.mBuf[j]);
157             }
158          }
159       }
160       
161       RETVALUE(RFAILED);
162    }
163
164 #ifdef LTE_L2_MEAS
165
166    if (RGU_L2M_UL_BURST_START == datIndInfo->burstInd)
167    {
168       ueCb->isUlBurstActive = TRUE;
169    }
170    else
171    {
172       ueCb->firstPacketTTI = 0;
173       ueCb->isUlBurstActive = FALSE;
174    }
175 #endif
176    for ( count = 0;count < datIndInfo->numLch; count++ )
177    {
178       rbCb = ueCb->lCh[datIndInfo->lchData[count].lcId - 1].ulRbCb;
179       /* kw002.201 Removed allocation of pduInfo */ 
180       pduInfo = &(datIndInfo->lchData[count].pdu);
181       /* Fix for CR ccpu00138374,sometimes rbCb is NULL in UL path,
182        * So inorder to avoid the crash, added this preventive check
183        */
184       if(rbCb == NULLP)
185       {
186          U32 j;
187          for(j = 0; j < pduInfo->numPdu; j++)
188          {
189             if(pduInfo->mBuf[j])
190             {
191                KW_FREE_BUF_WC(pduInfo->mBuf[j]);
192             }
193          }
194          continue;
195       }
196
197 #ifdef SS_RBUF
198       SMrkUlPkt(pduInfo->mBuf[0]);
199 #endif
200       if ( rbCb->mode == CM_LTE_MODE_UM )
201       {
202 /* kw005.201 added support for L2 Measurement */
203 #ifdef LTE_L2_MEAS
204          kwUmmProcessPdus(gCb,rbCb, pduInfo, datIndInfo->ttiCnt);
205 #else
206          kwUmmProcessPdus(gCb,rbCb,pduInfo);
207 #endif
208       }
209       else if (rbCb->mode == CM_LTE_MODE_AM )
210       {
211 /* kw005.201 added support for L2 Measurement */
212 #ifdef LTE_L2_MEAS
213          kwAmmProcessPdus(gCb,rbCb,  pduInfo, datIndInfo->ttiCnt);
214 #else
215          kwAmmProcessPdus(gCb,rbCb,pduInfo);
216 #endif
217       }
218    }
219    RETVALUE(ROK);
220 }
221
222 /**
223  *
224  * @brief 
225  *    Handler for sending Data Indication to the upper layer. 
226  * 
227  * @Details
228  *    This function is used to send re-assembled SDU to the upper layer.
229  *
230  * @param[in]  gCb    - RLC instance Control Block 
231  * @param[in]  rbCb   - RB Control Block 
232  * @param[in]  sdu    - SDU to be sent to upper layer 
233  *
234  * @return  S16
235  *      -# ROK 
236  */
237 #ifdef ANSI
238 PUBLIC S16 kwUtlSndDatInd
239 (
240 KwCb       *gCb,
241 KwUlRbCb   *rbCb,                   
242 Buffer     *sdu                    
243 )
244 #else
245 PUBLIC S16 kwUtlSndDatInd(gCb,rbCb,sdu)
246 KwCb       *gCb;
247 KwUlRbCb   *rbCb;                  
248 Buffer     *sdu;                    
249 #endif
250 {
251 #ifndef KW_PDCP
252    KwKwuSapCb      *kwKwSap;     /* KWU SAP Information */
253    KwuDatIndInfo   *datIndInfo;   /* Data Indication Information */
254    KwuDatIndInfo datIndInfoTmp;
255 #endif
256
257    TRC3(kwUtlSndDatInd)
258
259
260 #ifndef KW_PDCP
261    kwKwSap = gCb->u.ulCb->kwuUlSap + KW_UI_PDCP;
262    /* Creating static memory for KwuDatIndInfo. #else will be 
263     * removed once the testing is done on all platforms */
264    datIndInfo = &datIndInfoTmp;
265
266 #if (ERRCLASS & ERRCLS_ADD_RES )
267    if ( datIndInfo == NULLP  )
268    {
269       RLOG_ARG2(L_FATAL,DBG_RBID,rbCb->rlcId.rbId,
270                "Memory allocation failed UEID:%d CELLID:%d",
271                rbCb->rlcId.ueId,
272                rbCb->rlcId.cellId);
273       KW_FREE_BUF(sdu);
274       RETVALUE(RFAILED);
275    }
276 #endif /* ERRCLASS & ERRCLS_ADD_RES */
277
278    KW_MEM_CPY(&(datIndInfo->rlcId),&(rbCb->rlcId),sizeof(CmLteRlcId));
279    /* Set the "isOutofSeq" flag for each packet 
280     * If packets are in-sequence set flag as TRUE else FALSE */
281    datIndInfo->isOutOfSeq = rbCb->m.amUl.isOutOfSeq; 
282 #endif /* KW_PDCP */
283    
284    /* If trace flag is enabled send the trace indication */
285    if(gCb->init.trc == TRUE)
286    {
287       /* Populate the trace params */
288       kwLmmSendTrc(gCb,KWU_EVT_DAT_IND, sdu);
289    }
290 #ifndef KW_PDCP
291
292    KwUiKwuDatInd(&kwKwSap->pst, kwKwSap->suId, datIndInfo, sdu);
293 #endif   
294    RETVALUE(ROK);
295 } /* kwUtlSndDatInd */
296
297
298 PRIVATE Void dumpRLCUlRbInformation(KwUlRbCb* ulRbCb)
299 {
300    if(ulRbCb->mode == CM_LTE_MODE_UM)
301    {
302       U32 i;
303       U32 pdusInReceptionBuffer = 0;
304       U32 windSz  = ulRbCb->m.umUl.umWinSz << 1;
305
306       for(i = 0; i< windSz; i++)
307       {
308          if(ulRbCb->m.umUl.recBuf[i] != NULLP)
309          {
310             pdusInReceptionBuffer++;
311          }
312       }
313       
314       RLOG_ARG3(L_DEBUG,DBG_RBID,ulRbCb->rlcId.rbId,
315                "UM UL UEID:%d CELLID:%d Reception Buffer size = %d", 
316                        (int)ulRbCb->rlcId.ueId,
317                        (int)ulRbCb->rlcId.cellId,
318                        (int)pdusInReceptionBuffer);
319    }
320    else if(ulRbCb->mode == CM_LTE_MODE_AM)
321    {
322       U32 i;
323       U32 pdusInReceptionBuffer = 0;
324       U32 totalSegs = 0;
325       U32 windSz  = KW_AM_GET_WIN_SZ(ulRbCb->m.amUl.snLen) << 1;
326       
327       for(i = 0; i< windSz; i++)
328       {
329          KwAmRecBuf *recBuf = kwUtlGetRecBuf(ulRbCb->m.amUl.recBufLst, i);
330          if(recBuf != NULLP)
331          {
332             pdusInReceptionBuffer++;
333             totalSegs += (recBuf->segLst.count);
334          }
335       }
336
337       RLOG_ARG4(L_DEBUG,DBG_RBID,ulRbCb->rlcId.rbId,
338                 "AM UL UEID:%d CELLID:%d Reception Buf size = %d"
339                 "total segs = %d", 
340                        (int)ulRbCb->rlcId.ueId,
341                        (int)ulRbCb->rlcId.cellId,
342                        (int)pdusInReceptionBuffer, 
343                        (int)totalSegs);
344    }
345 }
346
347 Void DumpRLCUlDebugInformation(Void)
348 {
349    KwCb* ulInst = kwCb[0]; /* TODO : Check whether UL is 0 or 1 */
350    KwUlCb* ulCb = ulInst->u.ulCb;
351    KwUlUeCb *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       U32 i;
359       for(i = 0; i< KW_MAX_SRB_PER_UE; i++)
360       {
361          KwUlRbCb* ulRbCb = ueCb->srbCb[i]; 
362          if(ulRbCb != NULLP)
363          {
364             dumpRLCUlRbInformation(ulRbCb);
365          }
366       }
367       for(i = 0; i< KW_MAX_DRB_PER_UE; i++)
368       {
369          KwUlRbCb* 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  *  -  kwAmmFreeUlRbCb() ---> gp_amm_ul.c 
382  *  -  kwUmmFreeUlRbCb() ---> 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 kwUtlL2MeasUlInit(KwCb *gCb)
402 {
403    U16             cntr;
404
405    gCb->u.ulCb->kwL2Cb.kwNumMeas=0;
406    for(cntr = 0; cntr < LKW_MAX_L2MEAS; cntr++)
407    {
408       cmMemset((U8 *)&(gCb->u.ulCb->kwL2Cb.kwL2EvtCb[cntr]), 0, sizeof(KwL2MeasEvtCb));
409    }
410    gCb->u.ulCb->kwL2Cb.kwL2EvtCb[KW_L2MEAS_UL_IP].measCb.measType = LKW_L2MEAS_UL_IP;
411    RETVALUE(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 #ifdef ANSI
429 PUBLIC  Void kwUtlCalUlIpThrPutIncTTI
430 (
431 KwCb                  *gCb,
432 KwUlRbCb              *rbCb,
433 U32                   ttiCnt
434 )
435 #else
436 PUBLIC Void kwUtlCalUlIpThrPutIncTTI(gCb, rbCb, ttiCnt)
437 KwCb                  *gCb;
438 KwUlRbCb              *rbCb;
439 U32                   ttiCnt;
440 #endif
441 {
442    VOLATILE U32     startTime = 0;
443    TRC2(kwUtlCalUlIpThrPutIncTTI)
444
445       /*starting Task*/
446       SStartTask(&startTime, PID_RLC_IP_TPT_INCTTI);
447 #ifndef ALIGN_64BIT
448    RLOG_ARG4(L_UNUSED, DBG_RBID,rbCb->rlcId.rbId,"Log for ul ip throughput:"
449          "RB_MeasOn:%d ttiCnt :%ld UEID:%d CELLID:%d", 
450          rbCb->rbL2Cb.measOn,ttiCnt,
451          rbCb->rlcId.ueId,
452          rbCb->rlcId.cellId);
453 #else
454    RLOG_ARG4(L_UNUSED,DBG_RBID,rbCb->rlcId.rbId, "Log for ul ip throughput:"
455          "RB_MeasOn:%d ttiCnt :%d UEID:%d CELLID:%d", 
456          rbCb->rbL2Cb.measOn,ttiCnt,
457          rbCb->rlcId.ueId,
458          rbCb->rlcId.cellId);
459 #endif
460
461    /*Check if UL IP throughput measurement is ON for this RB or not*/
462    if(KW_MEAS_IS_UL_IP_MEAS_ON_FOR_RB(gCb,rbCb))              
463    {
464       if (TRUE  == rbCb->ueCb->isUlBurstActive)
465       {
466          if (ttiCnt < rbCb->l2MeasIpThruput.prevTtiCnt)
467          {
468             /*Removed Error Print*/
469          }
470          if (rbCb->l2MeasIpThruput.prevTtiCnt != 0)
471          {
472             rbCb->rbL2Cb.l2Sts[KW_L2MEAS_UL_IP]->ulIpThruput.timeSummation += 
473                (ttiCnt - rbCb->l2MeasIpThruput.prevTtiCnt);
474          }
475          else
476          {
477             rbCb->ueCb->firstPacketTTI = ttiCnt;
478          }
479          rbCb->l2MeasIpThruput.prevTtiCnt = ttiCnt;
480       }
481       else
482       {
483          rbCb->l2MeasIpThruput.prevTtiCnt = 0;
484       }
485    }   
486
487    /*stopping Task*/
488    SStopTask(startTime, PID_RLC_IP_TPT_INCTTI);
489 } /* kwUtlCalUlIpThrPutIncTTI */
490
491
492 /**
493  *
494  * @brief
495  *
496  *        Handler to calculate the Ul Ip throughput for a LCH
497  *
498  * @b Description:
499  *
500  *
501  * @param[in] rbCb         RB control block
502  * @param[in] pdu          Pdu of LCH
503  *
504  *  @return  Void
505  *
506  */
507 #ifdef ANSI
508 PUBLIC  Void kwUtlCalUlIpThrPut
509 (
510 KwCb                  *gCb,
511 KwUlRbCb              *rbCb,
512 Buffer                *pdu,
513 U32                   ttiCnt
514 )
515 #else
516 PUBLIC Void kwUtlCalUlIpThrPut(gCb, rbCb, pdu, ttiCnt)
517    KwCb                  *gCb;
518    KwUlRbCb              *rbCb;
519    Buffer                *pdu;
520    U32                   ttiCnt;
521 #endif
522 {
523    MsgLen        rlcSduSz = 0;  /*Holds length of Rlc Sdu*/
524    VOLATILE U32     startTime = 0;
525    TRC2(kwUtlCalUlIpThrPut)
526
527
528    /*starting Task*/
529    SStartTask(&startTime, PID_RLC_IP_TPT_INCVOL);
530
531    /*Check if UL IP throughput measurement is ON for this RB or not*/
532    if(KW_MEAS_IS_UL_IP_MEAS_ON_FOR_RB(gCb, rbCb) &&              
533          (TRUE  == rbCb->ueCb->isUlBurstActive) &&
534          (rbCb->ueCb->firstPacketTTI) &&
535          (ttiCnt != rbCb->ueCb->firstPacketTTI))
536    {
537       SFndLenMsg(pdu, &rlcSduSz);
538
539       rbCb->rbL2Cb.l2Sts[KW_L2MEAS_UL_IP]->ulIpThruput.volSummation += rlcSduSz;
540
541    }
542    /*stopping Task*/
543    SStopTask(startTime, PID_RLC_IP_TPT_INCVOL);
544 } /* kwUtlCalUlIpThrPut */
545
546 \f
547 /**
548  *
549  * @brief Handler for L2 Measurement timer expiry.
550  *
551  *
552  * @b Description
553  *        This function is called when the l2 measurement timer expires. 
554  *        This function sends a consolidates the mesaurements taken during
555  *        this time and sends the confirm .
556  *
557  *  @param[in] measEvtCb    Measurement Event Control Block.
558  *
559  *
560  *  @return  S16
561  *      -# ROK
562  */
563
564 #ifdef ANSI
565 PUBLIC S16 kwUtlHdlL2TmrExp
566 (
567 KwCb          *gCb,
568 KwL2MeasEvtCb *measEvtCb
569 )
570 #else
571 PUBLIC S16 kwUtlHdlL2TmrExp(measEvtCb)
572 KwCb          *gCb;
573 KwL2MeasEvtCb *measEvtCb;
574 #endif
575 {
576    TRC3(kwUtlHdlL2TmrExp)
577
578 #ifdef LTE_L2_MEAS_RLC
579    U16             qciIdx;
580    KwL2MeasCb     *measCb;
581    
582    /* Clean up the RB data structures */
583    if((measEvtCb->measCb.measType & LKW_L2MEAS_ACT_UE) &&
584       (measEvtCb->measCb.val.nonIpThMeas.numSamples))
585    {
586       measCb = &measEvtCb->measCb;
587
588       for(qciIdx = 0; qciIdx < measCb->val.nonIpThMeas.numQci;qciIdx++)
589       {
590          measCb->val.nonIpThMeas.measData[measCb->val.nonIpThMeas.qci[qciIdx]].actUe.numActvUe   +=   
591                      kwCb.kwL2Cb.numActUe[measCb->val.nonIpThMeas.qci[qciIdx]];
592          measCb->val.nonIpThMeas.measData[measCb->val.nonIpThMeas.qci[qciIdx]].actUe.sampOc++;
593       }
594       measEvtCb->val.nonIpThMeas.measCb.numSamples--;
595       kwStartTmr(gCb, (PTR)measEvtCb, KW_EVT_L2_TMR); 
596       RETVALUE(ROK);
597    }
598 #endif
599
600    kwUtlSndUlL2MeasCfm(gCb, measEvtCb);
601
602    RETVALUE(ROK);
603 } /* kwUtlHdlL2TmrExp */
604 /**
605  *
606  * @brief Handler for Sending L2 Measurement confirm.
607  *
608  *
609  * @b Description
610  *        This function sends a consolidates the mesaurements taken during
611  *        this time and sends the confirm .
612  *
613  *  @param[in] measEvtCb    Measurement Event Control Block.
614  *
615  *
616  *  @return  S16
617  *      -# ROK
618  */
619
620 #ifdef ANSI
621 PUBLIC S16 kwUtlSndUlL2MeasCfm
622 (
623 KwCb                  *gCb,
624 KwL2MeasEvtCb         *measEvtCb
625 )
626 #else
627 PUBLIC S16 kwUtlSndUlL2MeasCfm(gCb, measEvtCb)
628 KwCb                  *gCb;
629 KwL2MeasEvtCb         *measEvtCb;
630 #endif
631 {
632    U32                     qciIdx;
633    KwL2MeasCb              *measCb;
634    KwL2MeasCfmEvt          measCfmEvt;
635
636    U64                     ulDataVol;
637    U64                     ulTime;
638    U16                     cntr;
639    /* Discard new changes starts */
640    U8                      qci = 0;
641    U32                     cfmIdx =0;
642    /* Discard new changes ends */
643
644    TRC3(kwUtlSndUlL2MeasCfm)
645
646    /* kw006.201 ccpu00120058 emoved 64 bit compilation warning */
647 #ifndef ALIGN_64BIT
648    RLOG1(L_DEBUG,"kwUtlSndUlL2MeasCfm(transId(%ld))", measEvtCb->transId);
649 #else
650    RLOG1(L_DEBUG,"kwUtlSndUlL2MeasCfm(transId(%d))", measEvtCb->transId);
651 #endif
652
653    /* Clean up the RB data structures */
654    measCb = &measEvtCb->measCb;
655    
656    cmMemset((U8*)&measCfmEvt, 0, sizeof(KwL2MeasCfmEvt));
657    measCfmEvt.transId = measEvtCb->transId;
658
659    measCfmEvt.measType = measCb->measType;
660    measCfmEvt.status.status = LCM_PRIM_OK;
661    measCfmEvt.status.reason = LCM_REASON_NOT_APPL;
662    
663    if( measCb->measType & LKW_L2MEAS_UL_IP)
664    {
665       KwL2MeasCbUeMeasInfo *pUeInfoLstCb  = measCb->val.ipThMeas.ueInfoLst;
666       KwL2MeasCfmUeInfoLst *pUeInfoLstCfm = measCfmEvt.val.ipThMeas.ueInfoLst;
667       for(cntr = 0;(cntr < measCb->val.ipThMeas.numUes) && (cntr < gCb->genCfg.maxUe);cntr++)        
668       {
669          pUeInfoLstCfm[cfmIdx].numCfm = 0;
670          if (pUeInfoLstCb[cntr].isValid == TRUE)
671          {
672             pUeInfoLstCfm[cfmIdx].ueId = pUeInfoLstCb[cntr].ueId;
673             pUeInfoLstCfm[cfmIdx].cellId = pUeInfoLstCb[cntr].cellId;
674
675             for(qciIdx = 0; qciIdx < pUeInfoLstCb[cntr].numQci; qciIdx++)
676             {
677                qci = pUeInfoLstCb[cntr].qci[qciIdx];
678                pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].qci = qci;
679
680                if(measCb->measType & LKW_L2MEAS_UL_IP)
681                {
682                   ulDataVol = pUeInfoLstCb[cntr].measData[qci].ulIpThruput.volSummation;
683                   ulTime = pUeInfoLstCb[cntr].measData[qci].ulIpThruput.timeSummation;
684                   if(0 == ulTime)
685                   {
686                      pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.ulIpThPut = 0;
687                   }
688                   else
689                   {
690                      pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.ulIpThPut = (ulDataVol / ulTime);
691
692                      /* Converting it to kbps */
693                      pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.ulIpThPut *= 8;
694
695                   }
696                   /* Reset the values after reporting to Application */
697                   pUeInfoLstCb[cntr].measData[qci].ulIpThruput.volSummation = 0;
698                   pUeInfoLstCb[cntr].measData[qci].ulIpThruput.timeSummation = 0;
699                }
700                pUeInfoLstCfm[cfmIdx].numCfm++;
701             }
702             cfmIdx++;
703          }
704       }
705       measCfmEvt.val.ipThMeas.numUes = cfmIdx; 
706    }
707    KwMiLkwL2MeasCfm(&gCb->genCfg.lmPst, &measCfmEvt);
708    RETVALUE(ROK);
709 } /* kwUtlSndUlL2MeasCfm */
710 /**
711  *
712  * @brief Handler for Sending Negative confirm .
713  *
714  *
715   @b Description
716  *        This function is called when the l2 measurement cannot be started
717  *        This function sends  negative confirm for all the requests
718  *
719  * @param[in] gCb - RLC instance control block
720  * @param[in] measReqEvt    Measurement Req Structure
721  * @param[in] measCfmEvt  Confirmation to be sent to layer manager
722  *
723  *
724  *  @return  S16
725  *      -# ROK
726  */
727
728 #ifdef ANSI
729 PUBLIC S16 kwUtlSndUlL2MeasNCfm
730 (
731 KwCb           *gCb,
732 KwL2MeasReqEvt *measReqEvt,
733 KwL2MeasCfmEvt *measCfmEvt
734 )
735 #else
736 PUBLIC S16 kwUtlSndUlL2MeasNCfm(gCb, measReqEvt, measCfmEvt)
737 KwCb           *gCb;
738 KwL2MeasReqEvt *measReqEvt;
739 KwL2MeasCfmEvt *measCfmEvt;
740 #endif
741 {
742    TRC3(kwUtlSndUlL2MeasNCfm)
743
744    KwMiLkwL2MeasCfm(&gCb->genCfg.lmPst, measCfmEvt);
745    RETVALUE(ROK);
746 } /* kwUtlSndL2MeasNCfm */
747
748 #ifdef LTE_L2_MEAS_RLC
749 /**
750  * @brief  Validates the measurement request parameters. 
751  *
752  * @details
753  *
754  *     Function :kwUtlValidateL2Meas 
755  *
756  *  @param[in]  measReqEvt L2 measurement request received from layer manager.
757  *  @param[out] measCfmEvt L2 measurement confirm to be prepared.
758  *  @param[out] lChId      List of LCh for the given Ue corresponding to QCIs
759                            given in measurement request.
760  *  @param[out] numLCh     Number of LCh in array lChId.
761  **/
762
763 #ifdef ANSI
764 PUBLIC S16 kwUtlValidateL2Meas
765 (
766 KwL2MeasReqEvt *measReqEvt,
767 KwL2MeasCfmEvt *measCfmEvt,
768 CmLteLcId      *lChId,
769 U8             *numLCh
770 )
771 #else
772 PUBLIC S16 kwUtlValidateL2Meas(measReqEvt, measCfmEvt, lChId, numLCh)
773 KwL2MeasReqEvt *measReqEvt;
774 KwL2MeasCfmEvt *measCfmEvt;
775 CmLteLcId      *lChId;
776 U8             *numLCh;
777 #endif
778 {
779    U8      measType;
780    S16     ret;
781    U8      qciIdx;
782    U8      qci;
783    U8      idx;
784    U8      *qciVal;
785    U8      numQci;
786    KwRbCb  *rbCb;
787
788    KwUeCb     *ueCb;
789    RbCb       **rbCbLst;
790    U8         rbIdx;
791    U8         lsbNibble = 0;
792    U8         msbNibble = 0;
793    U8         numFaild = 0;
794
795
796    TRC3(kwUtlValidateL2Meas)
797    
798    idx = 0;
799    rbCb = NULLP;
800    ret = ROK;
801    measType = measReqEvt->measReq.measType;
802    /* Check for the range of measType */
803    /* LKW_L2MEAS_DL_IP+ LKW_L2MEAS_UL_IP = 0x0030*/
804    if((measType == 0x00) ||
805        measType > 0x30)
806    {
807       measCfmEvt->transId = measReqEvt->transId;
808       measCfmEvt->measType = measType;
809       measCfmEvt->status.status = LCM_PRIM_NOK;
810       measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
811       RETVALUE(RFAILED);
812    }
813    /*User can either request for Active UE,*
814     *Dl delay, Dl discard, Uu Loss OR Dl ip throughput, Ul ip throughput. */
815    lsbNibble = measType & 0x0F;
816    msbNibble = measType & 0xF0;
817
818    if( (lsbNibble != 0) && (msbNibble != 0) )
819    {
820       measCfmEvt->transId = measReqEvt->transId;
821       measCfmEvt->measType = measType;
822       measCfmEvt->status.status = LCM_PRIM_NOK;
823       measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
824       RETVALUE(RFAILED);
825    }
826
827    /* Check for total maximum number of Measurement Control Block */
828    if(kwCb.kwL2Cb.kwNumMeas >= LKW_MAX_L2MEAS )
829    {
830       measCfmEvt->transId = measReqEvt->transId;
831       measCfmEvt->measType = measType;
832       measCfmEvt->status.status = LCM_PRIM_NOK;
833       measCfmEvt->status.reason = LKW_CAUSE_EXCEED_NUMMEAS;
834       RETVALUE(RFAILED);
835    }
836
837    /* Check that number of samples should be a non-zero value */
838    if(((measType & LKW_L2MEAS_ACT_UE) &&
839       (measReqEvt->measReq.val.nonIpThMeas.numSamples == 0)))
840    {
841       measCfmEvt->transId = measReqEvt->transId;
842       measCfmEvt->measType = measType;
843       measCfmEvt->status.status = LCM_PRIM_NOK;
844       measCfmEvt->status.reason = LKW_CAUSE_ZERO_NUMSAM;
845       RETVALUE(RFAILED);
846    }
847    /* Check that measurement period  should be completely divisible *
848     * number of sample.                                             */
849    if(((measType & LKW_L2MEAS_ACT_UE) &&
850       ((measReqEvt->measPeriod % 
851         measReqEvt->measReq.val.nonIpThMeas.numSamples) != 0)))
852    {
853       measCfmEvt->transId = measReqEvt->transId;
854       measCfmEvt->measType = measType;
855       measCfmEvt->status.status = LCM_PRIM_NOK;
856       measCfmEvt->status.reason = LKW_CAUSE_INVALID_NUMSAM;
857       RETVALUE(RFAILED);
858    }
859    {
860       numQci = measReqEvt->measReq.val.nonIpThMeas.numQci;
861       qciVal = measReqEvt->measReq.val.nonIpThMeas.qci;
862    }
863    /* Check whether qci is configured or not */
864    for(qciIdx = 0; qciIdx < numQci; qciIdx++)
865    {
866       qci = qciVal[qciIdx];
867       ret = cmHashListFind(&(kwCb.kwL2Cb.qciHlCp), 
868             (U8 *)&qci, (U16)sizeof(qci), 0, (PTR *)&rbCb);
869       if(ret != ROK)
870       {
871          measCfmEvt->val.nonIpThMeas.measCfm[measCfmEvt->val.nonIpThMeas.numCfm].qci = qci;
872          measCfmEvt->val.nonIpThMeas.numCfm++;
873
874       }
875    }
876    if(measCfmEvt->val.nonIpThMeas.numCfm > 0)
877    {
878       measCfmEvt->status.status = LCM_PRIM_NOK;
879       measCfmEvt->status.reason = LKW_CAUSE_INVALID_QCI;
880       measCfmEvt->measType = measType;
881       measCfmEvt->transId = measReqEvt->transId;
882       RETVALUE(RFAILED);
883    }
884    {
885       for(qciIdx = 0; qciIdx < numQci; qciIdx++)
886       {
887          if(kwCb.kwL2Cb.measOn[qci] & measReqEvt->measReq.measType)
888          {
889             /* measurement is already ongoing */
890             measCfmEvt->status.status = LCM_PRIM_NOK;
891             measCfmEvt->status.reason = LKW_CAUSE_MEAS_ALREADY_ENA;
892             measCfmEvt->val.nonIpThMeas.measCfm[measCfmEvt->val.nonIpThMeas.numCfm].qci = qci;
893             measCfmEvt->measType = measType;
894             measCfmEvt->val.nonIpThMeas.numCfm++;
895          }
896       }
897    }
898    if(measCfmEvt->val.nonIpThMeas.numCfm > 0)
899    {
900       measCfmEvt->transId = measReqEvt->transId;
901       RETVALUE(RFAILED);
902    }
903
904    RETVALUE(ROK);
905 }/* kwUtlValidateL2Meas */
906 #endif
907
908 #ifdef ANSI
909 PUBLIC S16 kwUtlValidateIpThL2Meas
910 (
911 KwL2MeasReqEvt *measReqEvt,
912 KwL2MeasCfmEvt *measCfmEvt
913 )
914 #else
915 PUBLIC S16 kwUtlValidateIpThL2Meas(measReqEvt, measCfmEvt)
916 KwL2MeasReqEvt *measReqEvt;
917 KwL2MeasCfmEvt *measCfmEvt;
918 #endif
919 {
920    U8      measType;
921    U8         lsbNibble = 0;
922    U8         msbNibble = 0;
923
924    TRC3(kwUtlValidateIpThL2Meas)
925    
926    measType = measReqEvt->measReq.measType;
927    /* Check for the range of measType */
928    /* LKW_L2MEAS_DL_IP+ LKW_L2MEAS_UL_IP = 0x0030*/
929    if((measType == 0x00) ||
930        measType > 0x30)
931    {
932       measCfmEvt->transId = measReqEvt->transId;
933       measCfmEvt->measType = measType;
934       measCfmEvt->status.status = LCM_PRIM_NOK;
935       measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
936       RETVALUE(RFAILED);
937    }
938    /*User can either request for Active UE,*
939     *Dl delay, Dl discard, Uu Loss OR Dl ip throughput, Ul ip throughput. */
940    lsbNibble = measType & 0x0F;
941    msbNibble = measType & 0xF0;
942
943    if( (lsbNibble != 0) && (msbNibble != 0) )
944    {
945       measCfmEvt->transId = measReqEvt->transId;
946       measCfmEvt->measType = measType;
947       measCfmEvt->status.status = LCM_PRIM_NOK;
948       measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
949       RETVALUE(RFAILED);
950    }
951    RETVALUE(ROK);
952 }/* kwUtlValidateL2Meas */
953
954 /**
955  *
956  * @brief Handler for resetting the RB data structures
957  *
958  *
959  * @b Description
960  *        This function resets the RB data structure after the expiry of 
961  *        measurement timer.
962  *
963  *  @param[in] measCb    Measurement Control Block.
964  *
965  *
966  *  @return  Void
967  */
968 #ifdef ANSI
969
970 PUBLIC Void kwUtlResetUlL2MeasInKwRb
971 (
972 KwCb       *gCb,
973 KwL2MeasCb *measCb,
974 U8             measType
975 )
976 #else
977 PUBLIC Void kwUtlResetUlL2MeasInKwRb(measCb, measType)
978 KwCb       *gCb;
979 KwL2MeasCb *measCb;
980 U8             measType;
981 #endif
982 {
983    U32           rbIdx;
984    U32           ueIdx;
985    U32           qciIdx;
986    KwUlUeCb         *ueCb = NULL;
987
988
989
990    if (measCb->measType & LKW_L2MEAS_UL_IP)
991    {
992       for(ueIdx = 0; ueIdx < measCb->val.ipThMeas.numUes; ueIdx++)
993       {           
994          if (measCb->val.ipThMeas.ueInfoLst[ueIdx].isValid == TRUE)
995          {
996             for (qciIdx =0; qciIdx < measCb->val.ipThMeas.ueInfoLst[ueIdx].numQci; qciIdx++)
997             {
998                if (measType & LKW_L2MEAS_UL_IP)
999                {
1000                   measCb->val.ipThMeas.ueInfoLst[ueIdx].measData[qciIdx].ulIpThruput.volSummation = 0;
1001                   measCb->val.ipThMeas.ueInfoLst[ueIdx].measData[qciIdx].ulIpThruput.timeSummation = 0;
1002                }
1003             }
1004
1005             if(ROK  != kwDbmFetchUlUeCb(gCb, measCb->val.ipThMeas.ueInfoLst[ueIdx].ueId,
1006                      measCb->val.ipThMeas.ueInfoLst[ueIdx].cellId, &ueCb))
1007             {
1008                continue;
1009             }
1010
1011             for (rbIdx = 0; rbIdx < KW_MAX_DRB_PER_UE; rbIdx++)
1012             {
1013                if (ueCb->drbCb[rbIdx])
1014                {
1015                   ueCb->drbCb[rbIdx]->rbL2Cb.measOn &= ~measType;
1016                }
1017             }
1018          }
1019       }
1020    }
1021 } /* kwUtlResetUlL2MeasInKwRb */
1022
1023 /**
1024  *
1025  * @brief Handler for storing address of MeasData in rbCb at right index
1026  *
1027  *
1028  * @b Description
1029  *        This function is called when LM sends measReq message to RLC.
1030  *
1031  *  @param[in] 
1032  *  @param[out] 
1033  *  @param[in] 
1034  *
1035  *
1036  *  @return  S16
1037  *      -# ROK
1038  */
1039 #ifdef ANSI
1040 PUBLIC Void kwUtlPlcMeasDatInL2Sts
1041 (
1042 KwL2Cntr       *measData, 
1043 KwL2MeasRbCb   *rbL2Cb,
1044 U8             measType
1045 )
1046 #else
1047 PUBLIC Void kwUtlPlcMeasDatInL2Sts(measData, rbL2Cb, measType)
1048 KwL2Cntr       *measData; 
1049 KwL2MeasRbCb   *rbL2Cb;
1050 U8             measType;
1051 #endif
1052 {
1053    TRC3(kwUtlPlcMeasDatInL2Sts)
1054    
1055    /* We should check the number of measType in the request. This can be done 
1056     * by looking at each bit in the measType. Also store the measData in the 
1057     * correct index of l2Sts in RbCb.
1058     * */
1059
1060     if(measType & LKW_L2MEAS_ACT_UE)
1061     {
1062          rbL2Cb->l2Sts[KW_L2MEAS_ACT_UE] = measData;
1063     }
1064     if(measType & LKW_L2MEAS_UU_LOSS)
1065     {
1066          rbL2Cb->l2Sts[KW_L2MEAS_UU_LOSS] = measData;
1067     }
1068     if(measType & LKW_L2MEAS_DL_IP )
1069     {
1070          rbL2Cb->l2Sts[KW_L2MEAS_DL_IP] = measData;
1071     }
1072     if(measType & LKW_L2MEAS_UL_IP)
1073     {
1074          rbL2Cb->l2Sts[KW_L2MEAS_UL_IP] = measData;
1075     }
1076     if(measType & LKW_L2MEAS_DL_DISC)
1077     {
1078          rbL2Cb->l2Sts[KW_L2MEAS_DL_DISC] = measData;
1079     }
1080     if(measType & LKW_L2MEAS_DL_DELAY)
1081     {
1082          rbL2Cb->l2Sts[KW_L2MEAS_DL_DELAY] = measData;
1083     }
1084 }/* End of kwUtlPlcMeasDatInL2Sts */
1085 #endif /* LTE_L2_MEAS */
1086
1087 /**
1088  *
1089  * @brief Store the UL buffer in hashList  
1090  *
1091  *
1092  * @b Description
1093  *
1094  *   Use the SN % binSize as key and store the received UL buffer
1095  *  @param[in] recBufLst       List CP array
1096  *  @param[in] recBuf          received buffer
1097  *  @param[in] sn              sn of the received buffer 
1098  *
1099  *
1100  *  @return  Void
1101  */
1102 #ifdef ANSI
1103 PUBLIC Void kwUtlStoreRecBuf 
1104 (
1105 CmLListCp        *recBufLst,
1106 KwAmRecBuf       *recBuf,
1107 KwSn              sn
1108 )
1109 #else
1110 PUBLIC Void kwUtlStoreRecBuf(recBufLst, recBuf, sn)
1111 CmLListCp        *recBufLst;
1112 KwAmRecBuf       *recBuf;
1113 KwSn              sn;
1114 #endif
1115 {
1116    U32             hashKey; 
1117
1118    TRC3(kwUtlStoreRecBuf)
1119    
1120    hashKey = (sn % KW_RCV_BUF_BIN_SIZE ); 
1121    recBuf->lnk.node = (PTR)recBuf;
1122    cmLListAdd2Tail(&(recBufLst[hashKey]), &recBuf->lnk);
1123
1124    RETVOID;
1125 } /* kwUtlStoreRecBuf */
1126
1127 /**
1128  *
1129  * @brief Retrieve the UL buffer from the list
1130  *
1131  *
1132  * @Description
1133  *
1134  *   Use the SN % binSize as key and retrieve the UL buffer
1135  *  @param[in] recBufLst       List CP array
1136  *  @param[in] sn              sn of the received buffer 
1137  *
1138  *
1139  *  @return  Void
1140  */
1141 #ifdef ANSI
1142 PUBLIC KwAmRecBuf* kwUtlGetRecBuf 
1143 (
1144 CmLListCp        *recBufLst,
1145 KwSn             sn
1146 )
1147 #else
1148 PUBLIC KwAmRecBuf* kwUtlGetRecBuf(recBufLst, sn)
1149 CmLListCp        *recBufLst;
1150 KwSn             sn;
1151 #endif
1152 {
1153    U32                 hashKey; 
1154    CmLListCp           *recBufLstCp;
1155    KwAmRecBuf          *recBuf;
1156    CmLList             *node = NULLP;
1157
1158    TRC3(kwUtlGetRecBuf)
1159
1160    hashKey = (sn % KW_RCV_BUF_BIN_SIZE ); 
1161  
1162    recBufLstCp = &recBufLst[hashKey];
1163    CM_LLIST_FIRST_NODE(recBufLstCp, node);
1164    while(node)
1165    {
1166       recBuf = (KwAmRecBuf *) node->node;
1167       if(recBuf->amHdr.sn == sn)
1168       {
1169          RETVALUE(recBuf);
1170       }
1171       CM_LLIST_NEXT_NODE(recBufLstCp, node);
1172    }
1173    RETVALUE(NULLP);
1174 } /* kwUtlStoreRecBuf */
1175 /**
1176  *
1177  * @brief Delete the UL buffer from the list
1178  *
1179  *
1180  * @Description
1181  *
1182  *   Use the SN % binSize as key and retrieve the UL buffer
1183  *  @param[in] recBufLst       List CP array
1184  *  @param[in] sn              sn of the received buffer 
1185  *
1186  *
1187  *  @return  Void
1188  */
1189 #ifdef ANSI
1190 PUBLIC Void kwUtlDelRecBuf 
1191 (
1192 CmLListCp        *recBufLst,
1193 KwAmRecBuf       *recBuf,
1194 KwCb              *gCb                              
1195 )
1196 #else
1197 PUBLIC Void kwUtlDelRecBuf(recBufLst, recBufi, gCb)
1198 CmLListCp        *recBufLst;
1199 KwAmRecBuf       *recBuf;
1200 KwCb             *gCb;                              
1201 #endif
1202 {
1203    U32                 hashKey; 
1204    CmLListCp           *recBufLstCp;
1205
1206    TRC3(kwUtlDelRecBuf)
1207
1208    hashKey = (recBuf->amHdr.sn % KW_RCV_BUF_BIN_SIZE ); 
1209  
1210    recBufLstCp = &recBufLst[hashKey];
1211    cmLListDelFrm(recBufLstCp, &recBuf->lnk);
1212    KW_FREE_WC(gCb, recBuf, sizeof(KwAmRecBuf));
1213
1214    RETVOID;
1215 } /* kwUtlDelRecBuf */
1216
1217
1218
1219
1220 /********************************************************************30**
1221          End of file
1222 **********************************************************************/