a11d2e7c4641f1dc6fbbb4414a20c412f8fc79ac
[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    RlcData          *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(RlcData));
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].commCh = TRUE;
307    dlData->pduInfo[0].lcId = rbCb->lch.lChId;
308
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 )
314    {
315       DU_LOG("\nERROR  -->  RLC_DL : Memory allocation failed");
316       return;
317    }
318    ODU_COPY_MSG_TO_FIX_BUF(sdu->mBuf, 0, pduLen, \
319       dlData->pduInfo[0].pduBuf, (MsgLen *)&copyLen);
320    dlData->pduInfo[0].pduLen = pduLen;
321
322    /* Free message */
323    ODU_PUT_MSG_BUF(sdu->mBuf);
324
325    /* kw005.201 ccpu00117318, updating the statistics */
326    gCb->genSts.bytesSent += sdu->sduSz;
327    gCb->genSts.pdusSent++;
328
329    rlcUtlIncrementKwuStsSduTx(gCb->u.dlCb->rlcKwuDlSap + rbCb->k1wuSapId);   
330
331    /* remove SDU from queue */ 
332    sdu->mBuf = NULLP;
333    cmLListDelFrm(&(rbCb->m.tm.sduQ),
334                  &sdu->lstEnt); 
335    RLC_FREE(gCb,sdu, sizeof(RlcSdu));
336
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);
341
342    if(RlcSendDlDataToMac(&pst, dlData) != ROK)
343    {
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));
347    } 
348
349    return;
350 }
351
352 /**
353  *
354  * @brief 
355  *    Handler to process the re-establishment request received from the upper 
356  *    layer. 
357  *
358  * @details
359  *    This function empties the SDU queue for the RB in the downlink.
360  *            
361  * @param[in] gCb   RLC Instance Control Block 
362  * @param[in] rbCb  RB control block. 
363  *
364  * @return  S16
365  *    -# ROK 
366  */
367 Void rlcDlTmmReEstablish
368 (
369 RlcCb       *gCb,
370 RlcDlRbCb   *rbCb    
371 )
372 {
373
374 #ifdef LTE_L2_MEAS_RLC
375    rlcUtlEmptySduQ(gCb, rbCb, &rbCb->m.tm.sduQ);
376 #else
377    rlcUtlEmptySduQ(gCb,&rbCb->m.tm.sduQ);
378 #endif
379    
380    return;
381 }
382 /**
383  *
384  * @brief 
385  *    Handler to send Status Response to the lower layer.
386  *
387  * @details
388  *    This function is used to the BO to the lower layer after receiving a data
389  *    request from the upper layer. 
390  *            
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.
395  *
396  * @return  S16
397  *    -# ROK 
398  *    -# RFAILED 
399  */
400
401 static void rlcTmmSendBoSta(RlcCb *gCb, RlcDlRbCb *rbCb, MsgLen bo, RlcDatReqInfo *datReqInfo)
402 {
403    Pst              pst;            /* Post structure */    
404    RlcBoStatus      *boStatus;      /* Buffer occupancy status information */
405
406    RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
407                        boStatus, sizeof(RlcBoStatus));
408    if ( boStatus == NULLP )
409    {
410       DU_LOG("\nERROR  -->  RLC_DL : Memory Allocation failed UEID:%d CELLID:%d",\
411             rbCb->rlcId.ueId, rbCb->rlcId.cellId);   
412       return;
413    }
414
415    boStatus->cellId = rbCb->rlcId.cellId;
416    boStatus->ueIdx = rbCb->rlcId.ueId;
417    boStatus->commCh = TRUE;
418    boStatus->lcId = rbCb->lch.lChId;
419    boStatus->bo = bo;
420
421    /* If trace flag is enabled send the trace indication */
422    if(gCb->init.trc == TRUE)
423    {
424       /* Populate the trace params */
425       rlcLmmSendTrc(gCb, EVENT_BO_STATUS_TO_MAC, NULLP);
426    }
427
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);
432
433    if(RlcSendBoStatusToMac(&pst, boStatus) != ROK)
434    {
435       RLC_FREE_SHRABL_BUF(pst.region, pst.pool, boStatus, sizeof(RlcBoStatus));
436    }
437
438    return;
439
440
441 #ifdef _cplusplus
442 }
443 #endif
444 /*@}*/
445 /********************************************************************30**
446          End of file
447 **********************************************************************/