RLC BO, BO response and DL Data handling. [Issue-ID: ODUHIGH-181]
[o-du/l2.git] / src / 5gnrrlc / kw_umm_ul.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 Unacknowledged mode assembly and
26                reassembly.This file contains following functions
27
28                   --rlcUmmQSdu
29                   --rlcUmmProcessSdus
30                   --rlcUmmProcessPdus
31                   --rlcUmmReAssembleSdus
32                   --kwUmmReEstablish 
33
34      File:     kw_umm_ul.c
35
36 **********************************************************************/
37 /** 
38  * @file kw_umm_ul.c
39  * @brief RLC Unacknowledged Mode uplink module
40 */
41
42 /* header (.h) include files */
43 #include "common_def.h"
44 #include "ckw.h"                /* RRC layer */
45 #include "lkw.h"                /* RRC layer */
46 #include "kwu.h"                /* RLC service user */
47 #include "lkw.h"                /* LM Interface */
48 #include "rgu.h"                /* MAC layer */
49 #include "kw_env.h"             /* RLC environment options */
50
51 #include "kw.h"                 /* RLC layer */
52 #include "kw_err.h"
53 #include "kw_ul.h"
54
55
56 /* header/extern include files (.x) */
57
58 #include "ckw.x"                /* RRC layer */
59 #include "kwu.x"                /* RLC service user */
60 #include "lkw.x"                /* LM Interface */
61 #include "rgu.x"                /* MAC later */
62
63 #include "kw.x"                 /* RLC layer */
64 #include "kw_ul.x"
65
66 #define RLC_MODULE (RLC_DBGMASK_UM | RLC_DBGMASK_UL)
67
68 uint8_t rlcUmmExtractHdr ARGS ((RlcCb *gCb, 
69                                    RlcUlRbCb *rbCb,
70                                    Buffer *pdu,
71                                    RlcUmHdr *umHdr));
72
73 void rlcUmmReAssembleSdus ARGS ((RlcCb *gCb,
74                                         RlcUlRbCb *rbCb,
75                                         RlcUmRecBuf *umRecBuf));
76
77 #ifndef TENB_ACC
78 #ifndef LTE_PAL_ENB
79 extern U32 isMemThreshReached(Region region);
80 #endif
81 #endif
82 /**
83  * @brief  Finds and sets the next VR(UR) depending on the 
84  *         passed sequence number
85  *       
86  * @details
87  *    Finds the next VR(UR) depending on the passed SN. Updates VR(UR) to 
88  *    the SN of the first UMD PDU with SN >= _nextSn that has not been received
89  *
90  * @param[in] umUl      pointer to Um mode uplink control block
91  * @param[in] nextSn    Sequence number after which the VR(UR) is to set to
92  *
93  * @return  Void
94 */ 
95 void rlcUmmFindNextVRUR (RlcUmUl* umUl, RlcSn nextSn)
96 {
97    RlcSn ur = RLC_UM_GET_VALUE(umUl->vrUr, *umUl);
98    
99    RlcSn nextSnToCompare = RLC_UM_GET_VALUE(nextSn,*umUl);
100    
101    while (ur < nextSnToCompare)
102    {
103       if (!(umUl->recBuf[nextSn])) /* if the buffer is empty, SN not received */
104       {
105          umUl->vrUr = nextSn;
106          break;
107       }
108       nextSn = (nextSn + 1) & umUl->modBitMask; 
109       nextSnToCompare = RLC_UM_GET_VALUE(nextSn,*umUl);
110    }
111 }
112
113 /**
114  * @brief  Checks whether a sequence number is within the 
115  *         re-ordering window or not
116  *       
117  * @param[in] sn        Sequence Number to be checked
118  * @param[in] umUl      pointer to Um mode uplink control block
119  *
120  * @return  S16
121  *      -# TRUE 
122  *      -# FALSE
123  *
124  * @return  Void
125 */
126 int16_t rlcUmmCheckSnInReordWindow (RlcSn sn, CONSTANT RlcUmUl* CONSTANT umUl)  
127 {
128    return (RLC_UM_GET_VALUE(sn, *umUl) < RLC_UM_GET_VALUE(umUl->vrUh, *umUl)); 
129 }
130
131 /**
132  * @brief  Handler to process the Data Indication from the lower layer 
133  *         and send the PDUs to re-assembly unit. 
134  *       
135  * @details
136  *    This function processes the PDUs received from the lower layer
137  *    re-orders them and sends them one after the other in sequence 
138  *    to the re-assembly unit.
139  *
140  * @param[in] gCb      RLC Instance control block
141  * @param[in] rbCb     RB control block 
142  * @param[in] pduInfo  Pdu information 
143  *
144  *  @return Void
145 */
146 /* kw005.201 added support for L2 Measurement */
147 #ifdef LTE_L2_MEAS
148 void rlcUmmProcessPdus(RlcCb *gCb, RlcUlRbCb  *rbCb, KwPduInfo *pduInfo, uint32_t ttiCnt)
149 #else
150 void rlcUmmProcessPdus(RlcCb *gCb, RlcUlRbCb *rbCb, KwPduInfo *pduInfo)
151 #endif
152 {
153    RlcSn         *vrUh;      /* vr(uh) */
154    RlcSn         *vrUr;      /* vr(ur) */
155    RlcSn         *vrUx;      /* vr(ux) */
156    uint16_t      curSn;      /* Current Sequence Number */
157    uint32_t      pduCount;   /* PDU count */
158    uint32_t      count;      /* Loop counter */
159    RlcUmRecBuf   **recBuf;   /* UM Reception Buffer */
160
161    bool         tmrRunning;   /* Boolean for checking Tmr */
162
163    count = 0;
164
165    /* pduCount should be the min of RGU_MAX_PDU and pduInfo->numPdu */
166    pduCount = (pduInfo->numPdu < RGU_MAX_PDU)? pduInfo->numPdu : RGU_MAX_PDU;
167    
168    vrUh   = &(rbCb->m.umUl.vrUh);
169    vrUr   = &(rbCb->m.umUl.vrUr);
170    vrUx   = &(rbCb->m.umUl.vrUx);
171    recBuf = (rbCb->m.umUl.recBuf);
172
173    while (count < pduCount)
174    {
175       RlcSn   ur; 
176       RlcSn   uh; 
177       RlcSn   seqNum;
178       Buffer *pdu = pduInfo->mBuf[count];
179       RlcUmRecBuf *tmpRecBuf;
180       gCb->genSts.pdusRecv++;
181 #ifndef RGL_SPECIFIC_CHANGES
182 #ifndef TENB_ACC
183 #ifndef LTE_PAL_ENB
184       extern uint32_t ulrate_rgu;
185       MsgLen len;
186       ODU_GET_MSG_LEN(pdu, &len);
187       ulrate_rgu += len;
188 #endif
189 #endif      
190 #endif      
191       /* create a buffer to be later inserted into the reception buffer */
192       RLC_ALLOC_WC(gCb, tmpRecBuf, sizeof(RlcUmRecBuf));
193 #if (ERRCLASS & ERRCLS_ADD_RES)
194       if (tmpRecBuf == NULLP)
195       {   
196          DU_LOG("\nRLC : rlcUmmProcessPdus: Memory allocation failed UEID:%d CELLID:%d",\
197             rbCb->rlcId.ueId, rbCb->rlcId.cellId);
198          ODU_PUT_MSG_BUF(pdu);
199          return;
200       }
201 #endif /* ERRCLASS & ERRCLS_ADD_RES */      
202       /* ccpu00142274 - UL memory based flow control*/ 
203 #ifndef RGL_SPECIFIC_CHANGES
204 #ifndef TENB_ACC
205 #ifndef LTE_PAL_ENB
206     /* Changed the condition to TRUE from ROK  */
207 #ifndef XEON_SPECIFIC_CHANGES    
208      if(isMemThreshReached(rlcCb[0]->init.region) == TRUE)
209      {
210         extern uint32_t rlculdrop;
211         rlculdrop++;
212         RLC_FREE_BUF(pdu);
213         RLC_FREE_WC(gCb, tmpRecBuf, sizeof(RlcUmRecBuf));
214         /*Fix for CR ccpu00144030: If threshhold is hit then also count
215          *should be incrmented */
216         count++;
217         continue;
218      }
219 #endif     
220 #endif
221 #endif
222 #endif
223       /* get the pdu header */
224       if (rlcUmmExtractHdr(gCb, rbCb, pdu, &(tmpRecBuf->umHdr)))  
225       {
226          DU_LOG("\nRLC : rlcUmmProcessPdus: Header Extraction Failed UEID:%d CELLID:%d",\
227              rbCb->rlcId.ueId, rbCb->rlcId.cellId);
228
229          /* Header extraction is a problem. 
230           * log an error and free the allocated memory */
231          /* ccpu00136940 */
232          RLC_FREE_WC(gCb, tmpRecBuf, sizeof(RlcUmRecBuf));
233          ODU_PUT_MSG_BUF(pdu);
234          count++;
235          /* kw005.201 ccpu00117318, updating the statistics */
236          gCb->genSts.errorPdusRecv++;
237          continue;
238       }
239       curSn = tmpRecBuf->umHdr.sn;
240
241       /* Check if the PDU should be discarded or not */
242       ur = RLC_UM_GET_VALUE(RLC_UMUL.vrUr, RLC_UMUL); 
243       uh = RLC_UM_GET_VALUE(RLC_UMUL.vrUh, RLC_UMUL); 
244       seqNum = RLC_UM_GET_VALUE(curSn, RLC_UMUL); 
245
246       if (((ur < seqNum) && (seqNum < uh) && (RLC_UMUL.recBuf[curSn])) || 
247           (seqNum < ur)) 
248       {
249          /* PDU needs to be discarded */
250          DU_LOG("\nRLC : rlcUmmProcessPdus: Received a duplicate pdu with sn %d \
251             UEID:%d CELLID:%d", curSn, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
252
253          RLC_FREE_BUF(pdu);
254          RLC_FREE_WC(gCb, tmpRecBuf, sizeof(RlcUmRecBuf));
255          count++;
256          /* kw005.201 ccpu00117318, updating the statistics */
257          gCb->genSts.unexpPdusRecv++;
258          continue;
259       } 
260
261       /* kw005.201 added support for L2 Measurement */
262 #ifdef LTE_L2_MEAS
263
264       /* kw006.201 ccpu00120058, reduced code complexity by adding new function */
265       rlcUtlCalUlIpThrPut(gCb,rbCb, pdu, ttiCnt);
266
267 #endif 
268
269       recBuf[curSn] = tmpRecBuf;
270
271       recBuf[curSn]->pdu = pdu;
272       ODU_GET_MSG_LEN(pdu,&(recBuf[curSn]->pduSz));
273       /* kw005.201 ccpu00117318, updating the statistics */
274       gCb->genSts.bytesRecv += recBuf[curSn]->pduSz;
275       
276       if (!rlcUmmCheckSnInReordWindow(curSn,&RLC_UMUL))
277       {  /* currSn is outside re-ordering window */
278          *vrUh  = (curSn + 1) & RLC_UMUL.modBitMask;
279
280          /* re-assemble all pdus outside the modified re-ordering window */
281          /* the first SN is VR(UR) */
282          if (!rlcUmmCheckSnInReordWindow(*vrUr,&RLC_UMUL))
283          {
284             /* TODO : should it be VR(UR) + 1 ?... check, earlier it was so */
285             RlcSn sn = *vrUr; /* SN's which need to be re-assembled */
286             RlcSn lowerEdge;  /* to hold the lower-edge of the 
287                                 re-ordering window */
288
289             /* The new value ov VR(UR) is the lower end of the window i
290              * and SN's still this value need to be re-assembled */
291             
292             *vrUr = (*vrUh - RLC_UMUL.umWinSz) &  RLC_UMUL.modBitMask;         
293             lowerEdge = RLC_UM_GET_VALUE(*vrUr ,RLC_UMUL);
294             
295             while (RLC_UM_GET_VALUE(sn, RLC_UMUL) < lowerEdge)
296             {
297                if (recBuf[sn])
298                {
299                   rlcUmmReAssembleSdus(gCb,rbCb,recBuf[sn]);
300                   RLC_FREE_WC(gCb,recBuf[sn],sizeof(RlcUmRecBuf));
301                   recBuf[sn] = NULLP;
302                }
303                sn = (sn + 1) & RLC_UMUL.modBitMask;
304             }
305          }
306       }
307       if (recBuf[*vrUr])
308       {
309          RlcSn sn       = *vrUr;
310          RlcSn tSn      = RLC_UM_GET_VALUE(sn,RLC_UMUL); 
311          RlcSn tVrUr;       
312
313          /* set VR(UR) to next SN > current VR(UR) which is not received */
314          RlcSn nextVrUr = (*vrUr + 1) & RLC_UMUL.modBitMask;
315          rlcUmmFindNextVRUR(&RLC_UMUL, nextVrUr);
316
317          /* re-assemble SDUs with SN < Vr(UR) */
318          tVrUr = RLC_UM_GET_VALUE(*vrUr,RLC_UMUL);
319          while (recBuf[sn] && tSn < tVrUr)
320          {
321             rlcUmmReAssembleSdus(gCb,rbCb,recBuf[sn]);
322             RLC_FREE_WC(gCb,recBuf[sn],sizeof(RlcUmRecBuf));
323             recBuf[sn] = NULLP;
324             sn = (sn + 1) & RLC_UMUL.modBitMask;
325             tSn = RLC_UM_GET_VALUE(sn, RLC_UMUL);
326          }
327       }
328
329       tmrRunning = rlcChkTmr(gCb,(PTR)rbCb, RLC_EVT_UMUL_REORD_TMR);
330
331       if (tmrRunning) 
332       {
333          RlcSn tVrUx = RLC_UM_GET_VALUE(*vrUx, RLC_UMUL);
334          RlcSn tVrUr = RLC_UM_GET_VALUE(*vrUr ,RLC_UMUL);
335
336          RlcSn tVrUh = RLC_UM_GET_VALUE(*vrUh, RLC_UMUL);
337
338          S16 ret = rlcUmmCheckSnInReordWindow(*vrUx, &RLC_UMUL);
339
340          if ( (tVrUx <= tVrUr) || ((!ret) && (tVrUx != tVrUh))) 
341          {
342             rlcStopTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR);
343             tmrRunning = FALSE;
344          }
345       }
346
347       if (!tmrRunning)
348       {
349          if (RLC_UM_GET_VALUE(*vrUh, RLC_UMUL) > RLC_UM_GET_VALUE(*vrUr, RLC_UMUL))
350          {
351             rlcStartTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR); 
352             *vrUx = *vrUh;
353          }
354       }
355       count++;
356    }/* end while count < pduCount */
357 #ifdef LTE_L2_MEAS
358    rlcUtlCalUlIpThrPutIncTTI(gCb, rbCb,ttiCnt);
359 #endif /* LTE_L2_MEAS */
360    return;   
361 }
362
363 /**
364  * @brief  Handler to reassemble the SDUs and send them to the upper layer.
365  *       
366  * @details
367  *    This function processes the received in-sequence PDU and
368  *    re-assembles the SDUs and sends them to the upper layer.
369  *
370  * @param[in] gCb        RLC Instance control block
371  * @param[in] rbCb       RB control block
372  * @param[in] umRecBuf   Reception Buffer to be Re-Assembled 
373  *
374  * @return  Void
375 */
376 void rlcUmmReAssembleSdus(RlcCb *gCb, RlcUlRbCb *rbCb, RlcUmRecBuf *umRecBuf)
377 {
378    uint32_t  liCount;        /* LI count */
379    uint32_t  count;          /* Loop counter */
380    uint8_t   fi;             /* Framing Info */
381    uint16_t  sn;             /* Sequence Number of current PDU */
382    MsgLen    len;            /* PDU Length */
383    Buffer    *sdu;           /* SDU to be sent to upper layer */
384    Buffer    *remPdu;        /* Remaining PDU */
385    Buffer    **partialSdu;   /* Partial SDU */
386
387    liCount = umRecBuf->umHdr.numLi;
388    fi = umRecBuf->umHdr.fi;
389    sn =  umRecBuf->umHdr.sn;
390  
391    for (count = 0; (count <= liCount);count++)
392    {
393       if (count < liCount )
394          len = umRecBuf->umHdr.li[count];
395       else
396       {
397          if (!(umRecBuf->pdu))
398          {
399             return;
400          }
401          ODU_GET_MSG_LEN(umRecBuf->pdu,&len);
402       }
403          
404       /* get the sdu out of the pdu */
405       ODU_SEGMENT_MSG(umRecBuf->pdu,len,&remPdu);
406       sdu = umRecBuf->pdu;
407       umRecBuf->pdu = remPdu;
408       
409       partialSdu = &(rbCb->m.umUl.partialSdu);
410       /* While re-assembling the SDUs, consider the first LI and perform 
411        * the following steps.
412           -# If the first bit of FI(Framing Info of 2  bits) is set => 
413                 -# The current Data field in the PDU is a segment. 
414                    So form a SDU only if the 
415                        rbCb->m.um.umUl.partialSdu exists and the SNs are 
416                        in-sequence.
417                 -# If there are no LIs and the second bit of LI is 1 
418                    then a partial SDU is formed which would not be sent 
419                    to the upper layer.
420           -# else
421                 -# If rbCb->partialSdu is not NULL then flush it off.
422                 -# If LI count > 0 or LI count is 0 and second bit 
423                    of FI is not 1 
424                          The SDU is complete.So send it to upper layer.
425                 -# else
426                          The SDU is partial and is placed 
427                          in rbCb->m.um.umUl.partialSdu;
428       */
429              
430       if (0 == count )
431       {
432          if (fi & 2)
433          {
434             if ((*partialSdu) && 
435                 (sn == ((rbCb->m.umUl.sn + 1) & rbCb->m.umUl.modBitMask)))
436             {
437                ODU_CAT_MSG(*partialSdu,sdu,M1M2);
438                RLC_FREE_BUF(sdu);
439                if (liCount > 0 || !(fi & 1))
440                {
441                   rlcUtlSendUlDataToDu(gCb,rbCb,*partialSdu);
442                   *partialSdu = NULLP;
443                }
444             }
445             else
446             {
447                 /* Partial Sdu stored is not valid now.So free it */
448                if (*partialSdu)
449                {
450                   RLC_FREE_BUF(*partialSdu);
451                   *partialSdu = NULLP;
452                }
453                   
454                RLC_FREE_BUF(sdu);
455                sdu = NULLP;
456             }
457          }
458          else
459          {
460             if (*partialSdu)
461             {
462                RLC_FREE_BUF(*partialSdu);  /* RLC mem leak fix */
463                *partialSdu = NULLP;
464             }
465             
466             if (liCount > 0 || !( fi & 1))
467             {
468                rlcUtlSendUlDataToDu(gCb,rbCb,sdu);
469             }
470             else
471             {
472                   *partialSdu = sdu; 
473             }
474          }
475       }
476       /*
477           If the SDU pointer has the last Data field of the PDU
478             -# If FI is 1,place the SDU in rbCb->m.um.umDl.partialSdu
479             -# else send the SDU to upper layer.
480       */
481        else if (count == liCount)
482       {
483          if (fi & 1)
484          {
485             *partialSdu = sdu;
486          }
487          else
488          {
489             rlcUtlSendUlDataToDu(gCb, rbCb, sdu);
490          }
491       }
492       /*  
493          If the LI is something other than the first one, 
494          just send the SDU to the upper layer */
495       else
496       {
497          rlcUtlSendUlDataToDu(gCb, rbCb, sdu);
498       }
499    }
500    rbCb->m.umUl.sn = sn;
501
502    return;
503 }
504
505 /**
506  * @brief  Handler to process the re-establishment request received 
507  *         from the upper layer.
508  *       
509  * @details
510  *    This function does the following functions : 
511  *       - If direction of the RB is downlink : 
512  *         Remove all the SDUs in the SDU queue.
513  *       - If direction of the RB is uplink   : 
514  *         Call rlcUmmReAssembleSdus() for each PDU with SN < VR(UH)
515  *
516  * @param[in] gCb        RLC Instance control block
517  * @param[in] rlcID      Identity of the RLC entity for which 
518  *                       re-establishment is to be done
519  * @param[in] rbCb       RB control block for which re-establishment 
520  *                       is to be done
521  *
522  * @return  Void
523 */ 
524 #ifdef ANSI
525 Void rlcUmmUlReEstablish
526 (
527 RlcCb         *gCb,
528 CmLteRlcId   *rlcId,
529 RlcUlRbCb     *rbCb
530 )
531 #else
532 Void rlcUmmUlReEstablish(gCb, rlcId, rbCb)
533 RlcCb         *gCb;
534 CmLteRlcId   *rlcId;
535 RlcUlRbCb     *rbCb;
536 #endif
537 {
538    RlcSn         curSn;
539    RlcSn         vrUh;
540    RlcUmRecBuf   **recBuf;   /* UM Reception Buffer */
541    RlcKwuSapCb   *rlcKwSap;   /* KWU SAP Information */
542
543    TRC2(rlcUmmUlReEstablish)
544
545
546    curSn = rbCb->m.umUl.vrUr;
547    vrUh  = RLC_UM_GET_VALUE(rbCb->m.umUl.vrUh,rbCb->m.umUl);
548    recBuf =  rbCb->m.umUl.recBuf;
549
550    if(TRUE == rlcChkTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR))
551    {
552        rlcStopTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR);
553    }
554    
555    while (RLC_UM_GET_VALUE(curSn,rbCb->m.umUl) < vrUh)
556    {
557       if ( recBuf[curSn] != NULLP )
558       {
559          rlcUmmReAssembleSdus(gCb,rbCb,recBuf[curSn]);
560          RLC_FREE_WC(gCb,recBuf[curSn],sizeof(RlcUmRecBuf));
561          recBuf[curSn] = NULLP;
562       } 
563       curSn = (curSn + 1) & rbCb->m.umUl.modBitMask;
564    }
565    rbCb->m.umUl.vrUr = 0;
566    rbCb->m.umUl.vrUh = 0;
567    rbCb->m.umUl.vrUx = 0;
568
569    rlcKwSap = gCb->u.ulCb->rlcKwuUlSap + RLC_UI_PDCP;
570
571    /* In the UM Mode always send reestablish-indication to Upper Latyer*/
572    RlcUiKwuReEstCmpInd(&rlcKwSap->pst, rlcKwSap->suId, *rlcId);
573
574    RETVOID;
575 }
576
577 /**
578  * @brief  Handler to extract the header from a PDU
579  *       
580  * @details
581  *    This function is used to extract the header of a PDU and store it 
582  *    along with the PDU buffer.The sequence number,framing info 
583  *    and LIs are extracted by this function.
584  *
585  * @param[in] gCb      RLC Instance control block
586  * @param[in] rbCb     Rb Control block for which the pdu is received
587  * @param[in] pdu      PDU buffer
588  * @param[out] umHdr   UM header to be filled after extraction
589  *
590  * @return  S16
591  *      -# TRUE 
592  *      -# FALSE
593 */
594 uint8_t rlcUmmExtractHdr(RlcCb *gCb, RlcUlRbCb *rbCb, Buffer *pdu, RlcUmHdr *umHdr)
595 {
596    uint8_t   e;         /* Extension Bit */
597    Data      dst[2];    /* Destination Buffer */
598    int32_t   totalSz;   /* Sum of LIs */
599    MsgLen    pduSz;     /* PDU size */
600 #if (ERRCLASS & ERRCLS_DEBUG)
601    uint8_t   ret;       /* Return Value */
602 #endif
603
604    ODU_GET_MSG_LEN(pdu,&pduSz);
605  
606    if ( rbCb->m.umUl.snLen == 1)
607    {
608 #if (ERRCLASS & ERRCLS_DEBUG)
609       ret = ODU_REM_PRE_MSG(dst,pdu);
610       if (ret != ROK)
611       {
612          DU_LOG("\nRLC : rlcUmmExtractHdr : ODU_REM_PRE_MSG Failed for 5 bit SN \
613             UEID:%d CELLID:%d", rbCb->rlcId.ueId, rbCb->rlcId.cellId);
614          return RFAILED;
615       }
616 #else
617       ODU_REM_PRE_MSG(dst,pdu);
618 #endif
619       pduSz--;
620       umHdr->sn = (dst[0]) & 0x1F; 
621       umHdr->fi = (dst[0]) >> 6;
622       e       = (dst[0]>>5) & 0x01;
623    }
624    else
625    {
626       /* snLen - sequnce length will be 10 bits requiring 2 bytes */ 
627 #if (ERRCLASS & ERRCLS_DEBUG)
628       ret = ODU_REM_PRE_MSG_MULT(dst,2,pdu);
629       if (ret != ROK)
630       {
631          DU_LOG("\nRLC : rlcUmmExtractHdr : ODU_REM_PRE_MSG_MULT Failed for 10 bits SN \
632             UEID:%d CELLID:%d", rbCb->rlcId.ueId, rbCb->rlcId.cellId);
633          return RFAILED;
634       }
635 #else
636       ODU_REM_PRE_MSG_MULT(dst,2,pdu);
637 #endif
638       pduSz -= 2;
639    
640       /* kw005.201 R9 Upgrade 3gpp spec 36.322 ver9.3.0 CR0082      *
641        * Removed the "if" condition for checking the reserved field *
642        * Added mask 0x03 for extracting the FI field.          */
643
644       umHdr->fi = ( (dst[0] ) >> 3) & 0x03;
645       e       = ( (dst[0] ) >> 2) & 0x01;
646       umHdr->sn = (  dst[0] & 0x03) << 8;
647       umHdr->sn  |= dst[1];
648    }
649
650    umHdr->numLi = 0;
651    
652    totalSz = 0;
653    while(e && umHdr->numLi < RLC_MAX_UL_LI )
654    {
655 #if (ERRCLASS & ERRCLS_DEBUG)
656       ret = ODU_REM_PRE_MSG_MULT(dst,2,pdu);
657       if (ret != ROK)
658       {
659          DU_LOG("\nRLC : rlcUmmExtractHdr : ODU_REM_PRE_MSG_MULT Failed UEID:%d CELLID:%d",\
660             rbCb->rlcId.ueId, rbCb->rlcId.cellId);
661          return RFAILED;
662       }
663 #else
664       ODU_REM_PRE_MSG_MULT(dst,2,pdu);
665 #endif
666       umHdr->li[umHdr->numLi] = ((dst[0]) & 0x7F) << 4;
667       umHdr->li[umHdr->numLi] |= dst[1] >> 4;
668       if ( 0 == umHdr->li[umHdr->numLi] )
669       {
670          DU_LOG("\nRLC : rlcUmmExtractHdr : Received LI as 0 UEID:%d CELLID:%d",
671             rbCb->rlcId.ueId, rbCb->rlcId.cellId);
672          return RFAILED; 
673       }
674       totalSz += umHdr->li[umHdr->numLi];
675       if ( pduSz <=  totalSz )
676       {
677          DU_LOG("\nRLC : rlcUmmExtractHdr : SN [%d]: UEID:%d CELLID:%d",\
678             umHdr->sn, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
679          DU_LOG("\nRLC : rlcUmmExtractHdr : Corrupted PDU as TotSz[%d] PduSz[%d] \
680             UEID:%d CELLID:%d ", totalSz, pduSz, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
681          return RFAILED; /* the situation where in the PDU size 
682                             is something that does not match with 
683                             the size in LIs*/
684       }
685       umHdr->numLi++;
686       pduSz -= 2;
687
688       e = ((dst[0]) & 0x80) >> 7;
689    
690       if ( e && umHdr->numLi < RLC_MAX_UL_LI)
691       {
692          U8 tmp = ((dst[1]) & 0x08) >> 3;
693          umHdr->li[umHdr->numLi] = ( dst[1] & 0x07) << 8;
694
695
696 #if (ERRCLASS & ERRCLS_DEBUG)
697          ret = ODU_REM_PRE_MSG(dst,pdu);
698          if (ret != ROK)
699          {
700             DU_LOG("\nRLC : rlcUmmExtractHdr : ODU_REM_PRE_MSG Failed UEID:%d CELLID:%d",
701                rbCb->rlcId.ueId, rbCb->rlcId.cellId);
702             return RFAILED;
703          }
704 #else
705          ODU_REM_PRE_MSG(dst,pdu);
706 #endif
707          umHdr->li[umHdr->numLi] |= ( dst[0] );    /* The first byte lies in 
708                                                    the first 8 bits.We want 
709                                                    them in the last 8 bits */
710          if ( 0 == umHdr->li[umHdr->numLi] )
711          {
712             DU_LOG("\nRLC : rlcUmmExtractHdr :Received LI as 0 UEID:%d CELLID:%d",
713                rbCb->rlcId.ueId, rbCb->rlcId.cellId);
714             return RFAILED; 
715          }
716          totalSz += umHdr->li[umHdr->numLi];
717          pduSz--;
718          umHdr->numLi++;
719
720          if (pduSz < totalSz)
721          {
722             return RFAILED; /* the situation where in the PDU size is 
723                                something that does not match with the 
724                                size in LIs*/
725          }
726
727          e = tmp;
728       }
729    } /* while(e && umHdr->numLi < RLC_MAX_LI ) */
730    if (e)
731    {
732       /* PDU was constructed with LIs that exceeded RLC_MAX_LI */
733       return RFAILED;
734    }
735    return ROK; 
736 }
737    
738 /**
739  * @brief Handles expiry of re-ordering timer
740  *
741  * @param[in] gCb     RLC Instance control block
742  * @param[in] rbCb    Rb Control block for which re-order timer expired
743  *
744  * @return  Void
745 */
746 #ifdef ANSI
747 Void rlcUmmReOrdTmrExp
748 (
749 RlcCb       *gCb,
750 RlcUlRbCb   *rbCb     
751 )
752 #else
753 Void rlcUmmReOrdTmrExp(gCb, rbCb)
754 RlcCb       *gCb;
755 RlcUlRbCb   *rbCb;   
756 #endif
757 {
758    RlcSn prevVrUr;   /* prevVrUr */
759
760    TRC3(rlcUmmReOrdTmrExp)
761
762
763    prevVrUr = RLC_UMUL.vrUr;
764
765    /* set VR(UR) to SN >= VR(UX) that has not been received */
766    rlcUmmFindNextVRUR(&RLC_UMUL, RLC_UMUL.vrUx);
767
768    while (RLC_UM_GET_VALUE(prevVrUr,RLC_UMUL) < 
769           RLC_UM_GET_VALUE(RLC_UMUL.vrUr,RLC_UMUL))
770    {
771       if (RLC_UMUL.recBuf[prevVrUr])
772       {
773          rlcUmmReAssembleSdus(gCb, rbCb, RLC_UMUL.recBuf[prevVrUr]);
774          if(RLC_UMUL.recBuf[prevVrUr]->pdu != NULLP) /* RLC mem leak fix */
775          {
776             RLC_FREE_BUF(RLC_UMUL.recBuf[prevVrUr]->pdu);
777          }
778          RLC_FREE_WC(gCb, RLC_UMUL.recBuf[prevVrUr], sizeof(RlcUmRecBuf));
779          RLC_UMUL.recBuf[prevVrUr] = NULLP;
780       }
781
782       prevVrUr = (prevVrUr + 1) & rbCb->m.umUl.modBitMask;
783    }
784
785    if (RLC_UM_GET_VALUE(RLC_UMUL.vrUh, RLC_UMUL) > 
786        RLC_UM_GET_VALUE(RLC_UMUL.vrUr, RLC_UMUL))
787    {
788       rlcStartTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR);
789       RLC_UMUL.vrUx = RLC_UMUL.vrUh;
790    }
791 }
792
793 /**
794  * @brief
795  *   Function to release/free the UnAcknowledged Mode Module  RbCb buffers
796  *
797  * @details
798  *   This primitive Frees the UM RbCb transmission Buffer, retransmission
799  *   Buffer and reciption Buffers
800  *
801  * @param [in]   gCb   - RLC instance Control Block
802  * @param [in]   rbCb  - RB Control Block
803  *
804  * @return   void
805  */
806
807 #ifdef ANSI
808 Void rlcUmmFreeUlRbCb
809 (
810 RlcCb       *gCb,
811 RlcUlRbCb   *rbCb
812 )
813 #else
814 Void rlcUmmFreeUlRbCb(gCb,rbCb)
815 RlcCb       *gCb;
816 RlcUlRbCb   *rbCb;
817 #endif
818 {
819    RlcSn         curSn = 0;           /* sequence number of PDU */
820    RlcSn         windSz;              /* PDU window size */
821    RlcUmRecBuf   **umRecBuf;          /* UM module receive buffer */
822
823    TRC2(rlcUmmFreeUlRbCb)
824
825
826    windSz  = rbCb->m.umUl.umWinSz << 1;
827
828    umRecBuf =  rbCb->m.umUl.recBuf;
829
830    if(TRUE == rlcChkTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR))
831    {
832       rlcStopTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR);
833    }
834    while (curSn < windSz)
835    {
836       if (umRecBuf[curSn] != NULLP)
837       {
838          RLC_FREE_BUF_WC(umRecBuf[curSn]->pdu);
839          umRecBuf[curSn]->pdu = NULLP;
840
841          RLC_FREE_WC(gCb, umRecBuf[curSn], sizeof(RlcUmRecBuf));
842          umRecBuf[curSn] = NULLP;
843       }
844       curSn++;
845    }
846    RLC_FREE_WC(gCb,rbCb->m.umUl.recBuf, (windSz ) * sizeof(RlcUmRecBuf*));
847    rbCb->m.umUl.recBuf = NULLP;
848    RETVOID;
849
850
851
852 /********************************************************************30**
853          End of file
854 **********************************************************************/