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