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