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