1 /*******************************************************************************
2 ################################################################################
3 # Copyright (c) [2017-2019] [Radisys] #
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 #
9 # http://www.apache.org/licenses/LICENSE-2.0 #
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 *******************************************************************************/
19 /********************************************************************20**
21 Name: RLC - TMR module file
25 Desc: Source code for timer functions such as,
34 *********************************************************************21*/
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 "kw_env.h" /* RLC environment options */
44 #include "kw.h" /* RLC defines */
45 #include "kw_err.h" /* Error defines */
50 /* extern (.x) include files */
51 #include "lkw.x" /* LKW */
52 #include "ckw.x" /* CKW */
53 #include "kwu.x" /* KWU */
54 #include "rgu.x" /* RGU */
63 * @brief RLC Timer Module
67 * @def RLC_TMR_CALCUATE_WAIT
69 * This macro calculates and assigns wait time based on the value of the
70 * timer and the timer resolution. Timer value of 0 signifies that the
71 * timer is not configured
73 * @param[out] _wait Time for which to arm the timer changed to proper
74 * value according to the resolution
75 * @param[in] _tmrVal Value of the timer
76 * @param[in] _timerRes Resolution of the timer
79 #define RLC_TMR_CALCUATE_WAIT(_wait, _tmrVal, _timerRes) \
81 (_wait) = ((_tmrVal) * SS_TICKS_SEC)/((_timerRes) * 1000); \
82 if((0 != (_tmrVal)) && (0 == (_wait))) \
88 /* private function declarations */
89 static Void rlcBndTmrExpiry(PTR cb);
90 void rlcThptTmrExpiry(PTR cb);
93 * @brief Handler to start timer
95 * @param[in] gCb Pointer to the RLC instance control block
96 * @param[in] cb Control block depending on the type of the timer event.
97 * It can be uplink/downlink rbCb or rgu sap control block
98 * @param[in] tmrEvnt Timer event to be started
102 void rlcStartTmr(RlcCb *gCb, PTR cb, int16_t tmrEvnt)
104 /* kw005.201 added support for L2 Measurement */
106 RlcL2MeasEvtCb *measEvtCb = NULLP;
112 /* kw002.201 Adjusting the wait time as per timeRes configured by layer manager */
115 case EVENT_RLC_UMUL_REASSEMBLE_TMR:
117 RlcUmUl* umUl = &(((RlcUlRbCb *)cb)->m.umUl);
118 /* kw005.201 Changed wait calculation ccpu00117634*/
119 RLC_TMR_CALCUATE_WAIT(arg.wait, umUl->reAsmblTmrInt, gCb->genCfg.timeRes);
121 arg.timers = &umUl->reAsmblTmr;
122 arg.max = RLC_MAX_UM_TMR;
125 case EVENT_RLC_AMUL_REASSEMBLE_TMR:
127 RlcAmUl* amUl = &(((RlcUlRbCb *)cb)->m.amUl);
128 /* kw005.201 Changed wait calculation ccpu00117634*/
129 RLC_TMR_CALCUATE_WAIT(arg.wait, amUl->reAsmblTmrInt, gCb->genCfg.timeRes);
131 arg.timers = &amUl->reAsmblTmr;
132 arg.max = RLC_MAX_AM_TMR;
135 case EVENT_RLC_AMUL_STA_PROH_TMR:
137 RlcAmUl* amUl = &(((RlcUlRbCb *)cb)->m.amUl);
138 /* kw005.201 Changed wait calculation ccpu00117634*/
139 RLC_TMR_CALCUATE_WAIT(arg.wait,
141 gCb->genCfg.timeRes);
143 arg.timers = &amUl->staProhTmr;
144 arg.max = RLC_MAX_AM_TMR;
147 case EVENT_RLC_AMDL_POLL_RETX_TMR:
149 RlcAmDl* amDl = &(((RlcDlRbCb *)cb)->m.amDl);
150 /* kw005.201 Changed wait calculation ccpu00117634*/
151 RLC_TMR_CALCUATE_WAIT(arg.wait,
152 amDl->pollRetxTmrInt,
153 gCb->genCfg.timeRes);
155 arg.timers = &amDl->pollRetxTmr;
156 arg.max = RLC_MAX_AM_TMR;
159 case EVENT_RLC_WAIT_BNDCFM:
161 RlcRguSapCb* rguSap = (RlcRguSapCb *)cb;
162 /* kw005.201 Changed wait calculation ccpu00117634*/
163 RLC_TMR_CALCUATE_WAIT(arg.wait, rguSap->bndTmrInt, gCb->genCfg.timeRes);
165 arg.timers = &rguSap->bndTmr;
166 arg.max = RLC_MAX_RGUSAP_TMR;
169 /* kw005.201 added support for L2 Measurement */
171 case EVENT_RLC_L2_TMR:
173 measEvtCb = (RlcL2MeasEvtCb *)cb;
174 /* kw005.201 Changed wait calculation ccpu00117634*/
175 RLC_TMR_CALCUATE_WAIT(arg.wait,
176 measEvtCb->l2TmrCfg.val,
177 gCb->genCfg.timeRes);
179 arg.timers = &measEvtCb->l2Tmr;
180 arg.max = RLC_L2_MAX_TIMERS;
184 case EVENT_RLC_THROUGHPUT_TMR:
186 RlcThpt *thptCb = (RlcThpt *)cb;
187 RLC_TMR_CALCUATE_WAIT(arg.wait, ODU_THROUGHPUT_PRINT_TIME_INTERVAL, gCb->genCfg.timeRes);
188 arg.timers = &thptCb->thptTmr;
189 arg.max = RLC_MAX_THPT_TMR;
194 DU_LOG("\nERROR --> RLC : rlcStartTmr: Invalid tmr Evnt [%d]", tmrEvnt);
200 arg.tqCp = &gCb->rlcTqCp;
213 * @brief Handler to stop a timer
215 * @param[in] gCb Pointer to the RLC instance control block
216 * @param[in] cb Control block depending on the type of the timer event.
217 * It can be uplink/downlink rbCb or rgu sap control block
218 * @param[in] tmrType Timer event to be started
222 void rlcStopTmr(RlcCb *gCb, PTR cb, uint8_t tmrType)
225 /* kw005.201 added support for L2 Measurement */
227 RlcL2MeasEvtCb *measEvtCb = NULLP;
234 case EVENT_RLC_UMUL_REASSEMBLE_TMR:
236 arg.timers = &((RlcUlRbCb *)cb)->m.umUl.reAsmblTmr;
237 arg.max = RLC_MAX_UM_TMR;
240 case EVENT_RLC_AMUL_REASSEMBLE_TMR:
242 arg.timers = &((RlcUlRbCb *)cb)->m.amUl.reAsmblTmr;
243 arg.max = RLC_MAX_AM_TMR;
246 case EVENT_RLC_AMUL_STA_PROH_TMR:
248 arg.timers = &((RlcUlRbCb *)cb)->m.amUl.staProhTmr;
249 arg.max = RLC_MAX_AM_TMR;
252 case EVENT_RLC_AMDL_POLL_RETX_TMR:
254 arg.timers = &((RlcDlRbCb *)cb)->m.amDl.pollRetxTmr;
255 arg.max = RLC_MAX_AM_TMR;
258 case EVENT_RLC_WAIT_BNDCFM:
260 arg.timers = &((RlcRguSapCb *)cb)->bndTmr;
261 arg.max = RLC_MAX_RGUSAP_TMR;
264 /* kw005.201 added support for L2 Measurement */
266 case EVENT_RLC_L2_TMR:
268 measEvtCb = (RlcL2MeasEvtCb *)cb;
269 arg.timers = &measEvtCb->l2Tmr;
270 arg.max = RLC_L2_MAX_TIMERS;
274 case EVENT_RLC_THROUGHPUT_TMR:
276 arg.timers = &((RlcThpt *)cb)->thptTmr;
277 arg.max = RLC_MAX_THPT_TMR;
281 DU_LOG("\nERROR --> RLC : rlcStopTmr: Invalid tmr Evnt[%d]", tmrType);
286 arg.tqCp = &gCb->rlcTqCp;
299 * @brief Handler to invoke events on expiry of timer.
302 * This function is used to handle expiry of timer,it invokes relevant
305 * @param[in] cb Control block depending on the type of the timer event.
306 * It can be uplink/downlink rbCb or rgu sap control block
307 * @param[in] tmrEvnt Timer event to be started
311 Void rlcTmrExpiry(PTR cb,S16 tmrEvnt)
313 /* kw005.201 added support for L2 Measurement */
317 case EVENT_RLC_UMUL_REASSEMBLE_TMR:
319 RlcUlRbCb *ulRbCb = (RlcUlRbCb *)cb;
320 rlcUmmReAsmblTmrExp(RLC_GET_RLCCB(ulRbCb->inst), ulRbCb);
324 case EVENT_RLC_AMUL_REASSEMBLE_TMR:
326 RlcUlRbCb *ulRbCb = (RlcUlRbCb *)cb;
327 rlcAmmReAsmblTmrExp(RLC_GET_RLCCB(ulRbCb->inst), ulRbCb);
330 case EVENT_RLC_AMUL_STA_PROH_TMR:
332 RlcUlRbCb *ulRbCb = (RlcUlRbCb *)cb;
333 rlcAmmStaProTmrExp(RLC_GET_RLCCB(ulRbCb->inst), ulRbCb);
337 case EVENT_RLC_AMDL_POLL_RETX_TMR:
339 RlcDlRbCb *dlRbCb = (RlcDlRbCb *)cb;
340 RlcCb *gCb = RLC_GET_RLCCB(dlRbCb->inst);
342 rlcAmmPollRetxTmrExp(gCb, dlRbCb);
344 gCb->genSts.protTimeOut++;
347 case EVENT_RLC_WAIT_BNDCFM:
352 case EVENT_RLC_THROUGHPUT_TMR:
354 rlcThptTmrExpiry(cb);
367 * @brief Handler to check if the timer is running
369 * @param[in] gCb Pointer to the RLC instance control block
370 * @param[in] cb Control block depending on the type of the timer event.
371 * It can be uplink/downlink rbCb or rgu sap control block
372 * @param[in] tmrEvnt Timer event to be started
374 * @return Bool indicating whether the timer is running or not
378 bool rlcChkTmr(RlcCb *gCb, PTR cb, int16_t tmrEvnt)
382 case EVENT_RLC_UMUL_REASSEMBLE_TMR:
384 return (((RlcUlRbCb *)cb)->m.umUl.reAsmblTmr.tmrEvnt ==
385 EVENT_RLC_UMUL_REASSEMBLE_TMR);
387 case EVENT_RLC_AMUL_REASSEMBLE_TMR:
389 return (((RlcUlRbCb *)cb)->m.amUl.reAsmblTmr.tmrEvnt ==
390 EVENT_RLC_AMUL_REASSEMBLE_TMR);
392 case EVENT_RLC_AMUL_STA_PROH_TMR:
394 return (((RlcUlRbCb *)cb)->m.amUl.staProhTmr.tmrEvnt ==
395 EVENT_RLC_AMUL_STA_PROH_TMR);
397 case EVENT_RLC_AMDL_POLL_RETX_TMR:
399 return (((RlcDlRbCb *)cb)->m.amDl.pollRetxTmr.tmrEvnt ==
400 EVENT_RLC_AMDL_POLL_RETX_TMR);
402 case EVENT_RLC_WAIT_BNDCFM:
404 return (((RlcRguSapCb *)cb)->bndTmr.tmrEvnt == EVENT_RLC_WAIT_BNDCFM);
406 case EVENT_RLC_THROUGHPUT_TMR:
408 return (((RlcThpt *)cb)->thptTmr.tmrEvnt == EVENT_RLC_THROUGHPUT_TMR);
412 DU_LOG("\nERROR --> RLC : rlcChkTmr: Invalid tmr Evnt [%d]", tmrEvnt);
420 * @brief Handler to do processing on expiry of the bind timer
423 * This function processes the RLC bind timer expiry. If the number of
424 * retries is less than the maximum retry counter, bind request is sent
425 * again, else an alarm is raised to the layer manager.
427 * @param[in] cb Pointer to the Rgu sap
431 static Void rlcBndTmrExpiry(PTR cb)
433 RlcRguSapCb *rguSapCb;
435 rguSapCb = (RlcRguSapCb *) cb;
437 if (rguSapCb->state == RLC_SAP_BINDING)
439 if (rguSapCb->retryCnt < RLC_MAX_SAP_BND_RETRY)
441 /* start timer to wait for bind confirm */
442 rlcStartTmr(RLC_GET_RLCCB(rguSapCb->pst.srcInst),
444 EVENT_RLC_WAIT_BNDCFM);
446 /* Send bind request */
447 rguSapCb->retryCnt++;
448 RlcLiRguBndReq (&rguSapCb->pst, rguSapCb->suId, rguSapCb->spId);
452 rguSapCb->retryCnt = 0;
453 rguSapCb->state = RLC_SAP_CFG;
455 /* Send alarm to the layer manager */
457 rlcLmmSendAlarm(RLC_GET_RLCCB(rguSapCb->pst.srcInst),
458 LCM_CATEGORY_INTERFACE,
460 LCM_CAUSE_TMR_EXPIRED,
465 rlcLmmSendAlarm(RLC_GET_RLCCB(rguSapCb->pst.srcInst),
466 LCM_CATEGORY_INTERFACE,
468 LCM_CAUSE_TMR_EXPIRED,
479 * @brief Handler to do processing on expiry of the throughput timer
482 * This function processes the RLC throughput timer expiry.
484 * @param[in] cb Pointer to the RLC throughput struct
488 void rlcThptTmrExpiry(PTR cb)
492 RlcThpt *rlcThptCb = (RlcThpt*)cb;
494 /* Print throughput */
495 DU_LOG("\n===================== DL Throughput ==============================");
496 DU_LOG("\nNumber of UEs : %d", rlcThptCb->numActvUe);
497 for(ueIdx = 0; ueIdx < rlcThptCb->numActvUe; ueIdx++)
499 /* Spec 28.552, section 5.1.1.3 :
500 * Throughput in kilobits/sec = (dataVol in kiloBits * 1000)/time in milligseconds
502 * Since our dataVol is in bytes, multiplying 0.008 to covert into kilobits i.e.
503 * Throughput[kbits/sec] = (dataVol * 0.008 * 1000)/time in ms
505 tpt = (double)(rlcThptCb->thptPerUe[ueIdx].dataVol * 8)/(double)ODU_THROUGHPUT_PRINT_TIME_INTERVAL;
507 DU_LOG("\nUE Id : %d DL Tpt : %.2Lf", rlcThptCb->thptPerUe[ueIdx].ueIdx, tpt);
508 rlcThptCb->thptPerUe[ueIdx].dataVol = 0;
510 DU_LOG("\n==================================================================");
513 rlcStartTmr(RLC_GET_RLCCB(rlcThptCb->inst), (PTR)rlcThptCb, EVENT_RLC_THROUGHPUT_TMR);
519 /********************************************************************30**
522 **********************************************************************/