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