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