1 /*******************************************************************************
2 ################################################################################
3 # Copyright (c) [2017-2019] [Radisys] #
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 #
9 # http://www.apache.org/licenses/LICENSE-2.0 #
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 *******************************************************************************/
19 /* This file contains all SCTP related functionality */
21 #include "common_def.h"
22 #include "ric_stub_sctp.h"
24 #include "ric_e2ap_msg_hdl.h"
27 /**************************************************************************
28 * @brief Function to configure the Sctp Params during config Request
32 * Function : sctpCfgReq
35 * This function configures SCTP Params during the config Request
37 * @return ROK - success
40 ***************************************************************************/
46 sctpCb.sctpCfg = ricCfgParams.sctpParams;
47 for(destIdx=0; destIdx < sctpCb.sctpCfg.numDu; destIdx++)
49 sctpCb.destCb[destIdx].destPort = sctpCb.sctpCfg.sctpAssoc[destIdx].duPort;
50 sctpCb.destCb[destIdx].srcPort = sctpCb.sctpCfg.sctpAssoc[destIdx].ricPort;
51 sctpCb.destCb[destIdx].bReadFdSet = ROK;
52 memset(&sctpCb.destCb[destIdx].sockFd, -1, sizeof(CmInetFd));
53 memset(&sctpCb.destCb[destIdx].lstnSockFd, -1, sizeof(CmInetFd));
54 fillDestNetAddr(&sctpCb.destCb[destIdx].destIpNetAddr, &sctpCb.sctpCfg.sctpAssoc[destIdx].duIpAddr);
55 fillAddrLst(&sctpCb.destCb[destIdx].localAddrLst, &sctpCb.sctpCfg.sctpAssoc[destIdx].ricIpAddr);
56 sctpCb.destCb[destIdx].connUp = false;
58 sctpCb.numDu = sctpCb.sctpCfg.numDu;
62 /*******************************************************************
64 * @brief Fills the address List of the source Ip Address
68 * Function : fillAddrLst
71 * Fills the address List of source Ip Address
73 * @params[in] CmInetNetAddrLst *addrLstPtr, Address List pointer
74 * @params[in] F1IpAddr *srcIpAddr, src Ip Adrress to be filled in the Address List
75 * @return ROK - success
78 ******************************************************************/
80 uint8_t fillAddrLst(CmInetNetAddrLst *addrLstPtr, SctpIpAddr *ipAddr)
82 addrLstPtr->addrs[addrLstPtr->count].type = CM_INET_IPV4ADDR_TYPE;
83 addrLstPtr->addrs[addrLstPtr->count].u.ipv4NetAddr = CM_INET_NTOH_UINT32(ipAddr->ipV4Addr);
89 /******************************************************************************
91 * @brief Fills the address List of the source Ip Address
95 * Function : fillDestNetAddr
98 * Fills the address List of destinatoion Ip Address
100 * @params[in] CmInetNetAddr *destAddrPtr, Address List pointer
101 * @params[in] F1IpAddr *dstIpAddr, destIp Address to be filled in the Address List
102 * @return ROK - success
105 *******************************************************************************/
106 uint8_t fillDestNetAddr(CmInetNetAddr *destAddrPtr, SctpIpAddr *dstIpPtr)
108 /* Filling destination address */
109 destAddrPtr->type = CM_INET_IPV4ADDR_TYPE;
110 destAddrPtr->u.ipv4NetAddr = CM_INET_NTOH_UINT32(dstIpPtr->ipV4Addr);
114 /******************************************************************************
116 * @brief Eastablishes the Assoc Req for the received interface type
120 * Function : sctpStartReq
123 * Eastablishes the Assoc Req for the received interface type
125 * @params[in] DuSctpDestCb *paramPtr
126 * @return ROK - success
129 *******************************************************************************/
131 uint8_t sctpStartReq()
136 socket_type = CM_INET_STREAM;
138 for(destIdx=0; destIdx < sctpCb.numDu; destIdx++)
140 if((ret = cmInetSocket(socket_type, &sctpCb.destCb[destIdx].lstnSockFd, IPPROTO_SCTP) != ROK))
142 DU_LOG("\nERROR --> SCTP : Socket[%d] coudnt open for listening", sctpCb.destCb[destIdx].lstnSockFd.fd);
144 else if((ret = cmInetSctpBindx(&sctpCb.destCb[destIdx].lstnSockFd, &sctpCb.destCb[destIdx].localAddrLst, \
145 sctpCb.destCb[destIdx].srcPort)) != ROK)
147 DU_LOG("\nERROR --> SCTP: Binding failed at RIC");
149 else if((ret = sctpAccept(&sctpCb.destCb[destIdx])) != ROK)
151 DU_LOG("\nERROR --> SCTP: Unable to accept the connection at RIC");
155 if(sctpSockPoll() != ROK)
157 DU_LOG("\nERROR --> SCTP: Polling failed to start at RIC");
161 /*******************************************************************
163 * @brief Sets socket options as per requirement
167 * Function : sctpSetSockOpts
170 * Sets socket options as per requirement
173 * @return ROK - success
176 * ****************************************************************/
177 uint8_t sctpSetSockOpts(CmInetFd *sock_Fd)
180 CmSctpEvent sctpEvent;
182 sctpEvent.dataIoEvent = TRUE;
183 sctpEvent.associationEvent = TRUE;
184 sctpEvent.addressEvent = TRUE;
185 sctpEvent.sendFailureEvent = TRUE;
186 sctpEvent.peerErrorEvent = TRUE;
187 sctpEvent.shutdownEvent = TRUE;
188 sctpEvent.partialDeliveryEvent = TRUE;
189 sctpEvent.adaptationLayerEvent = TRUE;
191 if((ret = cmInetSetOpt(sock_Fd, CM_SOCKOPT_LEVEL_SCTP, CM_SOCKOPT_OPT_SCTP_EVENTS, &sctpEvent)) != ROK)
199 /*******************************************************************
201 * @brief Initiates connection with peer SCTP
205 * Function : sctpAccept
208 * Establishes SCTP connection with peer.
209 * Here, DU-SCTP will initate connection towards RIC-SCTP
212 * @return ROK - success
215 * ****************************************************************/
216 uint8_t sctpAccept(RicSctpDestCb *destCb)
220 ret = cmInetListen(&destCb->lstnSockFd, 1);
223 DU_LOG("\nERROR --> SCTP : Listening on socket failed");
224 cmInetClose(&destCb->lstnSockFd);
228 DU_LOG("\nINFO --> SCTP : Connecting");
230 while(!destCb->connUp)
232 ret = cmInetAccept(&destCb->lstnSockFd, &destCb->peerAddr, &destCb->sockFd);
239 DU_LOG("\nERROR --> SCTP : Failed to accept connection");
244 destCb->connUp = TRUE;
245 sctpSetSockOpts(&destCb->sockFd);
249 DU_LOG("\nINFO --> SCTP : Connection established");
254 /*******************************************************************
256 * @brief Handles an SCTP notification message
260 * Function : sctpNtfyHdlr
263 * Handles an SCTP notification message
265 * @params[in] Notify message
267 * @return ROK - success
270 * ****************************************************************/
271 uint8_t sctpNtfyHdlr(RicSctpDestCb *destCb, CmInetSctpNotification *ntfy)
273 switch(ntfy->header.nType)
275 case CM_INET_SCTP_ASSOC_CHANGE :
276 DU_LOG("\nINFO --> SCTP : Assoc change notification received");
277 switch(ntfy->u.assocChange.state)
279 case CM_INET_SCTP_COMM_UP:
280 DU_LOG("\nINFO --> Event : COMMUNICATION UP");
281 destCb->connUp = TRUE;
283 case CM_INET_SCTP_COMM_LOST:
284 DU_LOG("\nINFO --> Event : COMMUNICATION LOST");
285 destCb->connUp = FALSE;
287 case CM_INET_SCTP_RESTART:
288 DU_LOG("\nINFO --> Event : SCTP RESTART");
289 destCb->connUp = FALSE;
291 case CM_INET_SCTP_SHUTDOWN_COMP: /* association gracefully shutdown */
292 DU_LOG("\nINFO --> Event : SHUTDOWN COMPLETE");
293 destCb->connUp = FALSE;
295 case CM_INET_SCTP_CANT_STR_ASSOC:
296 DU_LOG("\nINFO --> Event : CANT START ASSOC");
297 destCb->connUp = FALSE;
300 DU_LOG("\nERROR --> Invalid event");
304 case CM_INET_SCTP_PEER_ADDR_CHANGE :
305 DU_LOG("\nINFO --> SCTP : Peer Address Change notificarion received");
306 /* Need to add handler */
308 case CM_INET_SCTP_REMOTE_ERROR :
309 DU_LOG("\nINFO --> SCTP : Remote Error notification received");
311 case CM_INET_SCTP_SEND_FAILED :
312 DU_LOG("\nINFO --> SCTP : Send Failed notification received\n");
314 case CM_INET_SCTP_SHUTDOWN_EVENT : /* peer socket gracefully closed */
315 DU_LOG("\nINFO --> SCTP : Shutdown Event notification received\n");
316 destCb->connUp = FALSE;
319 case CM_INET_SCTP_ADAPTATION_INDICATION :
320 DU_LOG("\nINFO --> SCTP : Adaptation Indication received\n");
322 case CM_INET_SCTP_PARTIAL_DELIVERY_EVENT:
323 DU_LOG("\nINFO --> SCTP : Partial Delivery Event received\n");
326 DU_LOG("\nERROR --> SCTP : Invalid notification type\n");
332 }/* End of sctpNtfyHdlr */
334 /*******************************************************************
336 * @brief Receives message on the socket
340 * Function : sctpSockPoll
343 * Receives message on the socket
346 * @return ROK - success
349 * ****************************************************************/
350 uint8_t sctpSockPoll()
355 uint32_t *timeoutPtr;
356 CmInetMemInfo memInfo;
357 sctpSockPollParams e2PollParams;
359 memset(&e2PollParams, 0, sizeof(sctpSockPollParams));
361 /* All sockets are non-blocking */
363 timeoutPtr = &timeout;
364 memInfo.region = RIC_APP_MEM_REG;
365 memInfo.pool = RIC_POOL;
367 CM_INET_FD_ZERO(&e2PollParams.readFd);
369 DU_LOG("\nINFO --> SCTP : Polling started at RIC\n");
372 /* Receiving SCTP data */
373 for(destIdx = 0; destIdx < sctpCb.numDu; destIdx++)
376 if((ret = processPolling(&e2PollParams, &sctpCb.destCb[destIdx], timeoutPtr, &memInfo)) != ROK)
378 DU_LOG("\nERROR --> SCTP : Failed to RecvMsg for E2 at RIC \n");
383 }/* End of sctpSockPoll() */
385 /*******************************************************************
387 * @brief checks for valid readFd and process the InetSctpRecvMsg
392 * Function : processPolling
395 * checks for valid readFd and process the InetSctpRecvMsg
398 * @params[in] Params required for polling
399 * @params[in] SockFd for file descriptor
400 * @params[in] timeoutPtr indicates the timeout value
401 * @params[in] MemInfo indicates memory region
403 * @return ROK - success
406 * ****************************************************************/
409 uint8_t processPolling(sctpSockPollParams *pollParams, RicSctpDestCb *destCb, uint32_t *timeoutPtr, CmInetMemInfo *memInfo)
413 CM_INET_FD_SET(&destCb->sockFd, &pollParams->readFd);
414 ret = cmInetSelect(&pollParams->readFd, NULLP, timeoutPtr, &pollParams->numFd);
415 if(CM_INET_FD_ISSET(&destCb->sockFd, &pollParams->readFd))
417 CM_INET_FD_CLR(&destCb->sockFd, &pollParams->readFd);
418 ret = cmInetSctpRecvMsg(&destCb->sockFd, &pollParams->addr, &pollParams->port, memInfo, &pollParams->mBuf, \
419 &pollParams->bufLen, &pollParams->info, &pollParams->flag, &pollParams->ntfy);
420 if(destCb->connUp & (ret != ROK))
422 destCb->bReadFdSet = RFAILED;
426 if(((pollParams->flag & CM_INET_SCTP_MSG_NOTIFICATION) != 0) && (ret == ROK))
428 ret = sctpNtfyHdlr(destCb, &pollParams->ntfy);
431 DU_LOG("\nERROR --> SCTP : Failed to process sctp notify msg\n");
434 else if(destCb->connUp & (pollParams->port == destCb->destPort))
436 E2APMsgHdlr(pollParams->mBuf);
437 ODU_PUT_MSG_BUF(pollParams->mBuf);
441 ODU_PUT_MSG_BUF(pollParams->mBuf);
446 }/* End of sctpSockPoll() */
448 /*******************************************************************
450 * @brief Send message on SCTP socket
454 * Function : sctpSend
457 * Send message on SCTP socket
460 * @return ROK - success
463 * ****************************************************************/
464 uint8_t sctpSend(Buffer *mBuf)
467 MsgLen len; /* number of actually sent octets */
468 CmInetMemInfo memInfo;
470 memInfo.region = RIC_APP_MEM_REG;
471 memInfo.pool = RIC_POOL;
473 ret = cmInetSctpSendMsg(&sctpCb.destCb[0].sockFd, &sctpCb.destCb[0].destIpNetAddr, sctpCb.destCb[0].destPort, &memInfo, \
474 mBuf, &len, 0, FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
476 if(ret != ROK && ret != RWOULDBLOCK)
478 DU_LOG("\nERROR --> SCTP : Send message failed");
483 } /* End of sctpSend */
484 /**********************************************************************
486 **********************************************************************/