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