1 /*******************************************************************************
2 ################################################################################
3 # Copyright (c) [2017-2019] [Radisys] #
5 # Licensed under the Apache License, Version 2.0 (the "License"); #
6 # you may not use this file except in compliance with the License. #
7 # You may obtain a copy of the License at #
9 # http://www.apache.org/licenses/LICENSE-2.0 #
11 # Unless required by applicable law or agreed to in writing, software #
12 # distributed under the License is distributed on an "AS IS" BASIS, #
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
14 # See the License for the specific language governing permissions and #
15 # limitations under the License. #
16 ################################################################################
17 *******************************************************************************/
19 /**********************************************************************
25 Desc: Source code for RLC Transparent mode assembly and
26 reassembly.This file contains following functions
35 **********************************************************************/
38 * @brief RLC Transparent Mode module
41 /* header (.h) include files */
42 #include "common_def.h"
43 #include "lkw.h" /* LKW defines */
44 #include "ckw.h" /* CKW defines */
45 #include "kwu.h" /* KWU defines */
46 #include "rgu.h" /* RGU defines */
47 #include "rlc_env.h" /* RLC environment options */
48 #include "rlc_err.h" /* RLC defines */
52 /* extern (.x) include files */
53 #include "lkw.x" /* LKW */
54 #include "ckw.x" /* CKW */
55 #include "kwu.x" /* KWU */
56 #include "rgu.x" /* RGU */
58 #include "rlc_utils.h" /* RLC defines */
59 #include "rlc_dl_ul_inf.h"
61 #include "rlc_mac_inf.h"
62 #include "rlc_lwr_inf_api.h"
64 #define RLC_MODULE (RLC_DBGMASK_TM | RLC_DBGMASK_DL)
66 static Void rlcTmmSendBoSta ARGS((RlcCb *gCb, RlcDlRbCb *rbCb,
67 MsgLen bo, RlcDatReqInfo *datReqInfo));
69 /** @addtogroup tmmode */
74 * Handler to queue the SDU in the SDU queue and update BO and report it to
78 * This function is used to queue the received SDU in the SDU queue
79 * maintained in the radio bearer control block. After queuing the SDU, BO
80 * is updated and is reported to the lower layer.
82 * @param[in] rbCb RB control block.
83 * @param[in] datReqInfo Data Request Information.
84 * @param[in] mBuf SDU Buffer.
94 RlcDatReqInfo *datReqInfo,
100 RLC_ALLOC(gCb,sdu,sizeof(RlcSdu));
101 #if (ERRCLASS & ERRCLS_ADD_RES)
104 DU_LOG("\nERROR --> RLC_DL : Memory Allocation failed UEID:%d CELLID:%d",
105 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
108 #endif /* ERRCLASS & ERRCLS_ADD_RES */
110 if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH ||
111 rbCb->lch.lChType == CM_LTE_LCH_PCCH )
113 sdu->mode.tm.sfn = datReqInfo->tm.tmg.sfn;
114 sdu->mode.tm.slot = datReqInfo->tm.tmg.slot;
116 if(rbCb->lch.lChType == CM_LTE_LCH_PCCH)
118 sdu->mode.tm.pnb = datReqInfo->pnb;
124 sdu->mode.tm.rnti = datReqInfo->tm.rnti;
127 sdu->arrTime = rgMacGT;
128 SFndLenMsg(mBuf,&sdu->sduSz);
131 cmLListAdd2Tail(&(rbCb->m.tm.sduQ), &(sdu->lstEnt));
132 sdu->lstEnt.node = (PTR)sdu;
134 rlcTmmSendBoSta(gCb, rbCb, sdu->sduSz, datReqInfo);
140 * Handler to form a pdu and send it to the lower layer.
143 * This function forms one pdu from the first SDU in the SDU queue and sends
144 * it to the lower layer.
146 * @param[in] gCb RLC Instance Control Block
147 * @param[in] rbCb RB control block.
148 * @param[in] staInd Status Indication of common logical channel
154 void rlcTmmSendToMac(RlcCb *gCb, SuId suId, RlcDlRbCb *rbCb, RguCStaIndInfo *staInd)
157 CmLList *node; /* Current Link List Node */
158 RlcSdu *sdu; /* SDU */
162 int16_t timeDiff = 0;
165 CM_LLIST_FIRST_NODE(&(rbCb->m.tm.sduQ),
168 /* (Sfn,slot) at which the message should be transmitted is
169 * validated with alloted (sfn,slot)in the MAC layer */
170 while (node != NULLP)
172 sdu = (RlcSdu *)(node->node);
173 if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH ||
174 rbCb->lch.lChType == CM_LTE_LCH_PCCH )
177 /* MS_FIX: syed sfn is of 10 bytes rather than 8 */
179 /* As part of CATM feature cross slot scheduling is implemented , so there is some delta(currently 2)
180 between MPDCCH and PDSCH,RLC expects cell crntTime of transmission of control dlsf, so one extra
181 information is provided in staInd, so that sfn,slot should calculate from paging Timing information
182 in case of EMTC paging, instead of transId */
183 if(staInd->isEmtcPaging)
185 sfn = staInd->pagingTimingInfo.sfn;
186 slot = staInd->pagingTimingInfo.slot;
191 sfn = (staInd->transId >> 8) & 0x3FF;
192 slot = staInd->transId & 0xFF;
196 * tm.slot - current slot
202 /* MS_FIX: syed Incorrect sfn determination.
203 * Take care of SFN wraparound. TODO: It is better for RLC
204 * not to be aware of SCH DELTAs. So we should look for
205 * sending actual transmission time to RLC. */
206 if ((slot + TFU_DELTA) >= 10)
208 sfn = (sfn + 1)%1024;
211 if ((sdu->mode.tm.sfn != sfn) ||
212 (sdu->mode.tm.slot != ((slot+TFU_DELTA)%10)))
215 DU_LOG("\nINFO --> RLC_DL : rlcTmmSendToMac: Releasing SDU of RNTI = %d for RNTI = %d \
216 UEID:%d CELLID:%d", sdu->mode.tm.rnti, staInd->rnti, rbCb->rlcId.ueId,
218 DU_LOG("\nINFO --> RLC_DL : rlcTmmSendToMac: sfn %d slot %d UEID:%d CELLID:%d",
219 sfn, slot, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
220 cmLListDelFrm(&(rbCb->m.tm.sduQ), &sdu->lstEnt);
221 ODU_PUT_MSG_BUF(sdu->mBuf);
222 RLC_FREE(gCb, sdu, sizeof(RlcSdu));
232 if (curTime < sdu->arrTime)
234 timeDiff = (10240 - sdu->arrTime) + curTime;
238 timeDiff = curTime - sdu->arrTime;
240 DU_LOG("\nDEBUG --> RLC_DL : rlcTmmSendToMac: TMM: TmSdu Sta Indication received \
241 for Rnti %d Sdu Rnti %d UEID:%d CELLID:%d", staInd->rnti,
242 sdu->mode.tm.rnti, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
243 DU_LOG("\nDEBUG --> RLC_DL : rlcTmmSendToMac: TMM: TmSdu Sta Indication received : \
244 timeDiff %d SduQCnt %d UEID:%d CELLID:%d", timeDiff, rbCb->m.tm.sduQ.count,
245 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
248 /* Memory leak needs to be fixed */
250 DU_LOG("\nERROR --> RLC_DL : rlcTmmSendToMac: timeDiff greater than 40, so deleting\
251 the Sdu %u UEID:%d CELLID:%d", sdu->mode.tm.rnti, rbCb->rlcId.ueId,
253 cmLListDelFrm(&(rbCb->m.tm.sduQ), &sdu->lstEnt);
254 ODU_PUT_MSG_BUF(sdu->mBuf);
255 RLC_FREE(gCb, sdu, sizeof(RlcSdu));
259 if (sdu->mode.tm.rnti != staInd->rnti)
261 /* Memory leak needs to be fixed */
263 DU_LOG("\nDEBUG --> RLC_DL : rlcTmmSendToMac: TMM: Searching for Rnti %d Skipping \
264 Sdu for Rnti %d UEID:%d CELLID:%d", staInd->rnti, sdu->mode.tm.rnti,
265 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
266 DU_LOG("\nINFO --> RLC_DL : rlcTmmSendToMac: timeDiff %d sdu->arrTime %d UEID:%d CELLID:%d",
267 timeDiff, sdu->arrTime, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
268 DU_LOG("\nINFO --> RLC_DL : rlcTmmSendToMac: curTime %d SduQCnt %d and continuing"
269 " UEID:%d CELLID:%d", curTime, rbCb->m.tm.sduQ.count, rbCb->rlcId.ueId,
275 DU_LOG("\nDEBUG --> RLC_DL : rlcTmmSendToMac: TMM: TmSdu found %u UEID:%d CELLID:%d",
276 sdu->mode.tm.rnti, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
284 DU_LOG("\nERROR --> RLC_DL : rlcTmmSendToMac: SDU not found TM Queue is empty UEID:%d CELLID:%d",
285 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
288 sdu = (RlcSdu *)node->node;
290 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
291 dlData,(Size)sizeof(RlcData));
292 #if (ERRCLASS & ERRCLS_ADD_RES)
293 if ( dlData == NULLP )
295 DU_LOG("\nERROR --> RLC_DL : rlcTmmSendToMac: Memory Allocation failed UEID:%d CELLID:%d",
296 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
299 #endif /* ERRCLASS & ERRCLS_ADD_RES */
301 dlData->slotInfo.sfn = sdu->mode.tm.sfn;
302 dlData->slotInfo.slot = sdu->mode.tm.slot;
303 dlData->cellId = rbCb->rlcId.cellId;
304 dlData->rnti = sdu->mode.tm.rnti;
306 dlData->pduInfo[0].commCh = TRUE;
307 dlData->pduInfo[0].lcId = rbCb->lch.lChId;
309 /* Copy Message to fixed buffer to send */
310 ODU_GET_MSG_LEN(sdu->mBuf, (MsgLen *)&pduLen);
311 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
312 dlData->pduInfo[0].pduBuf, pduLen);
313 if (dlData->pduInfo[0].pduBuf == NULLP )
315 DU_LOG("\nERROR --> RLC_DL : Memory allocation failed");
318 ODU_COPY_MSG_TO_FIX_BUF(sdu->mBuf, 0, pduLen, \
319 dlData->pduInfo[0].pduBuf, (MsgLen *)©Len);
320 dlData->pduInfo[0].pduLen = pduLen;
323 ODU_PUT_MSG_BUF(sdu->mBuf);
325 /* kw005.201 ccpu00117318, updating the statistics */
326 gCb->genSts.bytesSent += sdu->sduSz;
327 gCb->genSts.pdusSent++;
329 rlcUtlIncrementKwuStsSduTx(gCb->u.dlCb->rlcKwuDlSap + rbCb->k1wuSapId);
331 /* remove SDU from queue */
333 cmLListDelFrm(&(rbCb->m.tm.sduQ),
335 RLC_FREE(gCb,sdu, sizeof(RlcSdu));
337 /* Fill Pst structure. Copying rguSap->pst to pst to avoid any
338 * changes in rguSap->pst */
339 memset(&pst, 0, sizeof(Pst));
340 FILL_PST_RLC_TO_MAC(pst, RLC_DL_INST, EVENT_DL_DATA_TO_MAC);
342 if(RlcSendDlDataToMac(&pst, dlData) != ROK)
344 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData->pduInfo[0].pduBuf, \
345 dlData->pduInfo[0].pduLen);
346 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData, sizeof(RlcData));
355 * Handler to process the re-establishment request received from the upper
359 * This function empties the SDU queue for the RB in the downlink.
361 * @param[in] gCb RLC Instance Control Block
362 * @param[in] rbCb RB control block.
367 Void rlcDlTmmReEstablish
374 #ifdef LTE_L2_MEAS_RLC
375 rlcUtlEmptySduQ(gCb, rbCb, &rbCb->m.tm.sduQ);
377 rlcUtlEmptySduQ(gCb,&rbCb->m.tm.sduQ);
385 * Handler to send Status Response to the lower layer.
388 * This function is used to the BO to the lower layer after receiving a data
389 * request from the upper layer.
391 * @param[in] gCb RLC Instance Control Block
392 * @param[in] rbCb RB control block.
393 * @param[in] bo Buffer Occupancy
394 * @param[in] datReqInfo Data Request Information.
401 static void rlcTmmSendBoSta(RlcCb *gCb, RlcDlRbCb *rbCb, MsgLen bo, RlcDatReqInfo *datReqInfo)
403 Pst pst; /* Post structure */
404 RlcBoStatus *boStatus; /* Buffer occupancy status information */
406 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
407 boStatus, sizeof(RlcBoStatus));
408 if ( boStatus == NULLP )
410 DU_LOG("\nERROR --> RLC_DL : Memory Allocation failed UEID:%d CELLID:%d",\
411 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
415 boStatus->cellId = rbCb->rlcId.cellId;
416 boStatus->ueId = rbCb->rlcId.ueId;
417 boStatus->commCh = TRUE;
418 boStatus->lcId = rbCb->lch.lChId;
421 /* If trace flag is enabled send the trace indication */
422 if(gCb->init.trc == TRUE)
424 /* Populate the trace params */
425 rlcLmmSendTrc(gCb, EVENT_BO_STATUS_TO_MAC, NULLP);
428 /* Fill Pst structure. Copying rguSap->pst to pst to avoid any
429 * changes in rguSap->pst */
430 memset(&pst, 0, sizeof(Pst));
431 FILL_PST_RLC_TO_MAC(pst, RLC_DL_INST, EVENT_DL_DATA_TO_MAC);
433 if(RlcSendBoStatusToMac(&pst, boStatus) != ROK)
435 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, boStatus, sizeof(RlcBoStatus));
445 /********************************************************************30**
447 **********************************************************************/