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