RlcSn mSn;
uint8_t fByte;
bool discFlg;
-#ifdef LTE_L2_MEAS_RLC
- MsgLen rlcSduSz; /*Holds length of Rlc Sdu*/
-#endif /* LTE_L2_MEAS */
+ RlcTptPerSnssai *snssaiTputNode = NULLP;
+ MsgLen pduSz = 0; /*Holds length of Rlc Sdu*/
amUl = &RLC_AMUL;
numPduToProcess = RLC_MIN(pduInfo->numPdu, RGU_MAX_PDU);
DU_LOG("\nDEBUG --> RLC_UL : rlcAmmProcessPdus: numPdu[%d],numPduToProcess[%d] UEID:%d CELLID:%d",
- numPdu, numPduToProcess, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
+ numPdu, numPduToProcess, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
while (numPdu < numPduToProcess)
{
discFlg = FALSE;
pdu = pduInfo->mBuf[numPdu++];
-
+ snssaiTputNode = NULLP;
if (! pdu)
{
DU_LOG("\nERROR --> RLC_UL : rlcAmmProcessPdus: Null Pdu UEID:%d CELLID:%d",
- rbCb->rlcId.ueId, rbCb->rlcId.cellId);
+ rbCb->rlcId.ueId, rbCb->rlcId.cellId);
gCb->genSts.errorPdusRecv++;
break;
}
if (rlcAmmExtractHdr(gCb, rbCb, pdu, &amHdr, &fByte) != ROK)
{
DU_LOG("\nERROR --> RLC_UL : rlcAmmProcessPdus: Header Extraction Failed UEID:%d CELLID:%d",
- rbCb->rlcId.ueId, rbCb->rlcId.cellId);
+ rbCb->rlcId.ueId, rbCb->rlcId.cellId);
ODU_PUT_MSG_BUF(pdu);
gCb->genSts.errorPdusRecv++;
continue;
if((amHdr.si == RLC_SI_LAST_SEG) && (!amHdr.so))
{
DU_LOG("\nERROR --> RLC_UL : rlcAmmProcessPdus: Dropping PDU because SO can't be zero\
- for last segment sn:%u UEID:%d CELLID:%d", amHdr.sn, rbCb->rlcId.ueId,
- rbCb->rlcId.cellId);
+ for last segment sn:%u UEID:%d CELLID:%d", amHdr.sn, rbCb->rlcId.ueId,
+ rbCb->rlcId.cellId);
ODU_PUT_MSG_BUF(pdu);
continue;
}
#ifndef TENB_ACC
#ifndef TENB_T2K3K_SPECIFIC_CHANGES
#ifndef LTE_PAL_ENB
- /* Changed the condition to TRUE from ROK */
+ /* Changed the condition to TRUE from ROK */
if(isMemThreshReached(rlcCb[0]->init.region) == TRUE)
{
uint32_t rlculdrop;
- rlculdrop++;
- ODU_PUT_MSG_BUF(pdu);
- continue;
+ rlculdrop++;
+ ODU_PUT_MSG_BUF(pdu);
+ continue;
}
#endif
#else
rlcUtlCalUlIpThrPut(gCb, rbCb, pdu, ttiCnt);
#endif /* LTE_L2_MEAS */
+ if(rbCb->snssai)
+ {
+ snssaiTputNode = rlcHandleSnssaiTputlist(gCb, rbCb->snssai, SEARCH, DIR_UL);
+ if(snssaiTputNode != NULLP)
+ {
+ ODU_GET_MSG_LEN(pdu, &pduSz);
+ snssaiTputNode->dataVol += (uint64_t)pduSz;
+ DU_LOG("\nINFO --> RLC_UL: SNSSAI AMM_UL List PduLen:%d, lcId:%d, total :%ld",\
+ pduSz, rbCb->lch.lChId, snssaiTputNode->dataVol);
+ }
+ }
/* Update rxNextHighestRcvd */
MODAMR(sn, mSn, amUl->rxNext, amUl->snModMask);
MODAMR(amUl->rxNextHighestRcvd, mrxNextHighestRcvd, amUl->rxNext, amUl->snModMask);
amUl->rxNextHighestRcvd = ((sn + 1) & (amUl->snModMask));
DU_LOG("\nDEBUG --> RLC_UL : rlcAmmProcessPdus: Updated rxNextHighestRcvd = %d UEID:%d CELLID:%d",
- amUl->rxNextHighestRcvd, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
+ amUl->rxNextHighestRcvd, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
}
-
+
recBuf = rlcUtlGetRecBuf(amUl->recBufLst, sn);
if ((NULLP != recBuf) && ( recBuf->allRcvd))
{
/* deliver the reassembled RLC SDU to upper layer,
- But not removed from the table */
+ But not removed from the table */
rlcAmmUlReassembleSdus(gCb, rbCb, recBuf);
recBuf->isDelvUpperLayer = TRUE;
MODAMR(amUl->vrMr, tVrMr, amUl->rxNext, amUl->snModMask);
-
+
/* Update rxHighestStatus */
if (sn == amUl->rxHighestStatus)
{
while (mSn <= tVrMr)
{
if ((NULLP != recBuf) && (recBuf->allRcvd) &&
- (TRUE == recBuf->isDelvUpperLayer))
- {
- /* RecBuf should remove from table
- since PDU is already sent to upper layer */
- recBuf->isDelvUpperLayer = FALSE;
- rlcUtlDelRecBuf(amUl->recBufLst, recBuf, gCb);
+ (TRUE == recBuf->isDelvUpperLayer))
+ {
+ /* RecBuf should remove from table
+ since PDU is already sent to upper layer */
+ recBuf->isDelvUpperLayer = FALSE;
+ rlcUtlDelRecBuf(amUl->recBufLst, recBuf, gCb);
}
else
{
Bool snInWin = RLC_AM_CHK_SN_WITHIN_RECV_WINDOW(amUl->rxNextStatusTrig, amUl);
/* spec 38.322v15.3.0 - 5.2.3.2.3 */
if((amUl->rxNextStatusTrig == amUl->rxNext) || ( (!snInWin) &&
- (amUl->rxNextStatusTrig != amUl->vrMr) )||
- (amUl->rxNextStatusTrig == amUl->rxNext && recBuf &&recBuf->noMissingSeg))
+ (amUl->rxNextStatusTrig != amUl->vrMr) )||
+ (amUl->rxNextStatusTrig == amUl->rxNext && recBuf &&recBuf->noMissingSeg))
{
rlcStopTmr(gCb,(PTR)rbCb, EVENT_RLC_AMUL_REASSEMBLE_TMR);
tmrRunning = FALSE;
DU_LOG("\nINFO --> RLC_UL: rlcAmmProcessPdus: Stopped ReAssembly Timer rxNextStatusTigger = %d"
- "rxNextReassembly = %d", amUl->rxNextStatusTrig, amUl->rxNext);
+ "rxNextReassembly = %d", amUl->rxNextStatusTrig, amUl->rxNext);
}
}
{
/* spec 38.322v15.3.0 - 5.2.3.2.3 */
if((amUl->rxNextHighestRcvd > amUl->rxNext) || ((amUl->rxNextHighestRcvd == amUl->rxNext) &&
- (recBuf && (!recBuf->noMissingSeg))))
+ (recBuf && (!recBuf->noMissingSeg))))
{
rlcStartTmr(gCb,(PTR)rbCb, EVENT_RLC_AMUL_REASSEMBLE_TMR);
amUl->rxNextStatusTrig = amUl->rxNextHighestRcvd;
DU_LOG("\nDEBUG --> RLC_UL : rlcAmmProcessPdus: Updated rxNextStatusTrig = %d"
- "UEID:%d CELLID:%d", amUl->rxNextStatusTrig, rbCb->rlcId.ueId,
- rbCb->rlcId.cellId);
+ "UEID:%d CELLID:%d", amUl->rxNextStatusTrig, rbCb->rlcId.ueId,
+ rbCb->rlcId.cellId);
}
}
}
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)
+ if(rlcHandleSnssaiTputlist(gCb, rbCb->snssai, CREATE, DIR_DL) == NULLP)
{
DU_LOG("\nERROR --> RLC_DL : rlcCfgFillDlRbCb(): SNSSAI insertion in Tput list failed");
}
}
}
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, DIR_UL) == NULLP)
+ {
+ DU_LOG("\nERROR --> RLC_UL : rlcCfgFillUlRbCb(): SNSSAI insertion in Tput list failed");
+ }
}
rbCb->mode = entCfg->entMode;
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);
}
}
}
-
+
if(gCb->genCfg.rlcMode == LKW_RLC_MODE_DL)
{
rlcDbmDlShutdown(gCb);
+ rlcDelTputSnssaiList(gCb, DIR_DL);
}
else
{
rlcDbmUlShutdown(gCb);
+ rlcDelTputSnssaiList(gCb, DIR_UL);
}
- rlcDelTputSnssaiList(gCb);
rlcLmmCleanGblRsrcs(gCb);
RLC_MEM_SET (&(gCb->genSts), 0, sizeof (RlcGenSts));
return ret;
}
+/*******************************************************************
+*
+* @brief Send the Slice Metrics to DU APP
+*
+* @details
+*
+* Function : sendSlicePmToDu
+*
+* Functionality:
+* Handles the sending of Slice Metrics to DU APP
+*
+* @params[in] Post structure pointer
+* SlicePmList *sliceStats pointer
+*
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+uint8_t sendSlicePmToDu(SlicePmList *sliceStats)
+{
+ Pst pst;
+
+ FILL_PST_RLC_TO_DUAPP(pst, RLC_UL_INST, EVENT_RLC_SLICE_PM_TO_DU);
+
+ if(!sliceStats)
+ {
+ DU_LOG("\nERROR --> RLC: sendSlicePmToDu(): Memory allocation failed ");
+ return RFAILED;
+ }
+ else
+ {
+ if(rlcSendSlicePmToDu(&pst, sliceStats) == ROK)
+ {
+ DU_LOG("\nDEBUG --> RLC: Slice PM send successfully");
+ }
+ else
+ {
+ DU_LOG("\nERROR --> RLC: sendSlicePmToDu():Failed to send Slice PM to DU");
+ RLC_FREE_SHRABL_BUF(pst.region, pst.pool, sliceStats, sizeof(SlicePmList));
+ return RFAILED;
+ }
+ }
+ return ROK;
+}
+
+/**
+ * @brief
+ * Handler for searching the Slice Entry in Slice Metrics structure
+ *
+ * @details
+ * This func finds the slice entry in the SliceMetric record structure and
+ * return the index of the slice sot hat Tput entries can be done
+ *
+ * @param[in] snssaiVal : Snssai Val to be searched
+ * *snssaiIdx : O/P : Index of the Slice in Slice Metrics record
+ * sliceStats : Pointer of Slice metrics record list
+ *
+ * @return bool: True: If slice found in the record
+ * False: If Slice not found; thus parent function will create the
+ * recpord of this snssai
+ *
+ */
+bool rlcFindSliceEntry(uint32_t snssaiVal, uint8_t *snssaiIdx, SlicePmList *sliceStats)
+{
+ uint8_t cntSlices = sliceStats->numSlice;
+
+ for(*snssaiIdx = 0;(*snssaiIdx) < cntSlices; (*snssaiIdx)++)
+ {
+ if(snssaiVal == sliceStats->sliceRecord[*snssaiIdx].networkSliceIdentifier)
+ {
+ return TRUE;
+ }
+ }
+ DU_LOG("\nERROR --> RLC: Total no of Slice exhausted!");
+ return FALSE;
+}
+
+
+/*******************************************************************
+*
+* @brief Builds the Slice Performance Metrics structure to be sent to DU
+*
+* @details
+*
+* Function : BuildSliceReportToDu
+*
+* Functionality:
+* Builds the Slice Performance Metrics structure to be sent to DU
+*
+* @params[in] uint8_t snssaiCnt
+*
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+uint8_t BuildSliceReportToDu(uint8_t snssaiCnt)
+{
+ CmLList *node = NULLP;
+ RlcTptPerSnssai *snssaiNode = NULLP;
+ Direction dir = DIR_UL;
+ SlicePmList *sliceStats = NULLP; /*Slice metric */
+ uint32_t snssaiVal = 0;
+ uint8_t snssaiIdx = 0;
+
+ if(snssaiCnt == 0)
+ {
+ DU_LOG("\nERROR --> RLC: No SNSSAI to send the SLice PM");
+ return RFAILED;
+ }
+
+ RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL, sliceStats, sizeof(SlicePmList));
+ if(sliceStats == NULLP)
+ {
+ DU_LOG("\nERROR --> RLC: Memory Allocation Failed");
+ return RFAILED;
+ }
+ RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL, sliceStats->sliceRecord, snssaiCnt * (sizeof(SlicePm)));
+
+ if(sliceStats->sliceRecord == NULLP)
+ {
+ DU_LOG("\nERROR --> RLC: Memory Allocation Failed");
+ RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL, sliceStats, sizeof(SlicePmList));
+ return RFAILED;
+ }
+ while(dir < DIR_BOTH)
+ {
+ node = arrTputPerSnssai[dir]->first;
+ if(node == NULLP)
+ {
+ DU_LOG("\nERROR --> RLC: No SNSSAI in list");
+ RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL, sliceStats, sizeof(SlicePmList));
+ RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL, sliceStats->sliceRecord, (snssaiCnt * (sizeof(SlicePm))));
+ return RFAILED;
+ }
+
+ while(node)
+ {
+ snssaiVal = 0;
+ snssaiIdx = 0;
+ snssaiNode = (RlcTptPerSnssai *)node->node;
+
+ memcpy(&snssaiVal, snssaiNode->snssai, sizeof(Snssai));
+
+ if(rlcFindSliceEntry(snssaiVal, &snssaiIdx, sliceStats) == FALSE)
+ {
+ sliceStats->sliceRecord[snssaiIdx].networkSliceIdentifier = snssaiVal;
+ sliceStats->numSlice++;
+ }
+ if(dir == DIR_UL)
+ {
+ sliceStats->sliceRecord[snssaiIdx].ThpUl = snssaiNode->tpt;
+ }
+ else
+ {
+ sliceStats->sliceRecord[snssaiIdx].ThpDl = snssaiNode->tpt;
+ }
+ node = node->next;
+ }
+ dir++;
+ }
+
+ sendSlicePmToDu(sliceStats);
+ return ROK;
+}
/**********************************************************************
End of file
**********************************************************************/
/* private function declarations */
static Void rlcBndTmrExpiry(PTR cb);
+
/**
* @brief Handler to start timer
*
*/
void rlcSnssaiThptTmrExpiry(PTR cb)
{
- long double tpt;
RlcThpt *rlcThptCb = (RlcThpt*)cb;
+ static uint8_t snssaiCntDl = 0, snssaiCntUl = 0;
+ /*Bit map to keep record of reception of DL and UL Snssai Tput expiry*/
+ static uint8_t snssaiTputBitmap = DIR_NONE;
+
/* If cell is not up, throughput details cannot be printed */
if(gCellStatus != CELL_UP)
{
rlcStartTmr(RLC_GET_RLCCB(rlcThptCb->inst), (PTR)(rlcThptCb), EVENT_RLC_SNSSAI_THROUGHPUT_TMR);
return;
}
-
- DU_LOG("\n==================================================================");
- if(rlcThptCb->snssaiTputInfo.tputPerSnssaiList != NULLP)
+
+ if(rlcThptCb->snssaiTputInfo.dlTputPerSnssaiList != NULLP)
{
- DU_LOG("\n===================== DL Throughput Per SNSSAI ==============================");
-
- rlcCalculateTputPerSnssai(rlcThptCb->snssaiTputInfo.tputPerSnssaiList);
- DU_LOG("\n==================================================================");
+ snssaiCntDl = rlcCalculateTputPerSnssai(rlcThptCb->snssaiTputInfo.dlTputPerSnssaiList, DIR_DL);
+ snssaiTputBitmap |= DIR_DL;
+ arrTputPerSnssai[DIR_DL] = rlcThptCb->snssaiTputInfo.dlTputPerSnssaiList;
+ }
+ if(rlcThptCb->snssaiTputInfo.ulTputPerSnssaiList != NULLP)
+ {
+ snssaiCntUl = rlcCalculateTputPerSnssai(rlcThptCb->snssaiTputInfo.ulTputPerSnssaiList, DIR_UL);
+ snssaiTputBitmap |= DIR_UL;
+ arrTputPerSnssai[DIR_UL] = rlcThptCb->snssaiTputInfo.ulTputPerSnssaiList;
+ }
+ if(snssaiTputBitmap == DIR_BOTH)
+ {
+ //call the function
+ BuildSliceReportToDu(MAX(snssaiCntUl, snssaiCntDl));
+ snssaiTputBitmap = DIR_NONE;
}
/* Restart timer */
rlcStartTmr(RLC_GET_RLCCB(rlcThptCb->inst), (PTR)rlcThptCb, EVENT_RLC_SNSSAI_THROUGHPUT_TMR);
RlcSn tRxNextReassembly;
RlcSn tRxNextReassemblyNxt;
RlcSn tRxNextHighest;
+ RlcTptPerSnssai *snssaiTputNode = NULLP;
count = 0;
/* pduCount should be the min of RGU_MAX_PDU and pduInfo->numPdu */
pduCount = (pduInfo->numPdu < RGU_MAX_PDU)? pduInfo->numPdu : RGU_MAX_PDU;
-
+
vrUh = &(rbCb->m.umUl.vrUh);
vrUr = &(rbCb->m.umUl.vrUr);
vrUx = &(rbCb->m.umUl.vrUx);
RlcSn seqNum;
Buffer *pdu = pduInfo->mBuf[count];
+ pduSz = 0; /*re-intialize the size*/
+ snssaiTputNode = NULLP;
+
gCb->genSts.pdusRecv++;
#ifndef RGL_SPECIFIC_CHANGES
#ifndef TENB_ACC
#ifndef RGL_SPECIFIC_CHANGES
#ifndef TENB_ACC
#ifndef LTE_PAL_ENB
- /* Changed the condition to TRUE from ROK */
+ /* Changed the condition to TRUE from ROK */
#ifndef XEON_SPECIFIC_CHANGES
- if(isMemThreshReached(rlcCb[0]->init.region) == TRUE)
- {
- uint32_t rlculdrop;
- rlculdrop++;
- ODU_PUT_MSG_BUF(pdu);
- count++;
- continue;
- }
+ if(isMemThreshReached(rlcCb[0]->init.region) == TRUE)
+ {
+ uint32_t rlculdrop;
+ rlculdrop++;
+ ODU_PUT_MSG_BUF(pdu);
+ count++;
+ continue;
+ }
#endif
#endif
#endif
if (rlcUmmExtractHdr(gCb, rbCb, pdu, &umHdr))
{
DU_LOG("\nERROR --> RLC_UL: rlcUmmProcessPdus: Header Extraction Failed UEID:%d CELLID:%d",\
- rbCb->rlcId.ueId, rbCb->rlcId.cellId);
+ rbCb->rlcId.ueId, rbCb->rlcId.cellId);
ODU_PUT_MSG_BUF(pdu);
count++;
gCb->genSts.errorPdusRecv++;
continue;
}
+ if(rbCb->snssai)
+ {
+ snssaiTputNode = rlcHandleSnssaiTputlist(gCb, rbCb->snssai, SEARCH, DIR_UL);
+ if(snssaiTputNode != NULLP)
+ {
+ ODU_GET_MSG_LEN(pdu, &pduSz);
+ snssaiTputNode->dataVol += (uint64_t)pduSz;
+ DU_LOG("\nINFO --> RLC_UL: UMM_UL SNSSAI List PduLen:%d, lcId:%d, total :%ld",\
+ pduSz, rbCb->lch.lChId, snssaiTputNode->dataVol);
+ }
+ }
+
/* Check if the PDU should be delivered to upper layer */
if(umHdr.si == 0)
{
rlcUtlSendUlDataToDu(gCb, rbCb, pdu);
- ODU_PUT_MSG_BUF(pdu);
- count++;
- continue;
+ ODU_PUT_MSG_BUF(pdu);
+ count++;
+ continue;
}
curSn = umHdr.sn;
{
/* PDU needs to be discarded */
DU_LOG("\nINFO --> RLC_UL: rlcUmmProcessPdus: Received an unexpected pdu with sn %d \
- UEID:%d CELLID:%d", curSn, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
+ UEID:%d CELLID:%d", curSn, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
ODU_PUT_MSG_BUF(pdu);
count++;
if (recBuf == NULLP)
{
DU_LOG("\nERROR --> RLC_UL: rlcUmmProcessPdus: recBuf is NULLP UEID:%d CELLID:%d", \
- rbCb->rlcId.ueId, rbCb->rlcId.cellId);
- ODU_PUT_MSG_BUF(pdu);
- count++;
+ rbCb->rlcId.ueId, rbCb->rlcId.cellId);
+ ODU_PUT_MSG_BUF(pdu);
+ count++;
continue;
}
{
rlcUmmReAssembleSdus(gCb, rbCb, recBuf);
DU_LOG("\nDEBUG --> RLC_UL: rlcUmmProcessPdus: Assembled the Sdus for sn = %d UEID:%d CELLID:%d",\
- umHdr.sn, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
+ umHdr.sn, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
/* if curSn is same as the RX_NEXT_Reassembly */
if (seqNum == ur)
else if (!rlcUmmCheckSnInReassemblyWindow(curSn,&RLC_UMUL))
{
DU_LOG("\nDEBUG --> RLC_UL: rlcUmmProcessPdus: curent sn is outSide the re-Assembly window. \
- sn = %d UEID:%d CELLID:%d", umHdr.sn, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
+ sn = %d UEID:%d CELLID:%d", umHdr.sn, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
- /* update RX_NEXT_Highest */
+ /* update RX_NEXT_Highest */
*vrUh = (curSn + 1) & RLC_UMUL.modBitMask;
/* Discard all pdus outside the modified re-assembly window */
RlcSn packetCount;
/* Set RX_NEXT_Reassembly to next SN >= (RX_NEXT_Highest - windowSize) that has not been reassembled yet */
- *vrUr = (*vrUh - RLC_UMUL.umWinSz) & RLC_UMUL.modBitMask;
- lowerEdge = *vrUr;
+ *vrUr = (*vrUh - RLC_UMUL.umWinSz) & RLC_UMUL.modBitMask;
+ lowerEdge = *vrUr;
packetCount = (lowerEdge - sn) & RLC_UMUL.modBitMask;
-
+
while (packetCount)
{
recBuf = rlcUtlGetUmRecBuf(RLC_UMUL.recBufLst, sn);
sn = (sn + 1) & RLC_UMUL.modBitMask;
packetCount--;
}
- recBuf = rlcUtlGetUmRecBuf(RLC_UMUL.recBufLst, *vrUr);
- if (recBuf != NULLP && recBuf->allSegRcvd)
- {
- /* set rxNextReassembly to next SN > current rxNextReassembly which is not received */
- RlcSn nextRxNextReassembly = (*vrUr + 1) & RLC_UMUL.modBitMask;
- rlcUmmFindRxNextReassembly(gCb ,&RLC_UMUL, nextRxNextReassembly);
- }
+ recBuf = rlcUtlGetUmRecBuf(RLC_UMUL.recBufLst, *vrUr);
+ if (recBuf != NULLP && recBuf->allSegRcvd)
+ {
+ /* set rxNextReassembly to next SN > current rxNextReassembly which is not received */
+ RlcSn nextRxNextReassembly = (*vrUr + 1) & RLC_UMUL.modBitMask;
+ rlcUmmFindRxNextReassembly(gCb ,&RLC_UMUL, nextRxNextReassembly);
+ }
}
}
- tmrRunning = rlcChkTmr(gCb,(PTR)rbCb, EVENT_RLC_UMUL_REASSEMBLE_TMR);
+ tmrRunning = rlcChkTmr(gCb,(PTR)rbCb, EVENT_RLC_UMUL_REASSEMBLE_TMR);
tRxNextReassembly = RLC_UM_GET_VALUE(*vrUr ,RLC_UMUL);
tRxNextReassemblyNxt = (*vrUr + 1) & rbCb->m.umUl.modBitMask;
tRxNextHighest = RLC_UM_GET_VALUE(*vrUh, RLC_UMUL);
tRxNextReassemblyNxt = RLC_UM_GET_VALUE(tRxNextReassemblyNxt ,RLC_UMUL);
- /* If reassemby timer is running */
- if (tmrRunning)
- {
- RlcSn tRxTimerTigger = RLC_UM_GET_VALUE(*vrUx, RLC_UMUL);
- uint8_t ret = rlcUmmCheckSnInReassemblyWindow(*vrUx, &RLC_UMUL);
- recBuf = rlcUtlGetUmRecBuf(RLC_UMUL.recBufLst,*vrUr);
+ /* If reassemby timer is running */
+ if (tmrRunning)
+ {
+ RlcSn tRxTimerTigger = RLC_UM_GET_VALUE(*vrUx, RLC_UMUL);
+ uint8_t ret = rlcUmmCheckSnInReassemblyWindow(*vrUx, &RLC_UMUL);
+ recBuf = rlcUtlGetUmRecBuf(RLC_UMUL.recBufLst,*vrUr);
if ((tRxTimerTigger <= tRxNextReassembly) || ((!ret) && (tRxTimerTigger != tRxNextHighest)) ||
- (tRxNextHighest == tRxNextReassemblyNxt && recBuf && recBuf->noMissingSeg))
+ (tRxNextHighest == tRxNextReassemblyNxt && recBuf && recBuf->noMissingSeg))
{
rlcStopTmr(gCb,(PTR)rbCb, EVENT_RLC_UMUL_REASSEMBLE_TMR);
tmrRunning = FALSE;
DU_LOG("\nINFO --> RLC_UL: rlcUmmProcessPdus: Stopped ReAssembly Timer rxTimerTigger = %d \
- rxNextReassembly = %d rxNextHighest = %d ", tRxTimerTigger, tRxNextReassembly, tRxNextHighest);
+ rxNextReassembly = %d rxNextHighest = %d ", tRxTimerTigger, tRxNextReassembly, tRxNextHighest);
}
- }
+ }
- /* If Reassembly timer is not running */
- if (!tmrRunning)
- {
+ /* If Reassembly timer is not running */
+ if (!tmrRunning)
+ {
recBuf = rlcUtlGetUmRecBuf(RLC_UMUL.recBufLst, curSn);
if ((tRxNextHighest > tRxNextReassemblyNxt) || ((tRxNextHighest == tRxNextReassemblyNxt)
- && (recBuf && (!recBuf->noMissingSeg))))
+ && (recBuf && (!recBuf->noMissingSeg))))
{
- DU_LOG("\nDEBUG --> RLC_UL: rlcUmmProcessPdus: Start ReAssembly Timer tRxNextReassemblyNxt = %d \
- tRxNextHighest %d", tRxNextReassemblyNxt, tRxNextHighest);
- rlcStartTmr(gCb, (PTR)rbCb, EVENT_RLC_UMUL_REASSEMBLE_TMR);
- *vrUx = *vrUh;
+ DU_LOG("\nDEBUG --> RLC_UL: rlcUmmProcessPdus: Start ReAssembly Timer tRxNextReassemblyNxt = %d \
+ tRxNextHighest %d", tRxNextReassemblyNxt, tRxNextHighest);
+ rlcStartTmr(gCb, (PTR)rbCb, EVENT_RLC_UMUL_REASSEMBLE_TMR);
+ *vrUx = *vrUh;
}
- }
+ }
}
else
{
DU_LOG("\nERROR --> RLC_UL: rlcUmmProcessPdus:Failed to assemble the PDU for SN = %d UEID:%d CELLID:%d",\
- umHdr.sn, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
+ umHdr.sn, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
}
count++;
packRlcDuUeDeleteRsp /* 2 - LWLC loosely coupled */
};
+RlcSlicePmToDuFunc rlcSlicePmOpts[] =
+{
+ packRlcDuSlicePm, /* 0 - loosely coupled */
+ DuProcRlcSliceMetrics, /* 1 - tightly coupled */
+ packRlcDuSlicePm /* 2 - LWLC loosely coupled */
+};
/*******************************************************************
*
* @brief Sends UL RRC Message Info to DU APP
return (*rlcUeDeleteRspOpts[pst->selector])(pst, ueDeleteRsp);
}
+/*******************************************************************
+ *
+ * @brief Sends Slice Performance Metrics to DU APP
+ *
+ * @details
+ *
+ * Function : rlcSendSlicePmToDu
+ *
+ * Functionality: Sends Performace Metrics per slice together to DU APP
+ *
+ * @params[in] Pst *pst, SlicePmList *sliceStats
+ *
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t rlcSendSlicePmToDu(Pst *pst, SlicePmList *sliceStats)
+{
+ return (*rlcSlicePmOpts[pst->selector])(pst, sliceStats);
+}
/**********************************************************************
End of file
**********************************************************************/
uint8_t rlcSendDlRrcMsgRspToDu(Pst *pst, RlcDlRrcMsgRsp *dlRrcMsgRsp);
uint8_t rlcSendUlUserDataToDu(Pst *pst, RlcUlUserDatInfo *ulUserData);
uint8_t rlcSendUeDeleteRspToDu(Pst *pst, RlcUeDeleteRsp *ueDeleteRsp);
+uint8_t rlcSendSlicePmToDu(Pst *pst, SlicePmList *sliceStats);
/**********************************************************************
End of file
**********************************************************************/
* -# Snssai Node
*
*/
-RlcTptPerSnssai* rlcHandleSnssaiTputlist(RlcCb *gCb, Snssai *snssai, RlcSnssaiActionType action)
+RlcTptPerSnssai* rlcHandleSnssaiTputlist(RlcCb *gCb, Snssai *snssai, RlcSnssaiActionType action, Direction dir)
{
CmLListCp *snssaiList = NULLP;
CmLList *node = NULLP;
RlcTptPerSnssai *snssaiNode = NULLP;
bool found = FALSE;
- snssaiList = gCb->rlcThpt.snssaiTputInfo.tputPerSnssaiList;
- if(snssaiList == NULLP)
+ if(dir == DIR_DL)
+ {
+ snssaiList = gCb->rlcThpt.snssaiTputInfo.dlTputPerSnssaiList;
+ if(action == CREATE)
+ {
+ if(snssaiList == NULLP)
+ {
+ RLC_ALLOC(gCb, gCb->rlcThpt.snssaiTputInfo.dlTputPerSnssaiList, sizeof(CmLListCp));
+ snssaiList = gCb->rlcThpt.snssaiTputInfo.dlTputPerSnssaiList;
+ cmLListInit(snssaiList);
+ }
+ }
+ else
+ {
+ if(snssaiList == NULLP)
+ {
+ DU_LOG("\nERROR --> RLC: SNSSAI DL list doesnt exist!");
+ return NULLP;
+ }
+ }
+ }
+ else if(dir == DIR_UL)
{
+ snssaiList = gCb->rlcThpt.snssaiTputInfo.ulTputPerSnssaiList;
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");
+ if(snssaiList == NULLP)
+ {
+ RLC_ALLOC(gCb, gCb->rlcThpt.snssaiTputInfo.ulTputPerSnssaiList, sizeof(CmLListCp));
+ snssaiList = gCb->rlcThpt.snssaiTputInfo.ulTputPerSnssaiList;
+ cmLListInit(snssaiList);
+ }
}
else
{
- DU_LOG("\nERROR --> RLC: SNSSAI list doesnt exist!");
- return NULLP;
+ if(snssaiList == NULLP)
+ {
+ DU_LOG("\nERROR --> RLC: SNSSAI UL list doesnt exist!");
+ return NULLP;
+ }
}
}
+ else
+ {
+ DU_LOG("\nERROR --> RLC : Direction:%d is invalid", dir);
+ return NULLP;
+ }
node = snssaiList->first;
*
* @param[in] gCb RlcCb
*
- * @return void
+ * @return uint_8 (ROK/RFAILED)
*
*/
-void rlcDelTputSnssaiList(RlcCb *gCb)
+uint8_t rlcDelTputSnssaiList(RlcCb *gCb, Direction dir)
{
CmLListCp *snssaiList = NULLP;
CmLList *node = NULLP, *next = NULLP;
RlcTptPerSnssai *snssaiNode = NULLP;
-
- snssaiList = gCb->rlcThpt.snssaiTputInfo.tputPerSnssaiList;
+ if(dir == DIR_DL)
+ {
+ snssaiList = gCb->rlcThpt.snssaiTputInfo.dlTputPerSnssaiList;
+ }
+ else if(dir == DIR_UL)
+ {
+ snssaiList = gCb->rlcThpt.snssaiTputInfo.ulTputPerSnssaiList;
+ }
+ else
+ {
+ DU_LOG("\nERROR --> RLC: Invalid direction:%d",dir);
+ return RFAILED;
+ }
if(snssaiList == NULLP)
{
- DU_LOG("\nERROR --> RLC: SnssaiList not exist");
- return;
+ DU_LOG("\nERROR --> RLC: SnssaiList not exist");
+ return RFAILED;
}
node = snssaiList->first;
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");
+ DU_LOG("\nDEBUG --> RLC : This SNSSAI was last in the list thus freeing the list also");
}
+ return ROK;
}
/**
* @return void
*
*/
-void rlcCalculateTputPerSnssai(CmLListCp *snssaiList)
+uint8_t rlcCalculateTputPerSnssai(CmLListCp *snssaiList, Direction dir)
{
CmLList *node = NULLP;
RlcTptPerSnssai *snssaiNode = NULLP;
- double long tpt = 0;
+ uint8_t snssaiCnt = 0;
node = snssaiList->first;
if(node == NULLP)
{
DU_LOG("\n No SNSSAI in list");
- return;
+ return(snssaiCnt);
}
/*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->tpt = (double)(snssaiNode->dataVol * 8)/(double)(ODU_SNSSAI_THROUGHPUT_PRINT_TIME_INTERVAL * 0.001);
+
+ if(dir == DIR_DL)
+ {
+ DU_LOG("\nDEBUG --> RLC_DL: SNSSAI(sst:%d,sd [%d,%d, %d]), DL Tpt : %.5lf", snssaiNode->snssai->sst,\
+ snssaiNode->snssai->sd[0], snssaiNode->snssai->sd[1],snssaiNode->snssai->sd[2] , snssaiNode->tpt);
+ }
+ if(dir == DIR_UL)
+ {
+ DU_LOG("\nDEBUG --> RLC_UL: SNSSAI(sst:%d,sd [%d,%d, %d]), UL Tpt : %.5lf", snssaiNode->snssai->sst,\
+ snssaiNode->snssai->sd[0], snssaiNode->snssai->sd[1],snssaiNode->snssai->sd[2] , snssaiNode->tpt);
+ }
+
snssaiNode->dataVol = 0;
node = node->next;
+ snssaiCnt++;
}
- return;
+ return(snssaiCnt);
}
+
/********************************************************************30**
End of file
**********************************************************************/
#endif /* __cplusplus */
#include "du_log.h"
+#include "du_app_rlc_inf.h"
\f
#define EKWxxx 1
{
Snssai *snssai;
uint64_t dataVol;
+ double tpt;
}RlcTptPerSnssai;
typedef struct rlcSnssaiTputInfo
{
CmTimer snssaiThptTmr; /* Throughput Timer */
- CmLListCp *tputPerSnssaiList;
+ CmLListCp *dlTputPerSnssaiList;
+ CmLListCp *ulTputPerSnssaiList;
}RlcSnssaiTputInfo;
typedef struct rlcUeTputInfo
RlcCb *rlcCb[MAX_RLC_INSTANCES]; /*!< RLC global control block */
+CmLListCp *arrTputPerSnssai[DIR_BOTH]; /*Stores the address of Througput LL*/
/****************************************************************************
* Declarations
***************************************************************************/
void rlcSnssaiThptTmrExpiry(PTR cb);
RlcTptPerSnssai* rlcHandleSnssaiTputlist(RlcCb *gCb, Snssai *snssai,\
- RlcSnssaiActionType action);
-void rlcCalculateTputPerSnssai(CmLListCp *snssaiList);
-void rlcDelTputSnssaiList(RlcCb *gCb);
+ RlcSnssaiActionType action, Direction dir);
+uint8_t rlcCalculateTputPerSnssai(CmLListCp *snssaiList, Direction dir);
+uint8_t rlcDelTputSnssaiList(RlcCb *gCb, Direction dir);
+uint8_t BuildSliceReportToDu(uint8_t snssaiCnt);
+bool rlcFindSliceEntry(uint32_t snssaiVal, uint8_t *snssaiIdx,\
+ SlicePmList *sliceStats);
#ifdef LTE_L2_MEAS
Void rlcLmmSendAlarm ARGS (( RlcCb *gCb,
if(rbCb->snssai)
{
- snssaiTputNode = rlcHandleSnssaiTputlist(gCb, rbCb->snssai, SEARCH);
+ snssaiTputNode = rlcHandleSnssaiTputlist(gCb, rbCb->snssai, SEARCH, DIR_DL);
if(snssaiTputNode != NULLP)
{
snssaiTputNode->dataVol += staIndTb->lchStaInd[count].totBufSize;
- DU_LOG("\nINFO -->SCH: SNSSAI List Grant:%d, lcId:%d, total :%d",\
+ DU_LOG("\nINFO -->SCH: SNSSAI List Grant:%d, lcId:%d, total :%ld",\
staIndTb->lchStaInd[count].totBufSize, staIndTb->lchStaInd[count].lcId,\
snssaiTputNode->dataVol);
}
DELETE
}ActionTypeLcLL;
-typedef enum
-{
- DIR_UL,
- DIR_DL
-}Direction;
-
/**
* @brief
* Structure holding LTE MAC's General Configuration information.
if(cell == NULLP)
{
DU_LOG("\nERROR --> SCH : schPrachResAlloc(): Received cellCb is null");
- return RFAILED;
+ return;
}
/* If this slot is not a PRACH occassion, return */
CELL_DOWN
}OduCellStatus;
+
+typedef enum
+{
+ DIR_NONE,
+ DIR_UL,
+ DIR_DL,
+ DIR_BOTH
+}Direction;
+
typedef struct slotTimingInfo
{
uint16_t cellId;
return RFAILED;
}
+/*******************************************************************
+*
+* @brief Packs and Sends Slice PM from RLC to DUAPP
+*
+* @details
+*
+* Function : packRlcDuSlicePm
+*
+* Functionality:
+* Packs and Sends Slice Performance Metrics from RLC to DUAPP
+*
+*
+* @params[in] Post structure pointer
+* SlicePmList *sliceStats
+*
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+
+uint8_t packRlcDuSlicePm(Pst *pst, SlicePmList *sliceStats)
+{
+ Buffer *mBuf = NULLP;
+
+ if(pst->selector == ODU_SELECTOR_LWLC)
+ {
+ if (ODU_GET_MSG_BUF(pst->region, pst->pool, &mBuf) != ROK)
+ {
+ DU_LOG("\nERROR --> RLC : Memory allocation failed at packRlcDuSlicePm");
+ return RFAILED;
+ }
+ /* pack the address of the structure */
+ CMCHKPK(oduPackPointer,(PTR)sliceStats, mBuf);
+ }
+ else
+ {
+ DU_LOG("\nERROR --> RLC: Only LWLC supported for packRlcDuSlicePm");
+ return RFAILED;
+ }
+
+ return ODU_POST_TASK(pst,mBuf);
+}
+
+/*******************************************************************
+*
+* @brief Unpacks Slice PM received from RLC
+*
+* @details
+*
+* Function : unpackRlcSlicePm
+*
+* Functionality:
+* Unpacks Slice Performance Metrics received from RLC
+*
+* @params[in] Pointer to Handler
+* Post structure pointer
+* Message Buffer
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+
+uint8_t unpackRlcSlicePm(RlcSlicePmToDuFunc func, Pst *pst, Buffer *mBuf)
+{
+ if(pst->selector == ODU_SELECTOR_LWLC)
+ {
+ SlicePmList *sliceStats = NULLP;
+ /* unpack the address of the structure */
+ CMCHKUNPK(oduUnpackPointer, (PTR *)&sliceStats, mBuf);
+ ODU_PUT_MSG_BUF(mBuf);
+ return (*func)(pst, sliceStats);
+ }
+ else
+ {
+ /* Nothing to do for other selectors */
+ DU_LOG("\nERROR --> RLC: Only LWLC supported for Slice Metrics ");
+ ODU_PUT_MSG_BUF(mBuf);
+ }
+
+ return RFAILED;
+}
/**********************************************************************
End of file
***********************************************************************/
#define EVENT_UL_USER_DATA_TRANS_TO_DU 219
#define EVENT_RLC_UE_DELETE_REQ 220
#define EVENT_RLC_UE_DELETE_RSP 221
+#define EVENT_RLC_SLICE_PM_TO_DU 222
#define RB_ID_SRB 0
#define RB_ID_DRB 1
uint16_t triggeringMessage;
}RrcDeliveryStatus;
+/*Pm Metric for NW Slicing from RLC to DUAPP*/
+typedef struct slicePm
+{
+ uint32_t networkSliceIdentifier;
+ double ThpDl;
+ double ThpUl;
+}SlicePm;
+
+typedef struct slicePmList
+{
+ uint8_t numSlice;
+ SlicePm *sliceRecord;
+}SlicePmList;
+
typedef struct rrcDeliveryReportInfo
{
uint16_t cellId;
Pst *pst,
RlcDlUserDataInfo *dlDataMsg));
+/* Slice Metrics from RLC to DU APP */
+typedef uint8_t (*RlcSlicePmToDuFunc) ARGS((
+ Pst *pst,
+ SlicePmList *sliceStats));
+
/* Pack/Unpack function declarations */
uint8_t packDuRlcUeCreateReq(Pst *pst, RlcUeCfg *ueCfg);
uint8_t unpackRlcUeCreateReq(DuRlcUeCreateReq func, Pst *pst, Buffer *mBuf);
uint8_t unpackRlcUeDeleteReq(DuRlcUeDeleteReq func, Pst *pst, Buffer *mBuf);
uint8_t packRlcDuUeDeleteRsp(Pst *pst, RlcUeDeleteRsp *ueDeleteRsp);
uint8_t unpackRlcUeDeleteRsp(RlcDuUeDeleteRsp func, Pst *pst, Buffer *mBuf);
+uint8_t packRlcDuSlicePm(Pst *pst, SlicePmList *sliceStats);
+uint8_t unpackRlcSlicePm(RlcSlicePmToDuFunc func, Pst *pst, Buffer *mBuf);
/* Event Handler function declarations */
uint8_t RlcProcUeCreateReq(Pst *pst, RlcUeCfg *ueCfg);
uint8_t RlcProcDlUserDataTransfer(Pst *pst, RlcDlUserDataInfo *dlDataMsgInfo);
uint8_t RlcProcUeDeleteReq(Pst *pst, RlcUeDelete *ueDelete);
uint8_t DuProcRlcUeDeleteRsp(Pst *pst, RlcUeDeleteRsp *delRsp);
+uint8_t DuProcRlcSliceMetrics(Pst *pst, SlicePmList *sliceStats);
#endif /* RLC_INF_H */
/**********************************************************************
ret = unpackRlcUlUserDataToDu(DuProcRlcUlUserDataTrans, pst, mBuf);
break;
}
+ case EVENT_RLC_SLICE_PM_TO_DU:
+ {
+ ret = unpackRlcSlicePm(DuProcRlcSliceMetrics, pst, mBuf);
+ break;
+ }
default:
{
DU_LOG("\nERROR --> DU_APP : Invalid event %d received at duActvTsk from ENTRLC", \
#include "AlarmInterface.h"
#include "ConfigInterface.h"
+/*TODO: Uncomment when PM O1 gerrit gets ready*/
+#if 0
+#include "PmInterface.h"
+#endif
+
#endif
uint8_t rlcDlCfg = 0;
duFreeTempSliceCfg();
return ROK;
}
+
+/*******************************************************************
+*
+* @brief Handles received Slice Metrics from RLC and forward it to O1
+*
+* @details
+*
+* Function : DuProcRlcSliceMetrics
+*
+* Functionality:
+* Handles received Slice Metrics from RLC and forward it to O1
+*
+* @params[in] Post structure pointer
+* SlicePmList *sliceStats
+*
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+uint8_t DuProcRlcSliceMetrics(Pst *pst, SlicePmList *sliceStats)
+{
+ uint8_t sliceRecord = 0;
+
+ DU_LOG("\nDEBUG --> DU APP : Received Slice Metrics");
+ if(sliceStats == NULLP)
+ {
+ DU_LOG("\nERROR --> DU APP : Empty Metrics");
+ return RFAILED;
+ }
+
+ for(sliceRecord = 0; sliceRecord < sliceStats->numSlice; sliceRecord++)
+ {
+ DU_LOG("\nINFO --> DU_APP: SliceIndx:%d, DlTput %.5lf, UlTput:%.5lf", sliceStats->sliceRecord[sliceRecord].networkSliceIdentifier,\
+ sliceStats->sliceRecord[sliceRecord].ThpDl, sliceStats->sliceRecord[sliceRecord].ThpUl);
+ }
+/*TODO: Uncomment when PM O1 gerrit gets ready*/
+#if 0
+#ifdef O1_ENABLE
+ if(sliceStats)
+ {
+ sendSliceMetric(sliceStats);
+ }
+#endif
+#endif
+
+ DU_FREE_SHRABL_BUF(pst->region, pst->pool,sliceStats->sliceRecord, (sliceStats->numSlice) * (sizeof(SlicePm)));
+ DU_FREE_SHRABL_BUF(pst->region, pst->pool,sliceStats, sizeof(SlicePmList));
+
+ return ROK;
+}
+
/**********************************************************************
End of file
**********************************************************************/