UL data path changes at Phy stub, RLC UL UM and DU APP [Issue-ID: ODUHIGH-262]
[o-du/l2.git] / src / 5gnrrlc / kw_umm_ul.c
index 2f6755e..a1c88a3 100755 (executable)
      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
@@ -67,20 +63,28 @@ static int RLOG_FILE_ID=240;
 #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
 /**
@@ -89,34 +93,65 @@ extern U32 isMemThreshReached(Region region);
  *       
  * @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
@@ -127,10 +162,318 @@ PRIVATE Void kwUmmFindNextVRUR (KwUmUl* umUl, KwSn nextSn)
  *
  * @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;
 }
 
 /**
@@ -150,51 +493,24 @@ PRIVATE S16 kwUmmCheckSnInReordWindow (KwSn sn,
 */
 /* 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;
 
@@ -204,54 +520,35 @@ KwPduInfo *pduInfo;             /* Pdu  data and related information */
    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;
      }
@@ -260,305 +557,167 @@ KwPduInfo *pduInfo;             /* Pdu  data and related information */
 #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;   
 }
 
 /**
@@ -570,7 +729,7 @@ KwUmRecBuf   *umRecBuf;
  *       - 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 
@@ -580,44 +739,46 @@ KwUmRecBuf   *umRecBuf;
  *
  * @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;
    }
@@ -625,12 +786,12 @@ KwUlRbCb     *rbCb;
    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;
 }
 
 /**
@@ -638,8 +799,8 @@ KwUlRbCb     *rbCb;
  *       
  * @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
@@ -650,239 +811,95 @@ KwUlRbCb     *rbCb;
  *      -# 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;
    }
 }
 
@@ -900,50 +917,45 @@ KwUlRbCb   *rbCb;
  * @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