cb3c5c82e4f2f3afc116b45e085c4e040c5563d6
[o-du/l2.git] / src / cu_stub / cu_stub_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 "common_def.h"
22 #include "cu_f1ap_msg_hdl.h"
23 #include "cu_stub_egtp.h"
24 #include "du_log.h"
25
26 /* Global variable declaration */
27 EgtpGlobalCb egtpCb;
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()
49 {
50   DU_LOG("\n\nDEBUG  -->  EGTP : Initializing");
51   memset (&egtpCb, 0, sizeof(EgtpGlobalCb));
52   
53   //Initializing with INVALID value
54   memset(egtpCb.gCntPdu, 0xFF , sizeof(uint8_t)*(MAX_TEID+1)); 
55   protType = CM_INET_PROTO_UDP;
56   return ROK;
57 }
58
59
60 /**************************************************************************
61  * @brief Task Activation callback function. 
62  *
63  * @details
64  *
65  *      Function : egtpActvTsk 
66  * 
67  *      Functionality:
68  *           This function handles all EGTP messages received
69  *           This API is registered with SSI during the 
70  *           Task Registration of DU APP.
71  *     
72  * @param[in]  Pst     *pst, Post structure of the primitive.     
73  * @param[in]  Buffer *mBuf, Packed primitive parameters in the
74  *  buffer.
75  * @return ROK     - success
76  *         RFAILED - failure
77  *
78  ***************************************************************************/
79 uint8_t egtpInitReq()
80 {
81    uint8_t ret = ROK;
82
83    ret = cuEgtpCfgReq();
84    if(ret != ROK)
85    {
86       DU_LOG("\nERROR  -->  EGTP : Configuration failed");
87       return (ret);
88    }
89
90    ret = cuEgtpSrvOpenReq();
91    if(ret != ROK)
92    {
93        DU_LOG("\nERROR  -->  EGTP : Transport server open request failed");
94        return (ret);
95    }
96
97    return ret;
98 } /* egtpInitReq */
99
100 /**************************************************************************
101  * @brief EGTP server configuration 
102  *
103  * @details
104  *
105  *      Function : egtpCfgReq
106  * 
107  *      Functionality:
108  *           This function handles EGTP configuration request.
109  *     
110  * @return ROK     - success
111  *         RFAILED - failure
112  *
113  * ***********************************************************************/
114 S16 cuEgtpCfgReq()
115 {
116    uint8_t ret;
117
118    memcpy(&egtpCb.egtpCfg, &cuCfgParams.egtpParams, sizeof(EgtpParams));
119
120    egtpCb.recvTptSrvr.addr.address = CM_INET_NTOH_UINT32(egtpCb.egtpCfg.localIp.ipV4Addr);
121    egtpCb.recvTptSrvr.addr.port = EGTP_DFLT_PORT;
122
123    egtpCb.dstCb.dstIp = CM_INET_NTOH_UINT32(egtpCb.egtpCfg.destIp.ipV4Addr);
124    egtpCb.dstCb.dstPort = egtpCb.egtpCfg.destPort;
125    egtpCb.dstCb.sendTptSrvr.addr.address = CM_INET_NTOH_UINT32(egtpCb.egtpCfg.localIp.ipV4Addr);
126    egtpCb.dstCb.sendTptSrvr.addr.port = egtpCb.egtpCfg.localPort;
127    egtpCb.dstCb.numTunn = 0;
128
129    ret = cmHashListInit(&(egtpCb.dstCb.teIdLst), 1024, sizeof(EgtpTeIdCb), FALSE, CM_HASH_KEYTYPE_UINT32_MOD, CU_APP_MEM_REG, CU_POOL);
130
131    if(ret != ROK)
132    {
133       DU_LOG("\nERROR  -->  EGTP : TeId hash list initialization failed");
134       return RFAILED;
135    }
136    else
137    {
138       DU_LOG("\nINFO  -->  EGTP : Configuration successful");
139    }
140
141    return ROK;
142 } /* cuEgtpCfgReq */
143
144 /**************************************************************************
145  * @brief EGTP server open request 
146  *
147  * @details
148  *
149  *      Function : egtpSrvOpenReq
150  * 
151  *      Functionality:
152  *           This function handles EGTP open server request.
153  *           It opens udp socket to receive/send msgs.
154  *     
155  * @param[in]  Pst *pst, post structure
156  * @return ROK     - success
157  *         RFAILED - failure
158  *
159  ***************************************************************************/
160
161 S16 cuEgtpSrvOpenReq(Pst *pst)
162 {
163
164    uint8_t ret;
165
166    DU_LOG("\nINFO  -->  EGTP : Received open server request");
167  
168    sockType = CM_INET_DGRAM;
169    if((ret = (cmInetSocket(sockType, &(egtpCb.recvTptSrvr.sockFd), protType))) != ROK)
170    {
171       DU_LOG("\nERROR  -->  EGTP : Failed to open UDP socket");
172       return RFAILED;
173    }
174
175    ret = cmInetBind(&(egtpCb.recvTptSrvr.sockFd), &(egtpCb.recvTptSrvr.addr));
176    if(ret != ROK)
177    {
178       DU_LOG("\nERROR  -->  EGTP : Failed to bind socket");
179       return RFAILED;
180    }
181
182    if(ret = (cmInetSocket(sockType, &(egtpCb.dstCb.sendTptSrvr.sockFd), protType)) != ROK)
183    {  
184       DU_LOG("\nERROR  -->  EGTP : Failed to open UDP socket");
185       return RFAILED;
186    }
187       
188    ret = cmInetBind(&(egtpCb.dstCb.sendTptSrvr.sockFd), &(egtpCb.dstCb.sendTptSrvr.addr));
189    if(ret != ROK)
190    {  
191       DU_LOG("\nERROR  -->  EGTP : Failed to bind socket");
192       return RFAILED;
193    }
194        
195    /* TODO: set socket options */
196
197    DU_LOG("\nINFO  -->  EGTP : Receiver socket[%d] and Sender socket[%d] open", egtpCb.recvTptSrvr.sockFd.fd,\
198    egtpCb.dstCb.sendTptSrvr.sockFd.fd);
199    return ROK;
200 } /* cuEgtpSrvOpenReq */
201
202
203 /**************************************************************************
204  * @brief EGTP tunnel management request
205  *
206  * @details
207  *
208  *      Function : cuEgtpTnlMgmtReq
209  * 
210  *      Functionality:
211  *           This function handles EGTP tunnel managament request
212  *     
213  * @param[in]  Pst *pst, post structure
214  *             Tunnel Eveny structure
215  * @return ROK     - success
216  *         RFAILED - failure
217  *
218  
219  * ***************************************************************************/
220 S16 cuEgtpTnlMgmtReq(EgtpTnlEvt tnlEvt)
221 {
222    S8 ret;
223
224    DU_LOG("\nINFO  -->  EGTP : Received tunnel management request");
225    switch(tnlEvt.action)
226    {
227       case EGTP_TNL_MGMT_ADD:
228       {
229          ret = cuEgtpTnlAdd(tnlEvt);
230          break;
231       }
232       case EGTP_TNL_MGMT_MOD:
233       {
234          ret = cuEgtpTnlMod(tnlEvt);
235          break;
236       }
237       case EGTP_TNL_MGMT_DEL:
238       {
239          ret = cuEgtpTnlDel(tnlEvt);
240          break;
241       }
242       default:
243       {
244          DU_LOG("\nERROR  -->  EGTP : Invalid tunnel management action[%d]", tnlEvt.action);
245          ret = RFAILED;
246       }
247    }
248
249    return (ret);
250 }
251
252 /**************************************************************************
253  * @brief EGTP tunnel addition
254  *
255  * @details
256  *
257  *      Function : cuEgtpTnlAdd
258  * 
259  *      Functionality:
260  *           This function handles EGTP tunnel addition
261  *     
262  * @param[in]  Tunnel Event structure
263  * @return ROK     - success
264  *         RFAILED - failure
265  *
266  * ***************************************************************************/
267 S16 cuEgtpTnlAdd(EgtpTnlEvt tnlEvt)
268 {
269    S16   ret;
270    EgtpTeIdCb     *teidCb;
271    EgtpMsgHdr   preDefHdr; /* pre-define header for this tunnel */
272    
273
274    DU_LOG("\nINFO  -->  EGTP : Tunnel addition : LocalTeid[%d] Remote Teid[%d]", tnlEvt.lclTeid, tnlEvt.remTeid);
275
276    CU_ALLOC(teidCb, (Size)sizeof(EgtpTeIdCb));
277
278    if(teidCb == NULLP)
279    {
280       DU_LOG("\nERROR  -->  EGTP : Memory allocation failed");
281       return RFAILED;
282    }
283
284
285    memset(teidCb, 0, sizeof(EgtpTeIdCb));
286    teidCb->teId = tnlEvt.lclTeid;
287    teidCb->remTeId = tnlEvt.remTeid;
288
289    ret = cmHashListInsert(&(egtpCb.dstCb.teIdLst), (PTR)teidCb, (uint8_t *)&(teidCb->teId), sizeof(uint32_t));
290    if(ret != ROK)
291    {
292       DU_LOG("\nERROR  -->  EGTP : Failed to insert in hash list");
293       CU_FREE(teidCb, (Size)sizeof(EgtpTeIdCb));
294       return RFAILED;
295    }
296    egtpCb.dstCb.numTunn++;
297
298    /* Encoding pre-defined header */
299    memset(&preDefHdr, 0, sizeof(EgtpMsgHdr));
300    preDefHdr.msgType = EGTPU_MSG_GPDU;
301    preDefHdr.teId = teidCb->remTeId;
302    preDefHdr.extHdr.pdcpNmb.pres = FALSE;
303    preDefHdr.extHdr.udpPort.pres = FALSE;
304    preDefHdr.nPdu.pres = TRUE; //Including nPdu when sending data
305    preDefHdr.nPdu.val = 0;
306
307    cuEgtpEncodeHdr((uint8_t *)teidCb->preEncodedHdr.hdr, &preDefHdr, &(teidCb->preEncodedHdr.cnt));
308    egtpCb.gCntPdu[teidCb->remTeId] = 0;//Resetting the Cnt Value for this DRB which indicates its creation
309
310 /*   SPutSBuf(CU_APP_MEM_REG, CU_POOL, (Data *)teidCb, (Size)sizeof(EgtpTeIdCb));*/
311
312    return ROK;
313 } /* cuEgtpTnlAdd */
314
315 /**************************************************************************
316  * @brief EGTP tunnel modification
317  *
318  * @details
319  *
320  *      Function : cuEgtpTnlMod
321  * 
322  *      Functionality:
323  *           This function handles EGTP tunnel modification
324  *     
325  * @param[in]  Tunnel Event structure
326  * @return ROK     - success
327  *         RFAILED - failure
328  * 
329  * ***************************************************************************/
330 S16 cuEgtpTnlMod(EgtpTnlEvt tnlEvt)
331 {
332 #if 0
333    S16   ret;
334    EgtpTeIdCb     *teidCb = NULLP;
335
336    DU_LOG("\nDEBUG  -->  CU_STUB : Tunnel modification : LocalTeid[%d] Remote Teid[%d]", tnlEvt.lclTeid, tnlEvt.remTeid);
337
338    cmHashListFind(&(egtpCb.dstCb.teIdLst), (uint8_t *)&(tnlEvt.teId), sizeof(uint32_t), 0, (PTR *)&teidCb);
339    if(teidCb == NULLP)
340    {
341       DU_LOG("\nDEBUG --> CU_STUBTunnel id not found");
342       return RFAILED;
343    }  
344    
345    teidCb->teId = tnlEvt.lclTeid;
346    teidCb->remTeId = tnlEvt.remTeid;
347 #endif
348    return ROK;
349 }
350
351 /**************************************************************************
352  * @brief EGTP tunnel deletion
353  *
354  * @details
355  *
356  *     Function : cuEgtpTnlDel
357  * 
358  *     Functionality:
359  *         This function handles EGTP tunnel deletion
360  *    
361  * @param[in]  Tunnel Event structure
362  * @return ROK     - success
363  *         RFAILED - failure
364  * 
365  * ***************************************************************************/
366 S16 cuEgtpTnlDel(EgtpTnlEvt tnlEvt)
367 {
368    EgtpTeIdCb     *teidCb = NULLP;
369
370    DU_LOG("\nDEBUG  -->  EGTP : Tunnel deletion : Local Teid[%d] Remote Teid[%d]", tnlEvt.lclTeid, tnlEvt.remTeid);
371    
372    cmHashListFind(&(egtpCb.dstCb.teIdLst), (uint8_t *)&(tnlEvt.lclTeid), sizeof(uint32_t), 0, (PTR *)&teidCb);
373    if(teidCb == NULLP)
374    {
375       DU_LOG("\nERROR  -->  EGTP : Tunnel id[%d] not configured", tnlEvt.lclTeid);
376       return RFAILED;
377    } 
378
379    cmHashListDelete(&(egtpCb.dstCb.teIdLst), (PTR)teidCb);
380    CU_FREE(teidCb, (Size)sizeof(EgtpTeIdCb));
381    egtpCb.dstCb.numTunn--;
382
383    return ROK;
384 } /* cuEgtpTnlDel */
385
386 /*******************************************************************
387  *
388  * @brief Encodes message header
389  *
390  * @details
391  *
392  *    Function : cuEgtpEncodeHdr
393  * 
394  *    Functionality:
395  *       Encodes EGTP message haeder
396  *
397  * @params[in] EGTP message
398  *             Message Buffer 
399  * @return ROK     - success
400  *         RFAILED - failure
401  *
402  * ****************************************************************/
403 S16 cuEgtpEncodeHdr(uint8_t *preEncodedHdr, EgtpMsgHdr *preDefHdr, uint8_t *hdrIdx)
404 {
405    uint8_t         tmpByte = 0;                 /* Stores one byte of data for enc */
406    uint8_t         cnt     = EGTP_MAX_HDR_LEN;  /* Stores the position */
407    Bool       extPres = FALSE;             /* Flag for indication of S, E or P presense flag */
408    uint16_t        nwWord = 0;
409
410    /* Encoding header */
411    tmpByte |= EGTP_MASK_BIT6;   /* Setting 6th LSB of 1st byte as version */
412    tmpByte |= EGTP_MASK_BIT5;   /* Setting 5th LSB of 1st byte as protocol type */
413    
414    if(preDefHdr->extHdr.udpPort.pres || preDefHdr->extHdr.pdcpNmb.pres)
415    {
416       tmpByte |= EGTP_MASK_BIT3;  /* Setting 3rd LSB of 1st byte if Extension heaeder is present */
417    }
418     
419    if(preDefHdr->seqNum.pres)
420    {
421       tmpByte |= EGTP_MASK_BIT2;
422    }
423    
424    if(preDefHdr->nPdu.pres)
425    {
426       tmpByte |= EGTP_MASK_BIT1;
427    }
428    
429    if((tmpByte & EGTP_MASK_BIT1) || (tmpByte & EGTP_MASK_BIT2)||(tmpByte & EGTP_MASK_BIT3))
430    {
431       extPres = TRUE;
432    }
433    preEncodedHdr[--cnt] = tmpByte;
434    preEncodedHdr[--cnt] = preDefHdr->msgType;
435     
436    /* Encode Tunnel endpoint */
437    preEncodedHdr[--cnt] = 0;
438    preEncodedHdr[--cnt] = 0;
439    nwWord = (uint16_t)(GetHiWord(preDefHdr->teId));
440    preEncodedHdr[--cnt] = (uint8_t)(GetHiByte(nwWord));
441    preEncodedHdr[--cnt] = (uint8_t)(GetLoByte(nwWord));
442    nwWord = (uint16_t)(GetLoWord(preDefHdr->teId));
443    preEncodedHdr[--cnt] = (uint8_t)(GetHiByte(nwWord));
444    preEncodedHdr[--cnt] = (uint8_t)(GetLoByte(nwWord));
445     
446    /* Encode sequence number */
447    if(preDefHdr->seqNum.pres)
448    {
449       preEncodedHdr[--cnt] = GetHiByte(preDefHdr->seqNum.val);
450       preEncodedHdr[--cnt] = GetLoByte(preDefHdr->seqNum.val);
451    }
452    else if(extPres)
453    {
454       preEncodedHdr[--cnt] = 0;
455       preEncodedHdr[--cnt] = 0;
456    }
457
458    if(preDefHdr->nPdu.pres)
459    {
460       preEncodedHdr[--cnt] = preDefHdr->nPdu.val;
461    }
462    else if(extPres)
463    {
464       preEncodedHdr[--cnt] = 0;
465    }
466     
467    if(preDefHdr->extHdr.udpPort.pres)
468    {
469       preEncodedHdr[--cnt] = EGTP_EXT_HDR_UDP_TYPE;
470       preEncodedHdr[--cnt] = 1;
471       preEncodedHdr[--cnt] = GetHiByte(preDefHdr->extHdr.udpPort.val);
472       preEncodedHdr[--cnt] = GetLoByte(preDefHdr->extHdr.udpPort.val);
473    }
474    
475    if(preDefHdr->extHdr.pdcpNmb.pres)
476    {
477       preEncodedHdr[--cnt] = EGTP_EXT_HDR_PDCP_TYPE;
478       preEncodedHdr[--cnt] = 1;
479       preEncodedHdr[--cnt] = GetHiByte(preDefHdr->extHdr.pdcpNmb.val);
480       preEncodedHdr[--cnt] = GetLoByte(preDefHdr->extHdr.pdcpNmb.val);
481    }
482     
483    if(tmpByte & EGTP_MASK_BIT3)
484    {
485       preEncodedHdr[--cnt] = 0;
486    }
487    else if(extPres)
488    {
489       preEncodedHdr[--cnt] = 0;
490    } 
491    
492    *hdrIdx = cnt;
493    return ROK;
494
495 } /* egtpEncodeHdr */
496
497 S16 cuEgtpHdlRecvMsg(Buffer *mBuf)
498 {
499    /*Decoding of EGTP message header */
500    
501    cuEgtpDecodeHdr(mBuf);
502    
503    /* Start Pumping data from CU to DU */
504    //return (cuEgtpDatReq());
505
506 }
507
508 S16 cuEgtpDecodeHdr(Buffer *mBuf)
509 {
510    EgtpMsg  egtpMsg;
511    uint8_t       tmpByte[5];         /* Holds one byte of data after Dec */
512    uint8_t       version = 0;         /* Holds the version type, decoded */
513    MsgLen   msgLen  = 0;         /* Holds the msgLen from the Hdr */
514    MsgLen   bufLen  = 0;         /* Holds the total buffer length */
515    uint8_t       extHdrType = 0;       /* Holds the Extension hdr type */
516    uint8_t       extHdrLen = 0;        /* Extension hdr length */
517    Bool     extPres = FALSE;      /* Flag for indication of S, E or P presense flag */
518
519    ODU_GET_MSG_LEN(mBuf, &bufLen);
520
521    /* Decode version */
522    ODU_REM_PRE_MSG(&tmpByte[0], mBuf);
523    version = tmpByte[0] >> 5;
524
525    /* Decode message type */
526    ODU_REM_PRE_MSG((Data*)&(egtpMsg.msgHdr.msgType), mBuf);
527
528    /* Decode message length */
529    ODU_REM_PRE_MSG(&tmpByte[1], mBuf);
530    ODU_REM_PRE_MSG(&tmpByte[2], mBuf);
531    msgLen = (tmpByte[1] << 8) | tmpByte[2];
532
533    /* Decode tunnel id */
534    ODU_REM_PRE_MSG(&tmpByte[1], mBuf);
535    ODU_REM_PRE_MSG(&tmpByte[2], mBuf);
536    ODU_REM_PRE_MSG(&tmpByte[3], mBuf);
537    ODU_REM_PRE_MSG(&tmpByte[4], mBuf);
538    egtpMsg.msgHdr.teId = (tmpByte[1] << 24) | (tmpByte[2] << 16) | (tmpByte[3] << 8) | tmpByte[4];
539
540    if((tmpByte[0] & EGTP_MASK_BIT1) || (tmpByte[0] & EGTP_MASK_BIT2)||(tmpByte[0] & EGTP_MASK_BIT3))
541    {
542       extPres = TRUE;
543    }
544
545    /* Decode sequence number */
546    if ( tmpByte[0] & EGTP_MASK_BIT2 )
547    {
548       egtpMsg.msgHdr.seqNum.pres = TRUE;
549       ODU_REM_PRE_MSG(&tmpByte[1], mBuf);
550       ODU_REM_PRE_MSG(&tmpByte[2], mBuf);
551       egtpMsg.msgHdr.seqNum.val = (tmpByte[1] << 8) | tmpByte[2];
552    }
553    else  if(extPres)
554    {
555       egtpMsg.msgHdr.seqNum.pres = 0;
556       ODU_REM_PRE_MSG(&tmpByte[1], mBuf);
557       ODU_REM_PRE_MSG(&tmpByte[2], mBuf);
558       egtpMsg.msgHdr.seqNum.val = (tmpByte[1] << 8) | tmpByte[2];
559    }
560
561    /* Decode N-PDU number */
562    if ( tmpByte[0] & EGTP_MASK_BIT1 )
563    {
564       egtpMsg.msgHdr.nPdu.pres = TRUE;
565       ODU_REM_PRE_MSG(&(egtpMsg.msgHdr.nPdu.val), mBuf);
566    }
567    else if(extPres)
568    {
569       egtpMsg.msgHdr.nPdu.pres = TRUE;
570       ODU_REM_PRE_MSG(&(egtpMsg.msgHdr.nPdu.val), mBuf);
571    }
572
573    if(extPres & EGTP_MASK_BIT1)
574    {
575       ODU_REM_PRE_MSG(&extHdrType, mBuf);
576       while( 0 != extHdrType)
577       {
578          switch (extHdrType)
579          {
580             case EGTP_EXT_HDR_UDP_TYPE:
581             {
582                ODU_REM_PRE_MSG(&extHdrLen, mBuf);
583                if(extHdrLen == 0x01)
584                {
585                   egtpMsg.msgHdr.extHdr.udpPort.pres = TRUE;
586                   ODU_REM_PRE_MSG(&tmpByte[1], mBuf);
587                   ODU_REM_PRE_MSG(&tmpByte[2], mBuf);
588                   egtpMsg.msgHdr.extHdr.udpPort.val = (tmpByte[1] << 8) | tmpByte[2];
589                }
590                break;
591             }
592
593             case EGTP_EXT_HDR_PDCP_TYPE:
594             {
595                ODU_REM_PRE_MSG(&extHdrLen, mBuf);
596                if(extHdrLen == 0x01)
597                {
598                   egtpMsg.msgHdr.extHdr.pdcpNmb.pres = TRUE;
599                   ODU_REM_PRE_MSG(&tmpByte[1], mBuf);
600                   ODU_REM_PRE_MSG(&tmpByte[2], mBuf);
601                   egtpMsg.msgHdr.extHdr.pdcpNmb.val = (tmpByte[1] << 8) | tmpByte[2];
602                }
603                break;
604             }
605          } /* End of switch */
606
607          ODU_REM_PRE_MSG(&extHdrType, mBuf);
608
609       } /* End of while */
610    } /* End of if(extPres & EGTP_MASK_BIT1) */
611    else if(extPres)
612    {
613       ODU_REM_PRE_MSG(&extHdrType, mBuf);
614    }
615
616    DU_LOG("\nDEBUG  -->  EGTP : Message Buffer after decoding header [TEID:%d]",egtpMsg.msgHdr.teId);
617    ODU_PRINT_MSG(mBuf, 0, 0);
618
619    SPutMsg(mBuf);
620
621    return ROK;
622      
623 } /* End of cuEgtpDecodeHdr */
624
625 uint16_t cuEgtpDatReq(uint8_t teId)
626 {
627    uint8_t ret = ROK, cnt = 0;
628    EgtpMsg  egtpMsg;
629
630    egtpMsg.msgHdr.teId = teId;
631    
632    if(egtpCb.gCntPdu[teId] == 0xFF) //DRB not created
633    {
634       DU_LOG("\nERROR  -->  EGTP : DRB  not created");
635       return RFAILED ;
636    }
637    /* Build Application message that is supposed to come from app to egtp */
638    ret = BuildAppMsg(&egtpMsg);
639    if(ret != ROK)
640    {
641       DU_LOG("\nERROR  -->  EGTP : Failed to build App Msg");
642       return RFAILED;
643    }
644
645    /* Encode EGTP header to build final EGTP message */
646    ret = BuildEgtpMsg(&egtpMsg);
647    if(ret != ROK)
648    {
649       DU_LOG("\nERROR  -->  EGTP : Failed to build EGTP Msg");
650       return RFAILED;
651    }
652    cuEgtpSendMsg(egtpMsg.msg);
653    ODU_PUT_MSG_BUF(egtpMsg.msg);
654
655    return ROK;
656 }
657
658
659 S16 BuildAppMsg(EgtpMsg  *egtpMsg)
660 {
661    char data[1215] = "In telecommunications, 5G is the fifth generation technology standard for broadband cellular"
662    " networks, which cellular phone companies began deploying worldwide in 2019, and is the planned successor to the 4G "
663    " networks which provide connectivity to most current cellphones. 5G networks are predicted to have more than 1.7"
664    " billion subscribers worldwide by 2025, according to the GSM Association.Like its predecessors, 5G networks are"
665    " cellular networks,in which the service area is divided into small geographical areas called cells.All 5G wireless"
666    " devices in a cell are connected to the Internet and telephone network by radio waves through local antenna in the"
667    " cell. The main advantage of the new networks is that they will have greater bandwidth, giving higher download"
668    " speeds, eventually up to 10 gigabits per second(Gbit/s). Due to the increased bandwidth, it is expected the"
669    " networks will not exclusively serve cellphones like existing cellular networks, but also be used as general"
670    " internet service providers for laptops and desktop computers, competing with existing ISPs such as cable"
671    " internet, and also will make possible new applications in internet of things (IoT) and machine to machine areas.";
672
673    int datSize = 1215;
674  
675    Buffer   *mBuf;
676  
677    if(ODU_GET_MSG_BUF(CU_APP_MEM_REG, CU_POOL, &mBuf) == ROK)
678    {
679       if(ODU_ADD_POST_MSG_MULT((Data *)data, datSize, mBuf) != ROK)
680       {
681          DU_LOG("\nERROR  -->  EGTP : ODU_ADD_POST_MSG_MULT failed");
682          ODU_PUT_MSG_BUF(mBuf);
683          return RFAILED;
684       }
685    }
686    else
687    {
688        DU_LOG("\nERROR  -->  EGTP : Failed to allocate memory");
689        return RFAILED;
690    }
691  
692    /* filling IPv4 header */
693    CmIpv4Hdr ipv4Hdr;
694    MsgLen    mLen;
695  
696    mLen = 0;
697    ODU_GET_MSG_LEN(mBuf, &mLen);
698
699    memset(&ipv4Hdr, 0, sizeof(CmIpv4Hdr));
700    ipv4Hdr.length = CM_IPV4_HDRLEN + mLen;
701    ipv4Hdr.hdrVer = 0x45;
702    ipv4Hdr.proto = 1;
703    ipv4Hdr.srcAddr = CM_INET_NTOH_UINT32(egtpCb.egtpCfg.localIp.ipV4Addr);
704    ipv4Hdr.destAddr = CM_INET_NTOH_UINT32(egtpCb.egtpCfg.destIp.ipV4Addr);
705  
706    /* Packing IPv4 header into buffer */
707    S16          ret, cnt, idx;
708    Data         revPkArray[CM_IPV4_HDRLEN];
709    Data         pkArray[CM_IPV4_HDRLEN];
710  
711    /* initialize locals */
712    cnt = 0;
713    memset(revPkArray, 0, CM_IPV4_HDRLEN);
714    memset(pkArray, 0, CM_IPV4_HDRLEN);
715
716    /* Pack Header Version */
717    pkArray[cnt++] = ipv4Hdr.hdrVer;
718  
719    /* Pack TOS */
720    pkArray[cnt++] = ipv4Hdr.tos;
721  
722    pkArray[cnt++] = (Data)GetHiByte(ipv4Hdr.length);
723    pkArray[cnt++] = (Data)GetLoByte(ipv4Hdr.length);
724  
725    /* Pack Id */
726    pkArray[cnt++] = (Data) GetHiByte(ipv4Hdr.id);
727    pkArray[cnt++] = (Data) GetLoByte(ipv4Hdr.id);
728  
729    /* Pack Offset */
730    pkArray[cnt++] = (Data)GetHiByte(ipv4Hdr.off);
731    pkArray[cnt++] = (Data)GetLoByte(ipv4Hdr.off);
732  
733    /* Pack TTL */
734    pkArray[cnt++] = ipv4Hdr.ttl;
735  
736    /* Pack Protocol */
737    pkArray[cnt++] = ipv4Hdr.proto;
738  
739    /* Pack Checksum */
740    pkArray[cnt++] = (Data)GetHiByte(ipv4Hdr.chkSum);
741    pkArray[cnt++] = (Data)GetLoByte(ipv4Hdr.chkSum);
742                                                         
743    /* Pack Source Address */
744    pkArray[cnt++] = (Data)GetHiByte(GetHiWord(ipv4Hdr.srcAddr));
745    pkArray[cnt++] = (Data)GetLoByte(GetHiWord(ipv4Hdr.srcAddr));
746    pkArray[cnt++] = (Data)GetHiByte(GetLoWord(ipv4Hdr.srcAddr));
747    pkArray[cnt++] = (Data)GetLoByte(GetLoWord(ipv4Hdr.srcAddr));
748  
749    /* Pack Destination Address */
750    pkArray[cnt++] = (Data)GetHiByte(GetHiWord(ipv4Hdr.destAddr));
751    pkArray[cnt++] = (Data)GetLoByte(GetHiWord(ipv4Hdr.destAddr));
752    pkArray[cnt++] = (Data)GetHiByte(GetLoWord(ipv4Hdr.destAddr));
753    pkArray[cnt++] = (Data)GetLoByte(GetLoWord(ipv4Hdr.destAddr));
754  
755    for (idx = 0;  idx < CM_IPV4_HDRLEN;  idx++)
756       revPkArray[idx] = pkArray[CM_IPV4_HDRLEN - idx -1];
757  
758    /* this function automatically reverses revPkArray */
759    ret = ODU_ADD_PRE_MSG_MULT(revPkArray, (MsgLen)cnt, mBuf);
760  
761    egtpMsg->msgHdr.msgType = EGTPU_MSG_GPDU;
762    egtpMsg->msgHdr.nPdu.pres = TRUE;
763
764    if(egtpCb.gCntPdu[egtpMsg->msgHdr.teId] != NUM_DL_PACKETS)
765      egtpCb.gCntPdu[egtpMsg->msgHdr.teId]++;
766    else
767      egtpCb.gCntPdu[egtpMsg->msgHdr.teId] = 1;
768
769    egtpMsg->msgHdr.nPdu.val = egtpCb.gCntPdu[egtpMsg->msgHdr.teId];
770    egtpMsg->msgHdr.seqNum.pres = FALSE;
771    egtpMsg->msgHdr.extHdr.udpPort.pres = FALSE;
772    egtpMsg->msgHdr.extHdr.pdcpNmb.pres = FALSE;
773    egtpMsg->msg = mBuf;
774
775    return ret;
776 }
777
778 S16 BuildEgtpMsg(EgtpMsg *egtpMsg)
779 {
780    EgtpTeIdCb   *teidCb = NULLP;
781    MsgLen tPduSize;
782    uint8_t     hdrLen;
783    uint32_t    msgLen;
784    EgtpMsgHdr   *msgHdr;
785  
786    cmHashListFind(&(egtpCb.dstCb.teIdLst), (uint8_t *)&(egtpMsg->msgHdr.teId), sizeof(uint32_t), 0, (PTR *)&teidCb);
787    if(teidCb == NULLP)
788    {
789       DU_LOG("\nERROR  -->  EGTP : Tunnel id[%d] not configured", egtpMsg->msgHdr.teId);
790       return (LCM_REASON_INVALID_PAR_VAL);
791    }
792
793    msgHdr = &(egtpMsg->msgHdr);
794
795    hdrLen = teidCb->preEncodedHdr.cnt;
796
797    if(msgHdr->extHdr.pdcpNmb.pres)
798    {
799       teidCb->preEncodedHdr.hdr[EGTP_MAX_HDR_LEN - 1] |= EGTP_MASK_BIT3;
800       teidCb->preEncodedHdr.hdr[hdrLen] = EGTP_EXT_HDR_PDCP_TYPE;
801       teidCb->preEncodedHdr.hdr[--hdrLen] = 1;
802       teidCb->preEncodedHdr.hdr[--hdrLen] = GetHiByte(msgHdr->extHdr.pdcpNmb.val);
803       teidCb->preEncodedHdr.hdr[--hdrLen] = GetLoByte(msgHdr->extHdr.pdcpNmb.val);
804       teidCb->preEncodedHdr.hdr[--hdrLen] = 0;
805    }
806    else
807    {
808       teidCb->preEncodedHdr.hdr[EGTP_MAX_HDR_LEN - 1] &= ~(EGTP_MASK_BIT3);
809    }
810  
811    ODU_GET_MSG_LEN(egtpMsg->msg, &tPduSize);
812
813    /*Adjust the header to fill the correct length*/
814    msgLen = tPduSize +  (EGTP_MAX_HDR_LEN - hdrLen) - 0x08;
815
816    /***********************************************
817     * Fill the length field of the message header *
818     ***********************************************/
819    teidCb->preEncodedHdr.hdr[EGTP_MAX_HDR_LEN - 3] = (uint8_t)GetHiByte(msgLen);
820    teidCb->preEncodedHdr.hdr[EGTP_MAX_HDR_LEN - 4] = (uint8_t)GetLoByte(msgLen);
821
822    /*Update the sequence number*/
823    if(egtpMsg->msgHdr.seqNum.pres)
824    {
825       teidCb->preEncodedHdr.hdr[EGTP_MAX_HDR_LEN - 1] |= (EGTP_MASK_BIT2);
826       teidCb->preEncodedHdr.hdr[EGTP_MAX_HDR_LEN - 9] = (uint8_t)GetHiByte(egtpMsg->msgHdr.seqNum.val);
827       teidCb->preEncodedHdr.hdr[EGTP_MAX_HDR_LEN - 10] = (uint8_t)GetLoByte(egtpMsg->msgHdr.seqNum.val);
828    }
829    else
830    {
831       teidCb->preEncodedHdr.hdr[EGTP_MAX_HDR_LEN - 1] &= ~(EGTP_MASK_BIT2);
832    }
833
834    /*Update the nPdU number*/
835    if(egtpMsg->msgHdr.nPdu.pres)
836    {
837       teidCb->preEncodedHdr.hdr[EGTP_MAX_HDR_LEN - 1] |= (EGTP_MASK_BIT1);
838       teidCb->preEncodedHdr.hdr[EGTP_MAX_HDR_LEN - 11] = egtpMsg->msgHdr.nPdu.val;
839    }
840    else
841    {
842       teidCb->preEncodedHdr.hdr[EGTP_MAX_HDR_LEN - 1] &= ~(EGTP_MASK_BIT1);
843    }
844
845    ODU_ADD_PRE_MSG_MULT(&teidCb->preEncodedHdr.hdr[hdrLen], (EGTP_MAX_HDR_LEN - hdrLen), egtpMsg->msg);
846    return ROK;
847 }
848
849 S16 cuEgtpSendMsg(Buffer *mBuf)
850 {
851    S16            ret;
852    MsgLen         txLen;
853    CmInetMemInfo  info;
854    CmInetAddr     dstAddr;
855
856    info.region = CU_APP_MEM_REG;
857    info.pool = CU_POOL;
858  
859    dstAddr.port = EGTP_DFLT_PORT;
860    dstAddr.address = egtpCb.dstCb.dstIp;
861  
862    ret = cmInetSendMsg(&(egtpCb.dstCb.sendTptSrvr.sockFd), &dstAddr, &info, mBuf, &txLen, CM_INET_NO_FLAG);
863    if(ret != ROK && ret != RWOULDBLOCK)
864    {
865       DU_LOG("\nERROR  -->  EGTP : Message send failure");
866       return RFAILED;
867    }
868    
869    DU_LOG("\nDEBUG  -->  EGTP : Message Sent");
870  
871    return ROK;
872 }