Desc: Source code for RLC Unacknowledged mode assembly and
reassembly.This file contains following functions
- --kwUmmQSdu
- --kwUmmProcessSdus
- --kwUmmProcessPdus
- --kwUmmReAssembleSdus
+ --rlcUmmQSdu
+ --rlcUmmProcessSdus
+ --rlcUmmProcessPdus
+ --rlcUmUlReAssembleSdus
--kwUmmReEstablish
File: kw_umm_ul.c
**********************************************************************/
-static const char* RLOG_MODULE_NAME="RLC";
-static int RLOG_MODULE_ID=2048;
-static int RLOG_FILE_ID=240;
-
/**
* @file kw_umm_ul.c
* @brief RLC Unacknowledged Mode uplink module
*/
/* header (.h) include files */
-#include "envopt.h" /* environment options */
-#include "envdep.h" /* environment dependent */
-#include "envind.h" /* environment independent */
-
-#include "gen.h" /* general */
-#include "ssi.h" /* system services interface */
-#include "cm5.h" /* Timer Functions */
-#include "cm_lte.h" /* common umts header file */
-#include "cm_hash.h" /* common hash module file */
-#include "cm_llist.h" /* common list header file */
+#include "common_def.h"
#include "ckw.h" /* RRC layer */
#include "lkw.h" /* RRC layer */
#include "kwu.h" /* RLC service user */
/* header/extern include files (.x) */
-#include "gen.x" /* general */
-#include "ssi.x" /* system services interface */
-#include "cm_lib.x" /* common library */
-#include "cm5.x" /* Timer Functions */
-#include "cm_hash.x" /* common hash module */
-#include "cm_lte.x" /* common umts file */
-#include "cm_llist.x" /* common list header file */
#include "ckw.x" /* RRC layer */
#include "kwu.x" /* RLC service user */
#include "lkw.x" /* LM Interface */
#include "kw.x" /* RLC layer */
#include "kw_ul.x"
-#define KW_MODULE (KW_DBGMASK_UM | KW_DBGMASK_UL)
+#define RLC_MODULE (RLC_DBGMASK_UM | RLC_DBGMASK_UL)
-PRIVATE S16 kwUmmExtractHdr ARGS ((KwCb *gCb,
- KwUlRbCb *rbCb,
+static uint8_t rlcUmmExtractHdr ARGS ((RlcCb *gCb,
+ RlcUlRbCb *rbCb,
Buffer *pdu,
- KwUmHdr *umHdr));
+ RlcUmHdr *umHdr));
+
+uint8_t rlcUmmReAssembleSdus ARGS ((RlcCb *gCb,
+ RlcUlRbCb *rbCb,
+ RlcUmRecBuf *umRecBuf));
+
+bool rlcUmmAddRcvdSeg ARGS ((RlcCb *gCb,
+ RlcUlRbCb *rbCb,
+ RlcUmHdr *umHdr,
+ Buffer *pdu,
+ uint16_t pduSz));
-PRIVATE Void kwUmmReAssembleSdus ARGS ((KwCb *gCb,
- KwUlRbCb *rbCb,
- KwUmRecBuf *umRecBuf));
+void rlcUmmRelAllSegs(RlcCb *gCb, RlcUmRecBuf *recBuf);
#ifndef TENB_ACC
#ifndef LTE_PAL_ENB
-extern U32 isMemThreshReached(Region region);
+uint32_t isMemThreshReached(Region region);
#endif
#endif
/**
*
* @details
* Finds the next VR(UR) depending on the passed SN. Updates VR(UR) to
- * the SN of the first UMD PDU with SN >= _nextSn that has not been received
+ * the SN of the first UMD PDU with SN >= _nextSn that has not been reassembled
*
* @param[in] umUl pointer to Um mode uplink control block
* @param[in] nextSn Sequence number after which the VR(UR) is to set to
*
* @return Void
*/
-PRIVATE Void kwUmmFindNextVRUR (KwUmUl* umUl, KwSn nextSn)
+static void rlcUmmFindRxNextReassembly (RlcCb *gCb, RlcUmUl* umUl, RlcSn nextSn)
{
- KwSn ur = KW_UM_GET_VALUE(umUl->vrUr, *umUl);
-
- KwSn nextSnToCompare = KW_UM_GET_VALUE(nextSn,*umUl);
-
+ RlcSn ur = RLC_UM_GET_VALUE(umUl->vrUr, *umUl);
+ RlcSn prevRxNextReassembly = umUl->vrUr;
+
+ RlcSn nextSnToCompare = RLC_UM_GET_VALUE(nextSn,*umUl);
+ RlcUmRecBuf *recBuf = rlcUtlGetUmRecBuf(umUl->recBufLst,nextSn);
+ RlcUmRecBuf *prevRecBuf = rlcUtlGetUmRecBuf(umUl->recBufLst,prevRxNextReassembly);
while (ur < nextSnToCompare)
{
- if (!(umUl->recBuf[nextSn])) /* if the buffer is empty, SN not received */
+ if((ur + 1) == nextSnToCompare)
+ {
+ if ((recBuf == NULLP) || (!(recBuf->allSegRcvd))) /* if the buffer is empty, SN not received */
+ {
+ umUl->vrUr = nextSn;
+ if(prevRecBuf)
+ {
+ rlcUmmRelAllSegs(gCb, prevRecBuf);
+ rlcUtlDelUmRecBuf(gCb, umUl->recBufLst, prevRecBuf);
+ }
+ break;
+ }
+ else
+ {
+ if(prevRecBuf)
+ {
+ rlcUmmRelAllSegs(gCb, prevRecBuf);
+ rlcUtlDelUmRecBuf(gCb, umUl->recBufLst, prevRecBuf);
+ }
+ }
+ prevRecBuf = rlcUtlGetUmRecBuf(umUl->recBufLst,nextSn);
+ nextSn = (nextSn + 1) & umUl->modBitMask;
+ nextSnToCompare = RLC_UM_GET_VALUE(nextSn,*umUl);
+ recBuf = rlcUtlGetUmRecBuf(umUl->recBufLst,nextSn);
+ }
+ else
{
- umUl->vrUr = nextSn;
- break;
+ umUl->vrUr++;
+ ur = RLC_UM_GET_VALUE(umUl->vrUr, *umUl);
+ if(prevRecBuf)
+ {
+ rlcUmmRelAllSegs(gCb, prevRecBuf);
+ rlcUtlDelUmRecBuf(gCb, umUl->recBufLst, prevRecBuf);
+ }
+ prevRecBuf = rlcUtlGetUmRecBuf(umUl->recBufLst,umUl->vrUr);
}
- nextSn = (nextSn + 1) & umUl->modBitMask;
- nextSnToCompare = KW_UM_GET_VALUE(nextSn,*umUl);
}
}
/**
* @brief Checks whether a sequence number is within the
- * re-ordering window or not
+ * re-assembly window or not
*
* @param[in] sn Sequence Number to be checked
* @param[in] umUl pointer to Um mode uplink control block
*
* @return Void
*/
-PRIVATE S16 kwUmmCheckSnInReordWindow (KwSn sn,
- CONSTANT KwUmUl* CONSTANT umUl)
+static int16_t rlcUmmCheckSnInReassemblyWindow (RlcSn sn, const RlcUmUl* const umUl)
+{
+ return (RLC_UM_GET_VALUE(sn, *umUl) < RLC_UM_GET_VALUE(umUl->vrUh, *umUl));
+}
+
+/**
+ * @brief Handler to updated expected byte seg
+ *
+ * @details
+ * This function is used to update expected byte segment. The next segment
+ * expected is indicated by the SO of the segment which is expected. Intially
+ * the segment with SO 0 is expected and then in order. When all the segments
+ * are received (which would happen when an expected SO is encountered
+ * with LSF set) the allRcvd flag is set to TRUE
+ *
+ * @param[in] gCb RLC instance control block
+ * @param[in] umUl AM Uplink Control Block
+ * @param[in] seg Newly received segment
+ *
+ * @return void
+ *
+ */
+
+void rlcUmmUpdExpByteSeg(RlcCb *gCb, RlcUmUl *umUl, RlcUmSeg *seg)
+{
+ uint16_t newExpSo; /* The new expected SO */
+ RlcSn sn = seg->umHdr.sn;
+ bool lstRcvd=FALSE;
+ RlcUmRecBuf *recBuf = NULLP;
+
+ recBuf = rlcUtlGetUmRecBuf(umUl->recBufLst, sn);
+ if ((recBuf == NULLP) || (recBuf && (seg->umHdr.so != recBuf->expSo)))
+ {
+ return;
+ }
+ recBuf->noMissingSeg = FALSE;
+ newExpSo = seg->soEnd + 1;
+ recBuf->expSo = newExpSo;
+ if(seg->umHdr.si == RLC_SI_LAST_SEG)
+ {
+ lstRcvd = TRUE;
+ }
+ RLC_UMM_LLIST_NEXT_SEG(recBuf->segLst, seg);
+ while(seg)
+ {
+ /* keep going ahead as long as the expectedSo match with the header so
+ else store the expSo for later checking again */
+ if(seg->umHdr.si == RLC_SI_LAST_SEG)
+ {
+ lstRcvd = TRUE;
+ }
+ if (seg->umHdr.so == newExpSo)
+ {
+ newExpSo = seg->soEnd + 1;
+ recBuf->expSo = newExpSo;
+ RLC_UMM_LLIST_NEXT_SEG(recBuf->segLst, seg);
+ }
+ else
+ {
+ recBuf->expSo = newExpSo;
+ return;
+ }
+ }
+ if (lstRcvd == TRUE)
+ {
+ recBuf->allSegRcvd = TRUE;
+ }
+ recBuf->noMissingSeg = TRUE;
+
+ return;
+}
+/**
+ * @brief Private handler to store the received segment
+ *
+ * @details
+ * Private handler invokded by rlcUmmUlPlacePduInRecBuf to add a received
+ * segment in reception buffer of a RBCB.
+ * - It is responsible for detecting duplicate segments
+ * - Adding it at appropriate position in the received buffer
+ * - Calling ExpByteSeg to set expSo field in the receiver buffer
+ *
+ * @param[in] gCb RLC instance control block
+ * @param[in] rbCb Radio Bearer Contro Block
+ * @param[in] umHdr UM Header received
+ * @param[in] pdu Buffer received other than the headers
+ * @param[in] pduSz size of the PDU buffer received
+ *
+ * @return bool
+ * -#TRUE Successful insertion into the receiver buffer
+ * -#FALSE Possibly a duplicate segment
+ */
+
+bool rlcUmmAddRcvdSeg(RlcCb *gCb, RlcUlRbCb *rbCb, RlcUmHdr *umHdr, Buffer *pdu, uint16_t pduSz)
+{
+ RlcUmRecBuf *recBuf = NULLP;
+ RlcUmSeg *seg;
+ RlcUmSeg *tseg;
+ uint16_t soEnd; /* Holds the SoEnd of received segment */
+ uint16_t expSo = 0; /* Expected SO */
+
+ soEnd = umHdr->so + pduSz - 1;
+ recBuf = rlcUtlGetUmRecBuf(RLC_UMUL.recBufLst, umHdr->sn);
+
+ if (NULLP == recBuf)
+ {
+ RLC_ALLOC(gCb,recBuf, sizeof(RlcUmRecBuf));
+ if (recBuf == NULLP)
+ {
+ DU_LOG("\nERROR --> RLC_UL : Failed to allocate memory to recv buf for UEID:%d CELLID:%d in rlcUmmAddRcvdSeg()",
+ rbCb->rlcId.ueId, rbCb->rlcId.cellId);
+
+ ODU_PUT_MSG_BUF(pdu);
+ return FALSE;
+ }
+ rlcUtlStoreUmRecBuf(RLC_UMUL.recBufLst, recBuf, umHdr->sn);
+ }
+ else
+ {
+ if (recBuf->allSegRcvd == TRUE)
+ {
+ ODU_PUT_MSG_BUF(pdu);
+ return FALSE;
+ }
+ }
+
+ RLC_UMM_LLIST_FIRST_SEG(recBuf->segLst, seg);
+ while ((seg != NULLP) && (seg->umHdr.so < umHdr->so))
+ {
+ expSo = seg->umHdr.so + seg->segSz;
+ RLC_UMM_LLIST_NEXT_SEG(recBuf->segLst, seg);
+ }
+
+ if (expSo > umHdr->so)
+ {
+ DU_LOG("\nDEBUG --> RLC_UL : Received duplicate segment in rlcUmmAddRcvdSeg()");
+ /* This is a duplicate segment */
+ ODU_PUT_MSG_BUF(pdu);
+ return FALSE;
+ }
+
+ if ((seg) && (seg->umHdr.so <= soEnd))
+ {
+ DU_LOG("\nDEBUG --> RLC_UL : Received duplicate segment in rlcUmmAddRcvdSeg()");
+ /* This is a duplicate segment */
+ ODU_PUT_MSG_BUF(pdu);
+ return FALSE;
+ }
+
+ /* If we have come this far, we have to add this segment to the */
+ /* reception buffer as we either have eliminated duplicates or */
+ /* have found none. */
+ RLC_ALLOC_WC(gCb, tseg, sizeof(RlcUmSeg));
+ if (tseg == NULLP)
+ {
+ DU_LOG("\nERROR --> RLC_UL : Failed to allocate memory to segment for UEID:%d CELLID:%d in rlcUmmAddRcvdSeg()",
+ rbCb->rlcId.ueId, rbCb->rlcId.cellId);
+ ODU_PUT_MSG_BUF(pdu);
+ return FALSE;
+ }
+
+ tseg->seg = pdu;
+ tseg->segSz = pduSz;
+ RLC_MEM_CPY(&tseg->umHdr, umHdr, sizeof(RlcUmHdr));
+ RLC_MEM_CPY(&recBuf->umHdr, umHdr, sizeof(RlcUmHdr));
+ recBuf->sn = umHdr->sn;
+ tseg->soEnd = soEnd;
+ if (seg == NULLP)
+ {
+ cmLListAdd2Tail(&recBuf->segLst, &tseg->lstEnt);
+ }
+ else
+ {
+ recBuf->segLst.crnt = &seg->lstEnt;
+ cmLListInsCrnt(&recBuf->segLst, &tseg->lstEnt);
+ }
+ tseg->lstEnt.node = (PTR)tseg;
+ rlcUmmUpdExpByteSeg(gCb, &RLC_UMUL, tseg);
+ return TRUE;
+}
+
+/**
+ * @brief Private handler to release all stored segments
+ *
+ * @details
+ * Private handler invokded by rlcUmmRelAllSegs to release the
+ * stored segements in case a complete PDU is received later.
+ *
+ * @param[in] gCb RLC instance control block
+ * @param[in] recBuf Buffer that stores a received PDU or segments
+ *
+ * @return void
+ *
+ */
+void rlcUmmRelAllSegs(RlcCb *gCb, RlcUmRecBuf *recBuf)
+{
+ RlcUmSeg *seg;
+
+ RLC_UMM_LLIST_FIRST_SEG(recBuf->segLst, seg);
+ while (seg != NULLP)
+ {
+ ODU_PUT_MSG_BUF(seg->seg);
+ cmLListDelFrm(&(recBuf->segLst), &(seg->lstEnt));
+ RLC_FREE(gCb, seg, sizeof(RlcUmSeg));
+ RLC_UMM_LLIST_FIRST_SEG(recBuf->segLst, seg);
+ }
+
+ return;
+}
+
+/**
+ * @brief Private handler to reassemble from a segment or a PDU
+ *
+ * @details
+ * Private handler invokded by rlcUmmReAssembleSdus with either a
+ * PDU or a segment of a PDU. This is also called in the case of
+ * reestablishment and hence out of sequence joining is also to
+ * be supported
+ *
+ *
+ * @param[in] gCb RLC instance control block
+ * @param[in] rbCb Uplink RB control block
+ * @param[in] umHdr UM header received for this segment/PDU
+ * @param[in] pdu PDU to be reassembled
+ *
+ * @return ROK/RFILED
+ *
+ */
+
+uint8_t rlcUmmProcSeg(RlcCb *gCb, RlcUlRbCb *rbCb, RlcUmHdr *umHdr, Buffer *pdu)
+{
+
+ if ((RLC_UMUL.expSn != umHdr->sn) || (RLC_UMUL.expSo != umHdr->so))
+ {
+ /* Release the existing SDU as we have PDUs or */
+ /* segments that are out of sequence */
+ DU_LOG("\nDEBUG --> RLC_UL : Received Segments are out of sequence in rlcUmmProcSeg()");
+ ODU_PUT_MSG_BUF(RLC_UMUL.assembleSdu);
+ return RFAILED;
+ }
+
+ if (umHdr->si == RLC_SI_FIRST_SEG)
+ {/* first Segment of the SDU */
+ if (RLC_UMUL.assembleSdu != NULLP)
+ { /* Some old SDU may be present */
+ ODU_PUT_MSG_BUF(RLC_UMUL.assembleSdu);
+ }
+ RLC_UMUL.assembleSdu = pdu;
+ pdu = NULLP;
+ }
+ else if(umHdr->si == RLC_SI_MID_SEG)
+ {/* Middle Segment of the SDU */
+ ODU_CAT_MSG(RLC_UMUL.assembleSdu,pdu, M1M2);
+ ODU_PUT_MSG_BUF(pdu);
+ pdu = NULLP;
+ }
+ else if(umHdr->si == RLC_SI_LAST_SEG)
+ {
+ ODU_CAT_MSG(pdu, RLC_UMUL.assembleSdu, M2M1);
+ ODU_PUT_MSG_BUF(RLC_UMUL.assembleSdu);
+ }
+
+ if (pdu != NULLP)
+ {
+ RLC_UMUL.assembleSdu = NULLP;
+ rlcUtlSendUlDataToDu(gCb,rbCb, pdu);
+ }
+
+ return ROK;
+}
+/**
+ *
+ * @brief Private handler to reassemble SDUs
+ *
+ * @details
+ * Private handler invokded by rlcUmmProcessPdus with the PDU
+ * from the reception buffer in sequence to reassemble SDUs and
+ * send it to PDCP.
+ *
+ * - With the stored header info, FI and LSF segment / concatenate
+ * PDUs or byte segments of PDUs to get the associated SDU.
+ *
+ * @param[in] rbCb RB control block
+ * @param[in] pdu PDU to be reassembled
+ *
+ * @return uint8_t
+ * -# ROK
+ * -# RFAILED
+ *
+ */
+uint8_t rlcUmmReAssembleSdus(RlcCb *gCb, RlcUlRbCb *rbCb, RlcUmRecBuf *recBuf)
{
- return (KW_UM_GET_VALUE(sn, *umUl) < KW_UM_GET_VALUE(umUl->vrUh, *umUl));
+ RlcUmSeg *seg;
+
+ /* This is a set of segments */
+ RLC_UMM_LLIST_FIRST_SEG(recBuf->segLst, seg);
+ RLC_UMUL.expSn = recBuf->sn;
+ RLC_UMUL.expSo = 0;
+ while(seg)
+ {
+ if(rlcUmmProcSeg(gCb, rbCb, &seg->umHdr, seg->seg) == RFAILED)
+ {
+ rlcUmmRelAllSegs(gCb, recBuf);
+ break;
+ }
+ RLC_UMUL.expSo = seg->soEnd + 1;
+ cmLListDelFrm(&(recBuf->segLst),&(seg->lstEnt));
+ RLC_FREE(gCb, seg, sizeof(RlcSeg));
+ RLC_UMM_LLIST_FIRST_SEG(recBuf->segLst, seg);
+ }
+ RLC_UMUL.expSn = (recBuf->umHdr.sn + 1) & (RLC_UMUL.modBitMask);
+ RLC_UMUL.expSo = 0;
+ return ROK;
}
/**
*/
/* kw005.201 added support for L2 Measurement */
#ifdef LTE_L2_MEAS
-
-#ifdef ANSI
-PUBLIC Void kwUmmProcessPdus
-(
-KwCb *gCb,
-KwUlRbCb *rbCb, /* Rb Control Block */
-KwPduInfo *pduInfo, /* Pdu data and related information */
-U32 ttiCnt /* ttiCnt received from MAC */
-)
-#else
-PUBLIC Void kwUmmProcessPdus(rbCb,pduInfo,ttiCnt)
-KwCb *gCb;
-KwUlRbCb *rbCb; /* Rb Control Block */
-KwPduInfo *pduInfo; /* Pdu data and related information */
-U32 ttiCnt; /* ttiCnt received from MAC */
-#endif
+void rlcUmmProcessPdus(RlcCb *gCb, RlcUlRbCb *rbCb, KwPduInfo *pduInfo, uint32_t ttiCnt)
#else
-#ifdef ANSI
-PUBLIC Void kwUmmProcessPdus
-(
-KwCb *gCb,
-KwUlRbCb *rbCb, /* Rb Control Block */
-KwPduInfo *pduInfo /* Pdu data and related information */
-)
-#else
-PUBLIC Void kwUmmProcessPdus(rbCb,pduInfo)
-KwCb *gCb;
-KwUlRbCb *rbCb; /* Rb Control Block */
-KwPduInfo *pduInfo; /* Pdu data and related information */
-#endif
+void rlcUmmProcessPdus(RlcCb *gCb, RlcUlRbCb *rbCb, KwPduInfo *pduInfo)
#endif
{
- KwSn *vrUh; /* vr(uh) */
- KwSn *vrUr; /* vr(ur) */
- KwSn *vrUx; /* vr(ux) */
- U16 curSn; /* Current Sequence Number */
- U32 pduCount; /* PDU count */
- U32 count; /* Loop counter */
- KwUmRecBuf **recBuf; /* UM Reception Buffer */
-
- Bool tmrRunning; /* Boolean for checking Tmr */
-/* kw005.201 added support for L2 Measurement */
-
- TRC2(kwUmmProcessPdus)
-
+ RlcSn *vrUh; /* vr(uh) */
+ RlcSn *vrUr; /* vr(ur) */
+ RlcSn *vrUx; /* vr(ux) */
+ uint16_t curSn; /* Current Sequence Number */
+ uint32_t pduCount; /* PDU count */
+ uint32_t count; /* Loop counter */
+ RlcUmRecBuf *recBuf; /* UM Reception Buffer */
+ RlcUmHdr umHdr; /* Um header*/
+ bool tmrRunning; /* Boolean for checking Tmr */
+ MsgLen pduSz; /* Pdu Size */
+ RlcSn tRxNextReassembly;
+ RlcSn tRxNextReassemblyNxt;
+ RlcSn tRxNextHighest;
count = 0;
vrUh = &(rbCb->m.umUl.vrUh);
vrUr = &(rbCb->m.umUl.vrUr);
vrUx = &(rbCb->m.umUl.vrUx);
- recBuf = (rbCb->m.umUl.recBuf);
while (count < pduCount)
{
- KwSn ur;
- KwSn uh;
- KwSn seqNum;
- Buffer *pdu = pduInfo->mBuf[count];
- KwUmRecBuf *tmpRecBuf;
+ RlcSn ur;
+ RlcSn seqNum;
+ Buffer *pdu = pduInfo->mBuf[count];
+
gCb->genSts.pdusRecv++;
#ifndef RGL_SPECIFIC_CHANGES
#ifndef TENB_ACC
#ifndef LTE_PAL_ENB
- extern U32 ulrate_rgu;
+ uint32_t ulrate_rgu;
MsgLen len;
- SFndLenMsg(pdu, &len);
+ ODU_GET_MSG_LEN(pdu, &len);
ulrate_rgu += len;
#endif
#endif
#endif
- /* create a buffer to be later inserted into the reception buffer */
- KW_ALLOC_WC(gCb, tmpRecBuf, sizeof(KwUmRecBuf));
-#if (ERRCLASS & ERRCLS_ADD_RES)
- if (tmpRecBuf == NULLP)
- {
- RLOG_ARG2(L_FATAL, DBG_RBID,rbCb->rlcId.rbId,
- "Memory allocation failed UEID:%d CELLID:%d",
- rbCb->rlcId.ueId,
- rbCb->rlcId.cellId);
- SPutMsg(pdu);
-
- RETVOID;
- }
-#endif /* ERRCLASS & ERRCLS_ADD_RES */
/* ccpu00142274 - UL memory based flow control*/
#ifndef RGL_SPECIFIC_CHANGES
#ifndef TENB_ACC
#ifndef LTE_PAL_ENB
/* Changed the condition to TRUE from ROK */
#ifndef XEON_SPECIFIC_CHANGES
- if(isMemThreshReached(kwCb[0]->init.region) == TRUE)
+ if(isMemThreshReached(rlcCb[0]->init.region) == TRUE)
{
- extern U32 rlculdrop;
+ uint32_t rlculdrop;
rlculdrop++;
- KW_FREE_BUF(pdu);
- KW_FREE_WC(gCb, tmpRecBuf, sizeof(KwUmRecBuf));
- /*Fix for CR ccpu00144030: If threshhold is hit then also count
- *should be incrmented */
+ ODU_PUT_MSG_BUF(pdu);
count++;
continue;
}
#endif
#endif
/* get the pdu header */
- if (kwUmmExtractHdr(gCb, rbCb, pdu, &(tmpRecBuf->umHdr)))
+ if (rlcUmmExtractHdr(gCb, rbCb, pdu, &umHdr))
{
- RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
- "Header Extraction Failed UEID:%d CELLID:%d",
- rbCb->rlcId.ueId,
- rbCb->rlcId.cellId);
-
- /* Header extraction is a problem.
- * log an error and free the allocated memory */
- /* ccpu00136940 */
- KW_FREE_WC(gCb, tmpRecBuf, sizeof(KwUmRecBuf));
- SPutMsg(pdu);
+ DU_LOG("\nERROR --> RLC_UL: rlcUmmProcessPdus: Header Extraction Failed UEID:%d CELLID:%d",\
+ rbCb->rlcId.ueId, rbCb->rlcId.cellId);
+ ODU_PUT_MSG_BUF(pdu);
count++;
- /* kw005.201 ccpu00117318, updating the statistics */
gCb->genSts.errorPdusRecv++;
continue;
}
- curSn = tmpRecBuf->umHdr.sn;
+
+ /* 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;
+ }
+
+ curSn = umHdr.sn;
/* Check if the PDU should be discarded or not */
- ur = KW_UM_GET_VALUE(KW_UMUL.vrUr, KW_UMUL);
- uh = KW_UM_GET_VALUE(KW_UMUL.vrUh, KW_UMUL);
- seqNum = KW_UM_GET_VALUE(curSn, KW_UMUL);
+ ur = RLC_UM_GET_VALUE(RLC_UMUL.vrUr, RLC_UMUL);
+ seqNum = RLC_UM_GET_VALUE(curSn, RLC_UMUL);
- if (((ur < seqNum) && (seqNum < uh) && (KW_UMUL.recBuf[curSn])) ||
- (seqNum < ur))
+ if (seqNum < ur)
{
/* PDU needs to be discarded */
- RLOG_ARG3(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId,
- "Received a duplicate pdu with sn %d UEID:%d CELLID:%d",
- curSn,
- rbCb->rlcId.ueId,
- rbCb->rlcId.cellId);
-
- KW_FREE_BUF(pdu);
- KW_FREE_WC(gCb, tmpRecBuf, sizeof(KwUmRecBuf));
+ DU_LOG("\nINFO --> RLC_UL: rlcUmmProcessPdus: Received an unexpected pdu with sn %d \
+ UEID:%d CELLID:%d", curSn, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
+
+ ODU_PUT_MSG_BUF(pdu);
count++;
- /* kw005.201 ccpu00117318, updating the statistics */
gCb->genSts.unexpPdusRecv++;
continue;
}
- /* kw005.201 added support for L2 Measurement */
#ifdef LTE_L2_MEAS
-
- /* kw006.201 ccpu00120058, reduced code complexity by adding new function */
- kwUtlCalUlIpThrPut(gCb,rbCb, pdu, ttiCnt);
-
+ rlcUtlCalUlIpThrPut(gCb,rbCb, pdu, ttiCnt);
#endif
- recBuf[curSn] = tmpRecBuf;
-
- recBuf[curSn]->pdu = pdu;
- SFndLenMsg(pdu,&(recBuf[curSn]->pduSz));
- /* kw005.201 ccpu00117318, updating the statistics */
- gCb->genSts.bytesRecv += recBuf[curSn]->pduSz;
-
- if (!kwUmmCheckSnInReordWindow(curSn,&KW_UMUL))
- { /* currSn is outside re-ordering window */
- *vrUh = (curSn + 1) & KW_UMUL.modBitMask;
-
- /* re-assemble all pdus outside the modified re-ordering window */
- /* the first SN is VR(UR) */
- if (!kwUmmCheckSnInReordWindow(*vrUr,&KW_UMUL))
- {
- /* TODO : should it be VR(UR) + 1 ?... check, earlier it was so */
- KwSn sn = *vrUr; /* SN's which need to be re-assembled */
- KwSn lowerEdge; /* to hold the lower-edge of the
- re-ordering window */
-
- /* The new value ov VR(UR) is the lower end of the window i
- * and SN's still this value need to be re-assembled */
-
- *vrUr = (*vrUh - KW_UMUL.umWinSz) & KW_UMUL.modBitMask;
- lowerEdge = KW_UM_GET_VALUE(*vrUr ,KW_UMUL);
-
- while (KW_UM_GET_VALUE(sn, KW_UMUL) < lowerEdge)
- {
- if (recBuf[sn])
- {
- kwUmmReAssembleSdus(gCb,rbCb,recBuf[sn]);
- KW_FREE_WC(gCb,recBuf[sn],sizeof(KwUmRecBuf));
- recBuf[sn] = NULLP;
- }
- sn = (sn + 1) & KW_UMUL.modBitMask;
- }
- }
- }
- if (recBuf[*vrUr])
+ ODU_GET_MSG_LEN(pdu, &pduSz);
+ /* Place sdu segment into recption buffer */
+ if(rlcUmmAddRcvdSeg(gCb, rbCb, &umHdr, pdu, pduSz) == TRUE)
{
- KwSn sn = *vrUr;
- KwSn tSn = KW_UM_GET_VALUE(sn,KW_UMUL);
- KwSn tVrUr;
-
- /* set VR(UR) to next SN > current VR(UR) which is not received */
- KwSn nextVrUr = (*vrUr + 1) & KW_UMUL.modBitMask;
- kwUmmFindNextVRUR(&KW_UMUL, nextVrUr);
-
- /* re-assemble SDUs with SN < Vr(UR) */
- tVrUr = KW_UM_GET_VALUE(*vrUr,KW_UMUL);
- while (recBuf[sn] && tSn < tVrUr)
+ recBuf = rlcUtlGetUmRecBuf(RLC_UMUL.recBufLst, umHdr.sn);
+ if (recBuf == NULLP)
{
- kwUmmReAssembleSdus(gCb,rbCb,recBuf[sn]);
- KW_FREE_WC(gCb,recBuf[sn],sizeof(KwUmRecBuf));
- recBuf[sn] = NULLP;
- sn = (sn + 1) & KW_UMUL.modBitMask;
- tSn = KW_UM_GET_VALUE(sn, KW_UMUL);
+ 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++;
+ continue;
}
- }
- tmrRunning = kwChkTmr(gCb,(PTR)rbCb, KW_EVT_UMUL_REORD_TMR);
-
- if (tmrRunning)
- {
- KwSn tVrUx = KW_UM_GET_VALUE(*vrUx, KW_UMUL);
- KwSn tVrUr = KW_UM_GET_VALUE(*vrUr ,KW_UMUL);
-
- KwSn tVrUh = KW_UM_GET_VALUE(*vrUh, KW_UMUL);
-
- S16 ret = kwUmmCheckSnInReordWindow(*vrUx, &KW_UMUL);
-
- if ( (tVrUx <= tVrUr) || ((!ret) && (tVrUx != tVrUh)))
+ /* If all bytes segments of curSn are received, deliver assembled SDU to upper layer */
+ if(recBuf != NULLP && recBuf->allSegRcvd)
{
- kwStopTmr(gCb,(PTR)rbCb,KW_EVT_UMUL_REORD_TMR);
- tmrRunning = FALSE;
- }
- }
+ 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);
- if (!tmrRunning)
- {
- if (KW_UM_GET_VALUE(*vrUh, KW_UMUL) > KW_UM_GET_VALUE(*vrUr, KW_UMUL))
- {
- kwStartTmr(gCb,(PTR)rbCb,KW_EVT_UMUL_REORD_TMR);
- *vrUx = *vrUh;
- }
- }
- count++;
- }/* end while count < pduCount */
-#ifdef LTE_L2_MEAS
- kwUtlCalUlIpThrPutIncTTI(gCb, rbCb,ttiCnt);
-#endif /* LTE_L2_MEAS */
- RETVOID;
-}
-
-/**
- * @brief Handler to reassemble the SDUs and send them to the upper layer.
- *
- * @details
- * This function processes the received in-sequence PDU and
- * re-assembles the SDUs and sends them to the upper layer.
- *
- * @param[in] gCb RLC Instance control block
- * @param[in] rbCb RB control block
- * @param[in] umRecBuf Reception Buffer to be Re-Assembled
- *
- * @return Void
-*/
-#ifdef ANSI
-PRIVATE Void kwUmmReAssembleSdus
-(
-KwCb *gCb,
-KwUlRbCb *rbCb,
-KwUmRecBuf *umRecBuf
-)
-#else
-PRIVATE Void kwUmmReAssembleSdus(gCb,rbCb,umRecBuf)
-KwCb *gCb;
-KwUlRbCb *rbCb;
-KwUmRecBuf *umRecBuf;
-#endif
-{
- U32 liCount; /* LI count */
- U32 count; /* Loop counter */
- U8 fi; /* Framing Info */
- U16 sn; /* Sequence Number of current PDU */
- MsgLen len; /* PDU Length */
- Buffer *sdu; /* SDU to be sent to upper layer */
- Buffer *remPdu; /* Remaining PDU */
- Buffer **partialSdu; /* Partial SDU */
-
- TRC2(kwUmmReAssembleSdus)
-
-
- liCount = umRecBuf->umHdr.numLi;
- fi = umRecBuf->umHdr.fi;
- sn = umRecBuf->umHdr.sn;
-
- for (count = 0; (count <= liCount);count++)
- {
- if (count < liCount )
- len = umRecBuf->umHdr.li[count];
- else
- {
- if (!(umRecBuf->pdu))
- {
- RETVOID;
- }
- SFndLenMsg(umRecBuf->pdu,&len);
- }
-
- /* get the sdu out of the pdu */
- SSegMsg(umRecBuf->pdu,len,&remPdu);
- sdu = umRecBuf->pdu;
- umRecBuf->pdu = remPdu;
-
- partialSdu = &(rbCb->m.umUl.partialSdu);
- /* While re-assembling the SDUs, consider the first LI and perform
- * the following steps.
- -# If the first bit of FI(Framing Info of 2 bits) is set =>
- -# The current Data field in the PDU is a segment.
- So form a SDU only if the
- rbCb->m.um.umUl.partialSdu exists and the SNs are
- in-sequence.
- -# If there are no LIs and the second bit of LI is 1
- then a partial SDU is formed which would not be sent
- to the upper layer.
- -# else
- -# If rbCb->partialSdu is not NULL then flush it off.
- -# If LI count > 0 or LI count is 0 and second bit
- of FI is not 1
- The SDU is complete.So send it to upper layer.
- -# else
- The SDU is partial and is placed
- in rbCb->m.um.umUl.partialSdu;
- */
-
- if (0 == count )
- {
- if (fi & 2)
- {
- if ((*partialSdu) &&
- (sn == ((rbCb->m.umUl.sn + 1) & rbCb->m.umUl.modBitMask)))
+ /* if curSn is same as the RX_NEXT_Reassembly */
+ if (seqNum == ur)
{
- SCatMsg(*partialSdu,sdu,M1M2);
- KW_FREE_BUF(sdu);
- if (liCount > 0 || !(fi & 1))
- {
- kwUtlSndDatInd(gCb,rbCb,*partialSdu);
- *partialSdu = NULLP;
- }
+ /* set RX_NEXT_Reassembly to next SN > current RX_NEXT_Reassembly which is not reassembled yet */
+ RlcSn nextVrUr = (*vrUr + 1) & RLC_UMUL.modBitMask;
+ rlcUmmFindRxNextReassembly(gCb, &RLC_UMUL, nextVrUr);
}
- else
+ }
+ /* If curSn is outside re-assembly window */
+ 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);
+
+ /* update RX_NEXT_Highest */
+ *vrUh = (curSn + 1) & RLC_UMUL.modBitMask;
+
+ /* Discard all pdus outside the modified re-assembly window */
+ if (!rlcUmmCheckSnInReassemblyWindow(*vrUr,&RLC_UMUL))
{
- /* Partial Sdu stored is not valid now.So free it */
- if (*partialSdu)
+ RlcSn sn = *vrUr; /* Stores SNs which need to be discarded. First SN is VR(UR) */
+ RlcSn lowerEdge; /* to hold the lower-edge of the 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;
+ packetCount = (lowerEdge - sn) & RLC_UMUL.modBitMask;
+
+ while (packetCount)
{
- KW_FREE_BUF(*partialSdu);
- *partialSdu = NULLP;
+ recBuf = rlcUtlGetUmRecBuf(RLC_UMUL.recBufLst, sn);
+ if (recBuf)
+ {
+ rlcUmmRelAllSegs(gCb, recBuf);
+ rlcUtlDelUmRecBuf(gCb, RLC_UMUL.recBufLst, recBuf);
+ }
+ sn = (sn + 1) & RLC_UMUL.modBitMask;
+ packetCount--;
}
-
- KW_FREE_BUF(sdu);
- sdu = NULLP;
+ 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);
+ }
}
}
- else
- {
- if (*partialSdu)
- {
- KW_FREE_BUF(*partialSdu); /* RLC mem leak fix */
- *partialSdu = NULLP;
- }
-
- if (liCount > 0 || !( fi & 1))
+
+ 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 ((tRxTimerTigger <= tRxNextReassembly) || ((!ret) && (tRxTimerTigger != tRxNextHighest)) ||
+ (tRxNextHighest == tRxNextReassemblyNxt && recBuf && recBuf->noMissingSeg))
{
- kwUtlSndDatInd(gCb,rbCb,sdu);
+ 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);
}
- else
+ }
+
+ /* If Reassembly timer is not running */
+ if (!tmrRunning)
+ {
+ recBuf = rlcUtlGetUmRecBuf(RLC_UMUL.recBufLst, curSn);
+ if ((tRxNextHighest > tRxNextReassemblyNxt) || ((tRxNextHighest == tRxNextReassemblyNxt)
+ && (recBuf && (!recBuf->noMissingSeg))))
{
- *partialSdu = sdu;
+ 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;
}
- }
+ }
}
- /*
- If the SDU pointer has the last Data field of the PDU
- -# If FI is 1,place the SDU in rbCb->m.um.umDl.partialSdu
- -# else send the SDU to upper layer.
- */
- else if (count == liCount)
- {
- if (fi & 1)
- {
- *partialSdu = sdu;
- }
- else
- {
- kwUtlSndDatInd(gCb, rbCb, sdu);
- }
- }
- /*
- If the LI is something other than the first one,
- just send the SDU to the upper layer */
else
{
- kwUtlSndDatInd(gCb, rbCb, sdu);
- }
- }
- rbCb->m.umUl.sn = sn;
+ 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);
- RETVOID;
+ }
+ count++;
+ }/* end while count < pduCount */
+#ifdef LTE_L2_MEAS
+ rlcUtlCalUlIpThrPutIncTTI(gCb, rbCb,ttiCnt);
+#endif /* LTE_L2_MEAS */
+ return;
}
/**
* - If direction of the RB is downlink :
* Remove all the SDUs in the SDU queue.
* - If direction of the RB is uplink :
- * Call kwUmmReAssembleSdus() for each PDU with SN < VR(UH)
+ * Call rlcUmUlReAssembleSdus() for each PDU with SN < VR(UH)
*
* @param[in] gCb RLC Instance control block
* @param[in] rlcID Identity of the RLC entity for which
*
* @return Void
*/
-#ifdef ANSI
-PUBLIC Void kwUmmUlReEstablish
+Void rlcUmmUlReEstablish
(
-KwCb *gCb,
+RlcCb *gCb,
CmLteRlcId *rlcId,
-KwUlRbCb *rbCb
+RlcUlRbCb *rbCb
)
-#else
-PUBLIC Void kwUmmUlReEstablish(gCb, rlcId, rbCb)
-KwCb *gCb;
-CmLteRlcId *rlcId;
-KwUlRbCb *rbCb;
-#endif
{
- KwSn curSn;
- KwSn vrUh;
- KwUmRecBuf **recBuf; /* UM Reception Buffer */
- KwKwuSapCb *kwKwSap; /* KWU SAP Information */
-
- TRC2(kwUmmUlReEstablish)
-
+ RlcSn curSn;
+ RlcSn vrUh;
+ RlcUmRecBuf *recBuf; /* UM Reception Buffer */
+ RlcKwuSapCb *rlcKwSap; /* KWU SAP Information */
curSn = rbCb->m.umUl.vrUr;
- vrUh = KW_UM_GET_VALUE(rbCb->m.umUl.vrUh,rbCb->m.umUl);
- recBuf = rbCb->m.umUl.recBuf;
+ vrUh = RLC_UM_GET_VALUE(rbCb->m.umUl.vrUh,rbCb->m.umUl);
- if(TRUE == kwChkTmr(gCb,(PTR)rbCb,KW_EVT_UMUL_REORD_TMR))
+ if(TRUE == rlcChkTmr(gCb,(PTR)rbCb,EVENT_RLC_UMUL_REASSEMBLE_TMR))
{
- kwStopTmr(gCb,(PTR)rbCb,KW_EVT_UMUL_REORD_TMR);
+ rlcStopTmr(gCb,(PTR)rbCb,EVENT_RLC_UMUL_REASSEMBLE_TMR);
}
- while (KW_UM_GET_VALUE(curSn,rbCb->m.umUl) < vrUh)
+ while (RLC_UM_GET_VALUE(curSn, rbCb->m.umUl) < vrUh)
{
- if ( recBuf[curSn] != NULLP )
+ recBuf = rlcUtlGetUmRecBuf(RLC_UMUL.recBufLst, curSn);
+ if ( recBuf != NULLP )
{
- kwUmmReAssembleSdus(gCb,rbCb,recBuf[curSn]);
- KW_FREE_WC(gCb,recBuf[curSn],sizeof(KwUmRecBuf));
- recBuf[curSn] = NULLP;
+ if(recBuf->allRcvd == TRUE)
+ {
+ rlcUmmReAssembleSdus(gCb,rbCb,recBuf);
+ }
+ else
+ {
+ /* Remove PDU and segments */
+ if(recBuf->pdu)
+ {
+ ODU_PUT_MSG_BUF(recBuf->pdu);
+ }
+ /* Release all the segments*/
+ rlcUmmRelAllSegs(gCb,recBuf);
+ }
+ rlcUtlDelUmRecBuf(gCb, RLC_UMUL.recBufLst, recBuf);
}
curSn = (curSn + 1) & rbCb->m.umUl.modBitMask;
}
rbCb->m.umUl.vrUh = 0;
rbCb->m.umUl.vrUx = 0;
- kwKwSap = gCb->u.ulCb->kwuUlSap + KW_UI_PDCP;
+ rlcKwSap = gCb->u.ulCb->rlcKwuUlSap + RLC_UI_PDCP;
/* In the UM Mode always send reestablish-indication to Upper Latyer*/
- KwUiKwuReEstCmpInd(&kwKwSap->pst, kwKwSap->suId, *rlcId);
+ RlcUiKwuReEstCmpInd(&rlcKwSap->pst, rlcKwSap->suId, *rlcId);
- RETVOID;
+ return;
}
/**
*
* @details
* This function is used to extract the header of a PDU and store it
- * along with the PDU buffer.The sequence number,framing info
- * and LIs are extracted by this function.
+ * along with the PDU buffer.The sequence number, segmentation info
+ * and segmentation offset are extracted by this function.
*
* @param[in] gCb RLC Instance control block
* @param[in] rbCb Rb Control block for which the pdu is received
* -# TRUE
* -# FALSE
*/
-#ifdef ANSI
-PRIVATE S16 kwUmmExtractHdr
-(
-KwCb *gCb,
-KwUlRbCb *rbCb,
-Buffer *pdu,
-KwUmHdr *umHdr
-)
-#else
-PRIVATE S16 kwUmmExtractHdr(gCb, rbCb, pdu, umHdr)
-KwCb *gCb;
-KwUlRbCb *rbCb;
-Buffer *pdu;
-KwUmHdr *umHdr;
-#endif
+static uint8_t rlcUmmExtractHdr(RlcCb *gCb, RlcUlRbCb *rbCb, Buffer *pdu, RlcUmHdr *umHdr)
{
- U8 e; /* Extension Bit */
Data dst[2]; /* Destination Buffer */
- S32 totalSz; /* Sum of LIs */
- MsgLen pduSz; /* PDU size */
-#if (ERRCLASS & ERRCLS_DEBUG)
- S16 ret; /* Return Value */
-#endif
+ uint8_t ret; /* Return Value */
- TRC3(kwUmmExtractHdr)
+ memset(umHdr, 0, sizeof(RlcUmHdr));
-
- SFndLenMsg(pdu,&pduSz);
-
- if ( rbCb->m.umUl.snLen == 1)
+ ret = ODU_REM_PRE_MSG(dst,pdu);
+ if (ret != ROK)
{
-#if (ERRCLASS & ERRCLS_DEBUG)
- ret = SRemPreMsg(dst,pdu);
- if (ret != ROK)
- {
- RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
- "SRemPreMsg Failed for 5 bit SN UEID:%d CELLID:%d",
- rbCb->rlcId.ueId,
- rbCb->rlcId.cellId);
+ DU_LOG("\nERROR --> RLC_UL: rlcUmmExtractHdr : ODU_REM_PRE_MSG Failed for SI\
+ UEID:%d CELLID:%d", rbCb->rlcId.ueId, rbCb->rlcId.cellId);
+ return RFAILED;
+ }
+ umHdr->si = (dst[0]) >> 6;
- RETVALUE(RFAILED);
- }
-#else
- SRemPreMsg(dst,pdu);
-#endif
- pduSz--;
- umHdr->sn = (dst[0]) & 0x1F;
- umHdr->fi = (dst[0]) >> 6;
- e = (dst[0]>>5) & 0x01;
+ /* If SI = 0, the RLC PDU contains complete RLC SDU. Header extraction complete.
+ * No other fields present in header */
+ if(umHdr->si == 0)
+ return ROK;
+
+ /* If SI != 0, one SDU segment is present in RLC PDU. Hence extracting SN */
+ if (rbCb->m.umUl.snLen == RLC_UM_CFG_6BIT_SN_LEN)
+ {
+ /* Extractin 6-bit SN */
+ umHdr->sn = (dst[0]) & 0x3F;
}
else
{
- /* snLen - sequnce length will be 10 bits requiring 2 bytes */
-#if (ERRCLASS & ERRCLS_DEBUG)
- ret = SRemPreMsgMult(dst,2,pdu);
+ /* Extracting 12 bits SN */
+ umHdr->sn = (dst[0]) & 0x0F;
+ ret = ODU_REM_PRE_MSG(dst,pdu);
if (ret != ROK)
{
- RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
- "SRemPreMsgMult Failed for 10 bits SN UEID:%d CELLID:%d",
- rbCb->rlcId.ueId,
- rbCb->rlcId.cellId);
- RETVALUE(RFAILED);
+ DU_LOG("\nERROR --> RLC_UL: rlcUmmExtractHdr : ODU_REM_PRE_MSG Failed for SN\
+ UEID:%d CELLID:%d", rbCb->rlcId.ueId, rbCb->rlcId.cellId);
+ return RFAILED;
}
-#else
- SRemPreMsgMult(dst,2,pdu);
-#endif
- pduSz -= 2;
-
- /* kw005.201 R9 Upgrade 3gpp spec 36.322 ver9.3.0 CR0082 *
- * Removed the "if" condition for checking the reserved field *
- * Added mask 0x03 for extracting the FI field. */
-
- umHdr->fi = ( (dst[0] ) >> 3) & 0x03;
- e = ( (dst[0] ) >> 2) & 0x01;
- umHdr->sn = ( dst[0] & 0x03) << 8;
- umHdr->sn |= dst[1];
+ umHdr->sn = (umHdr->sn << 8) | dst[0];
}
- umHdr->numLi = 0;
-
- totalSz = 0;
- while(e && umHdr->numLi < KW_MAX_UL_LI )
+ /* SO field is present for middle and last segments of SDU, not present for first segment */
+ if((umHdr->si == RLC_SI_LAST_SEG) || (umHdr->si == RLC_SI_MID_SEG))
{
-#if (ERRCLASS & ERRCLS_DEBUG)
- ret = SRemPreMsgMult(dst,2,pdu);
+ ret = ODU_REM_PRE_MSG_MULT(dst,2,pdu);
if (ret != ROK)
{
- RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
- "SRemPreMsgMult Failed UEID:%d CELLID:%d",
- rbCb->rlcId.ueId,
- rbCb->rlcId.cellId);
- RETVALUE(RFAILED);
+ DU_LOG("\nERROR --> RLC_UL: rlcUmmExtractHdr : ODU_REM_PRE_MSG_MULT Failed for 16 bits SO \
+ UEID:%d CELLID:%d", rbCb->rlcId.ueId, rbCb->rlcId.cellId);
+ return RFAILED;
}
-#else
- SRemPreMsgMult(dst,2,pdu);
-#endif
- umHdr->li[umHdr->numLi] = ((dst[0]) & 0x7F) << 4;
- umHdr->li[umHdr->numLi] |= dst[1] >> 4;
- if ( 0 == umHdr->li[umHdr->numLi] )
- {
- RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
- "Received LI as 0 UEID:%d CELLID:%d",
- rbCb->rlcId.ueId,
- rbCb->rlcId.cellId);
- RETVALUE(RFAILED);
- }
- totalSz += umHdr->li[umHdr->numLi];
- if ( pduSz <= totalSz )
- {
- RLOG_ARG3(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
- "SN [%d]: UEID:%d CELLID:%d",
- umHdr->sn,
- rbCb->rlcId.ueId,
- rbCb->rlcId.cellId);
- RLOG_ARG4(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
- "Corrupted PDU as TotSz[%lu] PduSz[%lu] UEID:%d CELLID:%d ",
- totalSz,
- pduSz,
- rbCb->rlcId.ueId,
- rbCb->rlcId.cellId);
- RETVALUE(RFAILED); /* the situation where in the PDU size
- is something that does not match with
- the size in LIs*/
- }
- umHdr->numLi++;
- pduSz -= 2;
-
- e = ((dst[0]) & 0x80) >> 7;
-
- if ( e && umHdr->numLi < KW_MAX_UL_LI)
- {
- U8 tmp = ((dst[1]) & 0x08) >> 3;
- umHdr->li[umHdr->numLi] = ( dst[1] & 0x07) << 8;
-
-
-#if (ERRCLASS & ERRCLS_DEBUG)
- ret = SRemPreMsg(dst,pdu);
- if (ret != ROK)
- {
- RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
- "SRemPreMsg Failed UEID:%d CELLID:%d",
- rbCb->rlcId.ueId,
- rbCb->rlcId.cellId);
- RETVALUE(RFAILED);
- }
-#else
- SRemPreMsg(dst,pdu);
-#endif
- umHdr->li[umHdr->numLi] |= ( dst[0] ); /* The first byte lies in
- the first 8 bits.We want
- them in the last 8 bits */
- if ( 0 == umHdr->li[umHdr->numLi] )
- {
- RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
- "Received LI as 0 UEID:%d CELLID:%d",
- rbCb->rlcId.ueId,
- rbCb->rlcId.cellId);
- RETVALUE(RFAILED);
- }
- totalSz += umHdr->li[umHdr->numLi];
- pduSz--;
- umHdr->numLi++;
-
- if (pduSz < totalSz)
- {
- RETVALUE(RFAILED); /* the situation where in the PDU size is
- something that does not match with the
- size in LIs*/
- }
-
- e = tmp;
- }
- } /* while(e && umHdr->numLi < KW_MAX_LI ) */
- if (e)
- {
- /* PDU was constructed with LIs that exceeded KW_MAX_LI */
- RETVALUE(RFAILED);
+ umHdr->so = dst[0];
+ umHdr->so = (umHdr->so << 8) | dst[1];
}
- RETVALUE(ROK);
+ return ROK;
}
/**
- * @brief Handles expiry of re-ordering timer
+ * @brief Handles expiry of re-assembly timer
*
* @param[in] gCb RLC Instance control block
- * @param[in] rbCb Rb Control block for which re-order timer expired
+ * @param[in] rbCb Rb Control block for which re-assembly timer expired
*
* @return Void
*/
-#ifdef ANSI
-PUBLIC Void kwUmmReOrdTmrExp
+void rlcUmmReAsmblTmrExp
(
-KwCb *gCb,
-KwUlRbCb *rbCb
+RlcCb *gCb,
+RlcUlRbCb *rbCb
)
-#else
-PUBLIC Void kwUmmReOrdTmrExp(gCb, rbCb)
-KwCb *gCb;
-KwUlRbCb *rbCb;
-#endif
{
- KwSn prevVrUr; /* prevVrUr */
-
- TRC3(kwUmmReOrdTmrExp)
+ RlcSn tRxNextHighest;
+ RlcSn tRxNextReassembly;
+ RlcUmRecBuf *recBuf;
+ DU_LOG("\nINFO --> RLC_UL: rlcUmmReAsmblTmrExp: UM Re-assembly timer expired");
- prevVrUr = KW_UMUL.vrUr;
-
- /* set VR(UR) to SN >= VR(UX) that has not been received */
- kwUmmFindNextVRUR(&KW_UMUL, KW_UMUL.vrUx);
-
- while (KW_UM_GET_VALUE(prevVrUr,KW_UMUL) <
- KW_UM_GET_VALUE(KW_UMUL.vrUr,KW_UMUL))
- {
- if (KW_UMUL.recBuf[prevVrUr])
- {
- kwUmmReAssembleSdus(gCb, rbCb, KW_UMUL.recBuf[prevVrUr]);
- if(KW_UMUL.recBuf[prevVrUr]->pdu != NULLP) /* RLC mem leak fix */
- {
- KW_FREE_BUF(KW_UMUL.recBuf[prevVrUr]->pdu);
- }
- KW_FREE_WC(gCb, KW_UMUL.recBuf[prevVrUr], sizeof(KwUmRecBuf));
- KW_UMUL.recBuf[prevVrUr] = NULLP;
- }
-
- prevVrUr = (prevVrUr + 1) & rbCb->m.umUl.modBitMask;
- }
+ /* set VR(UR) to SN >= VR(UX) that has not been reassembled */
+ rlcUmmFindRxNextReassembly(gCb, &RLC_UMUL, RLC_UMUL.vrUx);
- if (KW_UM_GET_VALUE(KW_UMUL.vrUh, KW_UMUL) >
- KW_UM_GET_VALUE(KW_UMUL.vrUr, KW_UMUL))
+ tRxNextHighest = RLC_UM_GET_VALUE(RLC_UMUL.vrUh, RLC_UMUL);
+ tRxNextReassembly = (RLC_UMUL.vrUr + 1) & rbCb->m.umUl.modBitMask;
+ tRxNextReassembly = RLC_UM_GET_VALUE(tRxNextReassembly, RLC_UMUL);
+ recBuf = rlcUtlGetUmRecBuf(RLC_UMUL.recBufLst,RLC_UMUL.vrUr);
+ if ((tRxNextHighest > tRxNextReassembly) || ((tRxNextHighest == tRxNextReassembly) &&
+ ((recBuf) && !(recBuf->noMissingSeg))))
{
- kwStartTmr(gCb,(PTR)rbCb,KW_EVT_UMUL_REORD_TMR);
- KW_UMUL.vrUx = KW_UMUL.vrUh;
+ rlcStartTmr(gCb, (PTR)rbCb, EVENT_RLC_UMUL_REASSEMBLE_TMR);
+ RLC_UMUL.vrUx = RLC_UMUL.vrUh;
}
}
* @return void
*/
-#ifdef ANSI
-PUBLIC Void kwUmmFreeUlRbCb
+Void rlcUmmFreeUlRbCb
(
-KwCb *gCb,
-KwUlRbCb *rbCb
+RlcCb *gCb,
+RlcUlRbCb *rbCb
)
-#else
-PUBLIC Void kwUmmFreeUlRbCb(gCb,rbCb)
-KwCb *gCb;
-KwUlRbCb *rbCb;
-#endif
{
- KwSn curSn = 0; /* sequence number of PDU */
- KwSn windSz; /* PDU window size */
- KwUmRecBuf **umRecBuf; /* UM module receive buffer */
-
- TRC2(kwUmmFreeUlRbCb)
-
-
- windSz = rbCb->m.umUl.umWinSz << 1;
+ RlcSn curSn = 0; /* Sequence number of PDU */
+ RlcUmRecBuf *recBuf = NULLP;
- umRecBuf = rbCb->m.umUl.recBuf;
-
- if(TRUE == kwChkTmr(gCb,(PTR)rbCb,KW_EVT_UMUL_REORD_TMR))
+ if(TRUE == rlcChkTmr(gCb,(PTR)rbCb,EVENT_RLC_UMUL_REASSEMBLE_TMR))
{
- kwStopTmr(gCb,(PTR)rbCb,KW_EVT_UMUL_REORD_TMR);
+ rlcStopTmr(gCb,(PTR)rbCb, EVENT_RLC_UMUL_REASSEMBLE_TMR);
}
- while (curSn < windSz)
+
+ do
{
- if (umRecBuf[curSn] != NULLP)
+ recBuf = rlcUtlGetUmRecBuf(rbCb->m.umUl.recBufLst, curSn);
+ if ( recBuf != NULLP )
{
- KW_FREE_BUF_WC(umRecBuf[curSn]->pdu);
- umRecBuf[curSn]->pdu = NULLP;
-
- KW_FREE_WC(gCb, umRecBuf[curSn], sizeof(KwUmRecBuf));
- umRecBuf[curSn] = NULLP;
+ if (recBuf->pdu != NULLP)
+ {
+ ODU_PUT_MSG_BUF(recBuf->pdu);
+ }
+ /* Release all the segments */
+ rlcUmmRelAllSegs(gCb,recBuf);
+ rlcUtlDelUmRecBuf(gCb, rbCb->m.umUl.recBufLst, recBuf);
}
curSn++;
- }
- KW_FREE_WC(gCb,rbCb->m.umUl.recBuf, (windSz ) * sizeof(KwUmRecBuf*));
- rbCb->m.umUl.recBuf = NULLP;
- RETVOID;
-}
+ }while ( curSn < RLC_RCV_BUF_BIN_SIZE);
+
+ RLC_FREE(gCb,rbCb->m.umUl.recBufLst, (RLC_RCV_BUF_BIN_SIZE * sizeof(CmLListCp)));
+ rbCb->m.umUl.recBufLst = NULLP;
+ if(rbCb->m.umUl.assembleSdu != NULLP)
+ {
+ ODU_PUT_MSG_BUF(rbCb->m.umUl.assembleSdu);
+ }
+ return;
+} /* rlcAmmFreeUlRbCb */
/********************************************************************30**
End of file