[JIRA ID:ODUHIGH-331]-Renaming of RLC files
[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 "rlc_utils.h"            /* RLC defines */
52 #include "rlc_dl_ul_inf.h"
53 #include "rlc_dl.h"
54 #include "rlc_ul.h"
55 /** 
56  * @file gp_tmr.c
57  * @brief RLC Timer Module
58 */
59
60 /**
61  * @def RLC_TMR_CALCUATE_WAIT
62  *
63  *    This macro calculates and assigns wait time based on the value of the 
64  *    timer and the timer resolution. Timer value of 0 signifies that the
65  *    timer is not configured
66  *
67  * @param[out] _wait   Time for which to arm the timer changed to proper 
68  *                     value according to the resolution
69  * @param[in] _tmrVal   Value of the timer
70  * @param[in] _timerRes   Resolution of the timer
71  *
72 */
73 #define RLC_TMR_CALCUATE_WAIT(_wait, _tmrVal, _timerRes)       \
74 {                                                             \
75    (_wait) = ((_tmrVal) * SS_TICKS_SEC)/((_timerRes) * 1000); \
76    if((0 != (_tmrVal)) && (0 == (_wait)))                     \
77    {                                                          \
78       (_wait) = 1;                                            \
79    }                                                          \
80 }
81
82 /* private function declarations */
83 static Void rlcBndTmrExpiry(PTR cb);
84 void rlcThptTmrExpiry(PTR cb);
85
86 /**
87  * @brief Handler to start timer
88  *       
89  * @param[in] gCb       Pointer to the RLC instance control block
90  * @param[in] cb        Control block depending on the type of the timer event. 
91  *                      It can be uplink/downlink rbCb or rgu sap control block
92  * @param[in] tmrEvnt   Timer event to be started
93  *
94  * @return  Void
95 */
96 void rlcStartTmr(RlcCb *gCb, PTR cb, int16_t tmrEvnt)
97 {
98 /* kw005.201 added support for L2 Measurement */
99 #ifdef LTE_L2_MEAS
100    RlcL2MeasEvtCb *measEvtCb = NULLP;
101 #endif
102
103    CmTmrArg arg;
104    arg.wait = 0;
105
106    /* kw002.201 Adjusting the wait time as per timeRes configured by layer manager */
107    switch (tmrEvnt)
108    {
109       case EVENT_RLC_UMUL_REASSEMBLE_TMR:
110       {
111          RlcUmUl* umUl = &(((RlcUlRbCb *)cb)->m.umUl);
112          /* kw005.201 Changed wait calculation ccpu00117634*/ 
113          RLC_TMR_CALCUATE_WAIT(arg.wait, umUl->reAsmblTmrInt, gCb->genCfg.timeRes);
114
115          arg.timers = &umUl->reAsmblTmr;
116          arg.max = RLC_MAX_UM_TMR;
117          break;
118       }
119       case EVENT_RLC_AMUL_REASSEMBLE_TMR:
120       {
121          RlcAmUl* amUl = &(((RlcUlRbCb *)cb)->m.amUl);
122          /* kw005.201 Changed wait calculation ccpu00117634*/ 
123          RLC_TMR_CALCUATE_WAIT(arg.wait, amUl->reAsmblTmrInt, gCb->genCfg.timeRes);         
124
125          arg.timers = &amUl->reAsmblTmr;
126          arg.max = RLC_MAX_AM_TMR;
127          break;
128       }
129       case EVENT_RLC_AMUL_STA_PROH_TMR:
130       {
131          RlcAmUl* amUl = &(((RlcUlRbCb *)cb)->m.amUl);
132          /* kw005.201 Changed wait calculation ccpu00117634*/ 
133          RLC_TMR_CALCUATE_WAIT(arg.wait,
134                               amUl->staProhTmrInt,
135                               gCb->genCfg.timeRes);                  
136
137          arg.timers = &amUl->staProhTmr;
138          arg.max = RLC_MAX_AM_TMR;
139          break;
140       } 
141       case EVENT_RLC_AMDL_POLL_RETX_TMR:
142       {
143          RlcAmDl* amDl = &(((RlcDlRbCb *)cb)->m.amDl);
144          /* kw005.201 Changed wait calculation ccpu00117634*/ 
145          RLC_TMR_CALCUATE_WAIT(arg.wait, 
146                               amDl->pollRetxTmrInt, 
147                               gCb->genCfg.timeRes);                  
148
149          arg.timers = &amDl->pollRetxTmr;
150          arg.max = RLC_MAX_AM_TMR;
151          break;
152       } 
153       case EVENT_RLC_WAIT_BNDCFM:
154       {
155          RlcRguSapCb* rguSap = (RlcRguSapCb *)cb;
156          /* kw005.201 Changed wait calculation ccpu00117634*/ 
157          RLC_TMR_CALCUATE_WAIT(arg.wait, rguSap->bndTmrInt, gCb->genCfg.timeRes);                  
158
159          arg.timers = &rguSap->bndTmr;
160          arg.max = RLC_MAX_RGUSAP_TMR;
161          break;
162       }
163 /* kw005.201 added support for L2 Measurement */
164 #ifdef LTE_L2_MEAS
165       case EVENT_RLC_L2_TMR:
166       {
167          measEvtCb = (RlcL2MeasEvtCb *)cb;
168          /* kw005.201 Changed wait calculation ccpu00117634*/ 
169          RLC_TMR_CALCUATE_WAIT(arg.wait, 
170                               measEvtCb->l2TmrCfg.val, 
171                               gCb->genCfg.timeRes);                  
172
173          arg.timers = &measEvtCb->l2Tmr;
174          arg.max = RLC_L2_MAX_TIMERS;
175          break;
176       }
177 #endif
178       case EVENT_RLC_THROUGHPUT_TMR:
179       {
180          RlcThpt *thptCb = (RlcThpt *)cb;
181          RLC_TMR_CALCUATE_WAIT(arg.wait, ODU_THROUGHPUT_PRINT_TIME_INTERVAL, gCb->genCfg.timeRes);
182          arg.timers = &thptCb->thptTmr;
183          arg.max = RLC_MAX_THPT_TMR; 
184          break;
185       }
186       default:
187       {
188          DU_LOG("\nERROR  -->  RLC : rlcStartTmr: Invalid tmr Evnt [%d]", tmrEvnt);
189       }
190    } 
191
192    if(arg.wait != 0)
193    {
194       arg.tqCp   = &gCb->rlcTqCp;
195       arg.tq     = gCb->rlcTq;
196       arg.cb     = cb;
197       arg.evnt   = tmrEvnt;
198       arg.tNum   = 0;
199
200       cmPlcCbTq(&arg);
201    }
202
203    return;
204 }
205
206 /**
207  * @brief Handler to stop a timer
208  *       
209  * @param[in] gCb       Pointer to the RLC instance control block
210  * @param[in] cb        Control block depending on the type of the timer event. 
211  *                      It can be uplink/downlink rbCb or rgu sap control block
212  * @param[in] tmrType   Timer event to be started
213  *
214  * @return  Void
215 */
216 void rlcStopTmr(RlcCb *gCb, PTR cb, uint8_t tmrType)
217 {
218    CmTmrArg   arg;
219 /* kw005.201 added support for L2 Measurement */
220 #ifdef LTE_L2_MEAS
221    RlcL2MeasEvtCb *measEvtCb = NULLP;
222 #endif
223
224    arg.timers = NULLP;
225
226    switch (tmrType)
227    {
228       case EVENT_RLC_UMUL_REASSEMBLE_TMR:
229       {
230          arg.timers  = &((RlcUlRbCb *)cb)->m.umUl.reAsmblTmr;
231          arg.max = RLC_MAX_UM_TMR;
232          break;
233       }
234       case EVENT_RLC_AMUL_REASSEMBLE_TMR:
235       {
236          arg.timers = &((RlcUlRbCb *)cb)->m.amUl.reAsmblTmr;
237          arg.max = RLC_MAX_AM_TMR;
238          break;
239       }
240       case EVENT_RLC_AMUL_STA_PROH_TMR:
241       {
242          arg.timers = &((RlcUlRbCb *)cb)->m.amUl.staProhTmr;
243          arg.max = RLC_MAX_AM_TMR;
244          break;
245       } 
246       case EVENT_RLC_AMDL_POLL_RETX_TMR:
247       {
248          arg.timers = &((RlcDlRbCb *)cb)->m.amDl.pollRetxTmr;
249          arg.max = RLC_MAX_AM_TMR;
250          break;
251       } 
252       case EVENT_RLC_WAIT_BNDCFM:
253       {
254          arg.timers = &((RlcRguSapCb *)cb)->bndTmr;
255          arg.max = RLC_MAX_RGUSAP_TMR;
256          break;
257       }
258 /* kw005.201 added support for L2 Measurement */
259 #ifdef LTE_L2_MEAS
260       case EVENT_RLC_L2_TMR:
261       {
262          measEvtCb = (RlcL2MeasEvtCb *)cb;
263          arg.timers   = &measEvtCb->l2Tmr;
264          arg.max  = RLC_L2_MAX_TIMERS;
265          break;
266       }
267 #endif
268       case EVENT_RLC_THROUGHPUT_TMR:
269       {
270          arg.timers   = &((RlcThpt *)cb)->thptTmr;
271          arg.max  = RLC_MAX_THPT_TMR;
272       }
273       default:
274       {
275          DU_LOG("\nERROR  -->  RLC : rlcStopTmr: Invalid tmr Evnt[%d]", tmrType);
276       }
277    } 
278    if (tmrType != TMR0)
279    {
280       arg.tqCp   = &gCb->rlcTqCp;
281       arg.tq     = gCb->rlcTq;
282       arg.cb     = cb;
283       arg.evnt   = tmrType;
284       arg.wait   = 0;
285       arg.tNum   = 0;
286       cmRmvCbTq(&arg);
287    }
288    
289    return;
290 }
291
292 /**
293  * @brief Handler to invoke events on expiry of timer.
294  *
295  * @details
296  *    This function is used to handle expiry of timer,it invokes relevant 
297  *    functions.
298  *       
299  * @param[in] cb        Control block depending on the type of the timer event. 
300  *                      It can be uplink/downlink rbCb or rgu sap control block
301  * @param[in] tmrEvnt   Timer event to be started
302  *
303  * @return  Void
304 */
305 Void rlcTmrExpiry(PTR cb,S16 tmrEvnt)
306 {
307 /* kw005.201 added support for L2 Measurement */
308
309    switch (tmrEvnt)
310    {
311       case EVENT_RLC_UMUL_REASSEMBLE_TMR:
312       {
313          RlcUlRbCb *ulRbCb = (RlcUlRbCb *)cb;
314          rlcUmmReAsmblTmrExp(RLC_GET_RLCCB(ulRbCb->inst), ulRbCb);
315
316          break;
317       }
318       case EVENT_RLC_AMUL_REASSEMBLE_TMR:
319       {
320          RlcUlRbCb *ulRbCb = (RlcUlRbCb *)cb;
321          rlcAmmReAsmblTmrExp(RLC_GET_RLCCB(ulRbCb->inst), ulRbCb);
322          break;
323       }
324       case EVENT_RLC_AMUL_STA_PROH_TMR:
325       {
326          RlcUlRbCb *ulRbCb = (RlcUlRbCb *)cb;
327          rlcAmmStaProTmrExp(RLC_GET_RLCCB(ulRbCb->inst), ulRbCb);
328
329          break;
330       }
331       case EVENT_RLC_AMDL_POLL_RETX_TMR:
332       {
333          RlcDlRbCb *dlRbCb = (RlcDlRbCb *)cb;
334          RlcCb *gCb = RLC_GET_RLCCB(dlRbCb->inst);
335          
336          rlcAmmPollRetxTmrExp(gCb, dlRbCb);
337
338          gCb->genSts.protTimeOut++;
339          break;
340       }
341       case EVENT_RLC_WAIT_BNDCFM:
342       {
343          rlcBndTmrExpiry(cb);
344          break;
345       }
346       case EVENT_RLC_THROUGHPUT_TMR:
347       {
348          rlcThptTmrExpiry(cb);
349          break;
350       }
351       default:
352       {
353          break;
354       }
355    }
356
357    return;
358 }
359
360 /**
361  * @brief Handler to check if the timer is running
362  *       
363  * @param[in] gCb       Pointer to the RLC instance control block
364  * @param[in] cb        Control block depending on the type of the timer event. 
365  *                      It can be uplink/downlink rbCb or rgu sap control block
366  * @param[in] tmrEvnt   Timer event to be started
367  *
368  * @return  Bool indicating whether the timer is running or not
369  *      -# ROK 
370  *      -# RFAILED 
371 */
372 bool rlcChkTmr(RlcCb *gCb, PTR cb, int16_t tmrEvnt)
373 {
374    switch (tmrEvnt)
375    {
376       case EVENT_RLC_UMUL_REASSEMBLE_TMR:
377       {
378          return (((RlcUlRbCb *)cb)->m.umUl.reAsmblTmr.tmrEvnt == 
379                   EVENT_RLC_UMUL_REASSEMBLE_TMR);
380       }
381       case EVENT_RLC_AMUL_REASSEMBLE_TMR:
382       {
383          return (((RlcUlRbCb *)cb)->m.amUl.reAsmblTmr.tmrEvnt == 
384                   EVENT_RLC_AMUL_REASSEMBLE_TMR);
385       }
386       case EVENT_RLC_AMUL_STA_PROH_TMR:
387       {
388          return (((RlcUlRbCb *)cb)->m.amUl.staProhTmr.tmrEvnt == 
389                   EVENT_RLC_AMUL_STA_PROH_TMR);
390       } 
391       case EVENT_RLC_AMDL_POLL_RETX_TMR:
392       {
393          return (((RlcDlRbCb *)cb)->m.amDl.pollRetxTmr.tmrEvnt == 
394                   EVENT_RLC_AMDL_POLL_RETX_TMR);
395       } 
396       case EVENT_RLC_WAIT_BNDCFM:
397       {
398          return (((RlcRguSapCb *)cb)->bndTmr.tmrEvnt == EVENT_RLC_WAIT_BNDCFM);
399       }
400       case EVENT_RLC_THROUGHPUT_TMR:
401       {
402          return (((RlcThpt *)cb)->thptTmr.tmrEvnt == EVENT_RLC_THROUGHPUT_TMR);
403       }
404       default:
405       {
406          DU_LOG("\nERROR  -->  RLC : rlcChkTmr: Invalid tmr Evnt [%d]", tmrEvnt);
407       }
408    } 
409
410    return FALSE;
411 }
412
413 /**
414  * @brief Handler to do processing on expiry of the bind timer
415  *
416  * @details
417  *    This function processes the RLC bind timer expiry. If the number of 
418  *    retries is less than the maximum retry counter, bind request is sent 
419  *    again, else an alarm is raised to the layer manager.
420  *       
421  * @param[in] cb  Pointer to the Rgu sap
422  *
423  * @return  Void
424 */
425 static Void rlcBndTmrExpiry(PTR cb)
426 {
427    RlcRguSapCb *rguSapCb; 
428
429    rguSapCb = (RlcRguSapCb *) cb;
430
431    if (rguSapCb->state == RLC_SAP_BINDING)
432    {
433       if (rguSapCb->retryCnt < RLC_MAX_SAP_BND_RETRY)
434       {
435          /* start timer to wait for bind confirm */
436          rlcStartTmr(RLC_GET_RLCCB(rguSapCb->pst.srcInst),
437                     (PTR)rguSapCb, 
438                     EVENT_RLC_WAIT_BNDCFM);
439          
440          /* Send bind request */
441          rguSapCb->retryCnt++;
442          RlcLiRguBndReq (&rguSapCb->pst, rguSapCb->suId, rguSapCb->spId);
443       }
444       else
445       {
446          rguSapCb->retryCnt = 0;
447          rguSapCb->state = RLC_SAP_CFG;
448
449          /* Send alarm to the layer manager */
450 #ifdef LTE_L2_MEAS
451          rlcLmmSendAlarm(RLC_GET_RLCCB(rguSapCb->pst.srcInst),
452                         LCM_CATEGORY_INTERFACE, 
453                         LCM_EVENT_BND_FAIL,
454                         LCM_CAUSE_TMR_EXPIRED, 
455                         0, 
456                         0, 
457                         0);
458 #else
459          rlcLmmSendAlarm(RLC_GET_RLCCB(rguSapCb->pst.srcInst),
460                         LCM_CATEGORY_INTERFACE, 
461                         LCM_EVENT_BND_FAIL,
462                         LCM_CAUSE_TMR_EXPIRED, 
463                         0, /* suId */
464                         0 /* ueId */);
465 #endif
466       }
467    }
468
469    return;
470 }
471
472 /**
473  * @brief Handler to do processing on expiry of the throughput timer
474  *
475  * @details
476  *    This function processes the RLC throughput timer expiry.
477  *
478  * @param[in] cb  Pointer to the RLC throughput struct
479  *
480  * @return  Void
481  */
482 void rlcThptTmrExpiry(PTR cb)
483 {
484    uint16_t  ueIdx;
485    long double tpt;
486    RlcThpt *rlcThptCb = (RlcThpt*)cb; 
487
488    /* Print throughput */
489    DU_LOG("\n===================== DL Throughput ==============================");
490    DU_LOG("\nNumber of UEs : %d", rlcThptCb->numActvUe);
491    for(ueIdx = 0; ueIdx < rlcThptCb->numActvUe; ueIdx++)
492    {
493       /* Spec 28.552, section 5.1.1.3 : 
494        * Throughput in kilobits/sec = (dataVol in kiloBits * 1000)/time in milligseconds
495        * 
496        * Since our dataVol is in bytes, multiplying 0.008 to covert into kilobits i.e. 
497        * Throughput[kbits/sec] = (dataVol * 0.008 * 1000)/time in ms
498        */
499       tpt = (double)(rlcThptCb->thptPerUe[ueIdx].dataVol * 8)/(double)ODU_THROUGHPUT_PRINT_TIME_INTERVAL;
500       
501       DU_LOG("\nUE Id : %d   DL Tpt : %.2Lf", rlcThptCb->thptPerUe[ueIdx].ueIdx, tpt);
502       rlcThptCb->thptPerUe[ueIdx].dataVol = 0;
503    }
504    DU_LOG("\n==================================================================");
505
506    /* Restart timer */
507    rlcStartTmr(RLC_GET_RLCCB(rlcThptCb->inst), (PTR)rlcThptCb, EVENT_RLC_THROUGHPUT_TMR);
508
509    return;
510 }
511
512 \f  
513 /********************************************************************30**
514   
515          End of file
516 **********************************************************************/