[JIRA ID:ODUHIGH-255]- Fix for DL RRC Msg in Ue context setup Req
[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 static uint8_t rlcUmmExtractHdr ARGS ((RlcCb *gCb, 
69                                    RlcUlRbCb *rbCb,
70                                    Buffer *pdu,
71                                    RlcUmHdr *umHdr));
72
73 static void rlcUmmReAssembleSdus ARGS ((RlcCb *gCb,
74                                         RlcUlRbCb *rbCb,
75                                         RlcUmRecBuf *umRecBuf));
76
77 #ifndef TENB_ACC
78 #ifndef LTE_PAL_ENB
79 uint32_t 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 static 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 static int16_t rlcUmmCheckSnInReordWindow (RlcSn sn, const RlcUmUl* const 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       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         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 static 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 Void rlcUmmUlReEstablish
525 (
526 RlcCb         *gCb,
527 CmLteRlcId   *rlcId,
528 RlcUlRbCb     *rbCb
529 )
530 {
531    RlcSn         curSn;
532    RlcSn         vrUh;
533    RlcUmRecBuf   **recBuf;   /* UM Reception Buffer */
534    RlcKwuSapCb   *rlcKwSap;   /* KWU SAP Information */
535
536    curSn = rbCb->m.umUl.vrUr;
537    vrUh  = RLC_UM_GET_VALUE(rbCb->m.umUl.vrUh,rbCb->m.umUl);
538    recBuf =  rbCb->m.umUl.recBuf;
539
540    if(TRUE == rlcChkTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR))
541    {
542        rlcStopTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR);
543    }
544    
545    while (RLC_UM_GET_VALUE(curSn,rbCb->m.umUl) < vrUh)
546    {
547       if ( recBuf[curSn] != NULLP )
548       {
549          rlcUmmReAssembleSdus(gCb,rbCb,recBuf[curSn]);
550          RLC_FREE_WC(gCb,recBuf[curSn],sizeof(RlcUmRecBuf));
551          recBuf[curSn] = NULLP;
552       } 
553       curSn = (curSn + 1) & rbCb->m.umUl.modBitMask;
554    }
555    rbCb->m.umUl.vrUr = 0;
556    rbCb->m.umUl.vrUh = 0;
557    rbCb->m.umUl.vrUx = 0;
558
559    rlcKwSap = gCb->u.ulCb->rlcKwuUlSap + RLC_UI_PDCP;
560
561    /* In the UM Mode always send reestablish-indication to Upper Latyer*/
562    RlcUiKwuReEstCmpInd(&rlcKwSap->pst, rlcKwSap->suId, *rlcId);
563
564    return;
565 }
566
567 /**
568  * @brief  Handler to extract the header from a PDU
569  *       
570  * @details
571  *    This function is used to extract the header of a PDU and store it 
572  *    along with the PDU buffer.The sequence number,framing info 
573  *    and LIs are extracted by this function.
574  *
575  * @param[in] gCb      RLC Instance control block
576  * @param[in] rbCb     Rb Control block for which the pdu is received
577  * @param[in] pdu      PDU buffer
578  * @param[out] umHdr   UM header to be filled after extraction
579  *
580  * @return  S16
581  *      -# TRUE 
582  *      -# FALSE
583 */
584 static uint8_t rlcUmmExtractHdr(RlcCb *gCb, RlcUlRbCb *rbCb, Buffer *pdu, RlcUmHdr *umHdr)
585 {
586    uint8_t   e;         /* Extension Bit */
587    Data      dst[2];    /* Destination Buffer */
588    int32_t   totalSz;   /* Sum of LIs */
589    MsgLen    pduSz;     /* PDU size */
590 #if (ERRCLASS & ERRCLS_DEBUG)
591    uint8_t   ret;       /* Return Value */
592 #endif
593
594    ODU_GET_MSG_LEN(pdu,&pduSz);
595  
596    if ( rbCb->m.umUl.snLen == 1)
597    {
598 #if (ERRCLASS & ERRCLS_DEBUG)
599       ret = ODU_REM_PRE_MSG(dst,pdu);
600       if (ret != ROK)
601       {
602          DU_LOG("\nRLC : rlcUmmExtractHdr : ODU_REM_PRE_MSG Failed for 5 bit SN \
603             UEID:%d CELLID:%d", rbCb->rlcId.ueId, rbCb->rlcId.cellId);
604          return RFAILED;
605       }
606 #else
607       ODU_REM_PRE_MSG(dst,pdu);
608 #endif
609       pduSz--;
610       umHdr->sn = (dst[0]) & 0x1F; 
611       umHdr->fi = (dst[0]) >> 6;
612       e       = (dst[0]>>5) & 0x01;
613    }
614    else
615    {
616       /* snLen - sequnce length will be 10 bits requiring 2 bytes */ 
617 #if (ERRCLASS & ERRCLS_DEBUG)
618       ret = ODU_REM_PRE_MSG_MULT(dst,2,pdu);
619       if (ret != ROK)
620       {
621          DU_LOG("\nRLC : rlcUmmExtractHdr : ODU_REM_PRE_MSG_MULT Failed for 10 bits SN \
622             UEID:%d CELLID:%d", rbCb->rlcId.ueId, rbCb->rlcId.cellId);
623          return RFAILED;
624       }
625 #else
626       ODU_REM_PRE_MSG_MULT(dst,2,pdu);
627 #endif
628       pduSz -= 2;
629    
630       /* kw005.201 R9 Upgrade 3gpp spec 36.322 ver9.3.0 CR0082      *
631        * Removed the "if" condition for checking the reserved field *
632        * Added mask 0x03 for extracting the FI field.          */
633
634       umHdr->fi = ( (dst[0] ) >> 3) & 0x03;
635       e       = ( (dst[0] ) >> 2) & 0x01;
636       umHdr->sn = (  dst[0] & 0x03) << 8;
637       umHdr->sn  |= dst[1];
638    }
639
640    umHdr->numLi = 0;
641    
642    totalSz = 0;
643    while(e && umHdr->numLi < RLC_MAX_UL_LI )
644    {
645 #if (ERRCLASS & ERRCLS_DEBUG)
646       ret = ODU_REM_PRE_MSG_MULT(dst,2,pdu);
647       if (ret != ROK)
648       {
649          DU_LOG("\nRLC : rlcUmmExtractHdr : ODU_REM_PRE_MSG_MULT Failed UEID:%d CELLID:%d",\
650             rbCb->rlcId.ueId, rbCb->rlcId.cellId);
651          return RFAILED;
652       }
653 #else
654       ODU_REM_PRE_MSG_MULT(dst,2,pdu);
655 #endif
656       umHdr->li[umHdr->numLi] = ((dst[0]) & 0x7F) << 4;
657       umHdr->li[umHdr->numLi] |= dst[1] >> 4;
658       if ( 0 == umHdr->li[umHdr->numLi] )
659       {
660          DU_LOG("\nRLC : rlcUmmExtractHdr : Received LI as 0 UEID:%d CELLID:%d",
661             rbCb->rlcId.ueId, rbCb->rlcId.cellId);
662          return RFAILED; 
663       }
664       totalSz += umHdr->li[umHdr->numLi];
665       if ( pduSz <=  totalSz )
666       {
667          DU_LOG("\nRLC : rlcUmmExtractHdr : SN [%d]: UEID:%d CELLID:%d",\
668             umHdr->sn, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
669          DU_LOG("\nRLC : rlcUmmExtractHdr : Corrupted PDU as TotSz[%d] PduSz[%d] \
670             UEID:%d CELLID:%d ", totalSz, pduSz, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
671          return RFAILED; /* the situation where in the PDU size 
672                             is something that does not match with 
673                             the size in LIs*/
674       }
675       umHdr->numLi++;
676       pduSz -= 2;
677
678       e = ((dst[0]) & 0x80) >> 7;
679    
680       if ( e && umHdr->numLi < RLC_MAX_UL_LI)
681       {
682          uint8_t tmp = ((dst[1]) & 0x08) >> 3;
683          umHdr->li[umHdr->numLi] = ( dst[1] & 0x07) << 8;
684
685
686 #if (ERRCLASS & ERRCLS_DEBUG)
687          ret = ODU_REM_PRE_MSG(dst,pdu);
688          if (ret != ROK)
689          {
690             DU_LOG("\nRLC : rlcUmmExtractHdr : ODU_REM_PRE_MSG Failed UEID:%d CELLID:%d",
691                rbCb->rlcId.ueId, rbCb->rlcId.cellId);
692             return RFAILED;
693          }
694 #else
695          ODU_REM_PRE_MSG(dst,pdu);
696 #endif
697          umHdr->li[umHdr->numLi] |= ( dst[0] );    /* The first byte lies in 
698                                                    the first 8 bits.We want 
699                                                    them in the last 8 bits */
700          if ( 0 == umHdr->li[umHdr->numLi] )
701          {
702             DU_LOG("\nRLC : rlcUmmExtractHdr :Received LI as 0 UEID:%d CELLID:%d",
703                rbCb->rlcId.ueId, rbCb->rlcId.cellId);
704             return RFAILED; 
705          }
706          totalSz += umHdr->li[umHdr->numLi];
707          pduSz--;
708          umHdr->numLi++;
709
710          if (pduSz < totalSz)
711          {
712             return RFAILED; /* the situation where in the PDU size is 
713                                something that does not match with the 
714                                size in LIs*/
715          }
716
717          e = tmp;
718       }
719    } /* while(e && umHdr->numLi < RLC_MAX_LI ) */
720    if (e)
721    {
722       /* PDU was constructed with LIs that exceeded RLC_MAX_LI */
723       return RFAILED;
724    }
725    return ROK; 
726 }
727    
728 /**
729  * @brief Handles expiry of re-ordering timer
730  *
731  * @param[in] gCb     RLC Instance control block
732  * @param[in] rbCb    Rb Control block for which re-order timer expired
733  *
734  * @return  Void
735 */
736 Void rlcUmmReOrdTmrExp
737 (
738 RlcCb       *gCb,
739 RlcUlRbCb   *rbCb     
740 )
741 {
742    RlcSn prevVrUr;   /* prevVrUr */
743    prevVrUr = RLC_UMUL.vrUr;
744
745    /* set VR(UR) to SN >= VR(UX) that has not been received */
746    rlcUmmFindNextVRUR(&RLC_UMUL, RLC_UMUL.vrUx);
747
748    while (RLC_UM_GET_VALUE(prevVrUr,RLC_UMUL) < 
749           RLC_UM_GET_VALUE(RLC_UMUL.vrUr,RLC_UMUL))
750    {
751       if (RLC_UMUL.recBuf[prevVrUr])
752       {
753          rlcUmmReAssembleSdus(gCb, rbCb, RLC_UMUL.recBuf[prevVrUr]);
754          if(RLC_UMUL.recBuf[prevVrUr]->pdu != NULLP) /* RLC mem leak fix */
755          {
756             RLC_FREE_BUF(RLC_UMUL.recBuf[prevVrUr]->pdu);
757          }
758          RLC_FREE_WC(gCb, RLC_UMUL.recBuf[prevVrUr], sizeof(RlcUmRecBuf));
759          RLC_UMUL.recBuf[prevVrUr] = NULLP;
760       }
761
762       prevVrUr = (prevVrUr + 1) & rbCb->m.umUl.modBitMask;
763    }
764
765    if (RLC_UM_GET_VALUE(RLC_UMUL.vrUh, RLC_UMUL) > 
766        RLC_UM_GET_VALUE(RLC_UMUL.vrUr, RLC_UMUL))
767    {
768       rlcStartTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR);
769       RLC_UMUL.vrUx = RLC_UMUL.vrUh;
770    }
771 }
772
773 /**
774  * @brief
775  *   Function to release/free the UnAcknowledged Mode Module  RbCb buffers
776  *
777  * @details
778  *   This primitive Frees the UM RbCb transmission Buffer, retransmission
779  *   Buffer and reciption Buffers
780  *
781  * @param [in]   gCb   - RLC instance Control Block
782  * @param [in]   rbCb  - RB Control Block
783  *
784  * @return   void
785  */
786
787 Void rlcUmmFreeUlRbCb
788 (
789 RlcCb       *gCb,
790 RlcUlRbCb   *rbCb
791 )
792 {
793    RlcSn         curSn = 0;           /* sequence number of PDU */
794    RlcSn         windSz;              /* PDU window size */
795    RlcUmRecBuf   **umRecBuf;          /* UM module receive buffer */
796
797    windSz  = rbCb->m.umUl.umWinSz << 1;
798
799    umRecBuf =  rbCb->m.umUl.recBuf;
800
801    if(TRUE == rlcChkTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR))
802    {
803       rlcStopTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR);
804    }
805    while (curSn < windSz)
806    {
807       if (umRecBuf[curSn] != NULLP)
808       {
809          RLC_FREE_BUF_WC(umRecBuf[curSn]->pdu);
810          umRecBuf[curSn]->pdu = NULLP;
811
812          RLC_FREE_WC(gCb, umRecBuf[curSn], sizeof(RlcUmRecBuf));
813          umRecBuf[curSn] = NULLP;
814       }
815       curSn++;
816    }
817    RLC_FREE_WC(gCb,rbCb->m.umUl.recBuf, (windSz ) * sizeof(RlcUmRecBuf*));
818    rbCb->m.umUl.recBuf = NULLP;
819    return;
820
821
822
823 /********************************************************************30**
824          End of file
825 **********************************************************************/