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