*/
static S16 rlcCfgFillDlRbCb(RlcCb *gCb,RlcDlRbCb *rbCb,RlcDlUeCb *ueCb,RlcEntCfgInfo *entCfg)
{
-
DU_LOG("\nDEBUG --> RLC_DL : rlcCfgFillRbCb(ueId(%d),cellId(%d) rbType(%d))",
- rbCb->rlcId.ueId,
- rbCb->rlcId.cellId,
- entCfg->rbType);
+ rbCb->rlcId.ueId,
+ rbCb->rlcId.cellId,
+ entCfg->rbType);
/* Initialize according to entMode */
switch (entCfg->entMode)
{
case RLC_MODE_TM:
- {
- rbCb->lch.lChId = entCfg->lCh[0].lChId;
- rbCb->lch.lChType = entCfg->lCh[0].type;
- rbCb->dir = entCfg->dir;
- break;
- }
+ {
+ rbCb->lch.lChId = entCfg->lCh[0].lChId;
+ rbCb->lch.lChType = entCfg->lCh[0].type;
+ rbCb->dir = entCfg->dir;
+ break;
+ }
case RLC_MODE_UM:
- {
- rbCb->lch.lChId = entCfg->lCh[0].lChId;
- rbCb->lch.lChType = entCfg->lCh[0].type;
- rbCb->dir = entCfg->dir;
-
- /* Spec 38.322 Section 7.1
- * All UM state variables can take values from 0 to 63 for 6 bit SN or
- * from 0 to 4095 for 12 bit SN. All arithmetic operations on UM state
- * variables are affected by the UM modulus
- * (i.e. final value = [value from arithmetic operation] modulo 64
- * for 6 bit SN and 4096 for 12 bit SN)
- */
- rbCb->m.umDl.snLen = entCfg->m.umInfo.dl.snLen;
- if (entCfg->m.umInfo.dl.snLen == RLC_UM_CFG_6BIT_SN_LEN)
- rbCb->m.umDl.modBitMask = 0x3f;
- else
- rbCb->m.umDl.modBitMask = 0xfff;
+ {
+ rbCb->lch.lChId = entCfg->lCh[0].lChId;
+ rbCb->lch.lChType = entCfg->lCh[0].type;
+ rbCb->dir = entCfg->dir;
+
+ /* Spec 38.322 Section 7.1
+ * All UM state variables can take values from 0 to 63 for 6 bit SN or
+ * from 0 to 4095 for 12 bit SN. All arithmetic operations on UM state
+ * variables are affected by the UM modulus
+ * (i.e. final value = [value from arithmetic operation] modulo 64
+ * for 6 bit SN and 4096 for 12 bit SN)
+ */
+ rbCb->m.umDl.snLen = entCfg->m.umInfo.dl.snLen;
+ if (entCfg->m.umInfo.dl.snLen == RLC_UM_CFG_6BIT_SN_LEN)
+ rbCb->m.umDl.modBitMask = 0x3f;
+ else
+ rbCb->m.umDl.modBitMask = 0xfff;
- ueCb->lCh[rbCb->lch.lChId - 1].dlRbCb = rbCb;
+ ueCb->lCh[rbCb->lch.lChId - 1].dlRbCb = rbCb;
- break;
- }
- case RLC_MODE_AM:
- {
- /* Down Link Information
- * indx = 0 as Down Link */
- rbCb->lch.lChId = entCfg->lCh[0].lChId;
- rbCb->lch.lChType = entCfg->lCh[0].type;
- rbCb->dir = RLC_DIR_BOTH;
-
- rbCb->m.amDl.pollPdu = entCfg->m.amInfo.dl.pollPdu;
- rbCb->m.amDl.pollByte = entCfg->m.amInfo.dl.pollByte;
- rbCb->m.amDl.maxRetx = entCfg->m.amInfo.dl.maxRetx;
- rbCb->m.amDl.pollRetxTmrInt = entCfg->m.amInfo.dl.pollRetxTmr;
- rbCb->m.amDl.snLen = entCfg->m.amInfo.dl.snLen;
-
- if(RLC_AM_CFG_12BIT_SN_LEN == rbCb->m.amDl.snLen)
- {
- rbCb->m.amDl.snModMask = (1 << RLC_SN_LEN_12BITS) - 1; /* 5GNR */
+ break;
}
- else
+ case RLC_MODE_AM:
{
- rbCb->m.amDl.snModMask = (1 << RLC_SN_LEN_18BITS) - 1; /* 5GNR */
- }
+ /* Down Link Information
+ * indx = 0 as Down Link */
+ rbCb->lch.lChId = entCfg->lCh[0].lChId;
+ rbCb->lch.lChType = entCfg->lCh[0].type;
+ rbCb->dir = RLC_DIR_BOTH;
+
+ rbCb->m.amDl.pollPdu = entCfg->m.amInfo.dl.pollPdu;
+ rbCb->m.amDl.pollByte = entCfg->m.amInfo.dl.pollByte;
+ rbCb->m.amDl.maxRetx = entCfg->m.amInfo.dl.maxRetx;
+ rbCb->m.amDl.pollRetxTmrInt = entCfg->m.amInfo.dl.pollRetxTmr;
+ rbCb->m.amDl.snLen = entCfg->m.amInfo.dl.snLen;
+
+ if(RLC_AM_CFG_12BIT_SN_LEN == rbCb->m.amDl.snLen)
+ {
+ rbCb->m.amDl.snModMask = (1 << RLC_SN_LEN_12BITS) - 1; /* 5GNR */
+ }
+ else
+ {
+ rbCb->m.amDl.snModMask = (1 << RLC_SN_LEN_18BITS) - 1; /* 5GNR */
+ }
+
+ cmInitTimers(&(rbCb->m.amDl.pollRetxTmr), 1);
+ ueCb->lCh[rbCb->lch.lChId - 1].dlRbCb = rbCb;
- cmInitTimers(&(rbCb->m.amDl.pollRetxTmr), 1);
- ueCb->lCh[rbCb->lch.lChId - 1].dlRbCb = rbCb;
-
#ifndef LTE_TDD
- uint32_t hashIndex;
- RLC_ALLOC(gCb,
- rbCb->m.amDl.txBufLst,
- (RLC_TX_BUF_BIN_SIZE * sizeof(CmLListCp)));
- for(hashIndex = 0; hashIndex < RLC_TX_BUF_BIN_SIZE; hashIndex++)
- {
- cmLListInit(&(rbCb->m.amDl.txBufLst[hashIndex]));
- }
+ uint32_t hashIndex;
+ RLC_ALLOC(gCb,
+ rbCb->m.amDl.txBufLst,
+ (RLC_TX_BUF_BIN_SIZE * sizeof(CmLListCp)));
+ for(hashIndex = 0; hashIndex < RLC_TX_BUF_BIN_SIZE; hashIndex++)
+ {
+ cmLListInit(&(rbCb->m.amDl.txBufLst[hashIndex]));
+ }
#endif
- break;
- }
+ break;
+ }
default:
- {
- DU_LOG("\nERROR --> RLC_DL : Invalid RB Mode ueId(%d),cellId(%d)",
+ {
+ DU_LOG("\nERROR --> RLC_DL : Invalid RB Mode ueId(%d),cellId(%d)",
rbCb->rlcId.ueId,
rbCb->rlcId.cellId);
- return RFAILED;
- }
+ return RFAILED;
+ }
}
if(entCfg->snssai)
return RFAILED;
}
memcpy(rbCb->snssai, entCfg->snssai, sizeof(Snssai));
+
+ /*Create the entry of this SNSSAI if not exist in Snssai Tput list*/
+ if(rlcHandleSnssaiTputlist(gCb, rbCb->snssai, CREATE) == NULLP)
+ {
+ DU_LOG("\nERROR --> RLC_DL : rlcCfgFillDlRbCb(): SNSSAI insertion in Tput list failed");
+ }
}
rbCb->mode = entCfg->entMode;
rbCb->discTmrInt = entCfg->discardTmr;
uint8_t reason; /* Rb Identifier */
DU_LOG("\nDEBUG --> RLC_DL : rlcCfgAddRb(cellId(%d),UEID:%d cfgType(%d))",
- cellId,
- ueId,
- entCfg->cfgType);
+ cellId,
+ ueId,
+ entCfg->cfgType);
if (cellId == 0)
{
/* Fill entCfm structure */
RLC_CFG_FILL_CFG_CFM(entCfm, entCfg->rbId, entCfg->rbType, CKW_CFG_CFM_NOK,
- CKW_CFG_REAS_CELL_UNKWN);
+ CKW_CFG_REAS_CELL_UNKWN);
DU_LOG("\nERROR --> RLC_DL : Add DLRb,CellId is 0 for UEID:%d",
- ueId);
+ ueId);
return RFAILED;
}
if ((entCfg->rguSapId >= gCb->genCfg.maxRguSaps) || (entCfg->rguSapId < 0))
{
- RLCDBGP_ERROR(gCb, "rlcCfgAddDlRb(ueId(%u), cellId(%u), Invalid rguSapId (%d)\n",
- ueId, cellId, entCfg->rguSapId);
- return RFAILED;
+ RLCDBGP_ERROR(gCb, "rlcCfgAddDlRb(ueId(%u), cellId(%u), Invalid rguSapId (%d)\n",
+ ueId, cellId, entCfg->rguSapId);
+ return RFAILED;
}
{
/* Fill entCfm structure */
RLC_CFG_FILL_CFG_CFM(entCfm, entCfg->rbId, entCfg->rbType,
- CKW_CFG_CFM_NOK,
- CKW_CFG_REAS_RB_UNKWN);
+ CKW_CFG_CFM_NOK,
+ CKW_CFG_REAS_RB_UNKWN);
DU_LOG("\nERROR --> RLC_DL : Invalid RbId ,Max is [%d] CELLID:%d UEID:%d",
- RLC_MAX_RB_PER_CELL,
- cellId,
- ueId);
+ RLC_MAX_RB_PER_CELL,
+ cellId,
+ ueId);
return RFAILED;
}
if (((entCfg->lCh[0].type == CM_LTE_LCH_BCCH) ||
- (entCfg->lCh[0].type == CM_LTE_LCH_PCCH) ||
- (entCfg->lCh[0].type == CM_LTE_LCH_CCCH)) &&
- (entCfg->entMode == RLC_MODE_TM))
+ (entCfg->lCh[0].type == CM_LTE_LCH_PCCH) ||
+ (entCfg->lCh[0].type == CM_LTE_LCH_CCCH)) &&
+ (entCfg->entMode == RLC_MODE_TM))
{
/* Cell CB present */
rlcDbmFetchDlCellCb(gCb, cellId, &cellCb);
{
/* Fill entCfm structure */
RLC_CFG_FILL_CFG_CFM(entCfm, entCfg->rbId, entCfg->rbType,
- CKW_CFG_CFM_NOK,
- CKW_CFG_REAS_RB_PRSNT);
+ CKW_CFG_CFM_NOK,
+ CKW_CFG_REAS_RB_PRSNT);
DU_LOG("\nERROR --> RLC_DL : RbId [%d] already exists UEID:%d",
- entCfg->rbId,
- ueId);
+ entCfg->rbId,
+ ueId);
return RFAILED;
}
}
{
/* Fill entCfm structure */
RLC_CFG_FILL_CFG_CFM(entCfm, entCfg->rbId, entCfg->rbType,
- CKW_CFG_CFM_NOK,
- CKW_CFG_REAS_CELL_CREAT_FAIL);
+ CKW_CFG_CFM_NOK,
+ CKW_CFG_REAS_CELL_CREAT_FAIL);
DU_LOG("\nERROR --> RLC_DL : cellCb Creation failed RBID:%d UEID:%d",
- entCfg->rbId,
- ueId);
+ entCfg->rbId,
+ ueId);
return RFAILED;
}
}
if(entCfg->lCh[0].lChId <= 0)
{
DU_LOG("\nERROR --> RLC_DL : Invalid LcId CELLID:%d UEID:%d RBID:%d",
- cellId,
- ueId,
- entCfg->rbId);
+ cellId,
+ ueId,
+ entCfg->rbId);
/* Fill entCfm structure */
RLC_CFG_FILL_CFG_CFM(entCfm, entCfg->rbId, entCfg->rbType,
CKW_CFG_CFM_NOK, CKW_CFG_REAS_INVALID_LCHID);
if (!rlcRbCb)
{
DU_LOG("\nERROR --> RLC_DL : Memory allocation failed for rbId:%d CELLID:%d",
- entCfg->rbId,
- ueId);
+ entCfg->rbId,
+ ueId);
/* Fill entCfm structure */
RLC_CFG_FILL_CFG_CFM(entCfm, entCfg->rbId, entCfg->rbType,
- CKW_CFG_CFM_NOK, CKW_CFG_REAS_RB_CREAT_FAIL);
+ CKW_CFG_CFM_NOK, CKW_CFG_REAS_RB_CREAT_FAIL);
return RFAILED;
}
rlcRbCb->rlcId.rbId = entCfg->rbId;
else
{
reason= (entCfg->entMode != RLC_MODE_TM)? CKW_CFG_REAS_RB_MODE_MIS:
- CKW_CFG_REAS_LCHTYPE_MIS;
+ CKW_CFG_REAS_LCHTYPE_MIS;
/* Fill entCfm structure */
RLC_CFG_FILL_CFG_CFM(entCfm, entCfg->rbId, entCfg->rbType,
- CKW_CFG_CFM_NOK, reason);
+ CKW_CFG_CFM_NOK, reason);
return RFAILED;
}
}
RLC_CFG_FILL_CFG_CFM(entCfm, entCfg->rbId, entCfg->rbType, CKW_CFG_CFM_NOK,
CKW_CFG_REAS_RB_UNKWN);
DU_LOG("\nERROR --> RLC_DL : Invalid RbId for RbType[%d] UEID:%d",
- entCfg->rbType,
- ueId);
+ entCfg->rbType,
+ ueId);
return RFAILED;
}
if ((((entCfg->lCh[0].type == CM_LTE_LCH_DCCH) &&
- (entCfg->entMode != RLC_MODE_UM) &&
- (CM_LTE_SRB == entCfg->rbType)) ||
- ((entCfg->lCh[0].type == CM_LTE_LCH_DTCH) &&
- (CM_LTE_DRB == entCfg->rbType))) &&
- (entCfg->entMode != RLC_MODE_TM))
+ (entCfg->entMode != RLC_MODE_UM) &&
+ (CM_LTE_SRB == entCfg->rbType)) ||
+ ((entCfg->lCh[0].type == CM_LTE_LCH_DTCH) &&
+ (CM_LTE_DRB == entCfg->rbType))) &&
+ (entCfg->entMode != RLC_MODE_TM))
{
/* UE CB present */
if ( rlcDbmFetchDlUeCb(gCb,ueId, cellId, &ueCb) == ROK)
RLC_CFG_FILL_CFG_CFM(entCfm, entCfg->rbId, entCfg->rbType, CKW_CFG_CFM_NOK,
CKW_CFG_REAS_RB_PRSNT);
DU_LOG("\nERROR --> RLC_DL : CellId[%u]:rbId [%d] already exists",
- cellId,
- entCfg->rbId);
+ cellId,
+ entCfg->rbId);
return RFAILED;
}
}
RLC_CFG_FILL_CFG_CFM(entCfm, entCfg->rbId, entCfg->rbType, CKW_CFG_CFM_NOK,
CKW_CFG_REAS_UE_CREAT_FAIL);
DU_LOG("\nERROR --> RLC_DL : UeId [%u]:ueCb Creation Failed RBID:%d",
- ueId,
- entCfg->rbId);
+ ueId,
+ entCfg->rbId);
return RFAILED;
}
/* Start throughput calculation for this UE */
- gCb->rlcThpt.thptPerUe[ueId -1].ueId = ueId;
- gCb->rlcThpt.thptPerUe[ueId -1].dataVol = 0;
- gCb->rlcThpt.numActvUe++;
+ gCb->rlcThpt.ueTputInfo.thptPerUe[ueId -1].ueId = ueId;
+ gCb->rlcThpt.ueTputInfo.thptPerUe[ueId -1].dataVol = 0;
+ gCb->rlcThpt.ueTputInfo.numActvUe++;
}
/* Validate LChId for UM and AM modes */
if ((entCfg->lCh[0].lChId <= 0) ||
- ((entCfg->entMode == RLC_MODE_AM)&&
- (entCfg->lCh[1].lChId <= 0)))
+ ((entCfg->entMode == RLC_MODE_AM)&&
+ (entCfg->lCh[1].lChId <= 0)))
{
/* Fill entCfm structure */
RLC_CFG_FILL_CFG_CFM(entCfm, entCfg->rbId, entCfg->rbType,
{
/* Fill entCfm structure */
RLC_CFG_FILL_CFG_CFM(entCfm, entCfg->rbId, entCfg->rbType,CKW_CFG_CFM_NOK,
- CKW_CFG_REAS_RB_CREAT_FAIL);
+ CKW_CFG_REAS_RB_CREAT_FAIL);
DU_LOG("\nERROR --> RLC_DL : Memory allocation failed RBID:%d CELLID:%d",
- entCfg->rbId,
- cellId);
+ entCfg->rbId,
+ cellId);
return RFAILED;
}
ueCb->srbCb[entCfg->rbId] = rlcRbCb;
else
ueCb->drbCb[entCfg->rbId] = rlcRbCb;
-
+
RLC_LMM_RB_STS_INC(gCb);
}
{
/* Fill entCfm structure */
RLC_CFG_FILL_CFG_CFM(entCfm, entCfg->rbId, entCfg->rbType, CKW_CFG_CFM_NOK,
- CKW_CFG_REAS_RB_CREAT_FAIL);
+ CKW_CFG_REAS_RB_CREAT_FAIL);
/* Delete RB CB created */
RLC_FREE(gCb,rlcRbCb, sizeof(RlcDlRbCb));
DU_LOG("\nERROR --> RLC_DL : Filling of RbCb failed UEID:%d CELLID:%d",
- ueId,
- cellId);
+ ueId,
+ cellId);
return RFAILED;
}
rlcRbCb->qci = entCfg->qci;
DU_LOG("\nERROR --> RLC_DL : UeId[%u] HashList Insertion Failed",
ueCb->ueId);
}
- memset(&gCb->rlcThpt.thptPerUe[ueCb->ueId -1], 0, sizeof(RlcThptPerUe));
- gCb->rlcThpt.numActvUe--;
+ memset(&gCb->rlcThpt.ueTputInfo.thptPerUe[ueCb->ueId -1], 0, sizeof(RlcThptPerUe));
+ gCb->rlcThpt.ueTputInfo.numActvUe--;
/* kw005.201 ccpu00117318, updating the statistics */
gCb->genSts.numUe--;
rlcDbmDlDeInit(gCb);
-
return ROK;
} /* kwDbmShutdown */
rlcTqCp->nxtEnt = 0;
gCb->rlcThpt.inst = gCb->init.inst;
- gCb->rlcThpt.thptTmr.tmrEvnt = TMR_NONE;
- gCb->rlcThpt.numActvUe = 0;
- memset(gCb->rlcThpt.thptPerUe, 0, MAX_NUM_UE * sizeof(RlcThptPerUe));
+ gCb->rlcThpt.ueTputInfo.ueThptTmr.tmrEvnt = TMR_NONE;
+ gCb->rlcThpt.ueTputInfo.numActvUe = 0;
+ memset(gCb->rlcThpt.ueTputInfo.thptPerUe, 0, MAX_NUM_UE * sizeof(RlcThptPerUe));
+ gCb->rlcThpt.snssaiTputInfo.snssaiThptTmr.tmrEvnt = TMR_NONE;
+
if(gCb->genCfg.rlcMode == LKW_RLC_MODE_DL)
{
RLC_ALLOC(gCb,gCb->u.dlCb, sizeof (RlcDlCb));
if(gCb->genCfg.rlcMode == LKW_RLC_MODE_DL)
{
/* Starting timer to print throughput */
- if((rlcChkTmr(gCb, (PTR)(&gCb->rlcThpt), EVENT_RLC_THROUGHPUT_TMR)) == FALSE)
+ if((rlcChkTmr(gCb, (PTR)(&gCb->rlcThpt), EVENT_RLC_UE_THROUGHPUT_TMR)) == FALSE)
{
- DU_LOG("\nINFO --> RLC_DL : Starting Throughput timer");
- rlcStartTmr(gCb, (PTR)(&gCb->rlcThpt), EVENT_RLC_THROUGHPUT_TMR);
+ DU_LOG("\nINFO --> RLC_DL : Starting UE Throughput timer");
+ rlcStartTmr(gCb, (PTR)(&gCb->rlcThpt), EVENT_RLC_UE_THROUGHPUT_TMR);
+ }
+ /* Starting timer to print throughput */
+ if((rlcChkTmr(gCb, (PTR)(&gCb->rlcThpt), EVENT_RLC_SNSSAI_THROUGHPUT_TMR)) == FALSE)
+ {
+ DU_LOG("\nINFO --> RLC_DL : Starting SNSSAI Throughput timer");
+ rlcStartTmr(gCb, (PTR)(&gCb->rlcThpt), EVENT_RLC_SNSSAI_THROUGHPUT_TMR);
}
}
+
return (LCM_REASON_NOT_APPL);
}
rlcDbmUlShutdown(gCb);
}
+ rlcDelTputSnssaiList(gCb);
rlcLmmCleanGblRsrcs(gCb);
RLC_MEM_SET (&(gCb->genSts), 0, sizeof (RlcGenSts));
break;
}
#endif
- case EVENT_RLC_THROUGHPUT_TMR:
+ case EVENT_RLC_UE_THROUGHPUT_TMR:
{
RlcThpt *thptCb = (RlcThpt *)cb;
- RLC_TMR_CALCUATE_WAIT(arg.wait, ODU_THROUGHPUT_PRINT_TIME_INTERVAL, gCb->genCfg.timeRes);
- arg.timers = &thptCb->thptTmr;
+ RLC_TMR_CALCUATE_WAIT(arg.wait, ODU_UE_THROUGHPUT_PRINT_TIME_INTERVAL, gCb->genCfg.timeRes);
+ arg.timers = &thptCb->ueTputInfo.ueThptTmr;
arg.max = RLC_MAX_THPT_TMR;
break;
}
arg.max = RLC_MAX_UE_TMR;
break;
}
+ case EVENT_RLC_SNSSAI_THROUGHPUT_TMR:
+ {
+ RlcThpt *thptCb = (RlcThpt *)cb;
+ RLC_TMR_CALCUATE_WAIT(arg.wait, ODU_SNSSAI_THROUGHPUT_PRINT_TIME_INTERVAL, gCb->genCfg.timeRes);
+ arg.timers = &thptCb->snssaiTputInfo.snssaiThptTmr;
+ arg.max = RLC_MAX_THPT_TMR;
+ break;
+ }
default:
{
DU_LOG("\nERROR --> RLC : rlcStartTmr: Invalid tmr Evnt [%d]", tmrEvnt);
break;
}
#endif
- case EVENT_RLC_THROUGHPUT_TMR:
+ case EVENT_RLC_UE_THROUGHPUT_TMR:
{
- arg.timers = &((RlcThpt *)cb)->thptTmr;
+ arg.timers = &((RlcThpt *)cb)->ueTputInfo.ueThptTmr;
arg.max = RLC_MAX_THPT_TMR;
+ break;
}
case EVENT_RLC_UE_DELETE_TMR:
{
arg.timers = &((RlcUlUeCb*)cb)->ueDeleteInfo.ueDelTmr;
arg.max = EVENT_RLC_UE_DELETE_TMR;
+ break;
+ }
+ case EVENT_RLC_SNSSAI_THROUGHPUT_TMR:
+ {
+ arg.timers = &((RlcThpt *)cb)->snssaiTputInfo.snssaiThptTmr;
+ arg.max = RLC_MAX_THPT_TMR;
+ break;
}
default:
{
DU_LOG("\nERROR --> RLC : rlcStopTmr: Invalid tmr Evnt[%d]", tmrType);
+ break;
}
}
if (tmrType != TMR0)
rlcBndTmrExpiry(cb);
break;
}
- case EVENT_RLC_THROUGHPUT_TMR:
+ case EVENT_RLC_UE_THROUGHPUT_TMR:
{
- rlcThptTmrExpiry(cb);
+ rlcUeThptTmrExpiry(cb);
break;
}
case EVENT_RLC_UE_DELETE_TMR:
rlcUeDeleteTmrExpiry(cb);
break;
}
+ case EVENT_RLC_SNSSAI_THROUGHPUT_TMR:
+ {
+ rlcSnssaiThptTmrExpiry(cb);
+ break;
+ }
default:
{
break;
{
return (((RlcRguSapCb *)cb)->bndTmr.tmrEvnt == EVENT_RLC_WAIT_BNDCFM);
}
- case EVENT_RLC_THROUGHPUT_TMR:
+ case EVENT_RLC_UE_THROUGHPUT_TMR:
{
- return (((RlcThpt *)cb)->thptTmr.tmrEvnt == EVENT_RLC_THROUGHPUT_TMR);
+ return (((RlcThpt *)cb)->ueTputInfo.ueThptTmr.tmrEvnt == EVENT_RLC_UE_THROUGHPUT_TMR);
}
case EVENT_RLC_UE_DELETE_TMR:
{
return (((RlcUlUeCb *)cb)->ueDeleteInfo.ueDelTmr.tmrEvnt == EVENT_RLC_UE_DELETE_TMR);
}
+ case EVENT_RLC_SNSSAI_THROUGHPUT_TMR:
+ {
+ return (((RlcThpt *)cb)->snssaiTputInfo.snssaiThptTmr.tmrEvnt == EVENT_RLC_SNSSAI_THROUGHPUT_TMR);
+ }
default:
{
DU_LOG("\nERROR --> RLC : rlcChkTmr: Invalid tmr Evnt [%d]", tmrEvnt);
}
/**
- * @brief Handler to do processing on expiry of the throughput timer
+ * @brief Handler to do processing on expiry of UE throughput timer
*
* @details
- * This function processes the RLC throughput timer expiry.
+ * This function processes the RLC UE throughput timer expiry.
*
* @param[in] cb Pointer to the RLC throughput struct
*
* @return Void
*/
-void rlcThptTmrExpiry(PTR cb)
+void rlcUeThptTmrExpiry(PTR cb)
{
uint16_t ueIdx;
long double tpt;
if(gCellStatus != CELL_UP)
{
/* Restart timer */
- rlcStartTmr(RLC_GET_RLCCB(rlcThptCb->inst), (PTR)rlcThptCb, EVENT_RLC_THROUGHPUT_TMR);
+ rlcStartTmr(RLC_GET_RLCCB(rlcThptCb->inst), (PTR)(rlcThptCb), EVENT_RLC_UE_THROUGHPUT_TMR);
return;
}
/* If cell is up, print throughout for each UE attached to the cell */
- DU_LOG("\n===================== DL Throughput ==============================");
- DU_LOG("\nNumber of UEs : %d", rlcThptCb->numActvUe);
- if(rlcThptCb->numActvUe)
+ DU_LOG("\n===================== DL Throughput Per UE==============================");
+ DU_LOG("\nNumber of UEs : %d", rlcThptCb->ueTputInfo.numActvUe);
+ if(rlcThptCb->ueTputInfo.numActvUe)
{
for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++)
{
- if(rlcThptCb->thptPerUe[ueIdx].ueId)
+ if(rlcThptCb->ueTputInfo.thptPerUe[ueIdx].ueId)
{
/* Spec 28.552, section 5.1.1.3 :
* Throughput in kilobits/sec = (dataVol in kiloBits * 1000)/time in milligseconds
* Since our dataVol is in bytes, multiplying 0.008 to covert into kilobits i.e.
* Throughput[kbits/sec] = (dataVol * 0.008 * 1000)/time in ms
*/
- tpt = (double)(rlcThptCb->thptPerUe[ueIdx].dataVol * 8)/(double)ODU_THROUGHPUT_PRINT_TIME_INTERVAL;
+ tpt = (double)(rlcThptCb->ueTputInfo.thptPerUe[ueIdx].dataVol * 8)/(double)ODU_UE_THROUGHPUT_PRINT_TIME_INTERVAL;
- DU_LOG("\nUE Id : %d DL Tpt : %.2Lf", rlcThptCb->thptPerUe[ueIdx].ueId, tpt);
- rlcThptCb->thptPerUe[ueIdx].dataVol = 0;
+ DU_LOG("\nUE Id : %d DL Tpt : %.2Lf", rlcThptCb->ueTputInfo.thptPerUe[ueIdx].ueId, tpt);
+ rlcThptCb->ueTputInfo.thptPerUe[ueIdx].dataVol = 0;
}
}
}
DU_LOG("\n==================================================================");
/* Restart timer */
- rlcStartTmr(RLC_GET_RLCCB(rlcThptCb->inst), (PTR)rlcThptCb, EVENT_RLC_THROUGHPUT_TMR);
+ rlcStartTmr(RLC_GET_RLCCB(rlcThptCb->inst), (PTR)rlcThptCb, EVENT_RLC_UE_THROUGHPUT_TMR);
return;
}
+/**
+ * @brief Handler to do processing on expiry of the SNSSAI throughput timer
+ *
+ * @details
+ * This function processes the RLC SNSSAI throughput timer expiry.
+ *
+ * @param[in] cb Pointer to the RLC throughput struct
+ *
+ * @return Void
+ */
+void rlcSnssaiThptTmrExpiry(PTR cb)
+{
+ long double tpt;
+ RlcThpt *rlcThptCb = (RlcThpt*)cb;
+
+ /* If cell is not up, throughput details cannot be printed */
+ if(gCellStatus != CELL_UP)
+ {
+ /* Restart timer */
+ rlcStartTmr(RLC_GET_RLCCB(rlcThptCb->inst), (PTR)(rlcThptCb), EVENT_RLC_SNSSAI_THROUGHPUT_TMR);
+ return;
+ }
+
+ DU_LOG("\n==================================================================");
+ if(rlcThptCb->snssaiTputInfo.tputPerSnssaiList != NULLP)
+ {
+ DU_LOG("\n===================== DL Throughput Per SNSSAI ==============================");
+
+ rlcCalculateTputPerSnssai(rlcThptCb->snssaiTputInfo.tputPerSnssaiList);
+ DU_LOG("\n==================================================================");
+ }
+ /* Restart timer */
+ rlcStartTmr(RLC_GET_RLCCB(rlcThptCb->inst), (PTR)rlcThptCb, EVENT_RLC_SNSSAI_THROUGHPUT_TMR);
+ return;
+}
/**
*
* @brief filling RLC UE delete configuration
return ROK;
}
+
+/**
+ * @brief
+ * Handler for Creating, Searching or Deleting SnssnaiTput List.
+ *
+ * @details
+ * This function is called whenever a new LC is configured with a snssai.
+ * This function is called to search for Snssai Node during RLC SDU formation
+ *
+ * @param[in] gCb RlcCb
+ * @param[in] snssai Snssai to be handled
+ * @param[in] Action Type of action to be handled(Create,Search,Delete)
+ *
+ * @return RlcTptPerSnssai
+ * -# Snssai Node
+ *
+ */
+RlcTptPerSnssai* rlcHandleSnssaiTputlist(RlcCb *gCb, Snssai *snssai, RlcSnssaiActionType action)
+{
+ CmLListCp *snssaiList = NULLP;
+ CmLList *node = NULLP;
+ RlcTptPerSnssai *snssaiNode = NULLP;
+ bool found = FALSE;
+
+ snssaiList = gCb->rlcThpt.snssaiTputInfo.tputPerSnssaiList;
+ if(snssaiList == NULLP)
+ {
+ if(action == CREATE)
+ {
+ RLC_ALLOC(gCb, gCb->rlcThpt.snssaiTputInfo.tputPerSnssaiList, sizeof(CmLListCp));
+ snssaiList = gCb->rlcThpt.snssaiTputInfo.tputPerSnssaiList;
+ cmLListInit(snssaiList);
+ DU_LOG("\nINFO --> RLC: First SNSSAI to add in this List");
+ }
+ else
+ {
+ DU_LOG("\nERROR --> RLC: SNSSAI list doesnt exist!");
+ return NULLP;
+ }
+ }
+
+ node = snssaiList->first;
+
+ /*Traversing the LC LinkList*/
+ while(node)
+ {
+ snssaiNode = (RlcTptPerSnssai *)node->node;
+ if(memcmp(snssaiNode->snssai, snssai, sizeof(Snssai)) == 0)
+ {
+ DU_LOG("\nINFO --> RLC : SNSSAI found in LL");
+ found = TRUE;
+ break;
+ }
+ node = node->next;
+ }//end of while
+
+ switch(action)
+ {
+ case SEARCH:
+ {
+ if(!found)
+ {
+ snssaiNode = NULLP;
+ }
+ return (snssaiNode);
+ }
+
+ case CREATE:
+ {
+ if(found)
+ return (snssaiNode);
+
+ snssaiNode = NULLP;
+ /*Allocate the List*/
+ RLC_ALLOC(gCb, snssaiNode, sizeof(RlcTptPerSnssai));
+ if(snssaiNode)
+ {
+ RLC_ALLOC(gCb, snssaiNode->snssai, sizeof(Snssai));
+ if(snssaiNode->snssai == NULLP)
+ {
+ DU_LOG("\nERROR --> RLC : Allocation of SNSSAI node failed");
+ return NULLP;
+ }
+ memcpy(snssaiNode->snssai,snssai,sizeof(Snssai));
+ snssaiNode->dataVol = 0;
+ }
+ else
+ {
+ DU_LOG("\nERROR --> RLC : Allocation of SNSSAI node failed");
+ return NULLP;
+ }
+
+ node = NULLP;
+ RLC_ALLOC(gCb, node, sizeof(CmLList));
+ if(node)
+ {
+ node->node = (PTR)snssaiNode;
+ cmLListAdd2Tail(snssaiList, node);
+ }
+ else
+ {
+ DU_LOG("\nERROR --> RLC : Allocation of SNSSAI node failed");
+ return NULLP;
+ }
+ DU_LOG("\nINFO --> RLC : SNSSAI node added successfully");
+ return (snssaiNode);
+ }
+
+ case DELETE:
+ {
+ if(found && node)
+ {
+ node = cmLListDelFrm(snssaiList, node);
+ RLC_FREE(gCb, node, sizeof(CmLList));
+ RLC_FREE(gCb, snssaiNode, sizeof(RlcTptPerSnssai));
+ DU_LOG("\nINFO --> RLC : SNSSAI node found and deletion performed");
+
+ if(snssaiList->count == 0)
+ {
+ RLC_FREE(gCb, snssaiList, sizeof(CmLListCp));
+ DU_LOG("\nINFO --> RLC : This SNSSAI was last in the list thus freeing the list also");
+ }
+ }
+ else
+ {
+ DU_LOG("\nERROR --> RLC : SNSSAI node not found in List thus no deletion performed");
+ }
+ return NULLP;
+ }
+ }
+ return (snssaiNode);
+}
+
+/**
+ * @brief
+ * Handler for Deleting SnssnaiTput List.
+ *
+ * @details
+ * This function is called during Shutdown to remove all the snssai entries
+ * and deallocate the SNSSAI tput list as well
+ *
+ * @param[in] gCb RlcCb
+ *
+ * @return void
+ *
+ */
+void rlcDelTputSnssaiList(RlcCb *gCb)
+{
+ CmLListCp *snssaiList = NULLP;
+ CmLList *node = NULLP, *next = NULLP;
+ RlcTptPerSnssai *snssaiNode = NULLP;
+
+ snssaiList = gCb->rlcThpt.snssaiTputInfo.tputPerSnssaiList;
+ if(snssaiList == NULLP)
+ {
+ DU_LOG("\nERROR --> RLC: SnssaiList not exist");
+ return;
+ }
+ node = snssaiList->first;
+
+ /*Traversing the LC LinkList*/
+ while(node)
+ {
+ snssaiNode = (RlcTptPerSnssai *)node->node;
+ next = node->next;
+ node = cmLListDelFrm(snssaiList, node);
+ RLC_FREE(gCb, node, sizeof(CmLList));
+ RLC_FREE(gCb, snssaiNode, sizeof(RlcTptPerSnssai));
+ node = next;
+ }
+ if(snssaiList->count == 0)
+ {
+ RLC_FREE(gCb, snssaiList, sizeof(CmLListCp));
+ DU_LOG("\nINFO --> RLC : This SNSSAI was last in the list thus freeing the list also");
+ }
+}
+
+/**
+ * @brief
+ * Handler for calculating the Tput for each SNSSAI in Tput list after expiry.
+ *
+ * @details
+ * This function is called whenever SNSSAI Tput timer expires and calculate
+ * Tput for each Snssai in list
+ *
+ * @param[in] SnssaiList A list of Snssai
+ *
+ * @return void
+ *
+ */
+void rlcCalculateTputPerSnssai(CmLListCp *snssaiList)
+{
+ CmLList *node = NULLP;
+ RlcTptPerSnssai *snssaiNode = NULLP;
+ double long tpt = 0;
+
+ node = snssaiList->first;
+ if(node == NULLP)
+ {
+ DU_LOG("\n No SNSSAI in list");
+ return;
+ }
+ /*Traversing the LC LinkList*/
+ while(node)
+ {
+ snssaiNode = (RlcTptPerSnssai *)node->node;
+ tpt = (double)(snssaiNode->dataVol * 8)/(double)ODU_SNSSAI_THROUGHPUT_PRINT_TIME_INTERVAL;
+ DU_LOG("\nSNSSAI(sst:%d,sd [%d,%d, %d]), DL Tpt : %.2Lf", snssaiNode->snssai->sst, snssaiNode->snssai->sd[0], \
+ snssaiNode->snssai->sd[1],snssaiNode->snssai->sd[2] , tpt);
+ snssaiNode->dataVol = 0;
+ node = node->next;
+ }
+ return;
+}
/********************************************************************30**
End of file
**********************************************************************/
#ifdef LTE_L2_MEAS
#define EVENT_RLC_L2_TMR 6
#endif /* LTE_L2_MEAS */
-#define EVENT_RLC_THROUGHPUT_TMR 7
+#define EVENT_RLC_UE_THROUGHPUT_TMR 7
#define EVENT_RLC_UE_DELETE_TMR 8
+#define EVENT_RLC_SNSSAI_THROUGHPUT_TMR 9
/* Wait time for RLC Timers */
#define RLC_UE_DELETE_WAIT_TIME 5 /*in milliseconds */
#endif /* LTE_L2_MEAS */
}RlcUlCb;
+typedef enum
+{
+ SEARCH,
+ CREATE,
+ DELETE
+}RlcSnssaiActionType;
+
typedef struct rlcThptPerUe
{
uint16_t ueId;
uint64_t dataVol;
}RlcThptPerUe;
+typedef struct rlcTptPerSnssai
+{
+ Snssai *snssai;
+ uint64_t dataVol;
+}RlcTptPerSnssai;
+
+
+typedef struct rlcSnssaiTputInfo
+{
+ CmTimer snssaiThptTmr; /* Throughput Timer */
+ CmLListCp *tputPerSnssaiList;
+}RlcSnssaiTputInfo;
+
+typedef struct rlcUeTputInfo
+{
+ CmTimer ueThptTmr; /* Throughput Timer */
+ uint8_t numActvUe; /* Number of Active UEs */
+ RlcThptPerUe thptPerUe[MAX_NUM_UE]; /* Throughput calculated per UE */
+}RlcUeTputInfo;
/**
* @brief Structure to hold information about throughput at RLC
*
*/
typedef struct rlcThpt
{
- Inst inst; /* RLC instance */
- CmTimer thptTmr; /* Throughput Timer */
- uint8_t numActvUe; /* Number of Active UEs */
- RlcThptPerUe thptPerUe[MAX_NUM_UE]; /* Throughput calculated per UE */
+ Inst inst; /* RLC instance */
+ RlcUeTputInfo ueTputInfo;
+ RlcSnssaiTputInfo snssaiTputInfo;
}RlcThpt;
/**
bool rlcChkTmr ARGS((RlcCb *gCb,PTR cb, S16 tmrEvnt));
-void rlcThptTmrExpiry(PTR cb);
+void rlcUeThptTmrExpiry(PTR cb);
uint8_t rlcUeDeleteTmrExpiry(PTR cb);
+void rlcSnssaiThptTmrExpiry(PTR cb);
+RlcTptPerSnssai* rlcHandleSnssaiTputlist(RlcCb *gCb, Snssai *snssai,\
+ RlcSnssaiActionType action);
+void rlcCalculateTputPerSnssai(CmLListCp *snssaiList);
+void rlcDelTputSnssaiList(RlcCb *gCb);
+
#ifdef LTE_L2_MEAS
Void rlcLmmSendAlarm ARGS (( RlcCb *gCb,
uint16_t category,
//Debug
uint32_t staIndSz=0,datIndSz = 0;
+ RlcTptPerSnssai *snssaiTputNode = NULLP;
datReqInfo = NULLP;
RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
#ifdef LTE_L2_MEAS
ueCb->tbIdx = (ueCb->tbIdx+1) % RLC_MAX_TB_PER_UE;
#endif
+ snssaiTputNode = NULLP;
for (count = 0;count < staIndTb->nmbLch; count++)
{
#ifdef LTE_L2_MEAS
if (rbCb && (!rlcDlUtlIsReestInProgress(rbCb)))
{
/* Cosider buffer size for throughput calculation */
- if(gCb->rlcThpt.thptPerUe[ueId-1].ueId == ueId)
- gCb->rlcThpt.thptPerUe[ueId-1].dataVol += staIndTb->lchStaInd[count].totBufSize;
+ if(gCb->rlcThpt.ueTputInfo.thptPerUe[ueId-1].ueId == ueId)
+ gCb->rlcThpt.ueTputInfo.thptPerUe[ueId-1].dataVol += staIndTb->lchStaInd[count].totBufSize;
+
+ if(rbCb->snssai)
+ {
+ snssaiTputNode = rlcHandleSnssaiTputlist(gCb, rbCb->snssai, SEARCH);
+ if(snssaiTputNode != NULLP)
+ {
+ snssaiTputNode->dataVol += staIndTb->lchStaInd[count].totBufSize;
+ DU_LOG("\nINFO -->SCH: SNSSAI List Grant:%d, lcId:%d, total :%d",\
+ staIndTb->lchStaInd[count].totBufSize, staIndTb->lchStaInd[count].lcId,\
+ snssaiTputNode->dataVol);
+ }
+ }
staIndSz += staIndTb->lchStaInd[count].totBufSize;
datReq.pduSz = staIndTb->lchStaInd[count].totBufSize;
SchCellCb *cell = NULLP;
SchDlSlotInfo *schDlSlotInfo = NULLP;
Inst inst = pst->dstInst-SCH_INST_START;
+ CmLListCp *lcLL = NULLP;
#ifdef CALL_FLOW_DEBUG_LOG
DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_DL_RLC_BO_INFO_TO_SCH\n");
return RFAILED;
}
+ /*Expected when theres a case of Retransmission Failure or Resetablishment
+ *By Zero BO, the RLC is informing that previous data can be cleared out
+ *Thus clearing out the LC from the Lc priority list*/
+ if(dlBoInfo->dataVolume == 0)
+ {
+ /*Check the LC is Dedicated or default and accordingly LCList will
+ * be used*/
+ if(ueCb->dlInfo.dlLcCtxt[lcId].isDedicated)
+ {
+ lcLL = &(ueCb->dlLcPrbEst.dedLcInfo->dedLcList);
+ }
+ else
+ {
+ lcLL = &(ueCb->dlLcPrbEst.defLcList);
+ }
+ handleLcLList(lcLL, lcId, DELETE);
+ return ROK;
+ }
+
memset(&dlMsgInfo, 0, sizeof(DlMsgInfo));
dlMsgInfo.crnti = dlBoInfo->crnti;
dlMsgInfo.ndi = 1;
dlMsgInfo.pucchResInd = 0;
dlMsgInfo.harqFeedbackInd = 0;
dlMsgInfo.dciFormatId = 1;
-
+
if(lcId == SRB0_LCID)
{
cell->raCb[ueId -1].msg4recvd = true;
uint8_t updateDedLcInfo(Snssai *snssai, SchRrmPolicy *rrmPolicy, SchLcPrbEstimate *lcPrbEst,\
bool *isDedicated)
{
- if(memcmp(snssai, &(rrmPolicy->memberList.snssai), sizeof(Snssai)))
+ if(memcmp(snssai, &(rrmPolicy->memberList.snssai), sizeof(Snssai)) == 0)
{
if(lcPrbEst->dedLcInfo == NULLP)
{
#define MAX_NUM_RB TOTAL_PRB_20MHZ_MU0 /* value for numerology 0, 20 MHz */
#endif
-#define ODU_THROUGHPUT_PRINT_TIME_INTERVAL 5 /* in milliseconds */
+#define ODU_UE_THROUGHPUT_PRINT_TIME_INTERVAL 5 /* in milliseconds */
+#define ODU_SNSSAI_THROUGHPUT_PRINT_TIME_INTERVAL 60000 /* in milliseconds */
/* Defining macros for common utility functions */
#define ODU_GET_MSG_BUF SGetMsg