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