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