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