Fix for memory leak in UL data path at cu_stub [Issue-ID: ODUHIGH-398]
[o-du/l2.git] / src / cu_stub / cu_stub_sctp.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 SCTP related functionality */
20
21 #include "common_def.h" 
22 #include "cu_f1ap_msg_hdl.h"
23 #include "cu_stub_sctp.h"
24 #include "cu_stub_egtp.h"
25 #include "du_log.h"
26
27 CuSctpDestCb f1Params;
28 /**************************************************************************
29  * @brief Task Initiation callback function. 
30  *
31  * @details
32  *
33  *     Function : sctpActvInit 
34  *    
35  *     Functionality:
36  *             This function is supplied as one of parameters during SCTP's 
37  *             task registration. SSI will invoke this function once, after
38  *             it creates and attaches this TAPA Task to a system task.
39  *     
40  * @param[in]  Ent entity, the entity ID of this task.     
41  * @param[in]  Inst inst, the instance ID of this task.
42  * @param[in]  Region region, the region ID registered for memory 
43  *              usage of this task.
44  * @param[in]  Reason reason.
45  * @return ROK     - success
46  *         RFAILED - failure
47  ***************************************************************************/
48 S16 sctpActvInit()
49 {
50    DU_LOG("\n\nDEBUG  -->  SCTP : Initializing");
51    connUp = FALSE;
52    assocId = 0;
53    nonblocking = FALSE;
54    sctpCfg = cuCfgParams.sctpParams;
55    return ROK;
56
57 }
58
59 /**************************************************************************
60  * @brief Task Activation callback function. 
61  *
62  * @details
63  *
64  *      Function : sctpActvTsk 
65  * 
66  *      Functionality:
67  *           This function handles all SCTP messages received
68  *           This API is registered with SSI during the 
69  *           Task Registration of DU APP.
70  *     
71  * @param[in]  Pst     *pst, Post structure of the primitive.     
72  * @param[in]  Buffer *mBuf, Packed primitive parameters in the
73  *  buffer.
74  * @return ROK     - success
75  *         RFAILED - failure
76  *
77  ***************************************************************************/
78 S16 sctpActvTsk(Pst *pst, Buffer *mBuf)
79 {
80
81 //TODO: TBD
82    return ROK;
83 }
84
85 /**************************************************************************
86  * @brief Function to configure the Sctp Params during config Request
87  *
88  * @details
89  *
90  *      Function : duSctpCfgReq
91  * 
92  *      Functionality:
93  *           This function configures SCTP Params during the config Request
94  *     
95  * @return ROK     - success
96  *         RFAILED - failure
97  *
98  ***************************************************************************/
99
100 S16 sctpCfgReq()
101 {
102
103 /* Fill F1 Params */
104    f1Params.destPort             = sctpCfg.duPort;
105    f1Params.srcPort              = sctpCfg.cuPort;
106    f1Params.bReadFdSet           = ROK;
107    memset(&f1Params.sockFd, -1, sizeof(CmInetFd));
108    memset(&f1Params.lstnSockFd, -1, sizeof(CmInetFd));
109    fillDestNetAddr(&f1Params.destIpNetAddr, &sctpCfg.duIpAddr);
110
111    return ROK;
112 }
113
114
115 /*******************************************************************
116  *
117  * @brief Fills the address List of the source Ip Address
118  *
119  * @details
120  *
121  *    Function : fillAddrLst
122  *
123  *    Functionality:
124  *       Fills the address List of source Ip Address
125  *
126  * @params[in] CmInetNetAddrLst *addrLstPtr, Address List pointer
127  * @params[in] F1IpAddr *srcIpAddr, src Ip Adrress to be filled in the Address List
128  * @return ROK     - success
129  *         RFAILED - failure
130  *
131  ******************************************************************/
132
133 S16 fillAddrLst(CmInetNetAddrLst *addrLstPtr, SctpIpAddr *ipAddr)
134
135    addrLstPtr->count++;
136    addrLstPtr->addrs[(addrLstPtr->count - 1)].type = CM_INET_IPV4ADDR_TYPE;
137    addrLstPtr->addrs[(addrLstPtr->count - 1)].u.ipv4NetAddr = CM_INET_NTOH_UINT32(ipAddr->ipV4Addr);
138
139    return ROK;
140 }
141
142 /******************************************************************************
143  *
144  * @brief Fills the address List of the source Ip Address
145  *
146  * @details
147  *
148  *    Function : fillDestNetAddr
149  *
150  *    Functionality:
151  *       Fills the address List of destinatoion Ip Address
152  *
153  * @params[in] CmInetNetAddr *destAddrPtr, Address List pointer
154  * @params[in] F1IpAddr *dstIpAddr, destIp Address to be filled in the Address List
155  * @return ROK     - success
156  *         RFAILED - failure
157  *
158  *******************************************************************************/
159 S16 fillDestNetAddr(CmInetNetAddr *destAddrPtr, SctpIpAddr *dstIpPtr)
160 {
161    /* Filling destination address */
162    destAddrPtr->type = CM_INET_IPV4ADDR_TYPE;
163    destAddrPtr->u.ipv4NetAddr = CM_INET_NTOH_UINT32(dstIpPtr->ipV4Addr);
164    return ROK;
165 }
166
167 /******************************************************************************
168  *
169  * @brief Eastablishes the Assoc Req for the received interface type
170  *
171  * @details
172  *
173  *    Function : sctpStartReq
174  *
175  *    Functionality:
176  *       Eastablishes the Assoc Req for the received interface type
177  *
178  * @params[in] DuSctpDestCb *paramPtr
179  * @return ROK     - success
180  *         RFAILED - failure
181  *
182  *******************************************************************************/
183
184 S16 sctpStartReq()
185 {
186    S16 ret = ROK;
187    socket_type = CM_INET_STREAM;
188    fillAddrLst(&f1Params.localAddrLst, &sctpCfg.cuIpAddr);
189
190    if((ret = cmInetSocket(socket_type, &f1Params.lstnSockFd, IPPROTO_SCTP) != ROK))
191    {
192       DU_LOG("\nERROR  -->  SCTP : Socket[%d] coudnt open for listening", f1Params.lstnSockFd.fd);
193    } 
194    else if((ret = cmInetSctpBindx(&f1Params.lstnSockFd, &f1Params.localAddrLst, f1Params.srcPort)) != ROK)
195    {
196       DU_LOG("\nERROR  -->  SCTP: Binding failed at CU");
197    }
198    else if((ret = sctpAccept(&f1Params.lstnSockFd, &f1Params.peerAddr, &f1Params.sockFd)) != ROK)
199    {
200       DU_LOG("\nERROR  -->  SCTP: Unable to accept the connection at CU");
201    }
202    else if(sctpSockPoll() != ROK)
203    {
204       DU_LOG("\nERROR  -->  SCTP: Polling failed to start at CU");
205    }
206    return (ret);
207 }
208 /*******************************************************************
209  *
210  * @brief Sets socket options as per requirement
211  *
212  * @details
213  *
214  *    Function : sctpSetSockOpts
215  *
216  *    Functionality: 
217  *       Sets socket options as per requirement
218  *
219  * @params[in] 
220  * @return ROK     - success
221  *         RFAILED - failure
222  *
223  * ****************************************************************/
224 S16 sctpSetSockOpts(CmInetFd *sock_Fd)
225 {
226    S16 ret = ROK;
227    CmSctpEvent sctpEvent;
228   
229    sctpEvent.dataIoEvent          = TRUE;
230    sctpEvent.associationEvent     = TRUE;
231    sctpEvent.addressEvent         = TRUE;
232    sctpEvent.sendFailureEvent     = TRUE;
233    sctpEvent.peerErrorEvent       = TRUE;
234    sctpEvent.shutdownEvent        = TRUE;
235    sctpEvent.partialDeliveryEvent = TRUE;
236    sctpEvent.adaptationLayerEvent = TRUE;
237
238    if((ret = cmInetSetOpt(sock_Fd, CM_SOCKOPT_LEVEL_SCTP, CM_SOCKOPT_OPT_SCTP_EVENTS, &sctpEvent)) != ROK)
239    {
240      ret = RFAILED;
241    }
242   
243    return (ret);
244 }
245
246 /*******************************************************************
247  *
248  * @brief Initiates connection with peer SCTP
249  *
250  * @details
251  *
252  *    Function : sctpAccept
253  *
254  *    Functionality:
255  *       Establishes SCTP connection with peer.
256  *       Here, DU-SCTP will initate connection towards CU-SCTP
257  *
258  * @params[in] 
259  * @return ROK     - success
260  *         RFAILED - failure
261  *
262  * ****************************************************************/
263 S16 sctpAccept(CmInetFd *lstnSock_Fd, CmInetAddr *peerAddr, CmInetFd *sock_Fd)
264 {
265    uint8_t  ret;
266
267    ret = cmInetListen(lstnSock_Fd, 1);
268    if (ret != ROK)
269    {
270       DU_LOG("\nERROR  -->  SCTP : Listening on socket failed");
271       cmInetClose(lstnSock_Fd);
272       return RFAILED;
273    }
274    
275    DU_LOG("\nINFO  -->  SCTP : Connecting");
276
277    while(!connUp)
278    {
279       ret = cmInetAccept(lstnSock_Fd, peerAddr, sock_Fd);
280       if (ret == ROKDNA)
281       {
282          continue;
283       }
284       else if(ret != ROK)
285       {
286          DU_LOG("\nERROR  -->  SCTP : Failed to accept connection");
287          return RFAILED;
288       }
289       else
290       {
291          connUp = TRUE;
292          sctpSetSockOpts(sock_Fd);
293          break;
294       }
295    }
296    DU_LOG("\nINFO  -->  SCTP : Connection established");
297
298    return ROK;
299 }
300
301 /*******************************************************************
302  *
303  * @brief Handles an SCTP notification message
304  *
305  * @details
306  *
307  *    Function : sctpNtfyHdlr
308  *
309  *    Functionality:
310  *      Handles an SCTP notification message
311  *
312  * @params[in] Notify message
313  *
314  * @return ROK     - success
315  *         RFAILED - failure
316  *
317  * ****************************************************************/
318 S16 sctpNtfyHdlr(CmInetSctpNotification *ntfy)
319 {
320    switch(ntfy->header.nType)
321    {
322       case CM_INET_SCTP_ASSOC_CHANGE :
323          DU_LOG("\nINFO  -->  SCTP : Assoc change notification received");
324          switch(ntfy->u.assocChange.state)
325          {
326             case CM_INET_SCTP_COMM_UP:
327                DU_LOG("DEBUG  -->  Event : COMMUNICATION UP");
328                connUp = TRUE;
329                break;
330             case CM_INET_SCTP_COMM_LOST:
331                DU_LOG("DEBUG  -->  Event : COMMUNICATION LOST");
332                connUp = FALSE;
333                break;
334             case CM_INET_SCTP_RESTART:
335                DU_LOG("DEBUG  -->  Event : SCTP RESTART");
336                connUp = FALSE;
337                break;
338             case CM_INET_SCTP_SHUTDOWN_COMP: /* association gracefully shutdown */
339                DU_LOG("DEBUG  -->  Event : SHUTDOWN COMPLETE");
340                connUp = FALSE;
341                break;
342             case CM_INET_SCTP_CANT_STR_ASSOC:
343                DU_LOG("DEBUG  -->  Event : CANT START ASSOC");
344                connUp = FALSE;
345                break;
346             default:
347                DU_LOG("\nERROR  -->  Invalid event");
348                break;
349          }
350          break;
351       case CM_INET_SCTP_PEER_ADDR_CHANGE :
352          DU_LOG("\nINFO  -->  SCTP : Peer Address Change notificarion received");
353          /* Need to add handler */
354          break;
355       case CM_INET_SCTP_REMOTE_ERROR :
356          DU_LOG("\nINFO  -->  SCTP : Remote Error notification received");
357          break;
358       case CM_INET_SCTP_SEND_FAILED :
359          DU_LOG("\nINFO  -->  SCTP : Send Failed notification received\n");
360          break;
361       case CM_INET_SCTP_SHUTDOWN_EVENT : /* peer socket gracefully closed */
362          DU_LOG("\nINFO  -->  SCTP : Shutdown Event notification received\n");
363          connUp = FALSE;
364          exit(0);
365          break;
366       case CM_INET_SCTP_ADAPTATION_INDICATION :
367          DU_LOG("\nINFO  -->  SCTP : Adaptation Indication received\n");
368          break;
369       case CM_INET_SCTP_PARTIAL_DELIVERY_EVENT:
370          DU_LOG("\nINFO  -->  SCTP : Partial Delivery Event received\n");
371          break;
372       default:
373          DU_LOG("\nERROR  -->  SCTP : Invalid notification type\n");
374          break;
375    }
376
377    sctpNtfyInd(ntfy);
378    return ROK;
379 }/* End of sctpNtfyHdlr */
380
381 /*******************************************************************
382  *
383  * @brief Receives message on the socket
384  *
385  * @details
386  *
387  *    Function : sctpSockPoll
388  *
389  *    Functionality:
390  *      Receives message on the socket
391  *
392  * @params[in] 
393  * @return ROK     - success
394  *         RFAILED - failure
395  *
396  * ****************************************************************/
397 S16 sctpSockPoll()
398 {
399    uint16_t      ret = ROK;
400    uint32_t      timeout;
401    uint32_t      *timeoutPtr;
402    Buffer        *egtpBuf;
403    MsgLen        egtpBufLen;
404    CmInetAddr    egtpFromAddr;
405    CmInetMemInfo memInfo;
406    sctpSockPollParams f1PollParams;
407    uint64_t      numMsgRcvd = 0;
408
409    memset(&f1PollParams, 0, sizeof(sctpSockPollParams));
410     
411    egtpFromAddr.port = egtpCb.dstCb.dstPort;
412    egtpFromAddr.address = egtpCb.dstCb.dstIp;
413
414    if(f1Params.sockFd.blocking)
415    {
416       /* blocking */
417       timeoutPtr = NULLP;
418    }
419    else
420    {
421       /* non-blocking */
422       timeout = 0;
423       timeoutPtr = &timeout;
424    }
425    memInfo.region = CU_APP_MEM_REG;
426    memInfo.pool   = CU_POOL;
427    
428    CM_INET_FD_ZERO(&f1PollParams.readFd);
429
430    while(1)
431    {
432       if((ret = processPolling(&f1PollParams, &f1Params.sockFd, timeoutPtr, &memInfo)) != ROK)
433       {
434          DU_LOG("\nERROR  -->  SCTP : Failed to RecvMsg for F1 at CU\n");
435       }
436
437       /* Receiving EGTP data */
438       egtpBufLen = -1;
439       ret = cmInetRecvMsg(&(egtpCb.recvTptSrvr.sockFd), &egtpFromAddr, &memInfo, &egtpBuf, &egtpBufLen, CM_INET_NO_FLAG);
440       if(ret == ROK && egtpBuf != NULLP)
441       {
442          DU_LOG("\nINFO  -->  EGTP : Received UL Message [%ld]\n", numMsgRcvd+1);
443          numMsgRcvd++;
444          //ODU_PRINT_MSG(egtpBuf, 0 ,0);
445          cuEgtpHdlRecvMsg(egtpBuf);
446
447       }
448    };
449    return (ret);
450 }/* End of sctpSockPoll() */
451
452 /*******************************************************************
453  *
454  * @brief checks for valid readFd and process the InetSctpRecvMsg
455  * during polling 
456  *
457  * @details
458  *
459  *    Function : processPolling
460  *
461  *    Functionality:
462  *         checks for valid readFd and process the InetSctpRecvMsg
463  *         during polling
464  *
465  * @params[in]  Params required for polling
466  * @params[in]  SockFd for file descriptor
467  * @params[in]  timeoutPtr indicates the timeout value
468  * @params[in]  MemInfo indicates memory region
469  *
470  * @return ROK     - success
471  *         RFAILED - failure
472  *
473  * ****************************************************************/
474
475 S16 processPolling(sctpSockPollParams *pollParams, CmInetFd *sockFd, uint32_t *timeoutPtr, CmInetMemInfo *memInfo)
476 {
477    uint16_t ret = ROK;
478    CM_INET_FD_SET(sockFd, &pollParams->readFd);
479    ret = cmInetSelect(&pollParams->readFd, NULLP, timeoutPtr, &pollParams->numFd);
480    if(CM_INET_FD_ISSET(sockFd, &pollParams->readFd))
481    {
482       CM_INET_FD_CLR(sockFd, &pollParams->readFd);
483       ret = cmInetSctpRecvMsg(sockFd, &pollParams->addr, &pollParams->port, memInfo, &pollParams->mBuf, &pollParams->bufLen, &pollParams->info, &pollParams->flag, &pollParams->ntfy);
484       if(connUp & (ret != ROK))
485       {
486          f1Params.bReadFdSet = RFAILED;
487       }
488       else
489       {
490          if(((pollParams->flag & CM_INET_SCTP_MSG_NOTIFICATION) != 0) && (ret == ROK))
491          {
492             ret = sctpNtfyHdlr(&pollParams->ntfy);
493             if(ret != ROK)
494             {
495                DU_LOG("\nERROR  -->  SCTP : Failed to process sctp notify msg\n");
496             }
497          }
498          else if(connUp & (pollParams->port == f1Params.destPort))
499          {  
500             F1APMsgHdlr(pollParams->mBuf);
501             ODU_PUT_MSG_BUF(pollParams->mBuf);
502          }
503          else
504          {
505             ODU_PUT_MSG_BUF(pollParams->mBuf);
506          }
507       } 
508   }
509   return ROK;
510 }/* End of sctpSockPoll() */
511
512 /*******************************************************************
513  *
514  * @brief Send message on SCTP socket
515  *
516  * @details
517  *
518  *    Function : sctpSend 
519  *
520  *    Functionality:
521  *        Send message on SCTP socket
522  *
523  * @params[in] 
524  * @return ROK     - success
525  *         RFAILED - failure
526  *
527  * ****************************************************************/
528 S16 sctpSend(Buffer *mBuf)
529 {
530    uint8_t          ret = ROK;
531    MsgLen           len = 0;          /* number of actually sent octets */
532    CmInetMemInfo    memInfo;                        
533   
534    memset(&memInfo , 0, sizeof(CmInetMemInfo));
535    memInfo.region = CU_APP_MEM_REG;               
536    memInfo.pool   = CU_POOL;
537
538    ret = cmInetSctpSendMsg(&f1Params.sockFd, &f1Params.destIpNetAddr, f1Params.destPort, &memInfo, mBuf, &len, 0, FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
539
540    if(ret != ROK && ret != RWOULDBLOCK)
541    {
542       DU_LOG("\nERROR  -->  SCTP : Send message failed");
543       return RFAILED;
544    }
545
546    return ROK;
547 } /* End of sctpSend */
548
549 /**********************************************************************
550          End of file
551 **********************************************************************/