JIRA ID:[ODUHIGH-296]-Dl Data Changes from DUAPP to RLC
[o-du/l2.git] / src / 5gnrrlc / kw_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:     LTE-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:     kw_tmm_dl.c
34
35 **********************************************************************/
36 /** 
37  * @file kw_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 "kw_env.h"        /* RLC environment options */
48
49 #include "kw.h"            /* RLC defines */
50 #include "kw_err.h"            /* RLC defines */
51 #include "kw_udx.h"
52 #include "kw_dl.h"
53
54 /* extern (.x) include files */
55 #include "lkw.x"           /* LKW */
56 #include "ckw.x"           /* CKW */
57 #include "kwu.x"           /* KWU */
58 #include "rgu.x"           /* RGU */
59
60 #include "kw.x"
61 #include "kw_udx.x"
62 #include "kw_dl.x"
63 #include "rlc_utils.h"
64 #include "rlc_mac_inf.h"
65 #include "rlc_lwr_inf_api.h"
66
67 #define RLC_MODULE (RLC_DBGMASK_TM | RLC_DBGMASK_DL)
68
69 static Void rlcTmmSendBoSta ARGS((RlcCb *gCb, RlcDlRbCb *rbCb, 
70                                  MsgLen bo, RlcDatReqInfo *datReqInfo));
71 uint32_t rgMacGT ;  
72 /** @addtogroup tmmode */
73 /*@{*/
74
75 /**
76  * @brief 
77  *    Handler to queue the SDU in the SDU queue and update BO and report it to
78  *    the lower layer.
79  *
80  * @details 
81  *    This function is used to queue the received SDU in the SDU queue 
82  *    maintained in the radio bearer control block. After queuing the SDU, BO 
83  *    is updated and is reported to the lower layer. 
84  *            
85  *  @param[in] rbCb         RB control block. 
86  *  @param[in] datReqInfo   Data Request Information.
87  *  @param[in] mBuf         SDU Buffer.
88  *
89  *  @return  S16
90  *      -# ROK 
91  *      -# RFAILED 
92  */
93 Void rlcTmmQSdu
94 (
95 RlcCb            *gCb,
96 RlcDlRbCb        *rbCb,      
97 RlcDatReqInfo   *datReqInfo, 
98 Buffer          *mBuf       
99 )
100 {
101    RlcSdu   *sdu;              
102  
103    RLC_ALLOC(gCb,sdu,sizeof(RlcSdu));
104 #if (ERRCLASS & ERRCLS_ADD_RES)
105    if ( sdu == NULLP )
106    {
107       DU_LOG("\nERROR  -->  RLC_DL : Memory Allocation failed UEID:%d CELLID:%d",   
108             rbCb->rlcId.ueId, rbCb->rlcId.cellId);   
109       return;
110    }
111 #endif /* ERRCLASS & ERRCLS_ADD_RES */
112 #ifdef CCPU_OPT   
113    if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH || 
114         rbCb->lch.lChType == CM_LTE_LCH_PCCH )
115    {
116       sdu->mode.tm.sfn = datReqInfo->tm.tmg.sfn;
117       sdu->mode.tm.slot = datReqInfo->tm.tmg.slot;
118 #ifdef EMTC_ENABLE
119      if(rbCb->lch.lChType == CM_LTE_LCH_PCCH)
120      {
121         sdu->mode.tm.pnb = datReqInfo->pnb;
122      }
123 #endif
124    }
125    else
126    {
127       sdu->mode.tm.rnti = datReqInfo->tm.rnti;
128    }
129 #endif
130    sdu->arrTime = rgMacGT;
131    SFndLenMsg(mBuf,&sdu->sduSz); 
132    sdu->mBuf = mBuf;
133    
134    cmLListAdd2Tail(&(rbCb->m.tm.sduQ), &(sdu->lstEnt));  
135    sdu->lstEnt.node = (PTR)sdu; 
136
137    rlcTmmSendBoSta(gCb, rbCb, sdu->sduSz, datReqInfo); 
138    return;
139 }
140
141 /**
142 * @brief 
143 *    Handler to form a pdu and send it to the lower layer.
144
145 * @details 
146 *    This function forms one pdu from the first SDU in the SDU queue and sends 
147 *    it to the lower layer.
148 *             
149 * @param[in] gCb     RLC Instance Control Block
150 * @param[in] rbCb    RB control block. 
151 * @param[in] staInd  Status Indication of common logical channel 
152 *
153 * @return  S16
154 *    -# ROK 
155 *    -# RFAILED         
156 */
157 void rlcTmmSendToMac(RlcCb *gCb, SuId suId, RlcDlRbCb *rbCb, RguCStaIndInfo *staInd)
158 {
159    Pst              pst;
160    CmLList          *node;          /* Current Link List Node */
161    RlcSdu           *sdu;           /* SDU */
162    RlcData          *dlData;
163    uint16_t         pduLen;
164    uint16_t         copyLen;
165    int16_t          timeDiff = 0;
166    Ticks            curTime  = 0;
167
168    CM_LLIST_FIRST_NODE(&(rbCb->m.tm.sduQ), 
169                        node);
170
171    /* (Sfn,slot) at which the message should be transmitted is 
172     * validated with alloted (sfn,slot)in the MAC layer */
173    while (node != NULLP)
174    {
175       sdu = (RlcSdu *)(node->node);
176       if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH ||
177             rbCb->lch.lChType == CM_LTE_LCH_PCCH )
178       {
179          uint16_t sfn, slot;
180          /* MS_FIX: syed sfn is of 10 bytes rather than 8 */
181 #ifdef EMTC_ENABLE
182          /* As part of CATM feature cross slot scheduling is implemented , so there is some delta(currently 2)
183             between MPDCCH and PDSCH,RLC expects cell crntTime of transmission of control dlsf, so one extra 
184             information is provided in staInd, so that sfn,slot should calculate from paging Timing information 
185             in case of EMTC paging, instead of transId */
186          if(staInd->isEmtcPaging)
187          {
188             sfn      = staInd->pagingTimingInfo.sfn;
189             slot = staInd->pagingTimingInfo.slot;
190          }
191          else
192 #endif
193          {
194             sfn = (staInd->transId >> 8) & 0x3FF;
195             slot = staInd->transId & 0xFF;
196          }
197
198          /* Table
199           * tm.slot - current slot 
200           * 0,sfn        7,sfn-1
201           * 4,sfn        1,sfn
202           * 5,sfn        2,sfn
203           * 9,sfn        6,sfn
204           */
205          /* MS_FIX: syed Incorrect sfn determination. 
206           * Take care of SFN wraparound. TODO: It is better for RLC
207           * not to be aware of SCH DELTAs. So we should look for 
208           * sending actual transmission time to RLC. */
209          if ((slot + TFU_DELTA) >= 10)
210          {
211             sfn = (sfn + 1)%1024;
212          }
213
214          if ((sdu->mode.tm.sfn != sfn) ||
215                (sdu->mode.tm.slot != ((slot+TFU_DELTA)%10)))
216          {
217             node = node->next;
218             DU_LOG("\nINFO  -->  RLC_DL : rlcTmmSendToMac: Releasing SDU of RNTI = %d for RNTI = %d \
219                UEID:%d CELLID:%d", sdu->mode.tm.rnti, staInd->rnti, rbCb->rlcId.ueId,
220                rbCb->rlcId.cellId);   
221             DU_LOG("\nINFO  -->  RLC_DL : rlcTmmSendToMac: sfn %d slot %d  UEID:%d CELLID:%d",
222                   sfn, slot, rbCb->rlcId.ueId, rbCb->rlcId.cellId);   
223             cmLListDelFrm(&(rbCb->m.tm.sduQ), &sdu->lstEnt);
224             ODU_PUT_MSG_BUF(sdu->mBuf);
225             RLC_FREE(gCb, sdu, sizeof(RlcSdu));
226          }
227          else
228          {
229             break;
230          }
231       }
232       else
233       {
234          curTime = rgMacGT;
235          if (curTime < sdu->arrTime)
236          {
237             timeDiff = (10240 - sdu->arrTime) + curTime;
238          }
239          else
240          {
241             timeDiff = curTime - sdu->arrTime;
242          }
243          DU_LOG("\nDEBUG  -->  RLC_DL : rlcTmmSendToMac: TMM: TmSdu Sta Indication received \
244             for Rnti %d Sdu Rnti %d UEID:%d CELLID:%d", staInd->rnti, 
245             sdu->mode.tm.rnti, rbCb->rlcId.ueId, rbCb->rlcId.cellId);   
246          DU_LOG("\nDEBUG  -->  RLC_DL : rlcTmmSendToMac: TMM: TmSdu Sta Indication received : \
247             timeDiff %d SduQCnt %d UEID:%d CELLID:%d", timeDiff, rbCb->m.tm.sduQ.count,
248             rbCb->rlcId.ueId, rbCb->rlcId.cellId);   
249          if (timeDiff > 40)
250          {
251             /* Memory leak needs to be fixed */
252             node = node->next;
253             DU_LOG("\nERROR  -->  RLC_DL : rlcTmmSendToMac: timeDiff greater than 40, so deleting\
254                the Sdu %u UEID:%d CELLID:%d", sdu->mode.tm.rnti, rbCb->rlcId.ueId,
255                rbCb->rlcId.cellId);   
256             cmLListDelFrm(&(rbCb->m.tm.sduQ), &sdu->lstEnt);
257             ODU_PUT_MSG_BUF(sdu->mBuf);
258             RLC_FREE(gCb, sdu, sizeof(RlcSdu));
259             continue;
260          }
261
262          if (sdu->mode.tm.rnti != staInd->rnti)
263          {
264             /* Memory leak needs to be fixed */
265             node = node->next;
266             DU_LOG("\nDEBUG  -->  RLC_DL : rlcTmmSendToMac: TMM: Searching for Rnti %d Skipping \
267                Sdu for Rnti %d UEID:%d CELLID:%d", staInd->rnti, sdu->mode.tm.rnti, 
268                rbCb->rlcId.ueId, rbCb->rlcId.cellId);   
269             DU_LOG("\nINFO  -->  RLC_DL : rlcTmmSendToMac: timeDiff %d sdu->arrTime %d UEID:%d CELLID:%d", 
270                 timeDiff, sdu->arrTime, rbCb->rlcId.ueId, rbCb->rlcId.cellId);   
271             DU_LOG("\nINFO  -->  RLC_DL : rlcTmmSendToMac: curTime %d SduQCnt %d and continuing"
272                " UEID:%d CELLID:%d", curTime, rbCb->m.tm.sduQ.count, rbCb->rlcId.ueId,
273                rbCb->rlcId.cellId);   
274             continue;
275          }
276          else
277          {
278             DU_LOG("\nDEBUG  -->  RLC_DL : rlcTmmSendToMac: TMM: TmSdu found %u UEID:%d CELLID:%d",
279                sdu->mode.tm.rnti, rbCb->rlcId.ueId, rbCb->rlcId.cellId);   
280             break;
281          }
282       }
283
284    }
285    if ( node == NULLP )
286    {
287       DU_LOG("\nERROR  -->  RLC_DL : rlcTmmSendToMac: SDU not found TM Queue is empty UEID:%d CELLID:%d",
288          rbCb->rlcId.ueId, rbCb->rlcId.cellId);   
289       return;
290    }
291    sdu = (RlcSdu *)node->node;
292
293     RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
294                         dlData,(Size)sizeof(RlcData));
295 #if (ERRCLASS & ERRCLS_ADD_RES)
296    if ( dlData == NULLP )
297    {
298       DU_LOG("\nERROR  -->  RLC_DL : rlcTmmSendToMac: Memory Allocation failed UEID:%d CELLID:%d",   
299          rbCb->rlcId.ueId, rbCb->rlcId.cellId);   
300       return; 
301    }
302 #endif /* ERRCLASS & ERRCLS_ADD_RES */
303
304    dlData->slotInfo.sfn = sdu->mode.tm.sfn;
305    dlData->slotInfo.slot = sdu->mode.tm.slot;
306    dlData->cellId = rbCb->rlcId.cellId;
307    dlData->rnti = sdu->mode.tm.rnti;
308    dlData->numPdu = 1;
309    dlData->pduInfo[0].commCh = TRUE;
310    dlData->pduInfo[0].lcId = rbCb->lch.lChId;
311
312    /* Copy Message to fixed buffer to send */
313    ODU_GET_MSG_LEN(sdu->mBuf, (MsgLen *)&pduLen);
314    RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
315       dlData->pduInfo[0].pduBuf, pduLen);
316    if (dlData->pduInfo[0].pduBuf == NULLP )
317    {
318       DU_LOG("\nERROR  -->  RLC_DL : Memory allocation failed");
319       return;
320    }
321    ODU_COPY_MSG_TO_FIX_BUF(sdu->mBuf, 0, pduLen, \
322       dlData->pduInfo[0].pduBuf, (MsgLen *)&copyLen);
323    dlData->pduInfo[0].pduLen = pduLen;
324
325    /* Free message */
326    ODU_PUT_MSG_BUF(sdu->mBuf);
327
328    /* kw005.201 ccpu00117318, updating the statistics */
329    gCb->genSts.bytesSent += sdu->sduSz;
330    gCb->genSts.pdusSent++;
331
332    rlcUtlIncrementKwuStsSduTx(gCb->u.dlCb->rlcKwuDlSap + rbCb->k1wuSapId);   
333
334    /* remove SDU from queue */ 
335    sdu->mBuf = NULLP;
336    cmLListDelFrm(&(rbCb->m.tm.sduQ),
337                  &sdu->lstEnt); 
338    RLC_FREE(gCb,sdu, sizeof(RlcSdu));
339
340    /* Fill Pst structure. Copying rguSap->pst to pst to avoid any
341     * changes in rguSap->pst */
342    memset(&pst, 0, sizeof(Pst));
343    FILL_PST_RLC_TO_MAC(pst, RLC_DL_INST, EVENT_DL_DATA_TO_MAC);
344
345    if(RlcSendDlDataToMac(&pst, dlData) != ROK)
346    {
347       RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData->pduInfo[0].pduBuf, \
348          dlData->pduInfo[0].pduLen);
349       RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData, sizeof(RlcData));
350    } 
351
352    return;
353 }
354
355 /**
356  *
357  * @brief 
358  *    Handler to process the re-establishment request received from the upper 
359  *    layer. 
360  *
361  * @details
362  *    This function empties the SDU queue for the RB in the downlink.
363  *            
364  * @param[in] gCb   RLC Instance Control Block 
365  * @param[in] rbCb  RB control block. 
366  *
367  * @return  S16
368  *    -# ROK 
369  */
370 Void rlcDlTmmReEstablish
371 (
372 RlcCb       *gCb,
373 RlcDlRbCb   *rbCb    
374 )
375 {
376
377 #ifdef LTE_L2_MEAS_RLC
378    rlcUtlEmptySduQ(gCb, rbCb, &rbCb->m.tm.sduQ);
379 #else
380    rlcUtlEmptySduQ(gCb,&rbCb->m.tm.sduQ);
381 #endif
382    
383    return;
384 }
385 /**
386  *
387  * @brief 
388  *    Handler to send Status Response to the lower layer.
389  *
390  * @details
391  *    This function is used to the BO to the lower layer after receiving a data
392  *    request from the upper layer. 
393  *            
394  * @param[in] gCb          RLC Instance Control Block 
395  * @param[in] rbCb         RB control block. 
396  * @param[in] bo           Buffer Occupancy 
397  * @param[in] datReqInfo   Data Request Information.
398  *
399  * @return  S16
400  *    -# ROK 
401  *    -# RFAILED 
402  */
403
404 static void rlcTmmSendBoSta(RlcCb *gCb, RlcDlRbCb *rbCb, MsgLen bo, RlcDatReqInfo *datReqInfo)
405 {
406    Pst              pst;            /* Post structure */    
407    RlcBoStatus      *boStatus;      /* Buffer occupancy status information */
408
409    RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
410                        boStatus, sizeof(RlcBoStatus));
411    if ( boStatus == NULLP )
412    {
413       DU_LOG("\nERROR  -->  RLC_DL : Memory Allocation failed UEID:%d CELLID:%d",\
414             rbCb->rlcId.ueId, rbCb->rlcId.cellId);   
415       return;
416    }
417
418    boStatus->cellId = rbCb->rlcId.cellId;
419    boStatus->ueIdx = rbCb->rlcId.ueId;
420    boStatus->commCh = TRUE;
421    boStatus->lcId = rbCb->lch.lChId;
422    boStatus->bo = bo;
423
424    /* If trace flag is enabled send the trace indication */
425    if(gCb->init.trc == TRUE)
426    {
427       /* Populate the trace params */
428       rlcLmmSendTrc(gCb, EVENT_BO_STATUS_TO_MAC, NULLP);
429    }
430
431    /* Fill Pst structure. Copying rguSap->pst to pst to avoid any
432     * changes in rguSap->pst */
433    memset(&pst, 0, sizeof(Pst));
434    FILL_PST_RLC_TO_MAC(pst, RLC_DL_INST, EVENT_DL_DATA_TO_MAC);
435
436    if(RlcSendBoStatusToMac(&pst, boStatus) != ROK)
437    {
438       RLC_FREE_SHRABL_BUF(pst.region, pst.pool, boStatus, sizeof(RlcBoStatus));
439    }
440
441    return;
442
443
444 #ifdef _cplusplus
445 }
446 #endif
447 /*@}*/
448 /********************************************************************30**
449          End of file
450 **********************************************************************/