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