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 "rlc_env.h" /* RLC environment options */
43 #include "rlc_err.h" /* Error defines */
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 */
51 #include "du_app_rlc_inf.h"
52 #include "rlc_utils.h" /* RLC defines */
53 #include "rlc_dl_ul_inf.h"
60 * @brief RLC Timer Module
63 /* private function declarations */
64 static Void rlcBndTmrExpiry(PTR cb);
68 * @brief Handler to start timer
70 * @param[in] gCb Pointer to the RLC instance control block
71 * @param[in] cb Control block depending on the type of the timer event.
72 * It can be uplink/downlink rbCb or rgu sap control block
73 * @param[in] tmrEvnt Timer event to be started
77 void rlcStartTmr(RlcCb *gCb, PTR cb, int16_t tmrEvnt)
79 /* kw005.201 added support for L2 Measurement */
81 RlcL2MeasEvtCb *measEvtCb = NULLP;
87 /* kw002.201 Adjusting the wait time as per timeRes configured by layer manager */
90 case EVENT_RLC_UMUL_REASSEMBLE_TMR:
92 RlcUmUl* umUl = &(((RlcUlRbCb *)cb)->m.umUl);
93 /* kw005.201 Changed wait calculation ccpu00117634*/
94 TMR_CALCUATE_WAIT(arg.wait, umUl->reAsmblTmrInt, gCb->genCfg.timeRes);
96 arg.timers = &umUl->reAsmblTmr;
97 arg.max = RLC_MAX_UM_TMR;
100 case EVENT_RLC_AMUL_REASSEMBLE_TMR:
102 RlcAmUl* amUl = &(((RlcUlRbCb *)cb)->m.amUl);
103 /* kw005.201 Changed wait calculation ccpu00117634*/
104 TMR_CALCUATE_WAIT(arg.wait, amUl->reAsmblTmrInt, gCb->genCfg.timeRes);
106 arg.timers = &amUl->reAsmblTmr;
107 arg.max = RLC_MAX_AM_TMR;
110 case EVENT_RLC_AMUL_STA_PROH_TMR:
112 RlcAmUl* amUl = &(((RlcUlRbCb *)cb)->m.amUl);
113 /* kw005.201 Changed wait calculation ccpu00117634*/
114 TMR_CALCUATE_WAIT(arg.wait,
116 gCb->genCfg.timeRes);
118 arg.timers = &amUl->staProhTmr;
119 arg.max = RLC_MAX_AM_TMR;
122 case EVENT_RLC_AMDL_POLL_RETX_TMR:
124 RlcAmDl* amDl = &(((RlcDlRbCb *)cb)->m.amDl);
125 /* kw005.201 Changed wait calculation ccpu00117634*/
126 TMR_CALCUATE_WAIT(arg.wait,
127 amDl->pollRetxTmrInt,
128 gCb->genCfg.timeRes);
130 arg.timers = &amDl->pollRetxTmr;
131 arg.max = RLC_MAX_AM_TMR;
134 case EVENT_RLC_WAIT_BNDCFM:
136 RlcRguSapCb* rguSap = (RlcRguSapCb *)cb;
137 /* kw005.201 Changed wait calculation ccpu00117634*/
138 TMR_CALCUATE_WAIT(arg.wait, rguSap->bndTmrInt, gCb->genCfg.timeRes);
140 arg.timers = &rguSap->bndTmr;
141 arg.max = RLC_MAX_RGUSAP_TMR;
144 /* kw005.201 added support for L2 Measurement */
146 case EVENT_RLC_L2_TMR:
148 measEvtCb = (RlcL2MeasEvtCb *)cb;
149 /* kw005.201 Changed wait calculation ccpu00117634*/
150 TMR_CALCUATE_WAIT(arg.wait,
151 measEvtCb->l2TmrCfg.val,
152 gCb->genCfg.timeRes);
154 arg.timers = &measEvtCb->l2Tmr;
155 arg.max = RLC_L2_MAX_TIMERS;
159 case EVENT_RLC_UE_THROUGHPUT_TMR:
161 RlcThpt *thptCb = (RlcThpt *)cb;
162 TMR_CALCUATE_WAIT(arg.wait, gConfigInfo.gUeThrptTimeIntervl, gCb->genCfg.timeRes);
163 arg.timers = &thptCb->ueTputInfo.ueThptTmr;
164 arg.max = RLC_MAX_THPT_TMR;
167 case EVENT_RLC_UE_DELETE_TMR:
169 RlcUlUeCb *ulUeCb = (RlcUlUeCb*)cb;
170 TMR_CALCUATE_WAIT(arg.wait, RLC_UE_DELETE_WAIT_TIME, gCb->genCfg.timeRes);
171 arg.timers = &ulUeCb->ueDeleteInfo.ueDelTmr;
172 arg.max = RLC_MAX_UE_TMR;
175 case EVENT_RLC_SNSSAI_THROUGHPUT_TMR:
177 RlcThpt *thptCb = (RlcThpt *)cb;
178 TMR_CALCUATE_WAIT(arg.wait, gConfigInfo.gSnssaiThrptTimeIntervl, gCb->genCfg.timeRes);
179 arg.timers = &thptCb->snssaiTputInfo.snssaiThptTmr;
180 arg.max = RLC_MAX_THPT_TMR;
185 DU_LOG("\nERROR --> RLC : rlcStartTmr: Invalid tmr Evnt [%d]", tmrEvnt);
191 arg.tqCp = &gCb->rlcTqCp;
204 * @brief Handler to stop a timer
206 * @param[in] gCb Pointer to the RLC instance control block
207 * @param[in] cb Control block depending on the type of the timer event.
208 * It can be uplink/downlink rbCb or rgu sap control block
209 * @param[in] tmrType Timer event to be started
213 void rlcStopTmr(RlcCb *gCb, PTR cb, uint8_t tmrType)
216 /* kw005.201 added support for L2 Measurement */
218 RlcL2MeasEvtCb *measEvtCb = NULLP;
225 case EVENT_RLC_UMUL_REASSEMBLE_TMR:
227 arg.timers = &((RlcUlRbCb *)cb)->m.umUl.reAsmblTmr;
228 arg.max = RLC_MAX_UM_TMR;
231 case EVENT_RLC_AMUL_REASSEMBLE_TMR:
233 arg.timers = &((RlcUlRbCb *)cb)->m.amUl.reAsmblTmr;
234 arg.max = RLC_MAX_AM_TMR;
237 case EVENT_RLC_AMUL_STA_PROH_TMR:
239 arg.timers = &((RlcUlRbCb *)cb)->m.amUl.staProhTmr;
240 arg.max = RLC_MAX_AM_TMR;
243 case EVENT_RLC_AMDL_POLL_RETX_TMR:
245 arg.timers = &((RlcDlRbCb *)cb)->m.amDl.pollRetxTmr;
246 arg.max = RLC_MAX_AM_TMR;
249 case EVENT_RLC_WAIT_BNDCFM:
251 arg.timers = &((RlcRguSapCb *)cb)->bndTmr;
252 arg.max = RLC_MAX_RGUSAP_TMR;
255 /* kw005.201 added support for L2 Measurement */
257 case EVENT_RLC_L2_TMR:
259 measEvtCb = (RlcL2MeasEvtCb *)cb;
260 arg.timers = &measEvtCb->l2Tmr;
261 arg.max = RLC_L2_MAX_TIMERS;
265 case EVENT_RLC_UE_THROUGHPUT_TMR:
267 arg.timers = &((RlcThpt *)cb)->ueTputInfo.ueThptTmr;
268 arg.max = RLC_MAX_THPT_TMR;
271 case EVENT_RLC_UE_DELETE_TMR:
273 arg.timers = &((RlcUlUeCb*)cb)->ueDeleteInfo.ueDelTmr;
274 arg.max = EVENT_RLC_UE_DELETE_TMR;
277 case EVENT_RLC_SNSSAI_THROUGHPUT_TMR:
279 arg.timers = &((RlcThpt *)cb)->snssaiTputInfo.snssaiThptTmr;
280 arg.max = RLC_MAX_THPT_TMR;
285 DU_LOG("\nERROR --> RLC : rlcStopTmr: Invalid tmr Evnt[%d]", tmrType);
291 arg.tqCp = &gCb->rlcTqCp;
304 * @brief Handler to invoke events on expiry of timer.
307 * This function is used to handle expiry of timer,it invokes relevant
310 * @param[in] cb Control block depending on the type of the timer event.
311 * It can be uplink/downlink rbCb or rgu sap control block
312 * @param[in] tmrEvnt Timer event to be started
316 Void rlcTmrExpiry(PTR cb,S16 tmrEvnt)
318 /* kw005.201 added support for L2 Measurement */
322 case EVENT_RLC_UMUL_REASSEMBLE_TMR:
324 RlcUlRbCb *ulRbCb = (RlcUlRbCb *)cb;
325 rlcUmmReAsmblTmrExp(RLC_GET_RLCCB(ulRbCb->inst), ulRbCb);
329 case EVENT_RLC_AMUL_REASSEMBLE_TMR:
331 RlcUlRbCb *ulRbCb = (RlcUlRbCb *)cb;
332 rlcAmmReAsmblTmrExp(RLC_GET_RLCCB(ulRbCb->inst), ulRbCb);
335 case EVENT_RLC_AMUL_STA_PROH_TMR:
337 RlcUlRbCb *ulRbCb = (RlcUlRbCb *)cb;
338 rlcAmmStaProTmrExp(RLC_GET_RLCCB(ulRbCb->inst), ulRbCb);
342 case EVENT_RLC_AMDL_POLL_RETX_TMR:
344 RlcDlRbCb *dlRbCb = (RlcDlRbCb *)cb;
345 RlcCb *gCb = RLC_GET_RLCCB(dlRbCb->inst);
347 rlcAmmPollRetxTmrExp(gCb, dlRbCb);
349 gCb->genSts.protTimeOut++;
352 case EVENT_RLC_WAIT_BNDCFM:
357 case EVENT_RLC_UE_THROUGHPUT_TMR:
359 rlcUeThptTmrExpiry(cb);
362 case EVENT_RLC_UE_DELETE_TMR:
364 rlcUeDeleteTmrExpiry(cb);
367 case EVENT_RLC_SNSSAI_THROUGHPUT_TMR:
369 rlcSnssaiThptTmrExpiry(cb);
382 * @brief Handler to check if the timer is running
384 * @param[in] gCb Pointer to the RLC instance control block
385 * @param[in] cb Control block depending on the type of the timer event.
386 * It can be uplink/downlink rbCb or rgu sap control block
387 * @param[in] tmrEvnt Timer event to be started
389 * @return Bool indicating whether the timer is running or not
393 bool rlcChkTmr(RlcCb *gCb, PTR cb, int16_t tmrEvnt)
397 case EVENT_RLC_UMUL_REASSEMBLE_TMR:
399 return (((RlcUlRbCb *)cb)->m.umUl.reAsmblTmr.tmrEvnt ==
400 EVENT_RLC_UMUL_REASSEMBLE_TMR);
402 case EVENT_RLC_AMUL_REASSEMBLE_TMR:
404 return (((RlcUlRbCb *)cb)->m.amUl.reAsmblTmr.tmrEvnt ==
405 EVENT_RLC_AMUL_REASSEMBLE_TMR);
407 case EVENT_RLC_AMUL_STA_PROH_TMR:
409 return (((RlcUlRbCb *)cb)->m.amUl.staProhTmr.tmrEvnt ==
410 EVENT_RLC_AMUL_STA_PROH_TMR);
412 case EVENT_RLC_AMDL_POLL_RETX_TMR:
414 return (((RlcDlRbCb *)cb)->m.amDl.pollRetxTmr.tmrEvnt ==
415 EVENT_RLC_AMDL_POLL_RETX_TMR);
417 case EVENT_RLC_WAIT_BNDCFM:
419 return (((RlcRguSapCb *)cb)->bndTmr.tmrEvnt == EVENT_RLC_WAIT_BNDCFM);
421 case EVENT_RLC_UE_THROUGHPUT_TMR:
423 return (((RlcThpt *)cb)->ueTputInfo.ueThptTmr.tmrEvnt == EVENT_RLC_UE_THROUGHPUT_TMR);
425 case EVENT_RLC_UE_DELETE_TMR:
427 return (((RlcUlUeCb *)cb)->ueDeleteInfo.ueDelTmr.tmrEvnt == EVENT_RLC_UE_DELETE_TMR);
429 case EVENT_RLC_SNSSAI_THROUGHPUT_TMR:
431 return (((RlcThpt *)cb)->snssaiTputInfo.snssaiThptTmr.tmrEvnt == EVENT_RLC_SNSSAI_THROUGHPUT_TMR);
435 DU_LOG("\nERROR --> RLC : rlcChkTmr: Invalid tmr Evnt [%d]", tmrEvnt);
443 * @brief Handler to do processing on expiry of the bind timer
446 * This function processes the RLC bind timer expiry. If the number of
447 * retries is less than the maximum retry counter, bind request is sent
448 * again, else an alarm is raised to the layer manager.
450 * @param[in] cb Pointer to the Rgu sap
454 static Void rlcBndTmrExpiry(PTR cb)
456 RlcRguSapCb *rguSapCb;
458 rguSapCb = (RlcRguSapCb *) cb;
460 if (rguSapCb->state == RLC_SAP_BINDING)
462 if (rguSapCb->retryCnt < RLC_MAX_SAP_BND_RETRY)
464 /* start timer to wait for bind confirm */
465 rlcStartTmr(RLC_GET_RLCCB(rguSapCb->pst.srcInst),
467 EVENT_RLC_WAIT_BNDCFM);
469 /* Send bind request */
470 rguSapCb->retryCnt++;
471 RlcLiRguBndReq (&rguSapCb->pst, rguSapCb->suId, rguSapCb->spId);
475 rguSapCb->retryCnt = 0;
476 rguSapCb->state = RLC_SAP_CFG;
478 /* Send alarm to the layer manager */
480 rlcLmmSendAlarm(RLC_GET_RLCCB(rguSapCb->pst.srcInst),
481 LCM_CATEGORY_INTERFACE,
483 LCM_CAUSE_TMR_EXPIRED,
488 rlcLmmSendAlarm(RLC_GET_RLCCB(rguSapCb->pst.srcInst),
489 LCM_CATEGORY_INTERFACE,
491 LCM_CAUSE_TMR_EXPIRED,
502 * @brief Handler to do processing on expiry of UE throughput timer
505 * This function processes the RLC UE throughput timer expiry.
507 * @param[in] cb Pointer to the RLC throughput struct
511 void rlcUeThptTmrExpiry(PTR cb)
515 RlcThpt *rlcThptCb = (RlcThpt*)cb;
517 /* If cell is not up, throughput details cannot be printed */
518 if(gConfigInfo.gCellStatus != CELL_UP)
521 rlcStartTmr(RLC_GET_RLCCB(rlcThptCb->inst), (PTR)(rlcThptCb), EVENT_RLC_UE_THROUGHPUT_TMR);
525 /* If cell is up, print throughout for each UE attached to the cell */
526 DU_LOG("\n===================== DL Throughput Per UE==============================");
527 DU_LOG("\nNumber of UEs : %d", rlcThptCb->ueTputInfo.numActvUe);
528 if(rlcThptCb->ueTputInfo.numActvUe)
530 for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++)
532 if(rlcThptCb->ueTputInfo.thptPerUe[ueIdx].ueId)
534 /* Spec 28.552, section 5.1.1.3 :
535 * Throughput in kilobits/sec = (dataVol in kiloBits * 1000)/time in milligseconds
537 * Since our dataVol is in bytes, multiplying 0.008 to covert into kilobits i.e.
538 * Throughput[kbits/sec] = (dataVol * 0.008 * 1000)/time in ms
540 tpt = (double)(rlcThptCb->ueTputInfo.thptPerUe[ueIdx].dataVol * 8)/(double)gConfigInfo.gUeThrptTimeIntervl;
542 DU_LOG("\nUE Id : %d DL Tpt : %.2Lf", rlcThptCb->ueTputInfo.thptPerUe[ueIdx].ueId, tpt);
543 rlcThptCb->ueTputInfo.thptPerUe[ueIdx].dataVol = 0;
547 DU_LOG("\n==================================================================");
550 rlcStartTmr(RLC_GET_RLCCB(rlcThptCb->inst), (PTR)rlcThptCb, EVENT_RLC_UE_THROUGHPUT_TMR);
556 * @brief Handler to do processing on expiry of the SNSSAI throughput timer
559 * This function processes the RLC SNSSAI throughput timer expiry.
561 * @param[in] cb Pointer to the RLC throughput struct
565 void rlcSnssaiThptTmrExpiry(PTR cb)
567 RlcThpt *rlcThptCb = (RlcThpt*)cb;
569 static uint8_t snssaiCntDl = 0, snssaiCntUl = 0;
570 /*Bit map to keep record of reception of DL and UL Snssai Tput expiry*/
571 static uint8_t snssaiTputBitmap = DIR_NONE;
573 /* If cell is not up, throughput details cannot be printed */
574 if(gConfigInfo.gCellStatus != CELL_UP)
577 rlcStartTmr(RLC_GET_RLCCB(rlcThptCb->inst), (PTR)(rlcThptCb), EVENT_RLC_SNSSAI_THROUGHPUT_TMR);
581 if(rlcThptCb->snssaiTputInfo.dlTputPerSnssaiList != NULLP)
583 snssaiCntDl = rlcCalculateTputPerSnssai(rlcThptCb->snssaiTputInfo.dlTputPerSnssaiList, DIR_DL);
584 snssaiTputBitmap |= DIR_DL;
585 arrTputPerSnssai[DIR_DL] = rlcThptCb->snssaiTputInfo.dlTputPerSnssaiList;
587 if(rlcThptCb->snssaiTputInfo.ulTputPerSnssaiList != NULLP)
589 snssaiCntUl = rlcCalculateTputPerSnssai(rlcThptCb->snssaiTputInfo.ulTputPerSnssaiList, DIR_UL);
590 snssaiTputBitmap |= DIR_UL;
591 arrTputPerSnssai[DIR_UL] = rlcThptCb->snssaiTputInfo.ulTputPerSnssaiList;
593 if(snssaiTputBitmap == DIR_BOTH)
596 BuildSliceReportToDu(MAX(snssaiCntUl, snssaiCntDl));
597 snssaiTputBitmap = DIR_NONE;
600 rlcStartTmr(RLC_GET_RLCCB(rlcThptCb->inst), (PTR)rlcThptCb, EVENT_RLC_SNSSAI_THROUGHPUT_TMR);
605 * @brief filling RLC UE delete configuration
608 * filling RLC UE delete configuration
610 * @params[in] RlcUlUeCb *ueCb, RlcCfgInfo *rlcUeCfg
616 void fillRlcUeDelInfo(RlcUlUeCb *ueCb, RlcCfgInfo *rlcUeCfg)
620 rlcUeCfg->ueId = ueCb->ueId;
621 rlcUeCfg->cellId = ueCb->cellId;
622 rlcUeCfg->numEnt = 0;
623 for(lcIdx=0; lcIdx<RLC_MAX_LCH_PER_UE && rlcUeCfg->numEnt < 1; lcIdx++)
625 if(ueCb->lCh[lcIdx].ulRbCb != NULLP)
627 rlcUeCfg->entCfg[rlcUeCfg->numEnt].rbId = 0;
628 rlcUeCfg->entCfg[rlcUeCfg->numEnt].rbType = 0;
629 rlcUeCfg->entCfg[rlcUeCfg->numEnt].cfgType = CKW_CFG_DELETE_UE;
636 * @brief Handler to do processing on expiry of the UE delete timer
639 * This function processes the RLC UE delete timer expiry.
641 * @param[in] cb Pointer to the RlcUlUeCb
646 uint8_t rlcUeDeleteTmrExpiry(PTR cb)
648 RlcCb *gRlcCb = NULLP;
649 RlcCfgInfo *rlcUeCfg = NULLP;
650 RlcUlUeCb *ueCb = (RlcUlUeCb*)cb;
652 gRlcCb = RLC_GET_RLCCB(ueCb->ueDeleteInfo.pst.dstInst);
653 RLC_ALLOC(gRlcCb, rlcUeCfg, sizeof(RlcCfgInfo));
654 if(rlcUeCfg == NULLP)
656 DU_LOG("\nERROR --> RLC: rlcUeDeleteTmrExpiry(): Failed to allocate memory");
659 memset(rlcUeCfg, 0, sizeof(RlcCfgInfo));
660 fillRlcUeDelInfo(ueCb, rlcUeCfg);
661 if(RlcProcCfgReq(&ueCb->ueDeleteInfo.pst, rlcUeCfg) != ROK)
663 DU_LOG("\nERROR --> RLC: rlcUeDeleteTmrExpiry(): Failed to delete UE");
664 if(sendRlcUeDeleteRspToDu(rlcUeCfg->cellId, rlcUeCfg->ueId, UEID_INVALID) != ROK)
666 DU_LOG("ERROR --> RLC: rlcUeDeleteTmrExpiry(): Failed to send UE delete response ");
673 /********************************************************************30**
676 **********************************************************************/