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