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