[Epic-ID: ODUHIGH-510][Task-ID: ODUHIGH-512] Implementation of E2 setup failure
[o-du/l2.git] / src / du_app / du_egtp.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 /* This file contains all EGTP related functionality */
20 #include "common_def.h"
21 #include "du_tmr.h"
22 #include "lrg.h"
23 #include "lkw.x"
24 #include "lrg.x"
25 #include "cm_inet.h"
26 #include "legtp.h"
27 #include "cm_inet.x"
28 #include "du_app_mac_inf.h"
29 #include "du_e2ap_mgr.h"
30 #include "du_cfg.h"
31 #include "du_egtp.h"
32 #include "du_app_rlc_inf.h"
33 #include "du_mgr.h"
34 #include "du_utils.h"
35
36
37 /**************************************************************************
38  * @brief Task Initiation callback function. 
39  *
40  * @details
41  *
42  *     Function : egtpActvInit 
43  *    
44  *     Functionality:
45  *             This function is supplied as one of parameters during EGTP's 
46  *             task registration. SSI will invoke this function once, after
47  *             it creates and attaches this TAPA Task to a system task.
48  *     
49  * @param[in]  Ent entity, the entity ID of this task.     
50  * @param[in]  Inst inst, the instance ID of this task.
51  * @param[in]  Region region, the region ID registered for memory 
52  *              usage of this task.
53  * @param[in]  Reason reason.
54  * @return ROK     - success
55  *         RFAILED - failure
56  ***************************************************************************/
57 uint8_t egtpActvInit(Ent entity, Inst inst, Region region, Reason reason)
58 {
59   DU_LOG("\n\nDEBUG   -->  EGTP : Initializing");
60
61   memset (&egtpCb, 0, sizeof(EgtpGlobalCb));
62   protType = CM_INET_PROTO_UDP;
63   gDlDataRcvdCnt = 0;
64
65   return ROK;
66 }
67
68 #ifdef CALL_FLOW_DEBUG_LOG
69 /**************************************************************************
70 * @brief Function prints the src dest and msg reached to egtp.
71 *
72 * @details
73 *
74 *      Function : callFlowEgtpActvTsk 
75 *
76 *      Functionality:
77 *           Function prints the src dest and msg reached to egtp.
78 *
79 * @param[in]  Pst     *pst, Post structure of the primitive.
80 *
81 * @return void 
82 *
83 ***************************************************************************/
84
85 void callFlowEgtpActvTsk(Pst *pst)
86 {
87
88    char sourceTask[50];
89    char destTask[50]="ENTEGTP";
90    char message[100];
91
92    switch(pst->srcEnt)
93    {
94       case ENTDUAPP:
95          {
96             strcpy(sourceTask,"ENTDUAPP");
97             switch(pst->event)
98             {
99                case EVTCFGREQ:
100                   {
101                      strcpy(message,"EVTCFGREQ");
102                      break;
103                   }
104                case EVTSRVOPENREQ:
105                   {
106                      strcpy(message,"EVTSRVOPENREQ");
107                      break;
108                   }
109                case EVTTNLMGMTREQ:
110                   {
111                      strcpy(message,"EVTTNLMGMTREQ");
112                      break;
113                   }
114                default:
115                   {
116                      strcpy(message,"Invalid Event");
117                      break;
118                   }
119             }
120             break;
121          }
122       case ENTEGTP:
123          {
124             strcpy(sourceTask,"ENTEGTP");
125             switch(pst->event)
126             {
127                case EVTSTARTPOLL:
128                   {
129                      strcpy(message,"EVTSTARTPOLL");
130                      break;
131                   }
132                default:
133                   {
134                      strcpy(message,"Invalid Event");
135                      break;
136                   }
137             }
138             break;
139          }
140       case ENTRLC:
141          {
142             strcpy(sourceTask,"ENTRLC");
143             switch(pst->event)
144             {
145                case EVTDATIND:
146                   {
147                      strcpy(message,"EVTDATIND");
148                      break;
149                   }
150                default:
151                   {
152                      strcpy(message,"Invalid Event");
153                      break;
154                   }
155             }
156             break;
157          }
158       default:
159          {
160              strcpy(sourceTask,"Invalid Source Entity Id");
161          }
162    }
163    DU_LOG("\nCall Flow: %s -> %s : %s\n", sourceTask, destTask, message);
164 }
165 #endif
166
167 /**************************************************************************
168  * @brief Task Activation callback function. 
169  *
170  * @details
171  *
172  *      Function : egtpActvTsk 
173  * 
174  *      Functionality:
175  *           This function handles all EGTP messages received
176  *           This API is registered with SSI during the 
177  *           Task Registration of DU APP.
178  *     
179  * @param[in]  Pst     *pst, Post structure of the primitive.     
180  * @param[in]  Buffer *mBuf, Packed primitive parameters in the
181  *  buffer.
182  * @return ROK     - success
183  *         RFAILED - failure
184  *
185  ***************************************************************************/
186 uint8_t egtpActvTsk(Pst *pst, Buffer *mBuf)
187 {
188    uint8_t ret = ROK;
189   
190 #ifdef CALL_FLOW_DEBUG_LOG
191    callFlowEgtpActvTsk(pst);
192 #endif
193
194    switch(pst->srcEnt)
195    {
196       case ENTDUAPP:
197       {
198          switch(pst->event)
199          {
200             case EVTCFGREQ:
201             {
202                ret = unpackEgtpCfgReq(egtpCfgReq, pst, mBuf);
203                break;
204             }
205             case EVTSRVOPENREQ:
206             {
207                ret = unpackEgtpSrvOpenReq(egtpSrvOpenReq, pst, mBuf);
208                break;
209             }
210             case EVTTNLMGMTREQ:
211             {
212                ret = unpackEgtpTnlMgmtReq(egtpTnlMgmtReq, pst, mBuf);
213                break;
214             }
215             default:
216             {
217                DU_LOG("\nERROR  -->  EGTP : Invalid event %d", pst->event);
218                ODU_PUT_MSG_BUF(mBuf);
219                ret = RFAILED;
220             }
221          }
222          break;
223       }
224       case ENTEGTP:
225       {
226          switch(pst->event)
227          {
228             case EVTSTARTPOLL:
229             {
230                DU_LOG("\nDEBUG   -->  EGTP : Starting Socket Polling");
231                egtpRecvMsg();
232                ODU_PUT_MSG_BUF(mBuf);
233                break;
234             }
235             default:
236             {
237                DU_LOG("\nERROR  -->  EGTP : Invalid event %d", pst->event);
238                ODU_PUT_MSG_BUF(mBuf);
239                ret = RFAILED;
240             }
241         }
242         break;
243       }
244       case ENTRLC:
245       {
246          switch(pst->event)
247          {
248             case EVTDATIND:
249             {
250                //TODO
251                break;
252             }
253             default:
254             {
255                DU_LOG("\nERROR  -->  EGTP : Invalid event %d", pst->event);
256                ret = RFAILED;
257             }
258          }
259          break;
260       }
261       default:
262       {
263          DU_LOG("\nERROR  -->  EGTP : Invalid source entity %d", pst->srcEnt);
264          ret = RFAILED;
265       }
266    }
267    ODU_EXIT_TASK();
268    return ret;
269 }
270
271 /**************************************************************************
272  * @brief EGTP server configuration 
273  *
274  * @details
275  *
276  *      Function : egtpCfgReq
277  * 
278  *      Functionality:
279  *           This function handles EGTP configuration request.
280  *     
281  * @return ROK     - success
282  *         RFAILED - failure
283  *
284  * ***********************************************************************/
285 uint8_t egtpCfgReq(Pst *pst, EgtpConfig egtpCfg)
286 {
287    uint8_t  ret;          /* Return value */
288    Pst      rspPst;      /* Response Pst structure */
289    CmStatus cfgCfm; /* Configuration Confirm */
290
291    memcpy(&egtpCb.egtpCfg, &egtpCfg, sizeof(EgtpConfig));
292
293    egtpCb.localAddr.address = CM_INET_NTOH_UINT32(egtpCb.egtpCfg.localIp.ipV4Addr);
294    egtpCb.localAddr.port = egtpCb.egtpCfg.localPort;
295
296    egtpCb.dstCb.dstAddr.address = CM_INET_NTOH_UINT32(egtpCb.egtpCfg.destIp.ipV4Addr);
297    egtpCb.dstCb.dstAddr.port = egtpCb.egtpCfg.destPort;
298    egtpCb.dstCb.numTunn = 0;
299
300    ret = cmHashListInit(&(egtpCb.dstCb.teIdLst), 1024, sizeof(EgtpTeIdCb), FALSE, CM_HASH_KEYTYPE_UINT32_MOD, DU_APP_MEM_REGION, DU_POOL);
301
302    if(ret != ROK)
303    {
304       DU_LOG("\nERROR  -->  EGTP : TeId hash list initialization failed");
305       cfgCfm.status = LCM_PRIM_NOK;
306       cfgCfm.reason = LCM_REASON_HASHING_FAILED;
307    }
308    else
309    {
310       DU_LOG("\nDEBUG   -->  EGTP : EGTP configuration successful");
311       cfgCfm.status = LCM_PRIM_OK;
312       cfgCfm.reason = LCM_REASON_NOT_APPL;
313    }
314
315    /* Fill response Pst */
316    egtpFillRspPst(pst, &rspPst);
317    rspPst.event = EVTCFGCFM;
318
319    packEgtpCfgCfm(&rspPst, cfgCfm);
320
321    return ROK;
322 }
323
324 /**************************************************************************
325  * @brief Fills post structure to send response
326  *
327  * @details
328  *
329  *      Function : egtpFillRspPst
330  * 
331  *      Functionality:
332  *           Fills post struture to send response
333  *     
334  * @return ROK     - success
335  *         RFAILED - failure
336  *
337  *
338  * ***********************************************************************/
339 uint8_t egtpFillRspPst(Pst *pst, Pst *rspPst)
340 {
341
342    memset(rspPst, 0, sizeof(Pst));
343    rspPst->srcEnt = pst->dstEnt;
344    rspPst->srcInst = pst->dstInst;
345    rspPst->srcProcId = pst->dstProcId;
346    rspPst->dstEnt = pst->srcEnt;
347    rspPst->dstInst = pst->srcInst;
348    rspPst->dstProcId = pst->srcProcId;
349    rspPst->selector = ODU_SELECTOR_LC;
350    rspPst->pool= DU_POOL;
351     
352    return ROK;
353 }
354
355 /**************************************************************************
356  * @brief EGTP server open request 
357  *
358  * @details
359  *
360  *      Function : egtpSrvOpenReq
361  * 
362  *      Functionality:
363  *           This function handles EGTP open server request.
364  *           It opens udp socket to receive/send msgs.
365  *     
366  * @param[in]  Pst *pst, post structure
367  * @return ROK     - success
368  *         RFAILED - failure
369  *
370  ***************************************************************************/
371
372 uint8_t egtpSrvOpenReq(Pst *pst)
373 {
374
375    uint8_t  ret;       /* Return value */
376    Pst      rspPst;    /* Response Pst structure */ 
377    Pst      egtpPst;   /* Self post */
378    CmStatus cfm;       /* Confirmation status */
379    uint8_t  sockType;  /* Socket type */
380
381    DU_LOG("\nDEBUG  -->  EGTP : Received EGTP open server request");
382  
383    sockType = CM_INET_DGRAM;
384    ret = egtpSrvOpenPrc(sockType);
385    /* Opening and Binding receiver socket */
386    if(ret != ROK)
387    {
388       DU_LOG("\nERROR  -->  EGTP : Failed while opening receiver transport server");
389       return ret;
390    }
391
392    DU_LOG("\nDEBUG   -->  EGTP : Socket [%d] is open", egtpCb.sockFd.fd);
393
394    /* Start Socket polling */
395    memset(&egtpPst, 0, sizeof(egtpPst));
396    egtpPst.srcEnt = (Ent)ENTEGTP;
397    egtpPst.srcInst = (Inst)EGTP_INST;
398    egtpPst.srcProcId = DU_PROC;
399    egtpPst.dstEnt = (Ent)ENTEGTP;
400    egtpPst.dstInst = (Inst)EGTP_INST;
401    egtpPst.dstProcId = DU_PROC;
402    egtpPst.event = EVTSTARTPOLL;
403    egtpPst.selector = ODU_SELECTOR_LC;
404    egtpPst.pool= DU_POOL;
405    packEgtpStartPollingReq(&egtpPst);
406
407    /* Filling and sending response */
408    cfm.status = LCM_PRIM_OK;
409    cfm.reason = LCM_REASON_NOT_APPL;
410
411    egtpFillRspPst(pst, &rspPst);
412    rspPst.event = EVTSRVOPENCFM;
413    packEgtpSrvOpenCfm(&rspPst, cfm);
414
415    return ret;
416 }
417
418 /*******************************************************************
419  *
420  * @brief Processing Sever open request
421  *
422  * @details
423  *
424  *    Function : egtpSrvOpenPrc
425  *
426  *    Functionality:
427  *      
428  *
429  * @params[in] 
430  * @return ROK     - success
431  *         RFAILED - failure
432  *
433  * ****************************************************************/
434
435 uint8_t egtpSrvOpenPrc(uint8_t sockType)
436 {
437    S8 ret=ROK;
438    ret = cmInetSocket(sockType, &(egtpCb.sockFd), protType); 
439         if(ret != ROK)
440    {  
441       DU_LOG("\nERROR  -->  EGTP : Failed to open UDP socket");
442       return ret;
443    }
444    ret = cmInetBind(&(egtpCb.sockFd), &(egtpCb.localAddr));  
445    if(ret != ROK)
446    {  
447       DU_LOG("\nERROR  -->  EGTP : Failed to bind socket");
448       return ret;
449    }
450    
451    return ret;
452 }
453
454 /**************************************************************************
455  * @brief EGTP tunnel management request
456  *
457  * @details
458  *
459  *      Function : egtpTnlMgmtReq
460  * 
461  *      Functionality:
462  *           This function handles EGTP tunnel managament request
463  *     
464  * @param[in] Tunnel Eveny structure
465  * @return ROK     - success
466  *         RFAILED - failure
467  *
468  
469  * ***************************************************************************/
470 uint8_t egtpTnlMgmtReq(Pst *pst, EgtpTnlEvt tnlEvt)
471 {
472    uint8_t ret = ROK;
473
474 #ifdef CALL_FLOW_DEBUG_LOG
475    DU_LOG("\nCall Flow: ENTDUAPP -> ENTEGTP : TNL_MGMT\n");
476 #endif
477
478    DU_LOG("\nDEBUG   -->  EGTP : Received tunnel management request");
479    switch(tnlEvt.action)
480    {
481       case EGTP_TNL_MGMT_ADD:
482       {
483          ret = egtpTnlAdd(tnlEvt);
484          break;
485       }
486       case EGTP_TNL_MGMT_MOD:
487       {
488          ret = egtpTnlMod(tnlEvt);
489          break;
490       }
491       case EGTP_TNL_MGMT_DEL:
492       {
493          ret = egtpTnlDel(tnlEvt);
494          break;
495       }
496       default:
497       {
498          DU_LOG("\nERROR  -->  EGTP : Invalid tunnel management action[%d]", tnlEvt.action);
499          ret = LCM_REASON_INVALID_ACTION;
500       }
501    }
502
503    if(ret == ROK)
504    {
505       tnlEvt.cfmStatus.status = LCM_PRIM_OK;
506       tnlEvt.cfmStatus.reason = LCM_REASON_NOT_APPL;
507    }
508    else
509    {
510       tnlEvt.cfmStatus.status = LCM_PRIM_NOK;
511       tnlEvt.cfmStatus.reason = ret;
512    }
513
514    DU_LOG("\nDEBUG   -->  EGTP : Sending Tunnel management confirmation");
515    duHdlEgtpTnlMgmtCfm(tnlEvt);
516
517    return ret;
518 }
519
520 /**************************************************************************
521  * @brief EGTP tunnel addition
522  *
523  * @details
524  *
525  *      Function : egtpTnlAdd
526  * 
527  *      Functionality:
528  *           This function handles EGTP tunnel addition
529  *     
530  * @param[in]  Tunnel Event structure
531  * @return ROK     - success
532  *         RFAILED - failure
533  *
534  * ***************************************************************************/
535 uint8_t egtpTnlAdd(EgtpTnlEvt tnlEvt)
536 {
537    uint8_t    ret;
538    EgtpTeIdCb *teidCb;    /* Tunnel endpoint control block */
539    EgtpMsgHdr preDefHdr; /* pre-define header for this tunnel */
540
541    DU_LOG("\nINFO   -->  EGTP : Tunnel addition : LocalTeid[%d] Remote Teid[%d]", tnlEvt.lclTeid, tnlEvt.remTeid);
542
543    DU_ALLOC(teidCb, sizeof(EgtpTeIdCb));
544    if(teidCb == NULLP)
545    {
546       DU_LOG("\nERROR  -->  EGTP : Memory allocation failed");
547       return LCM_REASON_MEM_NOAVAIL;
548    }
549
550    memset(teidCb, 0, sizeof(EgtpTeIdCb));
551    teidCb->teId = tnlEvt.lclTeid;
552    teidCb->remTeId = tnlEvt.remTeid;
553
554    ret = cmHashListInsert(&(egtpCb.dstCb.teIdLst), (PTR)teidCb, (uint8_t *)&(teidCb->teId), sizeof(uint32_t));
555    if(ret != ROK)
556    {
557       DU_LOG("\nERROR  -->  EGTP : Failed to insert in hash list");
558       DU_FREE(teidCb, sizeof(EgtpTeIdCb));
559       return LCM_REASON_HASHING_FAILED;
560    }
561    egtpCb.dstCb.numTunn++;
562
563    /* Encoding pre-defined header */
564    memset(&preDefHdr, 0, sizeof(EgtpMsgHdr));
565    preDefHdr.msgType = EGTPU_MSG_GPDU;
566    preDefHdr.teId = teidCb->remTeId;
567    preDefHdr.extHdr.pdcpNmb.pres = FALSE;
568    preDefHdr.extHdr.udpPort.pres = FALSE;
569    preDefHdr.nPdu.pres = FALSE;
570   
571    egtpEncodeHdr((uint8_t *)teidCb->preEncodedHdr.hdr, &preDefHdr, &(teidCb->preEncodedHdr.cnt));
572
573    return ROK;
574 } /* egtpTnlAdd */
575
576 /**************************************************************************
577  * @brief EGTP tunnel modification
578  *
579  * @details
580  *
581  *      Function : egtpTnlMod
582  * 
583  *      Functionality:
584  *           This function handles EGTP tunnel modification
585  *     
586  * @param[in]  Tunnel Event structure
587  * @return ROK     - success
588  *         RFAILED - failure
589  * 
590  * ***************************************************************************/
591 uint8_t egtpTnlMod(EgtpTnlEvt tnlEvt)
592 {
593    EgtpTeIdCb     *teidCb = NULLP;
594
595    DU_LOG("\nINFO   -->  EGTP : Tunnel modification : LocalTeid[%d] Remote Teid[%d]", tnlEvt.lclTeid, tnlEvt.remTeid);
596
597    cmHashListFind(&(egtpCb.dstCb.teIdLst), (uint8_t *)&(tnlEvt.lclTeid), sizeof(uint32_t), 0, (PTR *)&teidCb);
598    if(teidCb == NULLP)
599    {
600       DU_LOG("\nERROR  -->  EGTP : Tunnel id not found");
601       return RFAILED;
602    }  
603    teidCb->teId = tnlEvt.remTeid;
604    teidCb->remTeId = tnlEvt.remTeid;
605    return ROK;
606 }
607
608 /**************************************************************************
609  * @brief EGTP tunnel deletion
610  *
611  * @details
612  *
613  *     Function : egtpTnlDel
614  * 
615  *     Functionality:
616  *         This function handles EGTP tunnel deletion
617  *    
618  * @param[in]  Tunnel Event structure
619  * @return ROK     - success
620  *         RFAILED - failure
621  * 
622  * ***************************************************************************/
623 uint8_t egtpTnlDel(EgtpTnlEvt tnlEvt)
624 {
625    EgtpTeIdCb     *teidCb = NULLP;
626
627    DU_LOG("\nINFO   -->  EGTP : Tunnel deletion : Local Teid[%d] Remote Teid[%d]", tnlEvt.lclTeid, tnlEvt.remTeid);
628    
629    cmHashListFind(&(egtpCb.dstCb.teIdLst), (uint8_t *)&(tnlEvt.lclTeid), sizeof(uint32_t), 0, (PTR *)&teidCb);
630    if(teidCb == NULLP)
631    {
632       DU_LOG("\nERROR  -->  EGTP : Tunnel id[%d] not configured", tnlEvt.lclTeid);
633       return LCM_REASON_INVALID_PAR_VAL;
634    } 
635
636    cmHashListDelete(&(egtpCb.dstCb.teIdLst), (PTR)teidCb);
637    DU_FREE(teidCb, sizeof(EgtpTeIdCb));
638    egtpCb.dstCb.numTunn--;
639    return ROK;
640 }
641
642 /*******************************************************************
643  *
644  * @brief Handles data indication
645  *
646  * @details
647  *
648  *    Function : EgtpHdlDatInd
649  *
650  *    Functionality:
651  *      Handles incoming data from peer to be passed 
652  *      on from DU to CU
653  *
654  * @params[in] 
655  * @return ROK     - success
656  *         RFAILED - failure
657  *
658  * ****************************************************************/
659 uint8_t egtpHdlDatInd(EgtpMsg egtpMsg)
660 {
661    EgtpTeIdCb  *teidCb = NULLP;
662    uint16_t    tPduSize;
663    uint8_t     hdrLen;
664    uint32_t    msgLen;
665    EgtpMsgHdr  *msgHdr;
666
667 #ifdef CALL_FLOW_DEBUG_LOG
668    DU_LOG("\nCall Flow: ENTDUAPP -> ENTEGTP : DATA_INDICATION\n");
669 #endif
670    
671    DU_LOG("\nDEBUG  -->  EGTP : Received Data Indication");
672
673    cmHashListFind(&(egtpCb.dstCb.teIdLst), (uint8_t *)&(egtpMsg.msgHdr.teId), sizeof(uint32_t), 0, (PTR *)&teidCb);
674    if(teidCb == NULLP)
675    {
676       DU_LOG("\nERROR  -->  EGTP : Tunnel id[%d] not configured", egtpMsg.msgHdr.teId);
677       return LCM_REASON_INVALID_PAR_VAL;
678    }
679    
680    msgHdr = &(egtpMsg.msgHdr);
681
682    hdrLen = teidCb->preEncodedHdr.cnt;
683
684    if(msgHdr->extHdr.pdcpNmb.pres)
685    {
686       teidCb->preEncodedHdr.hdr[EGTP_MAX_HDR_LEN - 1] |= EGTP_MASK_BIT3;
687       teidCb->preEncodedHdr.hdr[hdrLen] = EGTP_EXT_HDR_PDCP_TYPE;
688       teidCb->preEncodedHdr.hdr[--hdrLen] = 1;
689       teidCb->preEncodedHdr.hdr[--hdrLen] = GetHiByte(msgHdr->extHdr.pdcpNmb.val);
690       teidCb->preEncodedHdr.hdr[--hdrLen] = GetLoByte(msgHdr->extHdr.pdcpNmb.val);
691       teidCb->preEncodedHdr.hdr[--hdrLen] = 0;
692    }
693    else
694    {
695       teidCb->preEncodedHdr.hdr[EGTP_MAX_HDR_LEN - 1] &= ~(EGTP_MASK_BIT3);
696    }
697
698    ODU_GET_MSG_LEN(egtpMsg.msg, (int16_t *)&tPduSize);
699
700    /*Adjust the header to fill the correct length*/
701    msgLen = tPduSize +  (EGTP_MAX_HDR_LEN - hdrLen) - 0x08;
702
703    /***********************************************
704     * Fill the length field of the message header *
705     ***********************************************/
706    teidCb->preEncodedHdr.hdr[EGTP_MAX_HDR_LEN - 3] = (uint8_t)GetHiByte(msgLen);
707    teidCb->preEncodedHdr.hdr[EGTP_MAX_HDR_LEN - 4] = (uint8_t)GetLoByte(msgLen);
708
709    /*Update the sequence number*/
710    if(egtpMsg.msgHdr.seqNum.pres)
711    {
712       teidCb->preEncodedHdr.hdr[EGTP_MAX_HDR_LEN - 1] |= (EGTP_MASK_BIT2);
713       teidCb->preEncodedHdr.hdr[EGTP_MAX_HDR_LEN - 9] = (uint8_t)GetHiByte(egtpMsg.msgHdr.seqNum.val);
714       teidCb->preEncodedHdr.hdr[EGTP_MAX_HDR_LEN - 10] = (uint8_t)GetLoByte(egtpMsg.msgHdr.seqNum.val);
715    }
716    else
717    {
718       teidCb->preEncodedHdr.hdr[EGTP_MAX_HDR_LEN - 1] &= ~(EGTP_MASK_BIT2);
719    }
720
721    DU_LOG("\nDEBUG  -->  EGTP : UL Data buffer before encoding header");
722    ODU_PRINT_MSG(egtpMsg.msg, 0, 0);
723
724    ODU_ADD_PRE_MSG_MULT(&teidCb->preEncodedHdr.hdr[hdrLen], (EGTP_MAX_HDR_LEN - hdrLen), egtpMsg.msg);
725
726
727    DU_LOG("\nDEBUG  -->  EGTP : UL Data buffer after encoding header");
728    ODU_PRINT_MSG(egtpMsg.msg, 0, 0);
729
730    /* Send over UDP */
731    egtpSendMsg(egtpMsg.msg);
732    ODU_PUT_MSG_BUF(egtpMsg.msg);
733
734    return ROK;
735 }/* EgtpHdlDatInd */
736
737 /*******************************************************************
738  *
739  * @brief Encodes outgoing message
740  *
741  * @details
742  *
743  *    Function : egtpEncodeMsg
744  *
745  *    Functionality:
746  *       Encodes EGTP message to be sent
747  *
748  * @params[in] EGTP message
749  *             Message Buffer 
750  * @return ROK     - success
751  *         RFAILED - failure
752  *
753  * ****************************************************************/
754 uint8_t egtpEncodeHdr(uint8_t *preEncodedHdr, EgtpMsgHdr *preDefHdr, uint8_t *hdrIdx)
755 {
756    uint8_t    tmpByte = 0;                 /* Stores one byte of data for enc */
757    uint8_t    cnt     = EGTP_MAX_HDR_LEN;  /* Stores the position */
758    bool       extPres = FALSE;             /* Flag for indication of S, E or P presense flag */
759    uint16_t   nwWord = 0;
760    
761    /* Encoding header */
762    tmpByte |= EGTP_MASK_BIT6;   /* Setting 6th LSB of 1st byte as version */
763    tmpByte |= EGTP_MASK_BIT5;   /* Setting 5th LSB of 1st byte as protocol type */
764
765    if(preDefHdr->extHdr.udpPort.pres || preDefHdr->extHdr.pdcpNmb.pres)
766    {
767       tmpByte |= EGTP_MASK_BIT3;  /* Setting 3rd LSB of 1st byte if Extension heaeder is present */
768    }
769
770    if(preDefHdr->seqNum.pres)
771    {
772       tmpByte |= EGTP_MASK_BIT2;
773    }
774
775    if(preDefHdr->nPdu.pres)
776    {
777       tmpByte |= EGTP_MASK_BIT1;
778    }
779
780    if((tmpByte & EGTP_MASK_BIT1) || (tmpByte & EGTP_MASK_BIT2)||(tmpByte & EGTP_MASK_BIT3))
781    {
782       extPres = TRUE;
783    }
784
785    preEncodedHdr[--cnt] = tmpByte;
786    preEncodedHdr[--cnt] = preDefHdr->msgType;
787
788    /* Encode Tunnel endpoint */
789    preEncodedHdr[--cnt] = 0;
790    preEncodedHdr[--cnt] = 0;
791    nwWord = (uint16_t)(GetHiWord(preDefHdr->teId));
792    preEncodedHdr[--cnt] = (uint8_t)(GetHiByte(nwWord));
793    preEncodedHdr[--cnt] = (uint8_t)(GetLoByte(nwWord));
794    nwWord = (uint16_t)(GetLoWord(preDefHdr->teId));
795    preEncodedHdr[--cnt] = (uint8_t)(GetHiByte(nwWord));
796    preEncodedHdr[--cnt] = (uint8_t)(GetLoByte(nwWord));
797
798    /* Encode sequence number */
799    if(preDefHdr->seqNum.pres)
800    {
801       preEncodedHdr[--cnt] = GetHiByte(preDefHdr->seqNum.val);
802       preEncodedHdr[--cnt] = GetLoByte(preDefHdr->seqNum.val);
803    }
804    else if(extPres)
805    {
806       preEncodedHdr[--cnt] = 0;
807       preEncodedHdr[--cnt] = 0;
808    }
809
810    /* Encode nPdu number */
811    if(preDefHdr->nPdu.pres)
812    {
813       preEncodedHdr[--cnt] = preDefHdr->nPdu.val;
814    }
815    else if(extPres)
816    {
817       preEncodedHdr[--cnt] = 0;
818    }
819
820    if(preDefHdr->extHdr.udpPort.pres)
821    {
822       preEncodedHdr[--cnt] = EGTP_EXT_HDR_UDP_TYPE;
823       preEncodedHdr[--cnt] = 1;
824       preEncodedHdr[--cnt] = GetHiByte(preDefHdr->extHdr.udpPort.val);
825       preEncodedHdr[--cnt] = GetLoByte(preDefHdr->extHdr.udpPort.val);
826    }
827  
828    if(preDefHdr->extHdr.pdcpNmb.pres)
829    {
830       preEncodedHdr[--cnt] = EGTP_EXT_HDR_PDCP_TYPE;
831       preEncodedHdr[--cnt] = 1;
832       preEncodedHdr[--cnt] = GetHiByte(preDefHdr->extHdr.pdcpNmb.val);
833       preEncodedHdr[--cnt] = GetLoByte(preDefHdr->extHdr.pdcpNmb.val);
834    }
835  
836    if(tmpByte & EGTP_MASK_BIT3)
837    {
838       preEncodedHdr[--cnt] = 0;
839    }
840    else if(extPres)
841    {
842       preEncodedHdr[--cnt] = 0;
843    }
844
845    *hdrIdx = cnt;
846    return ROK;
847 } /* egtpEncodeHdr */
848
849 /*******************************************************************
850  *
851  * @brief Sends message over UDP
852  *
853  * @details
854  *
855  *    Function : egtpSendMsg
856  *
857  *    Functionality:
858  *           Sends message over UDP
859  *
860  * @params[in] Message Buffer 
861  * @return ROK     - success
862  *         RFAILED - failure
863  *
864  * ****************************************************************/
865 uint8_t egtpSendMsg(Buffer *mBuf)
866 {
867    uint8_t        ret;
868    uint16_t       txLen;
869    CmInetMemInfo  info;
870    static uint64_t numDataSent = 0;
871
872    info.region = DU_APP_MEM_REGION;
873    info.pool = DU_POOL;
874
875    ret = cmInetSendMsg(&egtpCb.sockFd, &egtpCb.dstCb.dstAddr, &info, mBuf, (int16_t *)&txLen, CM_INET_NO_FLAG);
876    if(ret != ROK && ret != RWOULDBLOCK)
877    {
878       DU_LOG("\nERROR  -->  EGTP : Failed sending the message");
879       return RFAILED;
880    }
881    else
882    {
883       DU_LOG("\nDEBUG -->  EGTP : Sent UL Message [%ld]", numDataSent+1);
884       numDataSent++;
885    }
886
887    return ROK;
888 }
889
890 /*******************************************************************
891  *
892  * @brief Receives EGTP message from UDP socket 
893  *
894  * @details
895  *
896  *    Function : egtpRecvMsg
897  *
898  *    Functionality:
899  *      Receive incoming messages from UDP socket
900  *
901  * @params[in] 
902  * @return ROK     - success
903  *         RFAILED - failure
904  *
905  * ****************************************************************/
906
907 uint8_t egtpRecvMsg()
908 {
909    uint8_t        ret;           /* Return value */
910    uint16_t       bufLen;        /* Length of received buffer */
911    Buffer         *recvBuf;      /* Received buffer */
912    CmInetMemInfo  memInfo;       /* Buffer allocation info */
913
914    memInfo.region = DU_APP_MEM_REGION;
915    memInfo.pool   = DU_POOL;
916     
917    while(true)
918    {
919       bufLen = -1;
920       ret = cmInetRecvMsg(&egtpCb.sockFd, &egtpCb.dstCb.dstAddr, &memInfo, &recvBuf, (int16_t *)&bufLen, CM_INET_NO_FLAG);
921       if(ret == ROK && recvBuf != NULLP)
922       {  
923          DU_LOG("\nDEBUG  -->  EGTP : Received DL Message[%ld]\n", gDlDataRcvdCnt + 1);
924          //ODU_PRINT_MSG(recvBuf, 0 ,0);
925          egtpHdlRecvData(recvBuf);
926          gDlDataRcvdCnt++;
927          
928       }
929    }
930    
931    return ROK;
932 }
933
934 /*******************************************************************
935  *
936  * @brief Handles DL User data received from CU
937  *
938  * @details
939  *
940  *    Function : egtpHdlRecvData
941  *
942  *    Functionality: Handles DL User data received from CU
943  *
944  * @params[in] DL Usre data buffer
945  * @return ROK     - success
946  *         RFAILED - failure
947  *
948  * ****************************************************************/
949 uint8_t egtpHdlRecvData(Buffer *mBuf)
950 {
951    EgtpMsg  egtpMsg;
952
953    /* Decode EGTP header */
954    egtpDecodeHdr(mBuf, &egtpMsg);
955
956    /* TODO : Send received message to RLC */
957    duHdlEgtpDlData(&egtpMsg);
958
959    return ROK;
960 }
961
962 /*******************************************************************
963  *
964  * @brief Decodes EGTP header from DL User data
965  *
966  * @details
967  *
968  *    Function : egtpDecodeHdr
969  *
970  *    Functionality: Decodes EGTP header from DL User data
971  *
972  * @params[in] 
973  * @return ROK     - success
974  *         RFAILED - failure
975  *
976  * ****************************************************************/
977 uint8_t egtpDecodeHdr(Buffer *mBuf, EgtpMsg  *egtpMsg)
978 {
979    uint8_t    tmpByte[5];         /* Holds 5 byte of data after Decoding */
980    uint8_t    version = 0;         /* Holds the version type, decoded */
981    uint16_t   msgLen  = 0;         /* Holds the msgLen from the Hdr */
982    uint16_t   bufLen  = 0;         /* Holds the total buffer length */
983    uint8_t    extHdrType = 0;       /* Holds the Extension hdr type */
984    uint8_t    extHdrLen = 0;        /* Extension hdr length */
985    bool       extPres = FALSE;      /* Flag for indication of S, E or P presense flag */
986  
987    ODU_GET_MSG_LEN(mBuf, (int16_t *)&bufLen);
988  
989    /* Decode first byte and storing in temporary variable */
990    ODU_REM_PRE_MSG(&tmpByte[0], mBuf);
991
992    /* Extracting version fro 1st byte */
993    version = tmpByte[0] >> 5;
994    
995    //DU_LOG("\nDEBUG   -->  EGTP : Version %d", version);
996  
997    /* Decode message type */
998    ODU_REM_PRE_MSG((Data*)&(egtpMsg->msgHdr.msgType), mBuf);
999    //DU_LOG("\nDEBUG   -->  EGTP : msgType %d", egtpMsg->msgHdr.msgType);
1000
1001    /****************************************************************************
1002     * Message length param is 2 bytes. So decode next 2 bytes from msg hdr and
1003     * performing OR operation on these two bytes to calculate message length 
1004     ***************************************************************************/
1005    ODU_REM_PRE_MSG(&tmpByte[1], mBuf);
1006    ODU_REM_PRE_MSG(&tmpByte[2], mBuf);
1007    msgLen = (tmpByte[1] << 8) | tmpByte[2];
1008    UNUSED(msgLen);
1009    UNUSED(version);
1010    //DU_LOG("\nDEBUG   -->  EGTP : msgLen %d", msgLen);
1011
1012
1013    /****************************************************************************
1014     * Tunnel id param is 4 bytes. So decode next 4 bytes from msg hdr and 
1015     * perform OR operation on these 4 bytes to calculate tunnel id
1016     ***************************************************************************/
1017    ODU_REM_PRE_MSG(&tmpByte[1], mBuf);
1018    ODU_REM_PRE_MSG(&tmpByte[2], mBuf);
1019    ODU_REM_PRE_MSG(&tmpByte[3], mBuf);
1020    ODU_REM_PRE_MSG(&tmpByte[4], mBuf);
1021    egtpMsg->msgHdr.teId = (tmpByte[1] << 24) | (tmpByte[2] << 16) | (tmpByte[3] << 8) | tmpByte[4];
1022    //DU_LOG("\nDEBUG   -->  EGTP : teId %d",egtpMsg->msgHdr.teId);
1023
1024
1025    /* If any one of S, E or PN flag is set, set extension present as true. */
1026    if((tmpByte[0] & EGTP_MASK_BIT1) || (tmpByte[0] & EGTP_MASK_BIT2)||(tmpByte[0] & EGTP_MASK_BIT3))
1027    {
1028       extPres = TRUE;
1029    }
1030
1031    /* Decode sequence number, if S flag is set in first byte */
1032    if (tmpByte[0] & EGTP_MASK_BIT2)
1033    {
1034       /************************************************************************
1035        * Sequence num is 2 bytes. So decode next 2 bytes from msg hdr and 
1036        * perform OR operation on them 
1037        ************************************************************************/
1038       egtpMsg->msgHdr.seqNum.pres = TRUE;
1039       ODU_REM_PRE_MSG(&tmpByte[1], mBuf);
1040       ODU_REM_PRE_MSG(&tmpByte[2], mBuf);
1041       egtpMsg->msgHdr.seqNum.val = (tmpByte[1] << 8) | tmpByte[2];
1042    }
1043    /**************************************************************************** 
1044     * If extPres is true, but S bit is not set, implies, either of PN or E bit 
1045     * was set during Encode so accordingly extract Byte fields for seqNum anyway 
1046     ***************************************************************************/
1047    else if(extPres)
1048    {
1049       /*************************************************************************
1050        * Sequence num is 2 bytes. So decode next 2 bytes from msg hdr and 
1051        * perform OR operation on them 
1052        ************************************************************************/
1053       egtpMsg->msgHdr.seqNum.pres = 0;
1054       ODU_REM_PRE_MSG(&tmpByte[1], mBuf);
1055       ODU_REM_PRE_MSG(&tmpByte[2], mBuf);
1056       egtpMsg->msgHdr.seqNum.val = (tmpByte[1] << 8) | tmpByte[2];
1057    }
1058
1059    /* Decode N-PDU number if present flag is set */
1060    if (tmpByte[0] & EGTP_MASK_BIT1)
1061    {
1062       egtpMsg->msgHdr.nPdu.pres = TRUE;
1063       ODU_REM_PRE_MSG(&(egtpMsg->msgHdr.nPdu.val), mBuf);
1064    }
1065    /****************************************************************************
1066     * If extPres is true, but PN bit is not set, implies, either of S or E bit 
1067     * was set during Encode. Aaccordingly extract Byte fields of N-PDU num anyway 
1068     ***************************************************************************/
1069    else if(extPres)
1070    {
1071       egtpMsg->msgHdr.nPdu.pres = TRUE;
1072       ODU_REM_PRE_MSG(&(egtpMsg->msgHdr.nPdu.val), mBuf);
1073    }
1074
1075    /* If E flag is set in first byte, decode extension header */ 
1076    if(tmpByte[0] & EGTP_MASK_BIT3)
1077    {
1078       ODU_REM_PRE_MSG(&extHdrType, mBuf);
1079       while( 0 != extHdrType)
1080       {
1081          switch (extHdrType)
1082          {
1083             case EGTP_EXT_HDR_UDP_TYPE:
1084             {
1085                ODU_REM_PRE_MSG(&extHdrLen, mBuf);
1086                if(extHdrLen == 0x01)
1087                {
1088                   /************************************************************
1089                    * UDP Port is 2 bytes. So decode next 2 bytes from msg hdr
1090                   * and perform OR operation on them 
1091                   *************************************************************/
1092                   egtpMsg->msgHdr.extHdr.udpPort.pres = TRUE;
1093                   ODU_REM_PRE_MSG(&tmpByte[1], mBuf);
1094                   ODU_REM_PRE_MSG(&tmpByte[2], mBuf);
1095                   egtpMsg->msgHdr.extHdr.udpPort.val = (tmpByte[1] << 8) | tmpByte[2];
1096                }
1097                break;
1098             }
1099
1100             case EGTP_EXT_HDR_PDCP_TYPE:
1101             {
1102                ODU_REM_PRE_MSG(&extHdrLen, mBuf);
1103                if(extHdrLen == 0x01)
1104                {
1105                   /*************************************************************
1106                    * PDCP num is 2 bytes. So decode next 2 bytes from msg hdr
1107                    * and perform OR operation on them 
1108                    ************************************************************/
1109                   egtpMsg->msgHdr.extHdr.pdcpNmb.pres = TRUE;
1110                   ODU_REM_PRE_MSG(&tmpByte[1], mBuf);
1111                   ODU_REM_PRE_MSG(&tmpByte[2], mBuf);
1112                   egtpMsg->msgHdr.extHdr.pdcpNmb.val = (tmpByte[1] << 8) | tmpByte[2];
1113                }
1114                break;
1115             }
1116          } /* End of switch */
1117  
1118          ODU_REM_PRE_MSG(&extHdrType, mBuf);
1119  
1120       } /* End of while */
1121    }  
1122    /****************************************************************************
1123     * If extPres is true, but E bit is not set, implies, either of PN or S bit 
1124     * was set during Encode so accordingly extract Byte fields for extension
1125     * header anyway 
1126     ***************************************************************************/
1127    else if(extPres)
1128    {
1129       ODU_REM_PRE_MSG(&extHdrType, mBuf);
1130    }
1131
1132    egtpMsg->msg = mBuf;
1133
1134    //DU_LOG("\nDEBUG   -->  EGTP : DL Data Buffer after decoding header ");
1135    //ODU_PRINT_MSG(mBuf, 0, 0);
1136
1137    /* Forward the data to duApp/RLC */
1138  
1139    return ROK;
1140
1141 }
1142 /**********************************************************************
1143          End of file
1144 **********************************************************************/