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