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