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