6c4d0f2fb77b9f56eea61f39be2a7434fd47d84b
[o-du/l2.git] / src / 5gnrrlc / rlc_upr_inf_mgr.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**
20   
21      Name:    NR RLC Layer - Upper Interface Functions
22     
23      Type:    C file
24   
25      Desc:     Source code for RLC Upper Interface Module
26                This file contains following functions
27       
28         --RlcUiCkwBndReq
29         --RlcUiCkwUbndReq
30         --RlcProcCfgReq
31
32         --RlcUiKwuBndReq
33         --RlcUiKwuUbndReq
34         --rlcProcDlData
35         --RlcUiKwuDiscSduReq 
36
37      File:     kw_uim.c
38
39 **********************************************************************/
40 /** 
41  * @file rlc_upr_inf_mgr.c
42  * @brief RLC Upper Interface Module
43 */
44
45 #define RLC_MODULE RLC_DBGMASK_INF
46
47 \f
48 /* header (.h) include files */
49 #include "common_def.h"
50 #include "lkw.h"           /* LKW defines */
51 #include "ckw.h"           /* CKW defines */
52 #include "kwu.h"           /* KWU defines */
53 #include "rgu.h"           /* RGU defines */
54 #include "rlc_env.h"        /* RLC environment options */
55 #include "rlc_err.h"
56
57
58 /* extern (.x) include files */
59 #include "lkw.x"           /* LKW */
60 #include "ckw.x"           /* CKW */
61 #include "kwu.x"           /* KWU */
62 #include "rgu.x"           /* RGU */
63
64 #include "rlc_utils.h"            /* RLC defines */
65 #include "rlc_dl_ul_inf.h"
66 #include "rlc_dl.h"
67 #include "rlc_ul.h"
68 /*****************************************************************************
69  *                          CKW INTERFACE
70  ****************************************************************************/
71
72 /**
73  * @brief 
74  *    Handler for binding the RLC upper layer service user with 
75  *    the RLC layer.
76  *
77  * @details
78  *    This function is used by RLC user to request for binding to 
79  *    RLC. This function is called by the CKW interface to bind 
80  *    RLC's SAP (identified by spId) with the service user's
81  *    SAP (identified by suId). 
82  *
83  * @param[in] pst     Post structure
84  * @param[in] suId    Service User ID
85  * @param[in] spId    Service provider ID
86  *
87  * @return  S16
88  *    -# ROK 
89  *    -# RFAILED
90  *
91 */
92 S16 RlcUiCkwBndReq 
93 (
94 Pst    *pst,
95 SuId   suId,
96 SpId   spId 
97 )
98 {
99    RlcCkwSapCb   *ckwSap;  
100    RlcCb         *tRlcCb;
101
102 #if (ERRCLASS & ERRCLS_INT_PAR)
103    if (pst->dstInst >= MAX_RLC_INSTANCES)
104    {
105       return RFAILED;
106    }
107 #endif
108
109    tRlcCb = RLC_GET_RLCCB(pst->dstInst);
110
111    DU_LOG("\nDEBUG  -->  RLC_UL : spId(%d), suId(%d)", spId, suId);
112    ckwSap = &(tRlcCb->u.ulCb->ckwSap);
113    /* Take action based on the current state of the SAP */
114    switch(ckwSap->state)
115    {
116       /* SAP is configured but not bound */
117       case RLC_SAP_CFG:
118       case RLC_SAP_UBND:
119       {
120          /* copy bind configuration parameters in SSAP sap */
121          ckwSap->suId = suId;
122          ckwSap->pst.dstProcId = pst->srcProcId;
123          ckwSap->pst.dstEnt = pst->srcEnt;
124          ckwSap->pst.dstInst = pst->srcInst;
125
126          /* Update the State */
127          ckwSap->state = RLC_SAP_BND;
128
129          DU_LOG("\nDEBUG  -->  RLC_UL : RlcUiCkwBndReq: state (%d)", ckwSap->state);
130          break;
131       }
132       case RLC_SAP_BND:
133       {
134          /* Sap is already bound check source, destination Entity and  
135           * Proc Id  */
136          if (ckwSap->pst.dstProcId != pst->srcProcId ||
137              ckwSap->pst.dstEnt != pst->srcEnt ||
138              ckwSap->pst.dstInst != pst->srcInst ||
139              ckwSap->suId != suId)
140          {
141             RLC_SEND_SAPID_ALARM(tRlcCb,
142                                 spId, 
143                                 LKW_EVENT_CKW_BND_REQ, 
144                                 LCM_CAUSE_INV_PAR_VAL);
145
146             DU_LOG("\nERROR  -->  RLC_UL : CKW SAP already Bound");
147             RlcUiCkwBndCfm(&(ckwSap->pst), ckwSap->suId, CM_BND_NOK);
148             return (RFAILED);
149          }
150          break;
151       }
152       default:
153       {
154 #if (ERRCLASS & ERRCLS_INT_PAR)
155          DU_LOG("\nERROR  -->  RLC_UL : Invalid CKW SAP State in Bind Req");
156          RLC_SEND_SAPID_ALARM(tRlcCb,
157                              spId, 
158                              LKW_EVENT_CKW_BND_REQ, 
159                              LCM_CAUSE_INV_STATE);
160 #endif /* ERRCLASS & ERRCLS_INT_PAR */
161          RlcUiCkwBndCfm(&(ckwSap->pst), ckwSap->suId, CM_BND_NOK);
162          return (RFAILED);
163          break;
164       }
165    }
166
167    RlcUiCkwBndCfm(&(ckwSap->pst), ckwSap->suId, CM_BND_OK);
168    return (ROK);
169
170
171 \f
172 /**
173  * @brief 
174  *    Handler for unbinding the RLC upper layer service user CKW with 
175  *    the RLC layer.
176  *
177  * @details
178  *    This function is used by RLC user to request for unbinding  
179  *    with RLC.This function is called by the CKW interface to 
180  *    unbind with RLC.  
181  *
182  * @param[in] pst     Post structure
183  * @param[in] spId    Service provider SAP ID
184  * @param[in] reason  Reason for Unbinding 
185  *
186  * @return  S16
187  *    -# ROK 
188  *    -# RFAILED
189 */ 
190 S16 RlcUiCkwUbndReq
191 (
192 Pst      *pst,   
193 SpId     spId,  
194 Reason   reason 
195 )
196 {
197    RlcCb *tRlcCb;
198
199 #if (ERRCLASS & ERRCLS_INT_PAR)
200    if (pst->dstInst >= MAX_RLC_INSTANCES)
201    {
202       return RFAILED;
203    }
204 #endif /* ERRCLASS & ERRCLS_INT_PAR */
205    tRlcCb = RLC_GET_RLCCB(pst->dstInst);
206
207    DU_LOG("\nDEBUG  -->  RLC_UL : spId(%d), reason(%d)", 
208                 spId, 
209                 reason);
210
211    UNUSED(reason);
212
213 #if (ERRCLASS & ERRCLS_INT_PAR)
214    RLC_GET_AND_VALIDATE_CKWSAP(tRlcCb, 
215                               (&(tRlcCb->u.ulCb->ckwSap)), 
216                               EKW208, 
217                               "RlcUiCkwUbndReq");
218 #endif /* ERRCLASS & ERRCLS_INT_PAR */
219
220    /* disable upper sap (CKW) */
221    tRlcCb->u.ulCb->ckwSap.state = RLC_SAP_CFG;
222    return ROK;
223
224
225 /**
226  * @brief  
227  *    Handler for configuring RLC entities.
228  *
229  * @details
230  *    This function is used by RRC to configure(add/delete/modify)
231  *    one or more RLC entities. 
232  *
233  * @param[in] pst   -  Post structure  
234  * @param[in] spId  -  Serive Provider ID 
235  * @param[in] cfg   -  Configuration information for one or more RLC entities. 
236  *
237  * @return  S16
238  *      -# ROK 
239  *      -# RFAILED
240  */
241 S16 RlcProcCfgReq
242 (
243 Pst          *pst,
244 RlcCfgInfo   *cfg
245 )
246 {
247    uint8_t cfgIdx = 0;
248    RlcCb        *tRlcCb;
249    RlcUlCfgTmpData   *cfgTmpData;
250
251    static uint32_t  transCount;
252
253 #if (ERRCLASS & ERRCLS_INT_PAR)
254    if (pst->dstInst >= MAX_RLC_INSTANCES)
255    {
256       for(cfgIdx=0; cfgIdx<cfg->numEnt; cfgIdx++)
257       {
258          RLC_PST_FREE(pst->region, pst->pool, cfg->entCfg[cfgIdx].snssai, sizeof(Snssai)); 
259       }
260       RLC_PST_FREE(pst->region, pst->pool, cfg, sizeof(RlcCfgInfo));
261       return RFAILED;
262    }
263 #endif
264    tRlcCb = RLC_GET_RLCCB(pst->dstInst);
265
266    RLC_ALLOC(tRlcCb, cfgTmpData, sizeof (RlcUlCfgTmpData));
267
268    if (cfgTmpData == NULLP)
269    {
270       for(cfgIdx=0; cfgIdx<cfg->numEnt; cfgIdx++)
271       {
272          RLC_PST_FREE(pst->region, pst->pool, cfg->entCfg[cfgIdx].snssai, sizeof(Snssai)); 
273       }
274       RLC_PST_FREE(pst->region, pst->pool, cfg, sizeof(RlcCfgInfo));
275       return RFAILED;
276    }
277    
278    cfgTmpData->uprLyrTransId = cfg->transId; /*Save User TransId*/
279    cfgTmpData->transId = ++transCount;       /*Generate new TransId*/
280    cfg->transId = cfgTmpData->transId;
281    cfgTmpData->cfgInfo  = cfg;
282
283  
284    tRlcCb->u.ulCb->rlcUlUdxEventType = pst->event;
285    if (rlcDbmAddUlTransaction(tRlcCb, cfgTmpData) != ROK)
286    {
287       DU_LOG("\nERROR  -->  RLC_UL : Addition to UL transId Lst Failed");
288       for(cfgIdx=0; cfgIdx<cfg->numEnt; cfgIdx++)
289       {
290          RLC_PST_FREE(pst->region, pst->pool, cfg->entCfg[cfgIdx].snssai, sizeof(Snssai)); 
291       }
292       RLC_PST_FREE(pst->region, pst->pool, cfg, sizeof(RlcCfgInfo));
293       
294       return RFAILED;
295    }
296    
297    rlcUlHdlCfgReq(tRlcCb, cfgTmpData, cfg);
298    rlcUlUdxCfgReq(&(RLC_GET_UDX_SAP(tRlcCb)->pst),RLC_GET_UDX_SAP(tRlcCb)->spId,cfg); 
299
300    return ROK;
301
302
303 /**
304  * @brief 
305  *    Handler to change the UeId
306  *
307  * @details 
308  *    This primitive is used by RRC to change the UeId for the existing UE
309  *    context.
310  *     
311  * @param[in] pst     -  Point to the pst structure
312  * @param[in] spId    -  The ID of the service provider SAP in the RLC layer 
313  * @param[in] transId -  Transaction ID. This field uniquily identifies
314  *                       transaction between RRC and RLC
315  * @param[in] ueInfo    -  Old UE Id Info for which the change request has come 
316  * @param[in] newUeInfo -  New UE Id Info for existing UE context 
317  * 
318  * @return S16
319  *    -# ROK
320  *    -# RFAILED
321  */
322 S16 RlcUiCkwUeIdChgReq
323 (
324 Pst         *pst, 
325 SpId        spId, 
326 uint32_t    transId, 
327 CkwUeInfo   *ueInfo,
328 CkwUeInfo   *newUeInfo
329 )
330 {
331    S16              ret = ROK;
332    RlcCb             *tRlcCb;
333    RlcUlCfgTmpData   *cfgTmpData = NULLP;
334
335    do
336    {
337 #if (ERRCLASS & ERRCLS_INT_PAR)
338       if (pst->dstInst >= MAX_RLC_INSTANCES)
339       {
340          ret = RFAILED;
341          break;
342       }
343 #endif
344
345       tRlcCb = RLC_GET_RLCCB(pst->dstInst);
346 #ifndef ALIGN_64BIT
347       DU_LOG("\nDEBUG  -->  RLC_UL : RlcUiCkwUeIdChgReq(pst, spId(%d), transId(%ld))", 
348                    spId, 
349                    transId);
350 #else
351       DU_LOG("\nDEBUG  -->  RLC_UL : RlcUiCkwUeIdChgReq(pst, spId(%d), transId(%d))\n", 
352                  spId, transId);
353 #endif
354
355       RLC_ALLOC(tRlcCb, cfgTmpData, sizeof (RlcUlCfgTmpData));
356       if (!cfgTmpData)
357       {
358          ret = RFAILED;
359          break;
360       }
361
362       cfgTmpData->transId = transId;
363       cfgTmpData->ueInfo  = ueInfo;
364       cfgTmpData->newUeInfo  = newUeInfo; 
365
366       if (rlcDbmAddUlTransaction(tRlcCb, cfgTmpData))
367       {
368          DU_LOG("\nERROR  -->  RLC_UL : Addition to UL transId Lst Failed");
369          ret = RFAILED;
370          break;
371       }
372    }while(0);
373
374    if(ret)
375    {
376       /* there was an error in the processing, free up all the memory
377        * that was passed and could have been allocated in this function
378        */
379       /* Freeing from proper region */
380       RLC_PST_FREE(pst->region, pst->pool, newUeInfo, sizeof(CkwUeInfo));
381       RLC_PST_FREE(pst->region, pst->pool, ueInfo, sizeof(CkwUeInfo));
382
383       if(cfgTmpData)
384       {
385          RLC_FREE(tRlcCb, cfgTmpData, sizeof (RlcUlCfgTmpData));
386       }
387       return RFAILED;
388    }
389
390    if(ROK != rlcCfgValidateUeIdChng(tRlcCb,ueInfo,newUeInfo,cfgTmpData))
391    {
392       DU_LOG("\nERROR  -->  RLC_UL : Validation Failure for UeId change");
393    }
394
395    rlcUlUdxUeIdChgReq(&(RLC_GET_UDX_SAP(tRlcCb)->pst),
396                      RLC_GET_UDX_SAP(tRlcCb)->spId,
397                      transId, 
398                      ueInfo,
399                      newUeInfo);
400
401    return ROK;
402
403
404 \f
405 /**
406  * @brief 
407  *    Handler for Configuration Request 
408  *
409  * @param[in] gCb      RLC Instance Control Block  
410  * @param[in] cfgTmpData  Configuration stored in Transaction Block  
411  * @param[in] cfg      Configuration block
412  *
413  * @return  S16
414  *    -# ROK 
415  *    -# RFAILED
416  */
417 Void rlcUlHdlCfgReq
418 (
419 RlcCb           *gCb,
420 RlcUlCfgTmpData *cfgTmpData,
421 RlcCfgInfo      *cfg
422 )
423 {
424    uint8_t   idx;  
425
426    cfgTmpData->ueId = cfg->ueId;
427    cfgTmpData->cellId = cfg->cellId;
428    for (idx = 0; idx < cfg->numEnt; idx++)
429    {
430       cfgTmpData->cfgEntData[idx].entUlCfgCfm.status.status = CKW_CFG_CFM_OK;
431       cfgTmpData->cfgEntData[idx].entUlCfgCfm.rbId = cfg->entCfg[idx].rbId; 
432       cfgTmpData->cfgEntData[idx].entUlCfgCfm.rbType = cfg->entCfg[idx].rbType;
433       switch(cfg->entCfg[idx].cfgType)
434       {
435          case CKW_CFG_ADD:
436          case CKW_CFG_MODIFY:
437          case CKW_CFG_DELETE:
438          {
439          
440             if(cfg->entCfg[idx].dir & RLC_DIR_UL)
441             {
442                /* Configuration is for UL , thus validating */
443                if(ROK != rlcCfgValidateUlRb(gCb,
444                                            &cfg->entCfg[idx], 
445                                            &cfgTmpData->cfgEntData[idx],
446                                            cfgTmpData))
447                {
448                   DU_LOG("\nERROR  -->  RLC_UL : CELLID [%u]:Validation Failure for UL RB [%d]",
449                          cfg->cellId,cfg->entCfg[idx].rbId);
450                   cfgTmpData->cfgEntData[idx].entUlCfgCfm.status.status = CKW_CFG_CFM_NOK;
451                   /*Validation is getting failed so no need to do configuration at DL.
452                    *Set dir as UL, so that no configuration is done at DL */
453                   cfg->entCfg[idx].dir = RLC_DIR_UL;
454                }
455             }
456             if(cfg->entCfg[idx].dir == RLC_DIR_UL)
457             {
458                /*If the configuration is for UL only then apply it */   
459                if (cfgTmpData->cfgEntData[idx].entUlCfgCfm.status.status == CKW_CFG_CFM_OK)
460                {
461                   rlcCfgApplyUlRb(gCb, 
462                                  &cfg->entCfg[idx], 
463                                  &cfgTmpData->cfgEntData[idx],
464                                  cfgTmpData);
465                }
466             }
467             break;
468          }
469          case CKW_CFG_REESTABLISH:   
470          {
471             if(cfg->entCfg[idx].dir & RLC_DIR_UL)
472             {
473                if(ROK != rlcCfgValidateReEstRb(gCb,
474                                               cfg->ueId, 
475                                               cfg->cellId, 
476                                               &cfg->entCfg[idx], 
477                                               &cfgTmpData->cfgEntData[idx]))
478                {
479                   DU_LOG("\nERROR  -->  RLC_UL : CellID [%u]:Validation Failure for Reest UL RB [%d]",
480                         cfg->cellId,cfg->entCfg[idx].rbId);
481                   cfgTmpData->cfgEntData[idx].entUlCfgCfm.status.status = CKW_CFG_CFM_NOK;
482                   /* Setting dir as UL, so that no configuration is done at DL */
483                   cfg->entCfg[idx].dir = RLC_DIR_UL;
484                   break;
485                }
486             }
487             if(cfg->entCfg[idx].dir == RLC_DIR_UL)
488             {
489                /*If the configuration is for UL only then apply it */   
490                if (cfgTmpData->cfgEntData[idx].entUlCfgCfm.status.status == CKW_CFG_CFM_OK)
491                {
492                   rlcCfgApplyReEstUlRb(gCb,  
493                                       cfg->ueId, 
494                                       cfg->cellId,
495                                       TRUE,
496                                       &cfgTmpData->cfgEntData[idx]);
497                }
498             }
499             break;
500          }
501          case CKW_CFG_DELETE_UE :   
502          {
503             if(ROK != rlcCfgValidateDelUlUe(gCb,  
504                                            &cfg->entCfg[idx], 
505                                            &cfgTmpData->cfgEntData[idx],
506                                            cfgTmpData))
507             {
508                DU_LOG("\nERROR  -->  RLC_UL : UL UEID [%d]:Validation Failure",
509                      cfgTmpData->ueId);
510                cfgTmpData->cfgEntData[idx].entUlCfgCfm.status.status = CKW_CFG_CFM_NOK;
511                /* Setting dir as UL, so that no configuration is done at DL */
512                cfg->entCfg[idx].dir = RLC_DIR_UL;
513             }
514             break;
515          }
516          case CKW_CFG_DELETE_CELL :   
517          {
518             if(ROK != rlcCfgValidateDelUlCell(gCb,
519                                              cfg->cellId, 
520                                              &cfg->entCfg[idx], 
521                                              &cfgTmpData->cfgEntData[idx],
522                                              cfgTmpData))
523             {
524                DU_LOG("\nERROR  -->  RLC_UL : Del UL Cell Validation Failure");
525                cfgTmpData->cfgEntData[idx].entUlCfgCfm.status.status = CKW_CFG_CFM_NOK;
526                /* Setting dir as UL, so that no configuration is done at DL */
527                cfg->entCfg[idx].dir = RLC_DIR_UL;
528             }
529             break;
530          }
531       }/* switch end */
532    }/* for end */
533    return;
534 }
535
536 \f
537 /*****************************************************************************
538  *                          KWU INTERFACE
539  ****************************************************************************/
540 /**
541  * @brief  
542  *    Handler for binding the RLC upper layer service user with 
543  *    the RLC layer.
544  *
545  * @details
546  *    This function is used by RLC user to request for binding to 
547  *    RLC.This function is called by the KWU interface to bind 
548  *    RLC's SAP (identified by spId) with the service user's
549  *    SAP (identified by suId). 
550  *
551  * @param[in] pst   Post structure  
552  * @param[in] suId  Service user SAP ID 
553  * @param[in] spId  Service provider ID
554  *
555  * @return  S16
556  *    -# ROK
557  *    -# RFAILED
558  *
559  */
560 S16 RlcUiKwuBndReq 
561 (
562 Pst    *pst,  
563 SuId   suId, 
564 SpId   spId 
565 )
566 {
567    RlcKwuSapCb   *rlckwuSap;     /* SAP Config Block */
568    RlcCb         *tRlcCb;
569    
570 #if (ERRCLASS & ERRCLS_INT_PAR)
571    if (pst->dstInst >= MAX_RLC_INSTANCES)
572    {
573       return RFAILED;
574    }
575 #endif
576    tRlcCb = RLC_GET_RLCCB(pst->dstInst);
577    DU_LOG("\nDEBUG  -->  RLC_UL : RlcUiKwuBndReq(pst, spId(%d), suId(%d))", spId, suId);
578
579     /* Validation of input parameters */
580 #if (ERRCLASS & ERRCLS_INT_PAR)
581    if(!((spId < (S16) tRlcCb->genCfg.maxKwuSaps) && (spId >=0))) 
582    {
583       DU_LOG("\nERROR  -->  RLC_UL : Invalid spId");
584       RLC_SEND_SAPID_ALARM(tRlcCb,spId, LKW_EVENT_KWU_BND_REQ, LCM_CAUSE_INV_SAP);
585       return RFAILED; 
586    }
587 #endif
588
589    /* Get Sap control block */
590    rlckwuSap = (tRlcCb->genCfg.rlcMode == LKW_RLC_MODE_DL) ?
591             (tRlcCb->u.dlCb->rlcKwuDlSap + spId):
592             (tRlcCb->u.ulCb->rlcKwuUlSap + spId);
593
594    /* Take action based on the current state of the SAP */
595    switch(rlckwuSap->state)
596    {
597       /* SAP is configured but not bound */
598       case RLC_SAP_CFG:
599       case RLC_SAP_UBND:
600       {
601          /* copy bind configuration parameters in sap */
602          rlckwuSap->suId          = suId;
603          rlckwuSap->pst.dstProcId = pst->srcProcId;
604          rlckwuSap->pst.dstEnt    = pst->srcEnt;
605          rlckwuSap->pst.dstInst   = pst->srcInst;
606
607          /* Update the State */
608          rlckwuSap->state = RLC_SAP_BND;
609
610          DU_LOG("\nDEBUG  -->  RLC_UL : RlcUiKwuBndReq: state (%d)", rlckwuSap->state);
611          break;
612       }
613       case RLC_SAP_BND:
614       {
615          /* Sap is already bound check source, destination Entity and Proc Id */
616          if (rlckwuSap->pst.dstProcId != pst->srcProcId ||
617              rlckwuSap->pst.dstEnt != pst->srcEnt ||
618              rlckwuSap->pst.dstInst != pst->srcInst ||
619              rlckwuSap->suId != suId)
620          {
621             RLC_SEND_SAPID_ALARM(tRlcCb,
622                                 spId, 
623                                 LKW_EVENT_KWU_BND_REQ, 
624                                 LCM_CAUSE_INV_PAR_VAL);
625             DU_LOG("\nERROR  -->  RLC_UL : RLC Mode [%d] : KWU SAP already Bound",
626                   tRlcCb->genCfg.rlcMode);
627             RlcUiKwuBndCfm(&(rlckwuSap->pst), rlckwuSap->suId, CM_BND_NOK);
628             return (RFAILED);
629          }
630          break;
631       }
632
633      default:
634       {
635 #if (ERRCLASS & ERRCLS_INT_PAR)
636          DU_LOG("\nERROR  -->  RLC_UL : RLC Mode [%d]:Invalid KWU SAP State in Bind Req",
637                tRlcCb->genCfg.rlcMode);
638          RLC_SEND_SAPID_ALARM(tRlcCb,
639                              spId,
640                              LKW_EVENT_KWU_BND_REQ, 
641                              LCM_CAUSE_INV_STATE);
642 #endif /* ERRCLASS & ERRCLS_INT_PAR */
643          RlcUiKwuBndCfm(&(rlckwuSap->pst), rlckwuSap->suId, CM_BND_NOK);
644          return (RFAILED);
645       }
646    }
647    RlcUiKwuBndCfm(&(rlckwuSap->pst), rlckwuSap->suId, CM_BND_OK);
648    return (ROK);
649
650
651 \f
652 /**
653  * @brief 
654  *    Handler for unbinding the RLC upper layer service user with 
655  *    the RLC layer.
656  *
657  * @details
658  *    This function is used by RLC user to request for unbinding  
659  *    with RLC.This function is called by the KWU interface to 
660  *    unbind with RLC. 
661  *
662  * @param[in] pst     Post structure  
663  * @param[in] spId    Service provider SAP ID 
664  * @param[in] reason  Reason for Unbinding 
665  *
666  * @return  S16
667  *     -# ROK 
668  *     -# RFAILED
669  */
670 S16 RlcUiKwuUbndReq
671 (
672 Pst      *pst,  
673 SpId     spId, 
674 Reason   reason 
675 )
676 {
677    RlcKwuSapCb   *rlckwuSap;   /* KWU SAP control block */
678    RlcCb         *tRlcCb;
679
680 #if (ERRCLASS & ERRCLS_INT_PAR)
681    if ((pst->dstInst >= MAX_RLC_INSTANCES) ||
682        (spId >= (S16) rlcCb[pst->dstInst]->genCfg.maxKwuSaps) ||
683        (spId < 0))
684    {
685       return  (RFAILED);
686    }
687 #endif
688
689    tRlcCb = RLC_GET_RLCCB(pst->dstInst);
690
691    DU_LOG("\nDEBUG  -->  RLC_UL : spId(%d), reason(%d)", 
692                 spId, 
693                 reason);
694
695    /* Get Sap control block */
696    rlckwuSap = (tRlcCb->genCfg.rlcMode == LKW_RLC_MODE_DL) ?
697             (tRlcCb->u.dlCb->rlcKwuDlSap + spId):
698             (tRlcCb->u.ulCb->rlcKwuUlSap + spId);
699
700    rlckwuSap->state = RLC_SAP_CFG;
701
702    return ROK;
703
704
705 /**
706  * @brief Handler for receiving the data(SDU) from upper layer. 
707  *
708  * @details
709  *    This function is used by RLC service user (PDCP) to 
710  *    transfer data (SDU) to RLC.
711  *
712  * @param[in] pst         Post structure  
713  * @param[in] spId        Service Provider SAP ID 
714  * @param[in] datreq  Data Request Information
715  * @param[in] mBuf        Data Buffer (SDU) 
716  *
717  * @return  uint8_t
718  *    -# ROK 
719  *    -# RFAILED
720  */
721 uint8_t rlcProcDlData(Pst *pst, RlcDatReqInfo *datReq, Buffer *mBuf)
722 {
723    uint8_t       ret = ROK;   /* Return Value */
724    RlcDlRbCb     *rbCb;       /* RB Control Block */
725    RlcCb         *tRlcCb;
726
727    DU_LOG("\nDEBUG  -->  RLC_DL : Received DL Data");
728
729 #if (ERRCLASS & ERRCLS_INT_PAR)
730    if(pst->dstInst >= MAX_RLC_INSTANCES)
731    {
732       ODU_PUT_MSG_BUF(mBuf);
733       return RFAILED;
734    }
735 #endif
736
737    tRlcCb = RLC_GET_RLCCB(pst->dstInst);
738
739    /* Fetch the RbCb */
740    rlcDbmFetchDlRbCbByRbId(tRlcCb, &datReq->rlcId, &rbCb);
741    if(!rbCb)
742    {
743       DU_LOG("\nERROR  -->  RLC_DL : CellId[%u]:DL RbId [%d] not found",
744             datReq->rlcId.cellId,datReq->rlcId.rbId);
745       ODU_PUT_MSG_BUF(mBuf);
746
747       return RFAILED;
748    }
749
750    /* Dispatch according to mode of the rbCb */
751    switch (rbCb->mode)
752    {
753       case RLC_MODE_TM:
754       {
755          /* Verify the user */
756          if (pst->srcEnt != ENTNH)
757          {
758             /* kw002.201 Freeing from proper region */
759             RLC_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, datReq, 
760                         sizeof(RlcDatReqInfo));
761             ODU_PUT_MSG_BUF(mBuf);
762              
763             return RFAILED;
764          }
765
766          rlcTmmQSdu(tRlcCb,rbCb, datReq, mBuf);
767          break;
768       }
769       case RLC_MODE_UM:
770       {
771          rlcUmmQSdu(tRlcCb,rbCb, datReq, mBuf);
772          break;
773       }
774       case RLC_MODE_AM:
775       {
776          rlcAmmQSdu(tRlcCb,rbCb, mBuf, datReq);
777          break;
778       }
779       default:
780       {
781          DU_LOG("\nERROR  -->  RLC_DL : Invalid RB Mode");
782          break;
783       }
784    }
785    return ret;
786
787
788 \f
789 /**
790  * @brief 
791  *    Handler for discarding a SDU. 
792  *
793  * @details
794  *    This function is used by RLC AM  and RLC UM entities. 
795  *    This function is called by the service user to discard a particular
796  *    RLC SDU if it is present in the SDU queue of the RB control block 
797  *    and if it is not mapped to any PDU. 
798  *
799  * @param[in] pst            Post structure  
800  * @param[in] spId           Service Provider SAP ID 
801  * @param[in] discSdu        SDU discard Information 
802  *
803  * @return  S16
804  *    -# ROK 
805  *    -# RFAILED
806  */
807 S16 RlcUiKwuDiscSduReq 
808 (
809 Pst              *pst,   
810 SpId             spId,  
811 KwuDiscSduInfo   *discSdu 
812 )
813 {
814    RLC_SHRABL_STATIC_BUF_FREE(pst->region, pst->pool, discSdu, sizeof(KwuDiscSduInfo));
815    return ROK;
816
817
818
819 /**
820  * @brief 
821  *    Handler for Creating, Searching or Deleting SnssnaiTput List. 
822  *
823  * @details
824  *    This function is called whenever a new LC is configured with a snssai.
825  *    This function is called to search for Snssai Node during RLC SDU formation
826  *
827  * @param[in] gCb            RlcCb 
828  * @param[in] snssai         Snssai to be handled 
829  * @param[in] Action         Type of action to be handled(Create,Search,Delete)
830  *
831  * @return  RlcTptPerSnssai
832  *    -# Snssai Node
833  *   
834  */
835 RlcTptPerSnssai* rlcHandleSnssaiTputlist(RlcCb *gCb, Snssai *snssai, RlcSnssaiActionType action, Direction dir)
836 {
837    CmLListCp *snssaiList = NULLP;
838    CmLList  *node = NULLP;
839    RlcTptPerSnssai *snssaiNode = NULLP;
840    bool found = FALSE;
841
842    if(dir == DIR_DL)
843    {
844       snssaiList = gCb->rlcThpt.snssaiTputInfo.dlTputPerSnssaiList;
845       if(action == CREATE)
846       {
847          if(snssaiList == NULLP)
848          {
849             RLC_ALLOC(gCb, gCb->rlcThpt.snssaiTputInfo.dlTputPerSnssaiList, sizeof(CmLListCp));
850             snssaiList = gCb->rlcThpt.snssaiTputInfo.dlTputPerSnssaiList;
851             cmLListInit(snssaiList);
852          }
853       }
854       else
855       {
856          if(snssaiList == NULLP)
857          {
858             DU_LOG("\nERROR --> RLC: SNSSAI DL list doesnt exist!");
859             return NULLP;
860          }
861       }
862    }
863    else if(dir == DIR_UL)
864    {
865       snssaiList = gCb->rlcThpt.snssaiTputInfo.ulTputPerSnssaiList;
866       if(action == CREATE)
867       {
868          if(snssaiList == NULLP)
869          {
870             RLC_ALLOC(gCb, gCb->rlcThpt.snssaiTputInfo.ulTputPerSnssaiList, sizeof(CmLListCp));
871             snssaiList = gCb->rlcThpt.snssaiTputInfo.ulTputPerSnssaiList;
872             cmLListInit(snssaiList);
873          }
874       }
875       else
876       {
877          if(snssaiList == NULLP)
878          {
879             DU_LOG("\nERROR --> RLC: SNSSAI UL list doesnt exist!");
880             return NULLP;
881          }
882       }
883    }
884    else
885    {
886       DU_LOG("\nERROR  -->  RLC : Direction:%d is invalid", dir);
887       return NULLP;
888    }
889
890    node = snssaiList->first;
891
892    /*Traversing the LC LinkList*/
893    while(node)
894    {
895       snssaiNode = (RlcTptPerSnssai *)node->node;
896       if(memcmp(snssaiNode->snssai, snssai, sizeof(Snssai)) == 0)
897       { 
898          DU_LOG("\nDEBUG  --> RLC : SNSSAI found in LL");
899          found = TRUE;
900          break;
901       }
902       node = node->next;
903    }//end of while
904
905    switch(action)
906    {
907       case SEARCH:
908          {
909             if(!found)
910             {
911                snssaiNode = NULLP;
912             }
913             return (snssaiNode);
914          }
915
916       case CREATE:
917          {
918             if(found)
919                return (snssaiNode);
920
921             snssaiNode = NULLP;
922             /*Allocate the List*/
923             RLC_ALLOC(gCb, snssaiNode, sizeof(RlcTptPerSnssai));
924             if(snssaiNode)
925             {
926                RLC_ALLOC(gCb, snssaiNode->snssai, sizeof(Snssai));
927                if(snssaiNode->snssai == NULLP)
928                {
929                  DU_LOG("\nERROR  --> RLC : Allocation of SNSSAI node failed");
930                  return NULLP;
931                }
932                memcpy(snssaiNode->snssai,snssai,sizeof(Snssai));
933                snssaiNode->dataVol = 0;
934             }
935             else
936             {
937                DU_LOG("\nERROR  --> RLC : Allocation of SNSSAI node failed");
938                return NULLP;
939             }
940
941             node = NULLP;
942             RLC_ALLOC(gCb, node, sizeof(CmLList));
943             if(node)
944             {
945                node->node = (PTR)snssaiNode;
946                cmLListAdd2Tail(snssaiList, node);
947             }
948             else
949             {
950                DU_LOG("\nERROR  --> RLC : Allocation of SNSSAI node failed");
951                return NULLP;
952             }
953             DU_LOG("\nDEBUG  --> RLC : SNSSAI node added successfully");
954             return (snssaiNode);
955          }
956
957       case DELETE:
958          {
959             if(found && node)
960             {
961                node = cmLListDelFrm(snssaiList, node);
962                RLC_FREE(gCb, node, sizeof(CmLList));
963                RLC_FREE(gCb, snssaiNode, sizeof(RlcTptPerSnssai));
964                DU_LOG("\nDEBUG  --> RLC : SNSSAI node found and deletion performed");
965
966                if(snssaiList->count == 0)
967                {
968                   RLC_FREE(gCb, snssaiList, sizeof(CmLListCp));
969                   DU_LOG("\nINFO   --> RLC : This SNSSAI was last in the list thus freeing the list also");
970                }
971             }
972             else
973             {
974                DU_LOG("\nERROR  --> RLC : SNSSAI node not found in List thus no deletion performed");
975             }
976             return NULLP;
977          }
978    }
979    return (snssaiNode);
980 }
981
982 /**
983  * @brief 
984  *    Handler for Deleting SnssnaiTput List. 
985  *
986  * @details
987  *    This function is called during Shutdown to remove all the snssai entries
988  *    and deallocate the SNSSAI tput list as well
989  *
990  * @param[in] gCb            RlcCb 
991  *
992  * @return uint_8 (ROK/RFAILED)
993  *   
994  */
995 uint8_t rlcDelTputSnssaiList(RlcCb *gCb, Direction dir)
996 {
997    CmLListCp *snssaiList = NULLP;
998    CmLList  *node = NULLP, *next = NULLP;
999    RlcTptPerSnssai *snssaiNode = NULLP;
1000    if(dir == DIR_DL)
1001    {
1002       snssaiList = gCb->rlcThpt.snssaiTputInfo.dlTputPerSnssaiList;
1003    }
1004    else if(dir == DIR_UL)
1005    {
1006       snssaiList = gCb->rlcThpt.snssaiTputInfo.ulTputPerSnssaiList;
1007    }
1008    else
1009    {
1010       DU_LOG("\nERROR  -->  RLC: Invalid direction:%d",dir);
1011       return RFAILED;
1012    }
1013    if(snssaiList == NULLP)
1014    {
1015       DU_LOG("\nERROR -->  RLC: SnssaiList not exist");
1016       return RFAILED;
1017    }
1018    node = snssaiList->first;
1019
1020    /*Traversing the LC LinkList*/
1021    while(node)
1022    {
1023       snssaiNode = (RlcTptPerSnssai *)node->node;
1024       next = node->next;
1025       node = cmLListDelFrm(snssaiList, node);
1026       RLC_FREE(gCb, node, sizeof(CmLList));
1027       RLC_FREE(gCb, snssaiNode, sizeof(RlcTptPerSnssai));
1028       node = next;
1029    }
1030    if(snssaiList->count == 0)
1031    {
1032       RLC_FREE(gCb, snssaiList, sizeof(CmLListCp));
1033       DU_LOG("\nDEBUG   -->  RLC : This SNSSAI was last in the list thus freeing the list also");
1034    }
1035    return ROK;
1036 }
1037
1038 /**
1039  * @brief 
1040  *    Handler for calculating the Tput for each SNSSAI in Tput list after expiry. 
1041  *
1042  * @details
1043  *    This function is called whenever SNSSAI Tput timer expires and calculate
1044  *    Tput for each Snssai in list
1045  *
1046  * @param[in] SnssaiList     A list of Snssai
1047  *
1048  * @return void 
1049  *   
1050  */
1051 uint8_t rlcCalculateTputPerSnssai(CmLListCp *snssaiList, Direction dir)
1052 {
1053    CmLList  *node = NULLP;
1054    RlcTptPerSnssai *snssaiNode = NULLP;
1055    uint8_t snssaiCnt = 0;
1056
1057    node = snssaiList->first;
1058    if(node == NULLP)
1059    {
1060       DU_LOG("\n No SNSSAI in list");
1061       return(snssaiCnt);
1062    }
1063    /*Traversing the LC LinkList*/
1064    while(node)
1065    {
1066       snssaiNode = (RlcTptPerSnssai *)node->node;
1067       snssaiNode->tpt =  (double)(snssaiNode->dataVol * 8)/(double)(ODU_SNSSAI_THROUGHPUT_PRINT_TIME_INTERVAL * 0.001);
1068      
1069       if(dir == DIR_DL)
1070       {
1071          DU_LOG("\nDEBUG  -->  RLC_DL: SNSSAI(sst:%d,sd [%d,%d, %d]), DL Tpt : %.5lf", snssaiNode->snssai->sst,\
1072                snssaiNode->snssai->sd[0], snssaiNode->snssai->sd[1],snssaiNode->snssai->sd[2] , snssaiNode->tpt);
1073       }
1074       if(dir == DIR_UL)
1075       {
1076          DU_LOG("\nDEBUG  -->  RLC_UL: SNSSAI(sst:%d,sd [%d,%d, %d]), UL Tpt : %.5lf", snssaiNode->snssai->sst,\
1077                snssaiNode->snssai->sd[0], snssaiNode->snssai->sd[1],snssaiNode->snssai->sd[2] , snssaiNode->tpt);
1078       }
1079
1080       snssaiNode->dataVol = 0;
1081       node = node->next;
1082       snssaiCnt++;
1083    }
1084    return(snssaiCnt);
1085 }
1086
1087 /********************************************************************30**
1088          End of file
1089 **********************************************************************/