+++ /dev/null
-/*******************************************************************************
-################################################################################
-# Copyright (c) [2017-2019] [Radisys] #
-# #
-# Licensed under the Apache License, Version 2.0 (the "License"); #
-# you may not use this file except in compliance with the License. #
-# You may obtain a copy of the License at #
-# #
-# http://www.apache.org/licenses/LICENSE-2.0 #
-# #
-# Unless required by applicable law or agreed to in writing, software #
-# distributed under the License is distributed on an "AS IS" BASIS, #
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
-# See the License for the specific language governing permissions and #
-# limitations under the License. #
-################################################################################
-*******************************************************************************/
-
-/********************************************************************20**
-
- Name: RLC - AM module file
-
- Type: C source file
-
- Desc: Source code for Acknowledged Mode Module functions such as,
-
- Transmission of data/control PDUs
- Retransmission (Feedback in terms of status)
- Polling
- Assemble SDUs
- Reception - reordering
- Duplicate detection for byte segments
- Reassemble SDUs
-
- File: kw_amm_ul.c
-
-*********************************************************************21*/
-
-/* header include files (.h) */
-#include "common_def.h"
-#include "lkw.h" /* LKW defines */
-#include "ckw.h" /* CKW defines */
-#include "kwu.h" /* KWU defines */
-#include "rgu.h" /* RGU defines */
-#include "kw_udx.h"
-#include "kw_err.h" /* Err defines */
-#include "kw_env.h" /* RLC environment options */
-
-#include "kw.h" /* RLC defines */
-#include "kw_ul.h"
-
-/* extern (.x) include files */
-#include "lkw.x" /* LKW */
-#include "ckw.x" /* CKW */
-#include "kwu.x" /* KWU */
-#include "rgu.x" /* RGU */
-
-#include "kw.x"
-#include "kw_ul.x"
-#include "kw_udx.x"
-
-/* Variable for logging, declared in cl */
-#ifndef RGL_SPECIFIC_CHANGES
-#ifndef TENB_ACC
-#ifndef LTE_PAL_ENB
-uint32_t ulrate_rgu;
-#endif
-#endif
-#endif
-#ifndef RGL_SPECIFIC_CHANGES
-#ifndef TENB_ACC
-#ifndef TENB_T2K3K_SPECIFIC_CHANGES
-#ifndef LTE_PAL_ENB
-uint32_t isMemThreshReached(Region region);
-#endif
-#else
-#ifndef LTE_PAL_ENB
-uint32_t isMemThreshReached(Region region);
-#endif
-#endif
-#endif
-#endif
-/** @file gp_amm_ul.c
-@brief RLC Acknowledged Mode Uplink Module
-**/
-#define RLC_MODULE (RLC_DBGMASK_AM | RLC_DBGMASK_UL) /* for debugging purpose */
-
-/* private function declarations */
-
-static void rlcAmmUlAssembleCntrlInfo ARGS ((RlcCb *gCb, RlcUlRbCb *rbCb));
-
-static uint8_t rlcAmmExtractHdr ARGS ((RlcCb *gCb,
- RlcUlRbCb *rbCb,
- Buffer *pdu,
- RlcAmHdr *amHdr,
- uint8_t *fByte));
-
-static bool rlcAmmUlPlacePduInRecBuf ARGS ((RlcCb *gCb,
- Buffer *pdu,
- RlcUlRbCb *rbCb,
- RlcAmHdr *amHdr));
-
-static void rlcAmmTriggerStatus ARGS ((RlcCb *gCb,
- RlcUlRbCb *rbCb,
- RlcSn sn,
- bool discFlg));
-
-static uint8_t rlcAmmUlReassembleSdus ARGS ((RlcCb *gCb,
- RlcUlRbCb *rbCb,
- RlcAmRecBuf *recBuf));
-
-static Void rlcAmmProcPduOrSeg ARGS ((RlcCb *gCb,
- RlcUlRbCb *rbCb,
- RlcAmHdr *amHdr,
- Buffer *pdu));
-
-static Void rlcAmmUpdExpByteSeg ARGS ((RlcCb *gCb,RlcAmUl *amUl, RlcSeg* newSeg));
-
-static Void rlcAmmExtractElmnt ARGS ((RlcCb *gCb, Buffer *pdu, RlcExtHdr *hdrInfo));
-
-static Void rlcAmmUlHndlStatusPdu ARGS ((RlcCb *gCb,
- RlcUlRbCb *rbCb,
- Buffer *cntrlPdu,
- uint8_t *fByte));
-
-/******************************************************************************
-
- AM Module contains the following funcitons:
-
- - rlcAmmProcessSdus
- - rlcAmmUlAssembleCntrlInfo
- - rlcResegRetxPdus
- - rlcAssembleSdus
- - kwChkandSetPoll
- - rlcAmmProcessPdus
- - rlcAmmUlHndlStatusPdu
- - rlcAmmTriggerStatus
- - rlcAmmUlReassembleSdus
-
-*******************************************************************************/
-/** @addtogroup ammode */
-/*@{*/
-
-/**
- * @brief Private function to fill NACK information in status Pdu as per 5GNR
- *
- * @param[in] rbCb Ul RbCb
- * @param[in] sn Sequence number of the PDU for which the NACK
- * @param[in] isSegment TRUE means NACK for segment; FALSE for PDU
- * @param[in] soStart SOStart
- * @param[in] soEnd SOEnd
- * @param[out] statusPdu status Pdu holder to be filled
- * @param[in] prevNackSn It holds previous nack Sn
- *
- * @return S16
- * The number of bytes required to encode this NACK information
- *
- */
-static uint8_t rlcAmmUlSetNackInfo(RlcUlRbCb *rbCb, RlcSn sn, bool isSegment, \
- uint16_t soStart, uint16_t soEnd, RlcUdxDlStaPdu *statusPdu, RlcSn *prevNackSn)
-{
- RlcNackInfo *nackInfo = (statusPdu->nackInfo + statusPdu->nackCount);
- uint16_t sizeToBeEncd = 0; /* Status PDu size to be encoded */
-
- /* In following cases we should increment the nackCnt & fill new NACK_SN info:
- * 1) First NACK_SN of the statusdPdu
- * 2) NACK_SN is not continuous with previous
- * 3) NACK_SN is same as previuos but segments are not continuous
- * 4) NACK_SN is continuous with previous but previous NACK_SN segments
- * are not missing in sequence till end
- */
- if((*prevNackSn == 0xffffffff) || ((((*prevNackSn) + 1) & RLC_AMUL.snModMask) != sn) ||
- (((*prevNackSn) == sn) && (((nackInfo->soEnd + 1) != soStart))) ||
- ((nackInfo->isSegment) && (((*prevNackSn) + 1) == sn) && (nackInfo->soEnd != RLC_ALL_BYTES_MISSING)))
- {
- if(nackInfo->nackRange)
- {
- if((nackInfo->soEnd) && (!nackInfo->soStart))
- {
- /*First nack_sn of this nackRange not segmented but last is segmented */
- sizeToBeEncd = 5; /*32 for soStart and soEnd and 8 for nackRange */
- }
- else
- {
- /*First nack_sn of this nackRange was segmented */
- sizeToBeEncd = 1; /*8 for nackRange */
- }
- }
-
- if(*prevNackSn != 0xffffffff)
- {
- /* Increment nackCount as this sn is continous */
- statusPdu->nackCount++;
- nackInfo = statusPdu->nackInfo + statusPdu->nackCount;
- }
-
- nackInfo->sn = sn;
- nackInfo->isSegment = isSegment;
- nackInfo->soStart = soStart;
- nackInfo->soEnd = soEnd;
- nackInfo->nackRange = 0;
-
- if(isSegment)
- {
- sizeToBeEncd += ((RLC_AMUL.snLen == RLC_AM_CFG_12BIT_SN_LEN)?6:7); /* NACK,E1,E2,Sostart,SoEnd */
- }
- else
- {
- sizeToBeEncd += ((RLC_AMUL.snLen == RLC_AM_CFG_12BIT_SN_LEN)?2:3); /* NACK,E1,E2 */
- }
- }
- else
- {
- if(!(nackInfo->nackRange))
- {
- nackInfo->nackRange++;
- }
- /* This case means there are continuous SNs/Segments. If it is the next
- * Sn then increment nackRnage. if same SN but different segment then
- * dont increment nackRange */
- if((((*prevNackSn) + 1) & RLC_AMUL.snModMask) == sn)
- {
- nackInfo->nackRange++;
- }
-
- /* If NackRange is reached to max value then increment statusPdu->nackCount*/
- if(nackInfo->nackRange == 255)
- {
- statusPdu->nackCount++;
- if(nackInfo->isSegment)
- {
- sizeToBeEncd = 1; /* return only nackRangeSize*/
- }
- else if (isSegment)
- {
- /* First SN was not segmented of this nackRange but last SN is segmented */
- sizeToBeEncd = 5; /* return size of soSatrt + soEnd + nackRnage */
- }
- }
-
- if(isSegment)
- {
- nackInfo->isSegment = isSegment;
- nackInfo->soEnd = soEnd;
- }
- else if(nackInfo->isSegment)
- {
- nackInfo->soEnd = RLC_ALL_BYTES_MISSING;
- }
- else
- {
- nackInfo->soStart = 0;
- nackInfo->soEnd = 0;
- }
-
- }
- *prevNackSn = sn;
-
- return (sizeToBeEncd);
-}
-
-/**
- * @brief Private handler to gather information required to create the STATUS
- * PDU
- *
- * @details
- * Scans the reception buffer and copies information to the UdxDlStaPdu
- * structure about SN's and segments not yet received. This data is
- * sent to the DL instance so that it can create an appropriate (depending
- * on the grants from MAC) STATUS PDU and send it to MAC.
- *
- * @param[in] gCb RLC instance control block
- * @param[in] rbCb Uplink RB control block
- *
- * @return Void
- *
- */
-static void rlcAmmUlAssembleCntrlInfo(RlcCb *gCb, RlcUlRbCb *rbCb)
-{
- RlcUdxDlStaPdu *pStatusPdu;
- RlcNackInfo *nackInfo;
- RlcSn sn; /* sequence number */
- RlcSn mSn; /* Mod val of sequence number */
- RlcSn rxHighestStatus; /* Mod val of rxHighestStatus */
- RlcSeg *seg; /* pdu segment */
- uint16_t nackCnt = 0; /* Index for staPdu */
- uint16_t seqSo; /* segmment offset */
- RlcUdxUlSapCb *sapCb;
- uint16_t staPduEncSize = 3; /* size that would be of the encoded
- STATUS PDU, it is in bits; 15 for
- first fixed part of STATUS PDU */
- RlcAmRecBuf *recBuf = NULLP;
- RlcSn prevNackSn = 0xffffffff;
-
- sapCb = RLC_GET_UDX_SAP(gCb);
-
- RLC_ALLOC_SHRABL_BUF(sapCb->pst.region,
- sapCb->pst.pool,
- pStatusPdu,
- sizeof(RlcUdxDlStaPdu));
-
-#if (ERRCLASS & ERRCLS_ADD_RES)
- /* Memory allocation failure can not be expected */
- if(!pStatusPdu)
- {
- return;
- }
-#endif
-
- sn = RLC_AMUL.rxNext;
- MODAMR(sn, mSn, RLC_AMUL.rxNext, RLC_AMUL.snModMask);
- MODAMR(RLC_AMUL.rxHighestStatus, rxHighestStatus, RLC_AMUL.rxNext, RLC_AMUL.snModMask);
-
- recBuf = rlcUtlGetRecBuf(RLC_AMUL.recBufLst, sn);
-
- while (mSn < rxHighestStatus )
- {
- /* For missing PDUs */
- if ((NULLP == recBuf) && nackCnt < RLC_MAX_NACK_CNT )
- {
- DU_LOG("\nERROR --> RLC_UL : rlcAmmUlAssembleCntrlInfo: Missing PDU's SN = %d UEID:%d \
- CELLID:%d", sn, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
- staPduEncSize += rlcAmmUlSetNackInfo(rbCb,
- sn,
- FALSE, /* isSegment */
- 0, /* SOStart */
- 0, /* SOEnd */
- pStatusPdu,
- &prevNackSn);
- }
- else if (recBuf && (recBuf->pdu == NULLP) &&
- (recBuf->segLst.count > 0))
- {
- /* Scan through the byte segments of PDU and add this sn
- with soStart and soEnd info to staPdu */
-
- seqSo = 0;
- RLC_LLIST_FIRST_SEG(recBuf->segLst, seg);
- while (seg != NULLP && nackCnt < RLC_MAX_NACK_CNT)
- {
- /* For missing byte segments */
- if (seg->amHdr.so != seqSo)
- {
- staPduEncSize += rlcAmmUlSetNackInfo(rbCb,
- sn,
- TRUE,
- seqSo,
- seg->amHdr.so - 1,
- pStatusPdu,
- &prevNackSn);
-
- DU_LOG("\nDEBUG --> RLC_UL : rlcAmmUlAssembleCntrlInfo: Missing byte segment's"
- " SN:%d UEID:%d CELLID:%d", sn, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
- DU_LOG("\nDEBUG --> RLC_UL : rlcAmmUlAssembleCntrlInfo: soStart and soEnd = %d, %d \
- UEID:%d CELLID:%d", seqSo, seg->amHdr.so - 1, rbCb->rlcId.ueId,
- rbCb->rlcId.cellId);
- }
-
- seqSo = seg->soEnd + 1;
- RLC_LLIST_NEXT_SEG(recBuf->segLst, seg);
- }
-
- /* Check if the last segment is missing */
- RLC_LLIST_LAST_SEG(recBuf->segLst, seg);
- if ((seg != NULLP) &&
- (seg->amHdr.si != RLC_SI_LAST_SEG && nackCnt < RLC_MAX_NACK_CNT))
- {
- staPduEncSize += rlcAmmUlSetNackInfo(rbCb,
- sn,
- TRUE,
- seqSo,
- RLC_ALL_BYTES_MISSING,
- pStatusPdu,
- &prevNackSn);
-
- DU_LOG("\nDEBUG --> RLC_UL : rlcAmmUlAssembleCntrlInfo: Missing (last) byte "
- "segment's SN:%d UEID:%d CELLID:%d", sn, rbCb->rlcId.ueId,
- rbCb->rlcId.cellId);
- DU_LOG("\nDEBUG --> RLC_UL : rlcAmmUlAssembleCntrlInfo: soStart and soEnd = %d, %d\
- UEID:%d CELLID:%d", seqSo, RLC_ALL_BYTES_MISSING, rbCb->rlcId.ueId,
- rbCb->rlcId.cellId);
- }
- }
-
-
- sn = (sn + 1) & (RLC_AMUL.snModMask); /* MOD 1024 */
- MODAMR(sn, mSn, RLC_AMUL.rxNext, RLC_AMUL.snModMask);
-
- /* Get the received Buffer the updated/next SN */
- recBuf = rlcUtlGetRecBuf(RLC_AMUL.recBufLst, sn);
-
- /* Find the next missing sequence number if nackCnt reaches maximum and
- still Reordering window has some missing AMDPDUs / AMDPDU segments. The
- next missing sequence number will be considered as the ack sequnece
- number in the status pdu.*/
- if((nackCnt == RLC_MAX_NACK_CNT) &&
- ((recBuf == NULLP) ||
- ((recBuf->pdu == NULLP) &&
- (recBuf->segLst.count > 0))))
- {
- break;
- }
- }
-
- /*Unfortunately i have write below peice of code here because kwAmmsetNackInfo()
- * don't know that this is the last nackSn with nackRange*/
- nackInfo = &(pStatusPdu->nackInfo[pStatusPdu->nackCount]);
- if(nackInfo->nackRange)
- {
- if((nackInfo->soEnd) && (!nackInfo->soStart))
- {
- /*First nack_sn of this nackRange not segmented but last is segmented */
- staPduEncSize += 5; /*32 for soStart and soEnd and 8 for nackRange */
- }
- else
- {
- /*First nack_sn of this nackRange was segmented */
- staPduEncSize += 1; /*8 for nackRange */
- }
- }
- /* nackCount is used as an index to nackInfo array but in status Pdu it
- * should be equal to number nackInfo that are filled. hence incrementing by 1*/
- if(prevNackSn != 0xffffffff)
- {
- pStatusPdu->nackCount++;
- }
- /* Update ACK SN with the last sn for which feedback is not assembled */
- if ( mSn == rxHighestStatus)
- {
- pStatusPdu->ackSn = RLC_AMUL.rxHighestStatus;
- }
- else
- {
- pStatusPdu->ackSn = sn;
- }
-
- DU_LOG("\nINFO --> RLC_UL : rlcAmmUlAssembleCntrlInfo: ACK PDU's SN = %d"
- "UEID:%d CELLID:%d", pStatusPdu->ackSn, rbCb->rlcId.ueId,
- rbCb->rlcId.cellId);
-
- pStatusPdu->controlBo = staPduEncSize; /*Its already in bytes */
-
- RLC_AMUL.staTrg = FALSE;
- RLC_AMUL.gatherStaPduInfo = FALSE;
-
-
- if (rlcUlUdxStaPduReq(&sapCb->pst,
- sapCb->spId,
- &rbCb->rlcId,
- pStatusPdu) != ROK)
- {
- DU_LOG("\nERROR --> RLC_UL : rlcAmmUlAssembleCntrlInfo: Failed to Send Sta Pdu UEID:%d \
- CELLID:%d", rbCb->rlcId.ueId, rbCb->rlcId.cellId);
- RLC_FREE_SHRABL_BUF_WC(sapCb->pst.region,
- sapCb->pst.pool,
- pStatusPdu,
- sizeof(RlcUdxDlStaPdu));
- }
-
- return;
-}
-
-#ifdef XEON_SPECIFIC_CHANGES
-uint32_t gRlcDatIndUL;
-#endif
-
-#ifdef T2K_TRIGGER_RLC_REEST
-uint32_t drpRlcDrbPack;
-#endif
-/**
- * @brief Handler to process the PDUs received from MAC and send it to PDCP
- *
- * @details
- * This function is invoked by UTL with the PDU(s) received from MAC.
- * It reorders the received data PDUs and trigger status report as
- * needed. Reassembles the SDUs in sequence and send it to PDCP.
- * It also processes the control PDU
- *
- * @param[in] gCb RLC instance control block
- * @param[in] rbCb RB control block
- * @param[out] pduInfo PDU Info received from MAC
- *
- * @return Void
- *
- */
-#ifdef LTE_L2_MEAS
-void rlcAmmProcessPdus(RlcCb *gCb, RlcUlRbCb *rbCb, KwPduInfo *pduInfo, uint32_t ttiCnt)
-#else
-void rlcAmmProcessPdus(RlcCb *gCb, RlcUlRbCb *rbCb, KwPduInfo *pduInfo)
-#endif
-{
- Buffer *pdu;
- RlcAmUl *amUl;
- RlcAmHdr amHdr;
- uint8_t numPdu = 0;
- uint8_t numPduToProcess;
- RlcSn sn;
- RlcSn tSn;
- RlcSn mSn;
- uint8_t fByte;
- bool discFlg;
-#ifdef LTE_L2_MEAS_RLC
- MsgLen rlcSduSz; /*Holds length of Rlc Sdu*/
-#endif /* LTE_L2_MEAS */
-
- 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);
-
- while (numPdu < numPduToProcess)
- {
- discFlg = FALSE;
- pdu = pduInfo->mBuf[numPdu++];
-
- if (! pdu)
- {
-
- DU_LOG("\nERROR --> RLC_UL : rlcAmmProcessPdus: Null Pdu UEID:%d CELLID:%d",
- rbCb->rlcId.ueId, rbCb->rlcId.cellId);
- gCb->genSts.errorPdusRecv++;
- break;
- }
-#ifndef RGL_SPECIFIC_CHANGES
-#ifndef TENB_ACC
-#ifndef LTE_PAL_ENB
- MsgLen len;
- ODU_GET_MSG_LEN(pdu, &len);
- ulrate_rgu += len;
-#endif
-#endif
-#endif
- /* Extract AM PDU/SEG header Info */
- RLC_MEM_ZERO(&amHdr, sizeof(RlcAmHdr));
- /* Avoided the allocation of amHdr and sending
- a single pointer */
- 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);
- ODU_PUT_MSG_BUF(pdu);
- gCb->genSts.errorPdusRecv++;
- continue;
- }
- /* Check if its a control PDU */
- if (amHdr.dc == 0)
- {
- rlcAmmUlHndlStatusPdu(gCb, rbCb, pdu, &fByte);
- ODU_PUT_MSG_BUF(pdu);
- 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);
- ODU_PUT_MSG_BUF(pdu);
- continue;
- }
-#ifndef RGL_SPECIFIC_CHANGES
-#ifdef LTE_TDD
-#ifndef TENB_ACC
-#ifndef TENB_T2K3K_SPECIFIC_CHANGES
-#ifndef LTE_PAL_ENB
- /* Changed the condition to TRUE from ROK */
- if(isMemThreshReached(rlcCb[0]->init.region) == TRUE)
- {
- uint32_t rlculdrop;
- rlculdrop++;
- ODU_PUT_MSG_BUF(pdu);
- continue;
- }
-#endif
-#else
-#ifndef LTE_PAL_ENB
- /*ccpu00142274 - UL memory based flow control*/
- if(isMemThreshReached(rlcCb[0]->init.region) != ROK)
- {
- uint32_t rlculdrop;
- rlculdrop++;
- ODU_PUT_MSG_BUF(pdu);
- continue;
- }
-#endif
-#endif
-#endif
-#endif
-#endif
-
-#ifdef T2K_TRIGGER_RLC_REEST
- if(drpRlcDrbPack > 1000)
- {
- if(rbCb->rlcId.rbType == CM_LTE_DRB)
- {
- ODU_PUT_MSG_BUF(pdu);
- continue;
- }
- }
- drpRlcDrbPack++;
-#endif
- /* Reordering data PDU */
- sn = amHdr.sn;
- if (rlcAmmUlPlacePduInRecBuf(gCb,pdu, rbCb, &amHdr) == TRUE)
- {
- RlcAmRecBuf *recBuf;
- bool tmrRunning;
- RlcSn tVrMr;
- RlcSn mrxNextHighestRcvd;
-
-#ifdef LTE_L2_MEAS
- rlcUtlCalUlIpThrPut(gCb, rbCb, pdu, ttiCnt);
-#endif /* LTE_L2_MEAS */
-
- /* Update rxNextHighestRcvd */
- MODAMR(sn, mSn, amUl->rxNext, amUl->snModMask);
- MODAMR(amUl->rxNextHighestRcvd, mrxNextHighestRcvd, amUl->rxNext, amUl->snModMask);
- if (mSn >= mrxNextHighestRcvd)
- {
- 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);
- }
-
- recBuf = rlcUtlGetRecBuf(amUl->recBufLst, sn);
- if ((NULLP != recBuf) && ( recBuf->allRcvd))
- {
- /* deliver the reassembled RLC SDU to upper layer,
- 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)
- {
- tSn = (sn + 1) & (amUl->snModMask) ; /* MOD (2 Pwr SN LEN- 1) */
-
- recBuf = rlcUtlGetRecBuf(amUl->recBufLst, tSn);
- /* Scan through till the upper edge of the window */
- MODAMR(tSn, mSn, amUl->rxNext, amUl->snModMask);
- while (mSn <= tVrMr)
- {
- if ((NULLP == recBuf) || (!recBuf->allRcvd))
- {
- DU_LOG("\nDEBUG --> RLC_UL : rlcAmmProcessPdus: Updated rxHighestStatus:%d "
- "UEID:%d CELLID:%d",
- tSn,
- rbCb->rlcId.ueId,
- rbCb->rlcId.cellId);
-
- amUl->rxHighestStatus = tSn;
- break;
- }
- tSn = (tSn + 1) & (amUl->snModMask); /* MOD (2 Pwr SN LEN- 1) */
- recBuf = rlcUtlGetRecBuf(amUl->recBufLst, tSn);
- mSn++;
- }
- }
-
-
- /* Update rxNext */
- if (sn == amUl->rxNext)
- {
- tSn = sn;
- recBuf = rlcUtlGetRecBuf(amUl->recBufLst, tSn);
- MODAMR(tSn, mSn, amUl->rxNext, amUl->snModMask);
- /* Scan through till the upper edge of the window */
- 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);
- }
- else
- {
- amUl->rxNext = tSn;
- amUl->vrMr = (amUl->rxNext + (RLC_AM_GET_WIN_SZ(amUl->snLen))) & (amUl->snModMask);
- break;
- }
- tSn = (tSn + 1) & (amUl->snModMask);
- recBuf = rlcUtlGetRecBuf(amUl->recBufLst, tSn);
- mSn++;
- }
- }
- }
-
- /* Check if reAsmblTmr is running and update rxNextStatusTrig accordingly */
- tmrRunning = rlcChkTmr(gCb,(PTR)rbCb, EVENT_RLC_AMUL_REASSEMBLE_TMR);
- if (tmrRunning)
- {
- 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))
- {
- 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);
- }
- }
-
- if (!tmrRunning)
- {
- /* spec 38.322v15.3.0 - 5.2.3.2.3 */
- if((amUl->rxNextHighestRcvd > amUl->rxNext) || ((amUl->rxNextHighestRcvd == amUl->rxNext) &&
- (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);
- }
- }
- }
- else
- {
- discFlg = TRUE;
- gRlcStats.amRlcStats.numULPdusDiscarded++;
- }
-
- if (amHdr.p)
- {
- rlcAmmTriggerStatus(gCb,rbCb, sn, discFlg);
- }
- }
-
-#ifdef LTE_L2_MEAS
- rlcUtlCalUlIpThrPutIncTTI(gCb, rbCb,ttiCnt);
-#endif /* LTE_L2_MEAS */
- gCb->genSts.pdusRecv += pduInfo->numPdu;
- if (amUl->gatherStaPduInfo)
- {
- rlcAmmUlAssembleCntrlInfo(gCb,rbCb);
- }
-
- return;
-}
-
-
-/**
- * @brief Private handler to extract header Information of the PDU
- *
- * @details
- * This function extracts the header elements of the PDU and store them
- * in db for future reference.
- *
- * fByte - is the first byte removed from the PDU as part of calling
- * functions
- *
- * @param[in] gCb RLC instance control block
- * @param[in] rbCb Uplink RB control block
- * @param[in] pdu Received PDU
- * @param[out] amHdr Pointer to the extracted AM header
- * @param[out] fByte First byte removed from the PDU
- *
- * @return S16
- * -# ROK
- * -# RFAILED
- *
- */
-static uint8_t rlcAmmExtractHdr(RlcCb *gCb, RlcUlRbCb *rbCb, Buffer *pdu, RlcAmHdr *amHdr, uint8_t *fByte)
-{
- uint8_t snByte;
- RlcSn sn = 0;
- MsgLen pduSz;
- RlcExtHdr hdrInfo;
-
- RLC_MEM_ZERO(&hdrInfo, sizeof(RlcExtHdr));
-
- /* Extract fixed part of the header */
- ODU_GET_MSG_LEN(pdu,&pduSz);
- ODU_REM_PRE_MSG(fByte, pdu);
- amHdr->dc = (*fByte & RLC_DC_POS) >> RLC_DC_SHT;
- if (RLC_CNTRL_PDU == amHdr->dc)
- {
- //DU_LOG ("\nINFO --> RLC_UL : ++++++++++++ 5GNRLOG HDR extracted CTRL : \n");
- return ROK;
- }
-
- amHdr->p = (*fByte & RLC_POLL_POS) >> RLC_POLL_SHT;
-
- amHdr->si = (*fByte & RLC_SI_POS) >> RLC_SI_SHT;
-
- /* 12 BIT SN */
- if (rbCb->m.amUl.snLen == RLC_AM_CFG_12BIT_SN_LEN)
- {
- ODU_REM_PRE_MSG(&snByte, pdu);
- sn = (RlcSn)(((*fByte & RLC_SN_POS_12BIT) << RLC_BYTE_LEN ) | snByte);
- amHdr->sn = sn;
- }
- else if (rbCb->m.amUl.snLen == RLC_AM_CFG_18BIT_SN_LEN)
- {
- ODU_REM_PRE_MSG(&snByte, pdu);
- sn = (RlcSn)(((*fByte & RLC_SN_POS_18BIT) << RLC_BYTE_LEN ) | snByte);
-
- ODU_REM_PRE_MSG(&snByte, pdu);
- sn = ((sn << RLC_BYTE_LEN) | snByte);
-
- amHdr->sn = sn;
- }
- if ((amHdr->si != 0) && (amHdr->si != RLC_SI_FIRST_SEG))
- {
- hdrInfo.len = RLC_SO_LEN_5GNR;
- rlcAmmExtractElmnt(gCb, pdu, &hdrInfo);
- amHdr->so = hdrInfo.val;
- pduSz -= 2;
- }
-
- return ROK;
-}
-
-#ifdef OLD
-/**
- * @brief Private handler to extract header Information of the PDU
- *
- * @details
- * This function extracts the header elements of the PDU and store them
- * in db for future reference.
- *
- * fByte - is the first byte removed from the PDU as part of calling
- * functions
- *
- * @param[in] gCb RLC instance control block
- * @param[in] rbCb Uplink RB control block
- * @param[in] pdu Received PDU
- * @param[out] amHdr Pointer to the extracted AM header
- * @param[out] fByte First byte removed from the PDU
- *
- * @return S16
- * -# ROK
- * -# RFAILED
- *
- */
-static S16 rlcAmmExtractHdrOld(RlcCb *gCb,Buffer *pdu,RlcAmHdr *amHdr,uint8_t *fByte)
-{
- uint8_t e;
- uint8_t snByte;
- uint16_t sn;
- MsgLen pduSz;
- MsgLen totalSz = 0;
- RlcExtHdr hdrInfo;
-
- RLC_MEM_ZERO(&hdrInfo, sizeof(RlcExtHdr));
-
- /* Extract fixed part of the header */
- SFndLenMsg(pdu,&pduSz);
- SRemPreMsg(fByte, pdu);
- amHdr->dc = (*fByte & RLC_DC_POS) >> RLC_DC_SHT;
- if (RLC_CNTRL_PDU == amHdr->dc)
- {
- return ROK;
- }
- /* kw002.201 : Changed the extraction of hdr elements to avoid */
- /* function calls */
- amHdr->rf = (*fByte & RLC_RF_POS) >> RLC_RF_SHT;
- amHdr->p = (*fByte & RLC_POLL_POS) >> RLC_POLL_SHT;
- amHdr->fi = (*fByte & RLC_FI_POS) >> RLC_FI_SHT;
- e = amHdr->e = (*fByte & RLC_E_POS)>> RLC_E_SHT;
-
- SRemPreMsg(&snByte, pdu);
- sn = (uint16_t)(((*fByte & RLC_SN_POS) << RLC_BYTE_LEN ) | snByte);
- amHdr->sn = sn;
- if (amHdr->rf == 1)
- {
- /* Extract extn part of the header */
- hdrInfo.len = RLC_LSF_LEN;
- rlcAmmExtractElmnt(gCb, pdu, &hdrInfo);
- amHdr->lsf = (uint8_t)hdrInfo.val;
-
- hdrInfo.len = RLC_SO_LEN;
- rlcAmmExtractElmnt(gCb, pdu, &hdrInfo);
- amHdr->so = hdrInfo.val;
- pduSz -= 2;
- }
-
- amHdr->numLi = 0;
- /* Extract LIs */
- while (e && (amHdr->numLi < RLC_MAX_UL_LI))
- {
- hdrInfo.len = RLC_E_LEN;
- rlcAmmExtractElmnt(gCb, pdu, &hdrInfo);
- e = amHdr->e = (uint8_t)hdrInfo.val;
-
- /* Extract LI value*/
- hdrInfo.len = RLC_LI_LEN;
- rlcAmmExtractElmnt(gCb, pdu, &hdrInfo);
- /* li = hdrInfo.val;*/
-
- /* check if LI is zero */
- if (! hdrInfo.val)
- {
- DU_LOG("\nERROR --> RLC_UL : Received LI as 0");
- return RFAILED;
- }
-
- /* store the extracted LI value */
- amHdr->li[amHdr->numLi++] = hdrInfo.val;
- totalSz += hdrInfo.val; /* incrment the size by LI value */
- }
-
- /*ccpu00122597:PDU is dropped if liCnt exceeds RLC_MAX_LI*/
- if(e && (amHdr->numLi >= RLC_MAX_UL_LI))
- {
- DU_LOG("\nERROR --> RLC_UL : LI Count [%u] exceeds Max LI Count[%u]",
- amHdr->numLi, RLC_MAX_UL_LI);
- return RFAILED;
- }
-
- /* first 2 bytes + Add one for Odd LI*/
- pduSz -= ( amHdr->numLi + (amHdr->numLi >> 1) + 2 + (amHdr->numLi & 1) );
-
- if ( totalSz >= pduSz )
- {
- DU_LOG("\nERROR --> RLC_UL : SN [%d]:Corrupted PDU as TotSz[%lu] PduSz[%lu] ",
- amHdr->sn, totalSz, pduSz);
- return RFAILED;
- }
-
- return ROK;
-}
-#endif
-
-/**
- * @brief Private handler to process the status PDU
- *
- * @details
- * Private handler invokded by rlcAmmProcessPdus to process the
- * control PDU (status report) received from its peer RLC entity.
- *
- * - Decode the values from the received control pdu
- * - Create a RlcUdxStaPdu structure, copy the values onto it and
- * send it to the DL instance for further processing
- *
- * @param[in] gCb RLC instance control block
- * @param[in] rbCb Uplink RB control block
- * @param[in] cntrlPdu Control PDU received from MAC
- * @param[in] fByte First byte already removed from the STATUS PDU
- *
- * @return Void
- *
- */
-static void rlcAmmUlHndlStatusPdu(RlcCb *gCb, RlcUlRbCb *rbCb, Buffer *cntrlPdu, uint8_t *fByte)
-{
- uint8_t e1;
- RlcExtHdr hdrInfo;
- RlcUdxStaPdu *pStaPdu;
- RlcUdxUlSapCb *sapCb;
- uint8_t e3; /* NACK RANGE : 5GNR */
- uint32_t snLen;
- uint32_t snRange;
- uint32_t resrvdBitsAckSn=0;
- uint32_t resrvdBitsNackSn=0;
-
- RLC_MEM_ZERO(&hdrInfo, sizeof(RlcExtHdr));
-
- /* Extract the Control PDU */
- hdrInfo.hdr = (*fByte << 1);
- hdrInfo.pLen = 4;
-
- /* D/C has been shifted in the calling function */
- if (hdrInfo.hdr & 0xE0)
- {
- DU_LOG("\nINFO --> RLC_UL : rlcAmmUlHndlStatusPdu: Reserved value for CPT received UEID:%d \
- CELLID:%d", rbCb->rlcId.ueId, rbCb->rlcId.cellId);
- return;
- }
-
- sapCb = RLC_GET_UDX_SAP(gCb);
-
- RLC_ALLOC_SHRABL_BUF(sapCb->pst.region,
- sapCb->pst.pool,
- pStaPdu,
- sizeof(RlcUdxStaPdu));
-
-#if (ERRCLASS & ERRCLS_ADD_RES)
- /* Memory allocation failure can not be expected */
- if(!pStaPdu)
- {
- return;
- }
-#endif
-
- if (rbCb->m.amUl.snLen == RLC_AM_CFG_12BIT_SN_LEN)
- {
- snLen = 12;
- resrvdBitsAckSn = RLC_STA_PDU_R_BITS_ACKSN_12BITS;
- resrvdBitsNackSn = RLC_STA_PDU_R_BITS_NACKSN_12BITS;
- }
- else if (rbCb->m.amUl.snLen == RLC_AM_CFG_18BIT_SN_LEN)
- {
- snLen = 18;
- resrvdBitsAckSn = RLC_STA_PDU_R_BITS_ACKSN_18BITS;
- resrvdBitsNackSn = RLC_STA_PDU_R_BITS_NACKSN_18BITS;
- }
- else
- {
- snLen = RLC_SN_LEN;
- resrvdBitsAckSn = 0;
- resrvdBitsAckSn = 0;
- }
-
- pStaPdu->nackCnt = 0;
- /* For CPT */
- hdrInfo.hdr = hdrInfo.hdr << RLC_CPT_LEN;
-
- /* ACK Sn */
- hdrInfo.len = snLen;
- rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
- pStaPdu->ackSn = hdrInfo.val;
-
- //DU_LOG ("\nINFO --> RLC_UL : ++++++++++++ 5GNRLOG HNDL STATUS acksn %d : \n", pStaPdu->ackSn);
- /* Check if NACK Exists */
- hdrInfo.len = RLC_E1_LEN;
- rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
- e1 = (uint8_t)hdrInfo.val;
- DU_LOG("\nDEBUG --> RLC_UL : rlcAmmUlHndlStatusPdu: ACK SN = %d UEID:%d CELLID:%d",
- pStaPdu->ackSn, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
-
- /* Extract the Reserved Bits after ACK SN field */
- hdrInfo.len = resrvdBitsAckSn;
- rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
-
- /* If NACK exists in control PDU */
- /* For ACKs and NACKs */
- while (e1 && (pStaPdu->nackCnt < RLC_MAX_NACK_CNT))
- {
- hdrInfo.len = snLen;
- rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
- pStaPdu->nackInfo[pStaPdu->nackCnt].sn = hdrInfo.val;
-
- hdrInfo.len = RLC_E1_LEN;
- rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
- e1 = (uint8_t)hdrInfo.val;
-
- /* Extract e2 */
- /* hdrInfo.len = RLC_E1_LEN; --> previusly stored value (for e1) is
- already present*/
- rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
- /* e2 = (uint8_t) hdrInfo.val;*/
-
- /* Store e2 value */
- pStaPdu->nackInfo[pStaPdu->nackCnt].isSegment = (uint8_t) hdrInfo.val;
-
- /* Extract e3 : 5GNR */
- /* hdrInfo.len = RLC_E1_LEN; --> previusly stored value (for e1) is
- already present*/
- rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
- e3 = (uint8_t) hdrInfo.val;
-
- /* Extract Reserved Bits after NACK SN */
- hdrInfo.len = resrvdBitsNackSn;
- rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
-
- /* Test for resegmentation */
- if (pStaPdu->nackInfo[pStaPdu->nackCnt].isSegment)
- {
- hdrInfo.len = RLC_SO_LEN_5GNR; /* 5GNR : SO Len 16 Bits */
- rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
- pStaPdu->nackInfo[pStaPdu->nackCnt].soStart = hdrInfo.val;
-
- rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
- pStaPdu->nackInfo[pStaPdu->nackCnt].soEnd = hdrInfo.val;
-
- DU_LOG("\nDEBUG --> RLC_UL : rlcAmmUlHndlStatusPdu: soStart and soEnd = %d %d"
- "UEID:%d CELLID:%d", pStaPdu->nackInfo[pStaPdu->nackCnt].soStart,
- pStaPdu->nackInfo[pStaPdu->nackCnt].soEnd, rbCb->rlcId.ueId,
- rbCb->rlcId.cellId);
- }
- else
- {
- hdrInfo.len = 0;
- pStaPdu->nackInfo[pStaPdu->nackCnt].soStart = 0;
- pStaPdu->nackInfo[pStaPdu->nackCnt].soEnd = 0;
-
- }
- /* NACK RANGE Field is SET */
- if (e3)
- {
- /* Extract NACK range field */
- hdrInfo.len = RLC_NACK_RANGE_LEN;
- rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
- snRange = (uint8_t)hdrInfo.val;
-
- pStaPdu->nackInfo[pStaPdu->nackCnt].nackRange = snRange;
-
- }
- pStaPdu->nackCnt++;
- }
-
- gRlcStats.amRlcStats.numULStaPduRcvd++;
- gRlcStats.amRlcStats.numULNackInStaPduRcvd += pStaPdu->nackCnt;
-
- /* In case we have reached the MAX NACK CNT, then we should modify the ACK_SN
- to the last NACK SN + 1 and discard the original ACK_SN*/
- if(pStaPdu->nackCnt == RLC_MAX_NACK_CNT)
- {
- pStaPdu->ackSn = (pStaPdu->nackInfo[RLC_MAX_NACK_CNT-1].sn + 1) & (rbCb->m.amUl.snModMask);
- }
-
-
- /* Parse & send Status PDU to RLC-DL */
- rlcUlUdxStaUpdReq(&(sapCb->pst), sapCb->spId, &rbCb->rlcId, pStaPdu);
-
- return;
-}
-
-/**
- * @brief Private handler to release all stored segments
- *
- * @details
- * Private handler invokded by rlcAmmUlPlacePduInRecBuf 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
- *
- */
-static void rlcAmmUlRlsAllSegs(RlcCb *gCb, RlcAmRecBuf *recBuf)
-{
- RlcSeg *seg;
-
- RLC_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(RlcSeg));
- RLC_LLIST_FIRST_SEG(recBuf->segLst, seg);
- }
-
- return;
-}
-
-/**
- * @brief Private handler to store the received segment
- *
- * @details
- * Private handler invokded by rlcAmmUlPlacePduInRecBuf 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] amHdr AM 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
- */
-static bool rlcAmmAddRcvdSeg(RlcCb *gCb, RlcUlRbCb *rbCb, RlcAmHdr *amHdr, Buffer *pdu, uint16_t pduSz)
-{
- RlcAmRecBuf *recBuf = NULLP;
- RlcSeg *seg;
- RlcSeg *tseg;
- uint16_t soEnd; /* Holds the SoEnd of received segment */
- uint16_t expSo = 0; /* Expected SO */
-
- soEnd = amHdr->so + pduSz - 1;
- recBuf = rlcUtlGetRecBuf(RLC_AMUL.recBufLst, amHdr->sn);
-
- if (NULLP == recBuf)
- {
- RLC_ALLOC(gCb,recBuf, sizeof(RlcAmRecBuf));
-#if (ERRCLASS & ERRCLS_ADD_RES)
- if (recBuf == NULLP)
- {
- DU_LOG("\nERROR --> RLC_UL : rlcAmmAddRcvdSeg: Memory allocation failed UEID:%d CELLID:%d",
- rbCb->rlcId.ueId, rbCb->rlcId.cellId);
-
- ODU_PUT_MSG_BUF(pdu);
- return FALSE;
- }
-#endif /* ERRCLASS & ERRCLS_RES */
- rlcUtlStoreRecBuf(RLC_AMUL.recBufLst, recBuf, amHdr->sn);
- }
- else
- {
- if (recBuf->allRcvd == TRUE)
- {
- ODU_PUT_MSG_BUF(pdu);
- return FALSE;
- }
- }
-
- recBuf->isDelvUpperLayer = FALSE;
- /* kw003.201 - Move past the segments that are different than the */
- /* one received. */
- RLC_LLIST_FIRST_SEG(recBuf->segLst, seg);
- while ((seg != NULLP) && (seg->amHdr.so < amHdr->so))
- {
- expSo = seg->amHdr.so + seg->segSz;
- RLC_LLIST_NEXT_SEG(recBuf->segLst, seg);
- }
-
- /* The received segment should start after the end of previous seg */
- if (expSo > amHdr->so)
- {
- /* This is a duplicate segment */
- gRlcStats.amRlcStats.numRlcAmCellDupPduRx++;
- ODU_PUT_MSG_BUF(pdu);
- return FALSE;
- }
-
- if ((seg) && (seg->amHdr.so <= soEnd))
- {
- /* This is a duplicate segment */
- gRlcStats.amRlcStats.numRlcAmCellDupPduRx++;
- 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(RlcSeg));
-#if (ERRCLASS & ERRCLS_ADD_RES)
- if (tseg == NULLP)
- {
- DU_LOG("\nERROR --> RLC_UL : rlcAmmAddRcvdSeg: Memory allocation failed UEID:%d CELLID:%d",
- rbCb->rlcId.ueId, rbCb->rlcId.cellId);
- ODU_PUT_MSG_BUF(pdu);
- return FALSE;
- }
-#endif /* ERRCLASS & ERRCLS_RES */
-
- tseg->seg = pdu;
- tseg->segSz = pduSz;
- RLC_MEM_CPY(&tseg->amHdr, amHdr, sizeof(RlcAmHdr));
- recBuf->amHdr.si = amHdr->si;
- recBuf->amHdr.sn = amHdr->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;
- rlcAmmUpdExpByteSeg(gCb,&RLC_AMUL,tseg);
-
- return TRUE;
-}
-
-/**
- * @brief Private handler to place the PDU in the reception buffer
- *
- * @details
- * This function checks if the received PDU's SN falls within the
- * receiving window, after which it places the same in the reception
- * buffer if its not a duplicate.
- *
- * @param[in] gCb RLC instance control block
- * @param[in] pdu Received PDU
- * @param[in] rbCb Uplink AM Radio Bearer
- * @param[out] amUl AM UL Info
- *
- * @return Bool
- * -# TRUE
- * -# FALSE
- *
- */
-static bool rlcAmmUlPlacePduInRecBuf(RlcCb *gCb, Buffer *pdu, RlcUlRbCb *rbCb, RlcAmHdr *amHdr)
-{
- RlcSn sn;
- MsgLen pduSz;
- RlcAmUl *amUl = &(rbCb->m.amUl);
-
- sn = amHdr->sn;
- SFndLenMsg(pdu, &pduSz);
-
- gCb->genSts.bytesRecv += pduSz;
- gRlcStats.amRlcStats.numRlcAmCellSduBytesRx += pduSz;
- if (!RLC_AM_CHK_SN_WITHIN_RECV_WINDOW(sn, amUl))
- {
- gRlcStats.amRlcStats.numRlcAmCellDropOutWinRx++;
- DU_LOG("\nERROR --> RLC_UL : rlcAmmUlPlacePduInRecBuf: SN %d outside the window"
- "UEID:%d CELLID:%d", sn, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
-
- gCb->genSts.unexpPdusRecv++;
- ODU_PUT_MSG_BUF(pdu);
- return FALSE;
- }
-
- if (amHdr->si == 0)
- {
- RlcAmRecBuf *recBuf = rlcUtlGetRecBuf(amUl->recBufLst, sn);
-
- /* We received a complete PDU. Either we already have it, in which */
- /* case we just ignore the new PDU and discard it. Otherwise, */
- /* store the received PDU in the reception buffer */
- if (NULLP == recBuf)
- {
- RLC_ALLOC(gCb, recBuf, sizeof(RlcAmRecBuf));
-#if (ERRCLASS & ERRCLS_ADD_RES)
- if (recBuf == NULLP)
- {
- DU_LOG("\nERROR --> RLC_UL : rlcAmmUlPlacePduInRecBuf: Memory allocation failed \
- UEID:%d CELLID:%d", rbCb->rlcId.ueId, rbCb->rlcId.cellId);
- ODU_PUT_MSG_BUF(pdu);
- return FALSE;
- }
-#endif /* ERRCLASS & ERRCLS_RES */
- rlcUtlStoreRecBuf(RLC_AMUL.recBufLst, recBuf, sn);
- }
- else if (recBuf->allRcvd != TRUE)
- {
- rlcAmmUlRlsAllSegs(gCb,recBuf);
- }
- else
- {
- gRlcStats.amRlcStats.numRlcAmCellDupPduRx++;
- gCb->genSts.unexpPdusRecv++;
- ODU_PUT_MSG_BUF(pdu);
- return FALSE;
- }
- recBuf->isDelvUpperLayer = FALSE;
- recBuf->pdu = pdu;
- recBuf->pduSz = pduSz;
- recBuf->allRcvd = TRUE;
- gRlcStats.amRlcStats.numRlcAmCellSduRx++;
- RLC_MEM_CPY(&recBuf->amHdr, amHdr, sizeof(RlcAmHdr));
- return TRUE;
- }
- else
- {
- /* We received a segment. We need to add that to the existing */
- /* segments, if any. */
- return (rlcAmmAddRcvdSeg(gCb,rbCb, amHdr, pdu, pduSz));
- }
-}
-
-/**
- * @brief Private handler to trigger status report
- *
- * @details
- * Private handler invokded by rlcAmmProcessPdus to check if the
- * status report need to be sent, and update the status trigger
- * flag accordingly based on status prohibit timer.
- *
- * - Check if the received pdu's sn is less than rxHighestStatus, set the
- * staTrg flag.
- * - If staProhTmr is not running, calculate cntrlBo, else it'll be
- * updated at the expiry of staProhTmr.
- * - Expiry of reAsmblTmr also will set staTrg flag.
- *
- * @param[in] gCb RLC instance control block
- * @param[in] rbCb Uplink RB control block
- * @param[in] sn Sequence number of the pdu based on which to check if
- * status needs to be triggered
- * @param[in] discFlg Whether this pdu was discarded or not
- *
- * @return Void
- *
- */
-static void rlcAmmTriggerStatus(RlcCb *gCb, RlcUlRbCb *rbCb, RlcSn sn, bool discFlg)
-{
- bool tmrRunning;
- RlcSn tSn;
- RlcSn tVrMr;
- RlcSn trxHighestStatus;
- RlcAmUl *amUl = &(rbCb->m.amUl);
-
- MODAMR(amUl->vrMr, tVrMr, amUl->rxNext, amUl->snModMask);
- MODAMR(amUl->rxHighestStatus, trxHighestStatus, amUl->rxNext, amUl->snModMask);
- MODAMR(sn , tSn, amUl->rxNext, amUl->snModMask);
-
- /* kw005.201 Product CR ccpu00117114 *
- * The "=" in the 2nd condition is removed */
- if ((discFlg) || (tSn < trxHighestStatus) || (tSn >= tVrMr))
- {
- DU_LOG("\nINFO --> RLC_UL : rlcAmmTriggerStatus: Set Status Trigger UEID:%d CELLID:%d",
- rbCb->rlcId.ueId, rbCb->rlcId.cellId);
-
- amUl->staTrg = TRUE;
- amUl->gatherStaPduInfo = FALSE;
-
- /* Check if staProhTmr is running */
- tmrRunning = rlcChkTmr(gCb,(PTR) rbCb, EVENT_RLC_AMUL_STA_PROH_TMR);
-
- if (!tmrRunning)
- {
- amUl->gatherStaPduInfo = TRUE;
- }
- }
-
- return;
-}
-
-/**
- * @brief Private handler to reassemble from a segment or a PDU
- *
- * @details
- * Private handler invokded by kwAmmReassembleSdus 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] amHdr AM header received for this segment/PDU
- * @param[in] pdu PDU to be reassembled
- *
- * @return Void
- *
- */
-static void rlcAmmProcPduOrSeg(RlcCb *gCb, RlcUlRbCb *rbCb, RlcAmHdr *amHdr, Buffer *pdu)
-{
-
- if ((RLC_AMUL.expSn != amHdr->sn) || (RLC_AMUL.expSo != amHdr->so))
- {
- /* Release the existing partial SDU as we have PDUs or */
- /* segments that are out of sequence */
- rbCb->m.amUl.isOutOfSeq = TRUE;
- ODU_PUT_MSG_BUF(RLC_AMUL.partialSdu);
- }
-
- if (amHdr->si == RLC_SI_FIRST_SEG)
- {/* first Segment of the SDU */
- if (RLC_AMUL.partialSdu != NULLP)
- { /* Some old SDU may be present */
- ODU_PUT_MSG_BUF(RLC_AMUL.partialSdu);
- }
- RLC_AMUL.partialSdu = pdu;
- pdu = NULLP;
- }
- else if(amHdr->si == RLC_SI_MID_SEG)
- {/* Middle or last segment of the SUD */
- ODU_CAT_MSG(RLC_AMUL.partialSdu,pdu, M1M2);
- ODU_PUT_MSG_BUF(pdu);
- pdu = NULLP;
- }
- else if (amHdr->si == RLC_SI_LAST_SEG)
- {
- ODU_CAT_MSG(pdu,RLC_AMUL.partialSdu,M2M1);
- ODU_PUT_MSG_BUF(RLC_AMUL.partialSdu);
- }
-
- if (pdu != NULLP)
- {
- RLC_AMUL.partialSdu = NULLP;
- rlcUtlSendUlDataToDu(gCb,rbCb, pdu);
- }
-
- return;
-}
-
-/**
- *
- * @brief Private handler to reassemble SDUs
- *
- * @details
- * Private handler invokded by rlcAmmProcessPdus 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 S16
- * -# ROK
- * -# RFAILED
- *
- */
-static uint8_t rlcAmmUlReassembleSdus(RlcCb *gCb, RlcUlRbCb *rbCb, RlcAmRecBuf *recBuf)
-{
- RlcSeg *seg;
-
- //if (recBuf->amHdr.rf == 0)
- if (recBuf->amHdr.si == 0)
- {
- /* This is a PDU */
- rlcAmmProcPduOrSeg(gCb,rbCb, &recBuf->amHdr, recBuf->pdu);
- /* Assign NULLP to recBuf->pdu as this PDU is sent to PDCP */
- recBuf->pdu = NULLP;
- RLC_AMUL.expSn = (recBuf->amHdr.sn + 1) & (RLC_AMUL.snModMask); /* MOD 1024 */
- RLC_AMUL.expSo = 0;
- }
- else
- {
- /* This is a set of segments */
- RLC_LLIST_FIRST_SEG(recBuf->segLst, seg);
- RLC_AMUL.expSn = recBuf->amHdr.sn;
- RLC_AMUL.expSo = 0;
- while(seg)
- {
- rlcAmmProcPduOrSeg(gCb,rbCb, &seg->amHdr, seg->seg);
- RLC_AMUL.expSo = seg->soEnd + 1;
-
- cmLListDelFrm(&(recBuf->segLst),&(seg->lstEnt));
- RLC_FREE(gCb, seg, sizeof(RlcSeg));
-
- RLC_LLIST_FIRST_SEG(recBuf->segLst, seg);
- }
- RLC_AMUL.expSn = (recBuf->amHdr.sn + 1) & (RLC_AMUL.snModMask); /* MOD 1024 */
- RLC_AMUL.expSo = 0;
- }
-
- return ROK;
-}
-
-/**
- * @brief Handler to process the re-establishment request received from UIM
- *
- * @param[in] gCb RLC instance control block
- * @param[in] rlcId RLC identifier
- * @param[in] sendReEst Whether to send back restablishment complete or not
- * @param[in] rbCb Uplink RB control block
- *
- * @return Void
- *
- */
-Void rlcAmmUlReEstablish(RlcCb *gCb,CmLteRlcId rlcId,Bool sendReEst,RlcUlRbCb *rbCb)
-{
- RlcSn sn;
- RlcSn mSn;
- RlcSn mVrMr;
-
-#ifndef KW_PDCP
- RlcKwuSapCb *rlcKwuSap;
-#endif
- RlcAmRecBuf *recBuf = NULLP;
-
- sn = RLC_AMUL.rxNext;
-
- MODAMR(RLC_AMUL.vrMr, mVrMr, RLC_AMUL.rxNext, RLC_AMUL.snModMask);
- MODAMR(sn, mSn, RLC_AMUL.rxNext, RLC_AMUL.snModMask);
-
- /* Reassemble SDUs from PDUs with SN less than upper edge of the window */
- while (mSn < mVrMr)
- {
- recBuf = rlcUtlGetRecBuf(RLC_AMUL.recBufLst, sn);
- if (NULLP != recBuf)
- {
- if (recBuf->allRcvd == TRUE)
- {
- rlcAmmUlReassembleSdus(gCb,rbCb, recBuf);
- }
- else
- {
- /* Remove PDU and segments */
- if(recBuf->pdu)
- {
- ODU_PUT_MSG_BUF(recBuf->pdu);
- }
- /* Release all the segments*/
- rlcAmmUlRlsAllSegs(gCb,recBuf);
- }
- rlcUtlDelRecBuf(RLC_AMUL.recBufLst, recBuf, gCb);
- }
- sn = (sn + 1) & (RLC_AMUL.snModMask); /* MOD 1024 */
- MODAMR(sn, mSn, RLC_AMUL.rxNext, RLC_AMUL.snModMask);
- }
- /* Discard remaining PDUs and bytesegments in recBuf */
-
- /* Stop all timers and reset variables */
- if(TRUE == rlcChkTmr(gCb,(PTR)rbCb,EVENT_RLC_AMUL_REASSEMBLE_TMR))
- {
- rlcStopTmr(gCb,(PTR)rbCb, EVENT_RLC_AMUL_REASSEMBLE_TMR);
- }
- if(TRUE == rlcChkTmr(gCb,(PTR)rbCb,EVENT_RLC_AMUL_STA_PROH_TMR))
- {
- rlcStopTmr(gCb,(PTR)rbCb, EVENT_RLC_AMUL_STA_PROH_TMR);
- }
-
- RLC_AMUL.rxNext = 0;
- RLC_AMUL.rxNextHighestRcvd = 0;
- RLC_AMUL.rxNextStatusTrig = 0;
- rbCb->m.amUl.vrMr = (rbCb->m.amUl.rxNext + RLC_AM_GET_WIN_SZ(rbCb->m.amUl.snLen)) & (rbCb->m.amUl.snModMask);
- RLC_AMUL.rxHighestStatus = 0;
- RLC_AMUL.staTrg = FALSE;
- RLC_AMUL.gatherStaPduInfo = FALSE;
- RLC_AMUL.expSn = 0;
- RLC_AMUL.expSo = 0;
- if (RLC_AMUL.partialSdu != NULLP)
- {
- ODU_PUT_MSG_BUF(RLC_AMUL.partialSdu);
- }
- rlcKwuSap = gCb->u.ulCb->rlcKwuUlSap + RLC_UI_PDCP;
-
- if(sendReEst)
- {
- RlcUiKwuReEstCmpInd(&rlcKwuSap->pst, rlcKwuSap->suId, rlcId);
- rbCb->m.amUl.isOutOfSeq = FALSE;
- }
-
- return;
-}
-
-/**
- * @brief Handler for reorder timer expiry
- *
- * @details
- * This function is used to handle events upon expiry of reorder timer
- *
- * @param[in] gCb RLC instance control block
- * @param[in] rbCb RB control block
- *
- * @return Void
- *
- */
-
-Void rlcAmmReAsmblTmrExp(RlcCb *gCb,RlcUlRbCb *rbCb)
-{
- RlcAmUl *amUl = &(rbCb->m.amUl);
- RlcSn sn;
- RlcSn mSn;
- RlcSn mVrMr;
- RlcSn mrxHighestStatus;
- RlcSn mrxNextHighestRcvd;
- Bool tmrRunning = FALSE;
- RlcAmRecBuf *recBuf = NULLP;
-
- /* Update rxHighestStatus */
- sn = amUl->rxNextStatusTrig;
-
- MODAMR(sn, mSn, amUl->rxNext, amUl->snModMask);
- MODAMR(amUl->vrMr, mVrMr, amUl->rxNext, amUl->snModMask);
- recBuf = rlcUtlGetRecBuf(RLC_AMUL.recBufLst, sn);
-
- while (mSn < mVrMr)
- {
- if ((recBuf == NULLP) ||
- ((recBuf != NULLP) && (!recBuf->allRcvd)) )
- {
- amUl->rxHighestStatus = sn;
- amUl->staTrg = TRUE;
- amUl->gatherStaPduInfo = FALSE;
-
- /* Check if staProhTmr is running */
- tmrRunning = rlcChkTmr(gCb,(PTR) rbCb, EVENT_RLC_AMUL_STA_PROH_TMR);
-
- if (!tmrRunning)
- {
- gRlcStats.amRlcStats.numULReAsmblTimerExpires++;
- amUl->gatherStaPduInfo = TRUE;
- rlcAmmUlAssembleCntrlInfo(gCb, rbCb);
- }
-
- break;
- }
- sn = (sn + 1) & (amUl->snModMask);
- MODAMR(sn, mSn, amUl->rxNext, amUl->snModMask);
- }
-
- /* Update rxNextStatusTrig */
- MODAMR(amUl->rxNextHighestRcvd, mrxNextHighestRcvd, amUl->rxNext, amUl->snModMask);
- MODAMR(amUl->rxHighestStatus, mrxHighestStatus, amUl->rxNext, amUl->snModMask);
- /* spec 38.322v15.3.0 - 5.2.3.2.4 */
- if((mrxNextHighestRcvd > mrxHighestStatus) || ((mrxNextHighestRcvd == mrxHighestStatus) &&
- ((recBuf) && !(recBuf->noMissingSeg))))
- {
- rlcStartTmr(gCb,(PTR)rbCb, EVENT_RLC_AMUL_REASSEMBLE_TMR);
- amUl->rxNextStatusTrig = amUl->rxNextHighestRcvd;
- }
-
- return;
-} /* rlcAmmReAsmblTmrExp */
-
-/**
- * @brief Handler for status prohibit timer expiry
- *
- * @details
- * This function is used to handle events upon expiry of status prohibit
- * timer
- *
- * @param[in] gCb RLC instance control block
- * @param[in] rbCb RB control block
- *
- * @return Void
- *
- */
-
-Void rlcAmmStaProTmrExp(RlcCb *gCb,RlcUlRbCb *rbCb)
-{
- RlcAmUl *amUl = &(rbCb->m.amUl);
-
- amUl->gatherStaPduInfo = FALSE;
-
- if (amUl->staTrg == TRUE)
- {
- amUl->gatherStaPduInfo = TRUE;
- /* kw002.201 : Sending StaRsp after StaProhibit tmr expiry */
- rlcAmmUlAssembleCntrlInfo(gCb,rbCb);
- }
-
- return;
-} /* rlcAmmStaProTmrExp */
-
-/**
- * @brief Handler to extract an element of AM Header
- *
- * @details
- * This function is used to extract an element of AM header.
- *
- * @param[in] pdu The pdu to be decoded
- * @param[in,out] hdrInfo Container to hold the decoded info
- *
- * @return Void
- *
- */
-
-static void rlcAmmExtractElmnt(RlcCb *gCb, Buffer *pdu, RlcExtHdr *hdrInfo)
-{
- uint8_t hdr;
- uint8_t pLen = hdrInfo->pLen;
- uint8_t len = (uint8_t)hdrInfo->len;
- uint32_t val;
- uint8_t tHdr;
- uint8_t fLen;
- uint8_t rLen;
- /* uint8_t rLen1 = 0; */
- uint16_t tVal;
-
- hdr = hdrInfo->hdr;
-
- if (pLen == 0)
- {
- ODU_REM_PRE_MSG(&hdr, pdu);
- pLen = 8;
- }
- tHdr = hdr;
- if (len <= 8)
- {
- val = tHdr >> (RLC_BYTE_LEN - (len));
- hdr = hdr << len;
- pLen -= len;
- }
- else /*if (len > 8) */
- {
- fLen = pLen;
- val = tHdr;
- val = val >> (RLC_BYTE_LEN - fLen);
- val = val << (len - fLen);
- rLen = len - fLen;
- ODU_REM_PRE_MSG(&hdr, pdu);
- tHdr = hdr;
- if (rLen <= 8)
- {
- hdr = hdr >> (RLC_BYTE_LEN - rLen);
- val = val | hdr;
- hdr = tHdr << rLen;
- pLen = (RLC_BYTE_LEN - rLen);
- }
- else
- {
- rLen = rLen - RLC_BYTE_LEN;
- tVal = hdr;
- tVal = tVal << rLen;
- val = val | tVal;
-
- ODU_REM_PRE_MSG(&hdr, pdu);
- tHdr = hdr;
- hdr = hdr >> (RLC_BYTE_LEN - rLen);
- val = val | hdr;
- hdr = tHdr << rLen;
- pLen = (RLC_BYTE_LEN - rLen);
- }
- }
-
- hdrInfo->pLen = pLen;
- hdrInfo->hdr = hdr;
- hdrInfo->val = val;
-
- return;
-}
-
-/**
- * @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] amUl AM Uplink Control Block
- * @param[in] seg Newly received segment
- *
- * @return Void
- *
- */
-
-static void rlcAmmUpdExpByteSeg(RlcCb *gCb, RlcAmUl *amUl, RlcSeg *seg)
-{
- uint16_t newExpSo; /* The new expected SO */
- RlcSn sn = seg->amHdr.sn;
- bool lstRcvd=FALSE;
- RlcAmRecBuf *recBuf = NULLP;
-
- recBuf = rlcUtlGetRecBuf(amUl->recBufLst, sn);
- if ((recBuf == NULLP) || (recBuf && (seg->amHdr.so != recBuf->expSo)))
- {
- return;
- }
- recBuf->noMissingSeg = FALSE;
- newExpSo = seg->soEnd + 1;
- recBuf->expSo = newExpSo;
- if(seg->amHdr.si == RLC_SI_LAST_SEG)
- {
- lstRcvd = TRUE;
- }
- /* kw003.201 - This should update seg with the one after newSeg */
- RLC_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->amHdr.si == RLC_SI_LAST_SEG)
- {
- lstRcvd = TRUE;
- }
- if (seg->amHdr.so == newExpSo)
- {
- newExpSo = seg->soEnd + 1;
- recBuf->expSo = newExpSo;
- RLC_LLIST_NEXT_SEG(recBuf->segLst, seg);
- }
- else
- {
- recBuf->expSo = newExpSo;
- return;
- }
- }
- if (lstRcvd == TRUE)
- {
- recBuf->allRcvd = TRUE;
- gRlcStats.amRlcStats.numRlcAmCellSduRx++;
- }
- recBuf->noMissingSeg = TRUE;
- return;
-}
-
-/**
- * @brief
- * Function to release/free the Acknowledged Mode Module RbCb buffers
- *
- * @details
- * This primitive Frees the AM RbCb transmission Buffer, retransmission
- * Buffer and reciption Buffers
- *
- * @param [in] gCb - RLC instance Control Block
- * @param [in] rbCb - RB Control Block
- *
- * @return void
- */
-Void rlcAmmFreeUlRbCb(RlcCb *gCb,RlcUlRbCb *rbCb)
-{
- RlcSn curSn = 0; /* Sequence number of PDU */
- RlcSn windSz; /* PDU window size */
- RlcAmRecBuf *recBuf = NULLP;
-
- windSz = (RLC_AM_GET_WIN_SZ(rbCb->m.amUl.snLen)) << 1;
-
- if(TRUE == rlcChkTmr(gCb,(PTR)rbCb,EVENT_RLC_AMUL_REASSEMBLE_TMR))
- {
- rlcStopTmr(gCb,(PTR)rbCb, EVENT_RLC_AMUL_REASSEMBLE_TMR);
- }
- if(TRUE == rlcChkTmr(gCb,(PTR)rbCb,EVENT_RLC_AMUL_STA_PROH_TMR))
- {
- rlcStopTmr(gCb,(PTR)rbCb, EVENT_RLC_AMUL_STA_PROH_TMR);
- }
-
-
- /* on the first loop winSz is always greater than zero
- while( ( curSn < windSz ) hence changing to do while */
- do
- {
- recBuf = rlcUtlGetRecBuf(rbCb->m.amUl.recBufLst, curSn);
- if ( recBuf != NULLP )
- {
- if (recBuf->pdu != NULLP)
- {
- ODU_PUT_MSG_BUF(recBuf->pdu);
- }
- /* Release all the segments */
- rlcAmmUlRlsAllSegs(gCb,recBuf);
- rlcUtlDelRecBuf(rbCb->m.amUl.recBufLst, recBuf, gCb);
- }
- curSn++;
- }while ( curSn < windSz );
-
-#ifndef LTE_TDD
- RLC_FREE(gCb,rbCb->m.amUl.recBufLst, (RLC_RCV_BUF_BIN_SIZE * sizeof(CmLListCp)));
- rbCb->m.amUl.recBufLst = NULLP;
-#endif
-
- if(rbCb->m.amUl.partialSdu != NULLP)
- {
- ODU_PUT_MSG_BUF(rbCb->m.amUl.partialSdu);
- }
- return;
-} /* rlcAmmFreeUlRbCb */
-
-
-/*@}*/
-
-\f
-/********************************************************************30**
-
- End of file
-**********************************************************************/