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