X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=src%2F5gnrrlc%2Fkw_amm_ul.c;fp=src%2F5gnrrlc%2Fkw_amm_ul.c;h=0000000000000000000000000000000000000000;hb=70e1fb5996d93ef4973ffb654ee6a66228e9031c;hp=afdd334993bcc4365b31675bd1a1f56a0a499be3;hpb=d48ca6903f310645ef58f09ad965f589660be068;p=o-du%2Fl2.git diff --git a/src/5gnrrlc/kw_amm_ul.c b/src/5gnrrlc/kw_amm_ul.c deleted file mode 100755 index afdd33499..000000000 --- a/src/5gnrrlc/kw_amm_ul.c +++ /dev/null @@ -1,1927 +0,0 @@ -/******************************************************************************* -################################################################################ -# 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 */ - - -/*@}*/ - - -/********************************************************************30** - - End of file -**********************************************************************/