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