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