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