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