[Epic-ID: ODUHIGH-464][Task-ID: ODUHIGH-480] WG8 Alignment | Third Phase | RLC-MAC...
[o-du/l2.git] / src / 5gnrrlc / rlc_tmm_dl.c
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2017-2019] [Radisys]                                        #
4 #                                                                              #
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                                    #
8 #                                                                              #
9 #       http://www.apache.org/licenses/LICENSE-2.0                             #
10 #                                                                              #
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 *******************************************************************************/
18
19 /**********************************************************************
20
21      Name:     NR RLC Layer 
22   
23      Type:     C file
24   
25      Desc:     Source code for RLC Transparent mode assembly and
26                reassembly.This file contains following functions
27                 
28                   --rlcTmmQSdu
29                   --rlcTmmSendToMac
30                   --rlcTmmRcvFrmMac
31                   --kwTmmReEstablish 
32
33      File:     rlc_tmm_dl.c
34
35 **********************************************************************/
36 /** 
37  * @file rlc_tmm_dl.c
38  * @brief RLC Transparent Mode module
39 */
40 \f
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 */
49
50
51
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 */
57
58 #include "rlc_utils.h"            /* RLC defines */
59 #include "rlc_dl_ul_inf.h"
60 #include "rlc_dl.h"
61 #include "rlc_mac_inf.h"
62 #include "rlc_lwr_inf_api.h"
63
64 #define RLC_MODULE (RLC_DBGMASK_TM | RLC_DBGMASK_DL)
65
66 static Void rlcTmmSendBoSta ARGS((RlcCb *gCb, RlcDlRbCb *rbCb, 
67                                  MsgLen bo, RlcDatReqInfo *datReqInfo));
68 uint32_t rgMacGT ;  
69 /** @addtogroup tmmode */
70 /*@{*/
71
72 /**
73  * @brief 
74  *    Handler to queue the SDU in the SDU queue and update BO and report it to
75  *    the lower layer.
76  *
77  * @details 
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. 
81  *            
82  *  @param[in] rbCb         RB control block. 
83  *  @param[in] datReqInfo   Data Request Information.
84  *  @param[in] mBuf         SDU Buffer.
85  *
86  *  @return  S16
87  *      -# ROK 
88  *      -# RFAILED 
89  */
90 Void rlcTmmQSdu
91 (
92 RlcCb            *gCb,
93 RlcDlRbCb        *rbCb,      
94 RlcDatReqInfo   *datReqInfo, 
95 Buffer          *mBuf       
96 )
97 {
98    RlcSdu   *sdu;              
99  
100    RLC_ALLOC(gCb,sdu,sizeof(RlcSdu));
101 #if (ERRCLASS & ERRCLS_ADD_RES)
102    if ( sdu == NULLP )
103    {
104       DU_LOG("\nERROR  -->  RLC_DL : Memory Allocation failed UEID:%d CELLID:%d",   
105             rbCb->rlcId.ueId, rbCb->rlcId.cellId);   
106       return;
107    }
108 #endif /* ERRCLASS & ERRCLS_ADD_RES */
109 #ifdef CCPU_OPT   
110    if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH || 
111         rbCb->lch.lChType == CM_LTE_LCH_PCCH )
112    {
113       sdu->mode.tm.sfn = datReqInfo->tm.tmg.sfn;
114       sdu->mode.tm.slot = datReqInfo->tm.tmg.slot;
115 #ifdef EMTC_ENABLE
116      if(rbCb->lch.lChType == CM_LTE_LCH_PCCH)
117      {
118         sdu->mode.tm.pnb = datReqInfo->pnb;
119      }
120 #endif
121    }
122    else
123    {
124       sdu->mode.tm.rnti = datReqInfo->tm.rnti;
125    }
126 #endif
127    sdu->arrTime = rgMacGT;
128    SFndLenMsg(mBuf,&sdu->sduSz); 
129    sdu->mBuf = mBuf;
130    
131    cmLListAdd2Tail(&(rbCb->m.tm.sduQ), &(sdu->lstEnt));  
132    sdu->lstEnt.node = (PTR)sdu; 
133
134    rlcTmmSendBoSta(gCb, rbCb, sdu->sduSz, datReqInfo); 
135    return;
136 }
137
138 /**
139 * @brief 
140 *    Handler to form a pdu and send it to the lower layer.
141
142 * @details 
143 *    This function forms one pdu from the first SDU in the SDU queue and sends 
144 *    it to the lower layer.
145 *             
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 
149 *
150 * @return  S16
151 *    -# ROK 
152 *    -# RFAILED         
153 */
154 void rlcTmmSendToMac(RlcCb *gCb, SuId suId, RlcDlRbCb *rbCb, RguCStaIndInfo *staInd)
155 {
156    Pst              pst;
157    CmLList          *node;          /* Current Link List Node */
158    RlcSdu           *sdu;           /* SDU */
159    RlcDlData        *dlData;
160    uint16_t         pduLen;
161    uint16_t         copyLen;
162    int16_t          timeDiff = 0;
163    Ticks            curTime  = 0;
164
165    CM_LLIST_FIRST_NODE(&(rbCb->m.tm.sduQ), 
166                        node);
167
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)
171    {
172       sdu = (RlcSdu *)(node->node);
173       if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH ||
174             rbCb->lch.lChType == CM_LTE_LCH_PCCH )
175       {
176          uint16_t sfn, slot;
177          /* MS_FIX: syed sfn is of 10 bytes rather than 8 */
178 #ifdef EMTC_ENABLE
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)
184          {
185             sfn      = staInd->pagingTimingInfo.sfn;
186             slot = staInd->pagingTimingInfo.slot;
187          }
188          else
189 #endif
190          {
191             sfn = (staInd->transId >> 8) & 0x3FF;
192             slot = staInd->transId & 0xFF;
193          }
194
195          /* Table
196           * tm.slot - current slot 
197           * 0,sfn        7,sfn-1
198           * 4,sfn        1,sfn
199           * 5,sfn        2,sfn
200           * 9,sfn        6,sfn
201           */
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)
207          {
208             sfn = (sfn + 1)%1024;
209          }
210
211          if ((sdu->mode.tm.sfn != sfn) ||
212                (sdu->mode.tm.slot != ((slot+TFU_DELTA)%10)))
213          {
214             node = node->next;
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,
217                rbCb->rlcId.cellId);   
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));
223          }
224          else
225          {
226             break;
227          }
228       }
229       else
230       {
231          curTime = rgMacGT;
232          if (curTime < sdu->arrTime)
233          {
234             timeDiff = (10240 - sdu->arrTime) + curTime;
235          }
236          else
237          {
238             timeDiff = curTime - sdu->arrTime;
239          }
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);   
246          if (timeDiff > 40)
247          {
248             /* Memory leak needs to be fixed */
249             node = node->next;
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,
252                rbCb->rlcId.cellId);   
253             cmLListDelFrm(&(rbCb->m.tm.sduQ), &sdu->lstEnt);
254             ODU_PUT_MSG_BUF(sdu->mBuf);
255             RLC_FREE(gCb, sdu, sizeof(RlcSdu));
256             continue;
257          }
258
259          if (sdu->mode.tm.rnti != staInd->rnti)
260          {
261             /* Memory leak needs to be fixed */
262             node = node->next;
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,
270                rbCb->rlcId.cellId);   
271             continue;
272          }
273          else
274          {
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);   
277             break;
278          }
279       }
280
281    }
282    if ( node == NULLP )
283    {
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);   
286       return;
287    }
288    sdu = (RlcSdu *)node->node;
289
290     RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
291                         dlData,(Size)sizeof(RlcDlData));
292 #if (ERRCLASS & ERRCLS_ADD_RES)
293    if ( dlData == NULLP )
294    {
295       DU_LOG("\nERROR  -->  RLC_DL : rlcTmmSendToMac: Memory Allocation failed UEID:%d CELLID:%d",   
296          rbCb->rlcId.ueId, rbCb->rlcId.cellId);   
297       return; 
298    }
299 #endif /* ERRCLASS & ERRCLS_ADD_RES */
300
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;
305    dlData->numPdu = 1;
306    dlData->pduInfo[0].lcId = rbCb->lch.lChId;
307
308    /* Copy Message to fixed buffer to send */
309    ODU_GET_MSG_LEN(sdu->mBuf, (MsgLen *)&pduLen);
310    RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
311       dlData->pduInfo[0].pduBuf, pduLen);
312    if (dlData->pduInfo[0].pduBuf == NULLP )
313    {
314       DU_LOG("\nERROR  -->  RLC_DL : Memory allocation failed");
315       return;
316    }
317    ODU_COPY_MSG_TO_FIX_BUF(sdu->mBuf, 0, pduLen, \
318       dlData->pduInfo[0].pduBuf, (MsgLen *)&copyLen);
319    dlData->pduInfo[0].pduLen = pduLen;
320
321    /* Free message */
322    ODU_PUT_MSG_BUF(sdu->mBuf);
323
324    /* kw005.201 ccpu00117318, updating the statistics */
325    gCb->genSts.bytesSent += sdu->sduSz;
326    gCb->genSts.pdusSent++;
327
328    rlcUtlIncrementKwuStsSduTx(gCb->u.dlCb->rlcKwuDlSap + rbCb->k1wuSapId);   
329
330    /* remove SDU from queue */ 
331    sdu->mBuf = NULLP;
332    cmLListDelFrm(&(rbCb->m.tm.sduQ),
333                  &sdu->lstEnt); 
334    RLC_FREE(gCb,sdu, sizeof(RlcSdu));
335
336    /* Fill Pst structure. Copying rguSap->pst to pst to avoid any
337     * changes in rguSap->pst */
338    memset(&pst, 0, sizeof(Pst));
339    FILL_PST_RLC_TO_MAC(pst, RLC_DL_INST, EVENT_DL_DATA_TO_MAC);
340
341    if(RlcSendDlDataToMac(&pst, dlData) != ROK)
342    {
343       RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData->pduInfo[0].pduBuf, \
344          dlData->pduInfo[0].pduLen);
345       RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData, sizeof(RlcDlData));
346    } 
347
348    return;
349 }
350
351 /**
352  *
353  * @brief 
354  *    Handler to process the re-establishment request received from the upper 
355  *    layer. 
356  *
357  * @details
358  *    This function empties the SDU queue for the RB in the downlink.
359  *            
360  * @param[in] gCb   RLC Instance Control Block 
361  * @param[in] rbCb  RB control block. 
362  *
363  * @return  S16
364  *    -# ROK 
365  */
366 Void rlcDlTmmReEstablish
367 (
368 RlcCb       *gCb,
369 RlcDlRbCb   *rbCb    
370 )
371 {
372
373 #ifdef LTE_L2_MEAS_RLC
374    rlcUtlEmptySduQ(gCb, rbCb, &rbCb->m.tm.sduQ);
375 #else
376    rlcUtlEmptySduQ(gCb,&rbCb->m.tm.sduQ);
377 #endif
378    
379    return;
380 }
381 /**
382  *
383  * @brief 
384  *    Handler to send Status Response to the lower layer.
385  *
386  * @details
387  *    This function is used to the BO to the lower layer after receiving a data
388  *    request from the upper layer. 
389  *            
390  * @param[in] gCb          RLC Instance Control Block 
391  * @param[in] rbCb         RB control block. 
392  * @param[in] bo           Buffer Occupancy 
393  * @param[in] datReqInfo   Data Request Information.
394  *
395  * @return  S16
396  *    -# ROK 
397  *    -# RFAILED 
398  */
399
400 static void rlcTmmSendBoSta(RlcCb *gCb, RlcDlRbCb *rbCb, MsgLen bo, RlcDatReqInfo *datReqInfo)
401 {
402    Pst              pst;            /* Post structure */    
403    RlcBoStatus      *boStatus;      /* Buffer occupancy status information */
404
405    RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
406                        boStatus, sizeof(RlcBoStatus));
407    if ( boStatus == NULLP )
408    {
409       DU_LOG("\nERROR  -->  RLC_DL : Memory Allocation failed UEID:%d CELLID:%d",\
410             rbCb->rlcId.ueId, rbCb->rlcId.cellId);   
411       return;
412    }
413
414    boStatus->cellId = rbCb->rlcId.cellId;
415    boStatus->ueId = rbCb->rlcId.ueId;
416    boStatus->lcId = rbCb->lch.lChId;
417    boStatus->bo = bo;
418
419    /* If trace flag is enabled send the trace indication */
420    if(gCb->init.trc == TRUE)
421    {
422       /* Populate the trace params */
423       rlcLmmSendTrc(gCb, EVENT_BO_STATUS_TO_MAC, NULLP);
424    }
425
426    /* Fill Pst structure. Copying rguSap->pst to pst to avoid any
427     * changes in rguSap->pst */
428    memset(&pst, 0, sizeof(Pst));
429    FILL_PST_RLC_TO_MAC(pst, RLC_DL_INST, EVENT_DL_DATA_TO_MAC);
430
431    if(RlcSendBoStatusToMac(&pst, boStatus) != ROK)
432    {
433       RLC_FREE_SHRABL_BUF(pst.region, pst.pool, boStatus, sizeof(RlcBoStatus));
434    }
435
436    return;
437
438
439 #ifdef _cplusplus
440 }
441 #endif
442 /*@}*/
443 /********************************************************************30**
444          End of file
445 **********************************************************************/