a32a9b35ffc1f554502e7a3bd98f65b23ba87663
[o-du/l2.git] / src / ric_stub / ric_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 <stdio.h> 
22 #include "ric_e2ap_msg_hdl.h"
23 #include "ric_stub_sctp.h"
24
25 CuSctpDestCb ricParams;
26
27
28 /**************************************************************************
29  * @brief Function to configure the Sctp Params during config Request
30  *
31  * @details
32  *
33  *      Function : sctpCfgReq
34  * 
35  *      Functionality:
36  *           This function configures SCTP Params during the config Request
37  *     
38  * @return ROK     - success
39  *         RFAILED - failure
40  *
41  ***************************************************************************/
42
43 S16 sctpCfgReq()
44 {
45    connUp = FALSE;
46    sctpCfg = ricCfgParams.sctpParams;
47
48 /* Fill F1 Params */
49    ricParams.destPort             = sctpCfg.duPort;
50    ricParams.srcPort              = sctpCfg.ricPort;
51    ricParams.bReadFdSet           = ROK;
52    memset(&ricParams.sockFd, -1, sizeof(CmInetFd));
53    memset(&ricParams.lstnSockFd, -1, sizeof(CmInetFd));
54    fillDestNetAddr(&ricParams.destIpNetAddr, &sctpCfg.duIpAddr);
55
56    return ROK;
57 }
58
59 /*******************************************************************
60  *
61  * @brief Fills the address List of the source Ip Address
62  *
63  * @details
64  *
65  *    Function : fillAddrLst
66  *
67  *    Functionality:
68  *       Fills the address List of source Ip Address
69  *
70  * @params[in] CmInetNetAddrLst *addrLstPtr, Address List pointer
71  * @params[in] F1IpAddr *srcIpAddr, src Ip Adrress to be filled in the Address List
72  * @return ROK     - success
73  *         RFAILED - failure
74  *
75  ******************************************************************/
76
77 S16 fillAddrLst(CmInetNetAddrLst *addrLstPtr, SctpIpAddr *ipAddr)
78
79    addrLstPtr->count++;
80    addrLstPtr->addrs[(addrLstPtr->count - 1)].type = CM_INET_IPV4ADDR_TYPE;
81    addrLstPtr->addrs[(addrLstPtr->count - 1)].u.ipv4NetAddr = CM_INET_NTOH_U32(ipAddr->ipV4Addr);
82
83    return ROK;
84 }
85
86 /******************************************************************************
87  *
88  * @brief Fills the address List of the source Ip Address
89  *
90  * @details
91  *
92  *    Function : fillDestNetAddr
93  *
94  *    Functionality:
95  *       Fills the address List of destinatoion Ip Address
96  *
97  * @params[in] CmInetNetAddr *destAddrPtr, Address List pointer
98  * @params[in] F1IpAddr *dstIpAddr, destIp Address to be filled in the Address List
99  * @return ROK     - success
100  *         RFAILED - failure
101  *
102  *******************************************************************************/
103 S16 fillDestNetAddr(CmInetNetAddr *destAddrPtr, SctpIpAddr *dstIpPtr)
104 {
105    /* Filling destination address */
106    destAddrPtr->type = CM_INET_IPV4ADDR_TYPE;
107    destAddrPtr->u.ipv4NetAddr = CM_INET_NTOH_U32(dstIpPtr->ipV4Addr);
108    return ROK;
109 }
110
111 /******************************************************************************
112  *
113  * @brief Eastablishes the Assoc Req for the received interface type
114  *
115  * @details
116  *
117  *    Function : sctpStartReq
118  *
119  *    Functionality:
120  *       Eastablishes the Assoc Req for the received interface type
121  *
122  * @params[in] DuSctpDestCb *paramPtr
123  * @return ROK     - success
124  *         RFAILED - failure
125  *
126  *******************************************************************************/
127
128 S16 sctpStartReq()
129 {
130    S16 ret = ROK;
131    socket_type = CM_INET_STREAM;
132    fillAddrLst(&ricParams.localAddrLst, &sctpCfg.ricIpAddr);
133
134    if((ret = cmInetSocket(socket_type, &ricParams.lstnSockFd, IPPROTO_SCTP) != ROK))
135    {
136       DU_LOG("\nSCTP : Socket[%d] coudnt open for listening", ricParams.lstnSockFd.fd);
137    } 
138    else if((ret = cmInetSctpBindx(&ricParams.lstnSockFd, &ricParams.localAddrLst, ricParams.srcPort)) != ROK)
139    {
140       DU_LOG("\nSCTP: Binding failed at RIC");
141    }
142    else if((ret = sctpAccept(&ricParams.lstnSockFd, &ricParams.peerAddr, &ricParams.sockFd)) != ROK)
143    {
144       DU_LOG("\nSCTP: Unable to accept the connection at RIC");
145    }
146    else if(sctpSockPoll() != ROK)
147    {
148       DU_LOG("\nSCTP: Polling failed to start at RIC");
149    }
150    RETVALUE(ret);
151 }
152 /*******************************************************************
153  *
154  * @brief Sets socket options as per requirement
155  *
156  * @details
157  *
158  *    Function : sctpSetSockOpts
159  *
160  *    Functionality: 
161  *       Sets socket options as per requirement
162  *
163  * @params[in] 
164  * @return ROK     - success
165  *         RFAILED - failure
166  *
167  * ****************************************************************/
168 S16 sctpSetSockOpts(CmInetFd *sock_Fd)
169 {
170    S16 ret = ROK;
171    CmSctpEvent sctpEvent;
172   
173    sctpEvent.dataIoEvent          = TRUE;
174    sctpEvent.associationEvent     = TRUE;
175    sctpEvent.addressEvent         = TRUE;
176    sctpEvent.sendFailureEvent     = TRUE;
177    sctpEvent.peerErrorEvent       = TRUE;
178    sctpEvent.shutdownEvent        = TRUE;
179    sctpEvent.partialDeliveryEvent = TRUE;
180    sctpEvent.adaptationLayerEvent = TRUE;
181
182    if((ret = cmInetSetOpt(sock_Fd, CM_SOCKOPT_LEVEL_SCTP, CM_SOCKOPT_OPT_SCTP_EVENTS, &sctpEvent)) != ROK)
183    {
184      ret = RFAILED;
185    }
186   
187    RETVALUE(ret);
188 }
189
190 /*******************************************************************
191  *
192  * @brief Initiates connection with peer SCTP
193  *
194  * @details
195  *
196  *    Function : sctpAccept
197  *
198  *    Functionality:
199  *       Establishes SCTP connection with peer.
200  *       Here, DU-SCTP will initate connection towards RIC-SCTP
201  *
202  * @params[in] 
203  * @return ROK     - success
204  *         RFAILED - failure
205  *
206  * ****************************************************************/
207 S16 sctpAccept(CmInetFd *lstnSock_Fd, CmInetAddr *peerAddr, CmInetFd *sock_Fd)
208 {
209    U8  ret;
210
211    ret = cmInetListen(lstnSock_Fd, 1);
212    if (ret != ROK)
213    {
214       DU_LOG("\nSCTP : Listening on socket failed");
215       cmInetClose(lstnSock_Fd);
216       return RFAILED;
217    }
218    
219    DU_LOG("\nSCTP : Connecting");
220
221    while(!connUp)
222    {
223       ret = cmInetAccept(lstnSock_Fd, peerAddr, sock_Fd);
224       if (ret == ROKDNA)
225       {
226          continue;
227       }
228       else if(ret != ROK)
229       {
230          DU_LOG("\nSCTP : Failed to accept connection");
231          return RFAILED;
232       }
233       else
234       {
235          connUp = TRUE;
236          sctpSetSockOpts(sock_Fd);
237          break;
238       }
239    }
240    DU_LOG("\nSCTP : Connection established");
241
242    return ROK;
243 }
244
245 /*******************************************************************
246  *
247  * @brief Handles an SCTP notification message
248  *
249  * @details
250  *
251  *    Function : sctpNtfyHdlr
252  *
253  *    Functionality:
254  *      Handles an SCTP notification message
255  *
256  * @params[in] Notify message
257  *
258  * @return ROK     - success
259  *         RFAILED - failure
260  *
261  * ****************************************************************/
262 S16 sctpNtfyHdlr(CmInetSctpNotification *ntfy)
263 {
264    switch(ntfy->header.nType)
265    {
266       case CM_INET_SCTP_ASSOC_CHANGE :
267          DU_LOG("\nSCTP : Assoc change notification received");
268          switch(ntfy->u.assocChange.state)
269          {
270             case CM_INET_SCTP_COMM_UP:
271                DU_LOG("Event : COMMUNICATION UP");
272                connUp = TRUE;
273                break;
274             case CM_INET_SCTP_COMM_LOST:
275                DU_LOG("Event : COMMUNICATION LOST");
276                connUp = FALSE;
277                break;
278             case CM_INET_SCTP_RESTART:
279                DU_LOG("Event : SCTP RESTART");
280                connUp = FALSE;
281                break;
282             case CM_INET_SCTP_SHUTDOWN_COMP: /* association gracefully shutdown */
283                DU_LOG("Event : SHUTDOWN COMPLETE");
284                connUp = FALSE;
285                break;
286             case CM_INET_SCTP_CANT_STR_ASSOC:
287                DU_LOG("Event : CANT START ASSOC");
288                connUp = FALSE;
289                break;
290             default:
291                DU_LOG("\nInvalid event");
292                break;
293          }
294          break;
295       case CM_INET_SCTP_PEER_ADDR_CHANGE :
296          DU_LOG("\nSCTP : Peer Address Change notificarion received");
297          /* Need to add handler */
298          break;
299       case CM_INET_SCTP_REMOTE_ERROR :
300          DU_LOG("\nSCTP : Remote Error notification received");
301          break;
302       case CM_INET_SCTP_SEND_FAILED :
303          DU_LOG("\nSCTP : Send Failed notification received\n");
304          break;
305       case CM_INET_SCTP_SHUTDOWN_EVENT : /* peer socket gracefully closed */
306          DU_LOG("\nSCTP : Shutdown Event notification received\n");
307          connUp = FALSE;
308          exit(0);
309          break;
310       case CM_INET_SCTP_ADAPTATION_INDICATION :
311          DU_LOG("\nSCTP : Adaptation Indication received\n");
312          break;
313       case CM_INET_SCTP_PARTIAL_DELIVERY_EVENT:
314          DU_LOG("\nSCTP : Partial Delivery Event received\n");
315          break;
316       default:
317          DU_LOG("\nSCTP : Invalid notification type\n");
318          break;
319    }
320
321    sctpNtfyInd(ntfy);
322    return ROK;
323 }/* End of sctpNtfyHdlr */
324
325 /*******************************************************************
326  *
327  * @brief Receives message on the socket
328  *
329  * @details
330  *
331  *    Function : sctpSockPoll
332  *
333  *    Functionality:
334  *      Receives message on the socket
335  *
336  * @params[in] 
337  * @return ROK     - success
338  *         RFAILED - failure
339  *
340  * ****************************************************************/
341 S16 sctpSockPoll()
342 {
343    U16 ret = ROK;
344    U32           timeout;
345    U32           *timeoutPtr;
346    CmInetMemInfo memInfo;
347    sctpSockPollParams e2PollParams;
348
349    memset(&e2PollParams, 0, sizeof(sctpSockPollParams));
350     
351    if(ricParams.sockFd.blocking)
352    {
353       /* blocking */
354       timeoutPtr = NULLP;
355    }
356    else
357    {
358       /* non-blocking */
359       timeout = 0;
360       timeoutPtr = &timeout;
361    }
362
363    memInfo.region = RIC_APP_MEM_REG;
364    memInfo.pool   = RIC_POOL;
365
366    CM_INET_FD_ZERO(&e2PollParams.readFd);
367
368    DU_LOG("\nSCTP : Polling started at RIC\n");
369    while(1)
370    {
371       if((ret = processPolling(&e2PollParams, &ricParams.sockFd, timeoutPtr, &memInfo)) != ROK)
372       {
373          DU_LOG("\nSCTP : Failed to RecvMsg for E2 at RIC \n");
374       }
375    };
376    RETVALUE(ret);
377 }/* End of sctpSockPoll() */
378
379 /*******************************************************************
380  *
381  * @brief checks for valid readFd and process the InetSctpRecvMsg
382  * during polling 
383  *
384  * @details
385  *
386  *    Function : processPolling
387  *
388  *    Functionality:
389  *         checks for valid readFd and process the InetSctpRecvMsg
390  *         during polling
391  *
392  * @params[in]  Params required for polling
393  * @params[in]  SockFd for file descriptor
394  * @params[in]  timeoutPtr indicates the timeout value
395  * @params[in]  MemInfo indicates memory region
396  *
397  * @return ROK     - success
398  *         RFAILED - failure
399  *
400  * ****************************************************************/
401
402  
403 S16 processPolling(sctpSockPollParams *pollParams, CmInetFd *sockFd, U32 *timeoutPtr, CmInetMemInfo *memInfo)
404 {
405    U16 ret = ROK;
406    CM_INET_FD_SET(sockFd, &pollParams->readFd);
407    ret = cmInetSelect(&pollParams->readFd, NULLP, timeoutPtr, &pollParams->numFd);
408    if(CM_INET_FD_ISSET(sockFd, &pollParams->readFd))
409    {
410       CM_INET_FD_CLR(sockFd, &pollParams->readFd);
411       ret = cmInetSctpRecvMsg(sockFd, &pollParams->addr, &pollParams->port, memInfo, &pollParams->mBuf, &pollParams->bufLen, &pollParams->info, &pollParams->flag, &pollParams->ntfy);
412       if(connUp & (ret != ROK))
413       {
414          ricParams.bReadFdSet = RFAILED;
415       }
416       else
417       {
418          if(((pollParams->flag & CM_INET_SCTP_MSG_NOTIFICATION) != 0) && (ret == ROK))
419          {
420             ret = sctpNtfyHdlr(&pollParams->ntfy);
421             if(ret != ROK)
422             {
423                DU_LOG("\nSCTP : Failed to process sctp notify msg\n");
424             }
425          }
426          else if(connUp & (pollParams->port == ricParams.destPort))
427          {  
428             E2APMsgHdlr(pollParams->mBuf);
429             SPutMsg(pollParams->mBuf);
430          }
431          else
432          {
433             SPutMsg(pollParams->mBuf);
434          }
435       } 
436   }
437   return ROK;
438 }/* End of sctpSockPoll() */
439
440 /*******************************************************************
441  *
442  * @brief Send message on SCTP socket
443  *
444  * @details
445  *
446  *    Function : sctpSend 
447  *
448  *    Functionality:
449  *        Send message on SCTP socket
450  *
451  * @params[in] 
452  * @return ROK     - success
453  *         RFAILED - failure
454  *
455  * ****************************************************************/
456 S16 sctpSend(Buffer *mBuf)
457 {
458    U8               ret;
459    MsgLen           len;          /* number of actually sent octets */
460    CmInetMemInfo    memInfo;                        
461    
462    memInfo.region = RIC_APP_MEM_REG;               
463    memInfo.pool   = RIC_POOL;
464
465    ret = cmInetSctpSendMsg(&ricParams.sockFd, &ricParams.destIpNetAddr, ricParams.destPort, &memInfo, mBuf, &len, 0, FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
466
467    if(ret != ROK && ret != RWOULDBLOCK)
468    {
469       DU_LOG("\nSCTP : Send message failed");
470       return RFAILED;
471    }
472
473    return ROK;
474 } /* End of sctpSend */
475 /**********************************************************************
476          End of file
477 **********************************************************************/