[Epic-ID: ODUHIGH-510][Task-ID: ODUHIGH-511] E2AP version upgrade from V2.00 to V3.00
[o-du/l2.git] / src / 5gnrrlc / rlc_tmr.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**
20   
21         Name:    RLC - TMR module file
22     
23         Type:    C source file
24   
25         Desc:    Source code for timer functions such as, 
26
27                  - rlcStartTmr
28                  - rlcStopTmr
29                  - rlcTmrExpiry
30                  - rlcBndTmrExpiry  
31                   
32         File:    rlc_tmr.c
33   
34 *********************************************************************21*/
35
36 /* header (.h) include files */
37 #include "common_def.h"
38 #include "lkw.h"           /* LKW defines */
39 #include "ckw.h"           /* CKW defines */
40 #include "kwu.h"           /* KWU defines */
41 #include "rgu.h"           /* RGU defines */
42 #include "rlc_env.h"        /* RLC environment options */
43 #include "rlc_err.h"        /* Error defines */
44
45 /* extern (.x) include files */
46 #include "lkw.x"           /* LKW */
47 #include "ckw.x"           /* CKW */
48 #include "kwu.x"           /* KWU */
49 #include "rgu.x"           /* RGU */
50
51 #include "du_app_rlc_inf.h"
52 #include "rlc_utils.h"            /* RLC defines */
53 #include "rlc_dl_ul_inf.h"
54 #include "rlc_dl.h"
55 #include "rlc_ul.h"
56 #include "rlc_mgr.h"
57
58 /** 
59  * @file gp_tmr.c
60  * @brief RLC Timer Module
61 */
62
63 /**
64  * @def RLC_TMR_CALCUATE_WAIT
65  *
66  *    This macro calculates and assigns wait time based on the value of the 
67  *    timer and the timer resolution. Timer value of 0 signifies that the
68  *    timer is not configured
69  *
70  * @param[out] _wait   Time for which to arm the timer changed to proper 
71  *                     value according to the resolution
72  * @param[in] _tmrVal   Value of the timer
73  * @param[in] _timerRes   Resolution of the timer
74  *
75 */
76 #define RLC_TMR_CALCUATE_WAIT(_wait, _tmrVal, _timerRes)       \
77 {                                                             \
78    (_wait) = ((_tmrVal) * SS_TICKS_SEC)/((_timerRes) * 1000); \
79    if((0 != (_tmrVal)) && (0 == (_wait)))                     \
80    {                                                          \
81       (_wait) = 1;                                            \
82    }                                                          \
83 }
84
85 /* private function declarations */
86 static Void rlcBndTmrExpiry(PTR cb);
87
88
89 /**
90  * @brief Handler to start timer
91  *       
92  * @param[in] gCb       Pointer to the RLC instance control block
93  * @param[in] cb        Control block depending on the type of the timer event. 
94  *                      It can be uplink/downlink rbCb or rgu sap control block
95  * @param[in] tmrEvnt   Timer event to be started
96  *
97  * @return  Void
98 */
99 void rlcStartTmr(RlcCb *gCb, PTR cb, int16_t tmrEvnt)
100 {
101 /* kw005.201 added support for L2 Measurement */
102 #ifdef LTE_L2_MEAS
103    RlcL2MeasEvtCb *measEvtCb = NULLP;
104 #endif
105
106    CmTmrArg arg;
107    arg.wait = 0;
108
109    /* kw002.201 Adjusting the wait time as per timeRes configured by layer manager */
110    switch (tmrEvnt)
111    {
112       case EVENT_RLC_UMUL_REASSEMBLE_TMR:
113       {
114          RlcUmUl* umUl = &(((RlcUlRbCb *)cb)->m.umUl);
115          /* kw005.201 Changed wait calculation ccpu00117634*/ 
116          RLC_TMR_CALCUATE_WAIT(arg.wait, umUl->reAsmblTmrInt, gCb->genCfg.timeRes);
117
118          arg.timers = &umUl->reAsmblTmr;
119          arg.max = RLC_MAX_UM_TMR;
120          break;
121       }
122       case EVENT_RLC_AMUL_REASSEMBLE_TMR:
123       {
124          RlcAmUl* amUl = &(((RlcUlRbCb *)cb)->m.amUl);
125          /* kw005.201 Changed wait calculation ccpu00117634*/ 
126          RLC_TMR_CALCUATE_WAIT(arg.wait, amUl->reAsmblTmrInt, gCb->genCfg.timeRes);         
127
128          arg.timers = &amUl->reAsmblTmr;
129          arg.max = RLC_MAX_AM_TMR;
130          break;
131       }
132       case EVENT_RLC_AMUL_STA_PROH_TMR:
133       {
134          RlcAmUl* amUl = &(((RlcUlRbCb *)cb)->m.amUl);
135          /* kw005.201 Changed wait calculation ccpu00117634*/ 
136          RLC_TMR_CALCUATE_WAIT(arg.wait,
137                               amUl->staProhTmrInt,
138                               gCb->genCfg.timeRes);                  
139
140          arg.timers = &amUl->staProhTmr;
141          arg.max = RLC_MAX_AM_TMR;
142          break;
143       } 
144       case EVENT_RLC_AMDL_POLL_RETX_TMR:
145       {
146          RlcAmDl* amDl = &(((RlcDlRbCb *)cb)->m.amDl);
147          /* kw005.201 Changed wait calculation ccpu00117634*/ 
148          RLC_TMR_CALCUATE_WAIT(arg.wait, 
149                               amDl->pollRetxTmrInt, 
150                               gCb->genCfg.timeRes);                  
151
152          arg.timers = &amDl->pollRetxTmr;
153          arg.max = RLC_MAX_AM_TMR;
154          break;
155       } 
156       case EVENT_RLC_WAIT_BNDCFM:
157       {
158          RlcRguSapCb* rguSap = (RlcRguSapCb *)cb;
159          /* kw005.201 Changed wait calculation ccpu00117634*/ 
160          RLC_TMR_CALCUATE_WAIT(arg.wait, rguSap->bndTmrInt, gCb->genCfg.timeRes);                  
161
162          arg.timers = &rguSap->bndTmr;
163          arg.max = RLC_MAX_RGUSAP_TMR;
164          break;
165       }
166 /* kw005.201 added support for L2 Measurement */
167 #ifdef LTE_L2_MEAS
168       case EVENT_RLC_L2_TMR:
169       {
170          measEvtCb = (RlcL2MeasEvtCb *)cb;
171          /* kw005.201 Changed wait calculation ccpu00117634*/ 
172          RLC_TMR_CALCUATE_WAIT(arg.wait, 
173                               measEvtCb->l2TmrCfg.val, 
174                               gCb->genCfg.timeRes);                  
175
176          arg.timers = &measEvtCb->l2Tmr;
177          arg.max = RLC_L2_MAX_TIMERS;
178          break;
179       }
180 #endif
181       case EVENT_RLC_UE_THROUGHPUT_TMR:
182       {
183          RlcThpt *thptCb = (RlcThpt *)cb;
184          RLC_TMR_CALCUATE_WAIT(arg.wait, ODU_UE_THROUGHPUT_PRINT_TIME_INTERVAL, gCb->genCfg.timeRes);
185          arg.timers = &thptCb->ueTputInfo.ueThptTmr;
186          arg.max = RLC_MAX_THPT_TMR; 
187          break;
188       }
189       case EVENT_RLC_UE_DELETE_TMR:
190       {
191          RlcUlUeCb *ulUeCb = (RlcUlUeCb*)cb;
192          RLC_TMR_CALCUATE_WAIT(arg.wait, RLC_UE_DELETE_WAIT_TIME, gCb->genCfg.timeRes);
193          arg.timers = &ulUeCb->ueDeleteInfo.ueDelTmr;
194          arg.max = RLC_MAX_UE_TMR;
195          break;
196       }
197       case EVENT_RLC_SNSSAI_THROUGHPUT_TMR:
198       {
199          RlcThpt *thptCb = (RlcThpt *)cb;
200          RLC_TMR_CALCUATE_WAIT(arg.wait, ODU_SNSSAI_THROUGHPUT_PRINT_TIME_INTERVAL, gCb->genCfg.timeRes);
201          arg.timers = &thptCb->snssaiTputInfo.snssaiThptTmr;
202          arg.max = RLC_MAX_THPT_TMR; 
203          break;
204       }
205       default:
206       {
207          DU_LOG("\nERROR  -->  RLC : rlcStartTmr: Invalid tmr Evnt [%d]", tmrEvnt);
208       }
209    } 
210
211    if(arg.wait != 0)
212    {
213       arg.tqCp   = &gCb->rlcTqCp;
214       arg.tq     = gCb->rlcTq;
215       arg.cb     = cb;
216       arg.evnt   = tmrEvnt;
217       arg.tNum   = 0;
218
219       cmPlcCbTq(&arg);
220    }
221
222    return;
223 }
224
225 /**
226  * @brief Handler to stop a timer
227  *       
228  * @param[in] gCb       Pointer to the RLC instance control block
229  * @param[in] cb        Control block depending on the type of the timer event. 
230  *                      It can be uplink/downlink rbCb or rgu sap control block
231  * @param[in] tmrType   Timer event to be started
232  *
233  * @return  Void
234 */
235 void rlcStopTmr(RlcCb *gCb, PTR cb, uint8_t tmrType)
236 {
237    CmTmrArg   arg;
238 /* kw005.201 added support for L2 Measurement */
239 #ifdef LTE_L2_MEAS
240    RlcL2MeasEvtCb *measEvtCb = NULLP;
241 #endif
242
243    arg.timers = NULLP;
244
245    switch (tmrType)
246    {
247       case EVENT_RLC_UMUL_REASSEMBLE_TMR:
248       {
249          arg.timers  = &((RlcUlRbCb *)cb)->m.umUl.reAsmblTmr;
250          arg.max = RLC_MAX_UM_TMR;
251          break;
252       }
253       case EVENT_RLC_AMUL_REASSEMBLE_TMR:
254       {
255          arg.timers = &((RlcUlRbCb *)cb)->m.amUl.reAsmblTmr;
256          arg.max = RLC_MAX_AM_TMR;
257          break;
258       }
259       case EVENT_RLC_AMUL_STA_PROH_TMR:
260       {
261          arg.timers = &((RlcUlRbCb *)cb)->m.amUl.staProhTmr;
262          arg.max = RLC_MAX_AM_TMR;
263          break;
264       } 
265       case EVENT_RLC_AMDL_POLL_RETX_TMR:
266       {
267          arg.timers = &((RlcDlRbCb *)cb)->m.amDl.pollRetxTmr;
268          arg.max = RLC_MAX_AM_TMR;
269          break;
270       } 
271       case EVENT_RLC_WAIT_BNDCFM:
272       {
273          arg.timers = &((RlcRguSapCb *)cb)->bndTmr;
274          arg.max = RLC_MAX_RGUSAP_TMR;
275          break;
276       }
277 /* kw005.201 added support for L2 Measurement */
278 #ifdef LTE_L2_MEAS
279       case EVENT_RLC_L2_TMR:
280       {
281          measEvtCb = (RlcL2MeasEvtCb *)cb;
282          arg.timers   = &measEvtCb->l2Tmr;
283          arg.max  = RLC_L2_MAX_TIMERS;
284          break;
285       }
286 #endif
287       case EVENT_RLC_UE_THROUGHPUT_TMR:
288       {
289          arg.timers   = &((RlcThpt *)cb)->ueTputInfo.ueThptTmr;
290          arg.max  = RLC_MAX_THPT_TMR;
291          break;
292       }
293       case EVENT_RLC_UE_DELETE_TMR:
294       {
295          arg.timers   = &((RlcUlUeCb*)cb)->ueDeleteInfo.ueDelTmr;
296          arg.max  = EVENT_RLC_UE_DELETE_TMR;
297          break;
298       }
299       case EVENT_RLC_SNSSAI_THROUGHPUT_TMR:
300       {
301          arg.timers   = &((RlcThpt *)cb)->snssaiTputInfo.snssaiThptTmr;
302          arg.max  = RLC_MAX_THPT_TMR;
303          break;
304       }
305       default:
306       {
307          DU_LOG("\nERROR  -->  RLC : rlcStopTmr: Invalid tmr Evnt[%d]", tmrType);
308          break;
309       }
310    } 
311    if (tmrType != TMR0)
312    {
313       arg.tqCp   = &gCb->rlcTqCp;
314       arg.tq     = gCb->rlcTq;
315       arg.cb     = cb;
316       arg.evnt   = tmrType;
317       arg.wait   = 0;
318       arg.tNum   = 0;
319       cmRmvCbTq(&arg);
320    }
321    
322    return;
323 }
324
325 /**
326  * @brief Handler to invoke events on expiry of timer.
327  *
328  * @details
329  *    This function is used to handle expiry of timer,it invokes relevant 
330  *    functions.
331  *       
332  * @param[in] cb        Control block depending on the type of the timer event. 
333  *                      It can be uplink/downlink rbCb or rgu sap control block
334  * @param[in] tmrEvnt   Timer event to be started
335  *
336  * @return  Void
337 */
338 Void rlcTmrExpiry(PTR cb,S16 tmrEvnt)
339 {
340 /* kw005.201 added support for L2 Measurement */
341
342    switch (tmrEvnt)
343    {
344       case EVENT_RLC_UMUL_REASSEMBLE_TMR:
345       {
346          RlcUlRbCb *ulRbCb = (RlcUlRbCb *)cb;
347          rlcUmmReAsmblTmrExp(RLC_GET_RLCCB(ulRbCb->inst), ulRbCb);
348
349          break;
350       }
351       case EVENT_RLC_AMUL_REASSEMBLE_TMR:
352       {
353          RlcUlRbCb *ulRbCb = (RlcUlRbCb *)cb;
354          rlcAmmReAsmblTmrExp(RLC_GET_RLCCB(ulRbCb->inst), ulRbCb);
355          break;
356       }
357       case EVENT_RLC_AMUL_STA_PROH_TMR:
358       {
359          RlcUlRbCb *ulRbCb = (RlcUlRbCb *)cb;
360          rlcAmmStaProTmrExp(RLC_GET_RLCCB(ulRbCb->inst), ulRbCb);
361
362          break;
363       }
364       case EVENT_RLC_AMDL_POLL_RETX_TMR:
365       {
366          RlcDlRbCb *dlRbCb = (RlcDlRbCb *)cb;
367          RlcCb *gCb = RLC_GET_RLCCB(dlRbCb->inst);
368          
369          rlcAmmPollRetxTmrExp(gCb, dlRbCb);
370
371          gCb->genSts.protTimeOut++;
372          break;
373       }
374       case EVENT_RLC_WAIT_BNDCFM:
375       {
376          rlcBndTmrExpiry(cb);
377          break;
378       }
379       case EVENT_RLC_UE_THROUGHPUT_TMR:
380       {
381          rlcUeThptTmrExpiry(cb);
382          break;
383       }
384       case EVENT_RLC_UE_DELETE_TMR:
385       {
386          rlcUeDeleteTmrExpiry(cb);
387          break;
388       }
389       case EVENT_RLC_SNSSAI_THROUGHPUT_TMR:
390       {
391          rlcSnssaiThptTmrExpiry(cb);
392          break;
393       }
394       default:
395       {
396          break;
397       }
398    }
399
400    return;
401 }
402
403 /**
404  * @brief Handler to check if the timer is running
405  *       
406  * @param[in] gCb       Pointer to the RLC instance control block
407  * @param[in] cb        Control block depending on the type of the timer event. 
408  *                      It can be uplink/downlink rbCb or rgu sap control block
409  * @param[in] tmrEvnt   Timer event to be started
410  *
411  * @return  Bool indicating whether the timer is running or not
412  *      -# ROK 
413  *      -# RFAILED 
414 */
415 bool rlcChkTmr(RlcCb *gCb, PTR cb, int16_t tmrEvnt)
416 {
417    switch (tmrEvnt)
418    {
419       case EVENT_RLC_UMUL_REASSEMBLE_TMR:
420       {
421          return (((RlcUlRbCb *)cb)->m.umUl.reAsmblTmr.tmrEvnt == 
422                   EVENT_RLC_UMUL_REASSEMBLE_TMR);
423       }
424       case EVENT_RLC_AMUL_REASSEMBLE_TMR:
425       {
426          return (((RlcUlRbCb *)cb)->m.amUl.reAsmblTmr.tmrEvnt == 
427                   EVENT_RLC_AMUL_REASSEMBLE_TMR);
428       }
429       case EVENT_RLC_AMUL_STA_PROH_TMR:
430       {
431          return (((RlcUlRbCb *)cb)->m.amUl.staProhTmr.tmrEvnt == 
432                   EVENT_RLC_AMUL_STA_PROH_TMR);
433       } 
434       case EVENT_RLC_AMDL_POLL_RETX_TMR:
435       {
436          return (((RlcDlRbCb *)cb)->m.amDl.pollRetxTmr.tmrEvnt == 
437                   EVENT_RLC_AMDL_POLL_RETX_TMR);
438       } 
439       case EVENT_RLC_WAIT_BNDCFM:
440       {
441          return (((RlcRguSapCb *)cb)->bndTmr.tmrEvnt == EVENT_RLC_WAIT_BNDCFM);
442       }
443       case EVENT_RLC_UE_THROUGHPUT_TMR:
444       {
445          return (((RlcThpt *)cb)->ueTputInfo.ueThptTmr.tmrEvnt == EVENT_RLC_UE_THROUGHPUT_TMR);
446       }
447       case EVENT_RLC_UE_DELETE_TMR:
448       {
449          return (((RlcUlUeCb *)cb)->ueDeleteInfo.ueDelTmr.tmrEvnt == EVENT_RLC_UE_DELETE_TMR);
450       }
451       case EVENT_RLC_SNSSAI_THROUGHPUT_TMR:
452       {
453          return (((RlcThpt *)cb)->snssaiTputInfo.snssaiThptTmr.tmrEvnt == EVENT_RLC_SNSSAI_THROUGHPUT_TMR);
454       }
455       default:
456       {
457          DU_LOG("\nERROR  -->  RLC : rlcChkTmr: Invalid tmr Evnt [%d]", tmrEvnt);
458       }
459    } 
460
461    return FALSE;
462 }
463
464 /**
465  * @brief Handler to do processing on expiry of the bind timer
466  *
467  * @details
468  *    This function processes the RLC bind timer expiry. If the number of
469  *    retries is less than the maximum retry counter, bind request is sent
470  *    again, else an alarm is raised to the layer manager.
471  *
472  * @param[in] cb  Pointer to the Rgu sap
473  *
474  * @return  Void
475 */
476 static Void rlcBndTmrExpiry(PTR cb)
477 {
478    RlcRguSapCb *rguSapCb;
479
480    rguSapCb = (RlcRguSapCb *) cb;
481
482    if (rguSapCb->state == RLC_SAP_BINDING)
483    {
484       if (rguSapCb->retryCnt < RLC_MAX_SAP_BND_RETRY)
485       {
486          /* start timer to wait for bind confirm */
487          rlcStartTmr(RLC_GET_RLCCB(rguSapCb->pst.srcInst),
488                     (PTR)rguSapCb,
489                     EVENT_RLC_WAIT_BNDCFM);
490
491          /* Send bind request */
492          rguSapCb->retryCnt++;
493          RlcLiRguBndReq (&rguSapCb->pst, rguSapCb->suId, rguSapCb->spId);
494       }
495       else
496       {
497          rguSapCb->retryCnt = 0;
498          rguSapCb->state = RLC_SAP_CFG;
499
500          /* Send alarm to the layer manager */
501 #ifdef LTE_L2_MEAS
502          rlcLmmSendAlarm(RLC_GET_RLCCB(rguSapCb->pst.srcInst),
503                         LCM_CATEGORY_INTERFACE,
504                         LCM_EVENT_BND_FAIL,
505                         LCM_CAUSE_TMR_EXPIRED,
506                         0,
507                         0,
508                         0);
509 #else
510          rlcLmmSendAlarm(RLC_GET_RLCCB(rguSapCb->pst.srcInst),
511                         LCM_CATEGORY_INTERFACE,
512                         LCM_EVENT_BND_FAIL,
513                         LCM_CAUSE_TMR_EXPIRED,
514                         0, /* suId */
515                         0 /* ueId */);
516 #endif
517       }
518    }
519
520    return;
521 }
522
523 /**
524  * @brief Handler to do processing on expiry of UE throughput timer
525  *
526  * @details
527  *    This function processes the RLC UE throughput timer expiry.
528  *
529  * @param[in] cb  Pointer to the RLC throughput struct
530  *
531  * @return  Void
532  */
533 void rlcUeThptTmrExpiry(PTR cb)
534 {
535    uint16_t  ueIdx;
536    long double tpt;
537    RlcThpt *rlcThptCb = (RlcThpt*)cb; 
538    
539    /* If cell is not up, throughput details cannot be printed */
540    if(gCellStatus != CELL_UP)
541    {
542       /* Restart timer */
543       rlcStartTmr(RLC_GET_RLCCB(rlcThptCb->inst), (PTR)(rlcThptCb), EVENT_RLC_UE_THROUGHPUT_TMR);
544       return;
545    }
546
547    /* If cell is up, print throughout for each UE attached to the cell */
548    DU_LOG("\n===================== DL Throughput Per UE==============================");
549    DU_LOG("\nNumber of UEs : %d", rlcThptCb->ueTputInfo.numActvUe);
550    if(rlcThptCb->ueTputInfo.numActvUe)
551    {
552       for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++)
553       {
554          if(rlcThptCb->ueTputInfo.thptPerUe[ueIdx].ueId)
555          {
556             /* Spec 28.552, section 5.1.1.3 : 
557              * Throughput in kilobits/sec = (dataVol in kiloBits * 1000)/time in milligseconds
558              * 
559              * Since our dataVol is in bytes, multiplying 0.008 to covert into kilobits i.e. 
560              * Throughput[kbits/sec] = (dataVol * 0.008 * 1000)/time in ms
561              */
562              tpt = (double)(rlcThptCb->ueTputInfo.thptPerUe[ueIdx].dataVol * 8)/(double)ODU_UE_THROUGHPUT_PRINT_TIME_INTERVAL;
563       
564              DU_LOG("\nUE Id : %d   DL Tpt : %.2Lf", rlcThptCb->ueTputInfo.thptPerUe[ueIdx].ueId, tpt);
565              rlcThptCb->ueTputInfo.thptPerUe[ueIdx].dataVol = 0;
566          }
567       }
568    }
569    DU_LOG("\n==================================================================");
570
571    /* Restart timer */
572    rlcStartTmr(RLC_GET_RLCCB(rlcThptCb->inst), (PTR)rlcThptCb, EVENT_RLC_UE_THROUGHPUT_TMR);
573
574    return;
575 }
576
577 /**
578  * @brief Handler to do processing on expiry of the SNSSAI throughput timer
579  *
580  * @details
581  *    This function processes the RLC SNSSAI throughput timer expiry.
582  *
583  * @param[in] cb  Pointer to the RLC throughput struct
584  *
585  * @return  Void
586  */
587 void rlcSnssaiThptTmrExpiry(PTR cb)
588 {
589    RlcThpt *rlcThptCb = (RlcThpt*)cb; 
590    
591    static uint8_t snssaiCntDl = 0, snssaiCntUl = 0;
592    /*Bit map to keep record of reception of DL and UL Snssai Tput expiry*/
593    static uint8_t snssaiTputBitmap = DIR_NONE;
594
595    /* If cell is not up, throughput details cannot be printed */
596    if(gCellStatus != CELL_UP)
597    {
598       /* Restart timer */
599       rlcStartTmr(RLC_GET_RLCCB(rlcThptCb->inst), (PTR)(rlcThptCb), EVENT_RLC_SNSSAI_THROUGHPUT_TMR);
600       return;
601    }
602    
603    if(rlcThptCb->snssaiTputInfo.dlTputPerSnssaiList != NULLP)
604    {
605       snssaiCntDl = rlcCalculateTputPerSnssai(rlcThptCb->snssaiTputInfo.dlTputPerSnssaiList, DIR_DL);
606       snssaiTputBitmap |= DIR_DL;
607       arrTputPerSnssai[DIR_DL] = rlcThptCb->snssaiTputInfo.dlTputPerSnssaiList;
608    }
609    if(rlcThptCb->snssaiTputInfo.ulTputPerSnssaiList != NULLP)
610    {
611       snssaiCntUl = rlcCalculateTputPerSnssai(rlcThptCb->snssaiTputInfo.ulTputPerSnssaiList, DIR_UL);
612       snssaiTputBitmap |= DIR_UL;
613       arrTputPerSnssai[DIR_UL] = rlcThptCb->snssaiTputInfo.ulTputPerSnssaiList;
614    }
615    if(snssaiTputBitmap == DIR_BOTH)
616    {
617       //call the function
618       BuildSliceReportToDu(MAX(snssaiCntUl, snssaiCntDl));
619       snssaiTputBitmap = DIR_NONE;
620    }
621    /* Restart timer */
622    rlcStartTmr(RLC_GET_RLCCB(rlcThptCb->inst), (PTR)rlcThptCb, EVENT_RLC_SNSSAI_THROUGHPUT_TMR);
623    return;
624 }
625 /**
626 *
627 * @brief filling RLC UE delete configuration
628 *
629 * @details
630 *    filling RLC UE delete configuration
631 *
632 * @params[in] RlcUlUeCb *ueCb, RlcCfgInfo *rlcUeCfg
633 *
634 * @return void
635 *
636 */
637
638 void fillRlcUeDelInfo(RlcUlUeCb *ueCb, RlcCfgInfo *rlcUeCfg)
639 {
640    uint8_t lcIdx;
641
642    rlcUeCfg->ueId    = ueCb->ueId;
643    rlcUeCfg->cellId  = ueCb->cellId;
644    rlcUeCfg->numEnt = 0;
645    for(lcIdx=0; lcIdx<RLC_MAX_LCH_PER_UE && rlcUeCfg->numEnt < 1; lcIdx++)
646    {
647       if(ueCb->lCh[lcIdx].ulRbCb != NULLP)
648       {
649          rlcUeCfg->entCfg[rlcUeCfg->numEnt].rbId    = 0;
650          rlcUeCfg->entCfg[rlcUeCfg->numEnt].rbType  = 0;
651          rlcUeCfg->entCfg[rlcUeCfg->numEnt].cfgType = CKW_CFG_DELETE_UE;
652          rlcUeCfg->numEnt++;
653       }
654    }
655 }
656
657 /**
658 * @brief Handler to do processing on expiry of the UE delete timer
659 *
660 * @details
661 *    This function processes the RLC UE delete timer expiry.
662 *
663 * @param[in] cb  Pointer to the RlcUlUeCb  
664 *
665 * @return  uint8_t
666 */
667
668 uint8_t rlcUeDeleteTmrExpiry(PTR cb)
669 {
670    RlcCb *gRlcCb = NULLP;
671    RlcCfgInfo *rlcUeCfg = NULLP;
672    RlcUlUeCb *ueCb = (RlcUlUeCb*)cb;
673
674    gRlcCb = RLC_GET_RLCCB(ueCb->ueDeleteInfo.pst.dstInst);
675    RLC_ALLOC(gRlcCb, rlcUeCfg, sizeof(RlcCfgInfo));
676    if(rlcUeCfg == NULLP)
677    {
678       DU_LOG("\nERROR  -->  RLC: rlcUeDeleteTmrExpiry(): Failed to allocate memory");
679       return RFAILED;
680    }
681    memset(rlcUeCfg, 0, sizeof(RlcCfgInfo));
682    fillRlcUeDelInfo(ueCb, rlcUeCfg);
683    if(RlcProcCfgReq(&ueCb->ueDeleteInfo.pst, rlcUeCfg) != ROK)
684    {
685       DU_LOG("\nERROR  -->  RLC: rlcUeDeleteTmrExpiry(): Failed to delete UE");
686       if(sendRlcUeDeleteRspToDu(rlcUeCfg->cellId, rlcUeCfg->ueId, UEID_INVALID) != ROK)
687       {
688          DU_LOG("ERROR  --> RLC: rlcUeDeleteTmrExpiry(): Failed to send UE delete response ");
689          return RFAILED;
690       }
691    }
692    return ROK;
693 }
694 \f  
695 /********************************************************************30**
696   
697          End of file
698 **********************************************************************/