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