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"
30 /**************************************************************************
31 * @brief Function to configure the Sctp Params during config Request
35 * Function : sctpCfgReq
38 * This function configures SCTP Params during the config Request
40 * @return ROK - success
43 ***************************************************************************/
47 int destIdx = 0, assocIdx = 0;
49 sctpCb.sctpCfg = ricCb.ricCfgParams.sctpParams;
50 fillAddrLst(&sctpCb.localAddrLst, &sctpCb.sctpCfg.localIpAddr);
51 memset(&sctpCb.e2LstnSockFd, -1, sizeof(CmInetFd));
52 for(destIdx=0; destIdx < sctpCb.sctpCfg.numDestNode; destIdx++)
54 sctpCb.assocCb[assocIdx].destPort = sctpCb.sctpCfg.destCb[destIdx].destPort;
55 sctpCb.assocCb[assocIdx].bReadFdSet = ROK;
56 memset(&sctpCb.assocCb[assocIdx].sockFd, -1, sizeof(CmInetFd));
57 fillDestNetAddr(&sctpCb.assocCb[assocIdx].destIpNetAddr, &sctpCb.sctpCfg.destCb[destIdx].destIpAddr);
58 sctpCb.assocCb[assocIdx].connUp = false;
61 sctpCb.numAssoc = assocIdx;
65 /*******************************************************************
67 * @brief Fills the address List of the source Ip Address
71 * Function : fillAddrLst
74 * Fills the address List of source Ip Address
76 * @params[in] CmInetNetAddrLst *addrLstPtr, Address List pointer
77 * @params[in] F1IpAddr *srcIpAddr, src Ip Adrress to be filled in the Address List
78 * @return ROK - success
81 ******************************************************************/
83 uint8_t fillAddrLst(CmInetNetAddrLst *addrLstPtr, SctpIpAddr *ipAddr)
85 addrLstPtr->addrs[addrLstPtr->count].type = CM_INET_IPV4ADDR_TYPE;
86 addrLstPtr->addrs[addrLstPtr->count].u.ipv4NetAddr = CM_INET_NTOH_UINT32(ipAddr->ipV4Addr);
92 /******************************************************************************
94 * @brief Fills the address List of the source Ip Address
98 * Function : fillDestNetAddr
101 * Fills the address List of destinatoion Ip Address
103 * @params[in] CmInetNetAddr *destAddrPtr, Address List pointer
104 * @params[in] F1IpAddr *dstIpAddr, destIp Address to be filled in the Address List
105 * @return ROK - success
108 *******************************************************************************/
109 uint8_t fillDestNetAddr(CmInetNetAddr *destAddrPtr, SctpIpAddr *dstIpPtr)
111 /* Filling destination address */
112 destAddrPtr->type = CM_INET_IPV4ADDR_TYPE;
113 destAddrPtr->u.ipv4NetAddr = CM_INET_NTOH_UINT32(dstIpPtr->ipV4Addr);
117 /******************************************************************************
119 * @brief Eastablishes the Assoc Req for the received interface type
123 * Function : sctpStartReq
126 * Eastablishes the Assoc Req for the received interface type
128 * @params[in] DuSctpDestCb *paramPtr
129 * @return ROK - success
132 *******************************************************************************/
134 uint8_t sctpStartReq()
136 uint8_t assocIdx = 0;
139 socket_type = CM_INET_STREAM;
144 if((ret = cmInetSocket(socket_type, &sctpCb.e2LstnSockFd, IPPROTO_SCTP) != ROK))
146 DU_LOG("\nERROR --> SCTP : Socket[%d] coudnt open for listening", sctpCb.e2LstnSockFd.fd);
148 else if((ret = cmInetSctpBindx(&sctpCb.e2LstnSockFd, &sctpCb.localAddrLst, sctpCb.sctpCfg.e2SctpPort)) != ROK)
150 DU_LOG("\nERROR --> SCTP: Binding failed at RIC");
152 else if((ret = cmInetListen(&sctpCb.e2LstnSockFd, 1)) != ROK)
154 DU_LOG("\nERROR --> SCTP: Unable to accept the connection at CU");
155 DU_LOG("\nERROR --> SCTP : Listening on socket failed");
156 cmInetClose(&sctpCb.e2LstnSockFd);
161 for(assocIdx=0; assocIdx < sctpCb.numAssoc; assocIdx++)
163 if((ret = sctpAccept(&sctpCb.assocCb[assocIdx])) != ROK)
165 DU_LOG("\nERROR --> SCTP: Unable to accept the connection at RIC");
173 if(sctpSockPoll() != ROK)
175 DU_LOG("\nERROR --> SCTP: Polling failed to start at RIC");
181 /*******************************************************************
183 * @brief Sets socket options as per requirement
187 * Function : sctpSetSockOpts
190 * Sets socket options as per requirement
193 * @return ROK - success
196 * ****************************************************************/
197 uint8_t sctpSetSockOpts(CmInetFd *sock_Fd)
200 CmSctpEvent sctpEvent;
202 sctpEvent.dataIoEvent = TRUE;
203 sctpEvent.associationEvent = TRUE;
204 sctpEvent.addressEvent = TRUE;
205 sctpEvent.sendFailureEvent = TRUE;
206 sctpEvent.peerErrorEvent = TRUE;
207 sctpEvent.shutdownEvent = TRUE;
208 sctpEvent.partialDeliveryEvent = TRUE;
209 sctpEvent.adaptationLayerEvent = TRUE;
211 if((ret = cmInetSetOpt(sock_Fd, CM_SOCKOPT_LEVEL_SCTP, CM_SOCKOPT_OPT_SCTP_EVENTS, &sctpEvent)) != ROK)
219 /*******************************************************************
221 * @brief Initiates connection with peer SCTP
225 * Function : sctpAccept
228 * Establishes SCTP connection with peer.
229 * Here, DU-SCTP will initate connection towards RIC-SCTP
232 * @return ROK - success
235 * ****************************************************************/
236 uint8_t sctpAccept(RicSctpAssocCb *assocCb)
240 DU_LOG("\nINFO --> SCTP : Connecting");
242 while(!assocCb->connUp)
244 ret = cmInetAccept(&sctpCb.e2LstnSockFd, &assocCb->peerAddr, &assocCb->sockFd);
251 DU_LOG("\nERROR --> SCTP : Failed to accept connection");
256 assocCb->connUp = TRUE;
257 sctpSetSockOpts(&assocCb->sockFd);
261 DU_LOG("\nINFO --> SCTP : Connection established");
266 /*******************************************************************
268 * @brief Handles an SCTP notification message
272 * Function : sctpNtfyHdlr
275 * Handles an SCTP notification message
277 * @params[in] Notify message
279 * @return ROK - success
282 * ****************************************************************/
283 uint8_t sctpNtfyHdlr(RicSctpAssocCb *assocCb, CmInetSctpNotification *ntfy)
285 switch(ntfy->header.nType)
287 case CM_INET_SCTP_ASSOC_CHANGE :
288 DU_LOG("\nINFO --> SCTP : Assoc change notification received");
289 switch(ntfy->u.assocChange.state)
291 case CM_INET_SCTP_COMM_UP:
292 DU_LOG("\nINFO --> Event : COMMUNICATION UP");
293 assocCb->connUp = TRUE;
295 case CM_INET_SCTP_COMM_LOST:
296 DU_LOG("\nINFO --> Event : COMMUNICATION LOST");
297 assocCb->connUp = FALSE;
299 case CM_INET_SCTP_RESTART:
300 DU_LOG("\nINFO --> Event : SCTP RESTART");
301 assocCb->connUp = FALSE;
303 case CM_INET_SCTP_SHUTDOWN_COMP: /* association gracefully shutdown */
304 DU_LOG("\nINFO --> Event : SHUTDOWN COMPLETE");
305 assocCb->connUp = FALSE;
307 case CM_INET_SCTP_CANT_STR_ASSOC:
308 DU_LOG("\nINFO --> Event : CANT START ASSOC");
309 assocCb->connUp = FALSE;
312 DU_LOG("\nERROR --> Invalid event");
316 case CM_INET_SCTP_PEER_ADDR_CHANGE :
317 DU_LOG("\nINFO --> SCTP : Peer Address Change notificarion received");
318 /* Need to add handler */
320 case CM_INET_SCTP_REMOTE_ERROR :
321 DU_LOG("\nINFO --> SCTP : Remote Error notification received");
323 case CM_INET_SCTP_SEND_FAILED :
324 DU_LOG("\nINFO --> SCTP : Send Failed notification received\n");
326 case CM_INET_SCTP_SHUTDOWN_EVENT : /* peer socket gracefully closed */
327 DU_LOG("\nINFO --> SCTP : Shutdown Event notification received\n");
328 assocCb->connUp = FALSE;
329 deleteE2NodeInfo(&ricCb.duInfo[0]);
332 case CM_INET_SCTP_ADAPTATION_INDICATION :
333 DU_LOG("\nINFO --> SCTP : Adaptation Indication received\n");
335 case CM_INET_SCTP_PARTIAL_DELIVERY_EVENT:
336 DU_LOG("\nINFO --> SCTP : Partial Delivery Event received\n");
339 DU_LOG("\nERROR --> SCTP : Invalid notification type\n");
345 }/* End of sctpNtfyHdlr */
347 /*******************************************************************
349 * @brief Receives message on the socket
353 * Function : sctpSockPoll
356 * Receives message on the socket
359 * @return ROK - success
362 * ****************************************************************/
363 uint8_t sctpSockPoll()
368 uint32_t *timeoutPtr;
369 CmInetMemInfo memInfo;
370 sctpSockPollParams e2PollParams;
372 memset(&e2PollParams, 0, sizeof(sctpSockPollParams));
374 /* All sockets are non-blocking */
376 timeoutPtr = &timeout;
377 memInfo.region = RIC_APP_MEM_REG;
378 memInfo.pool = RIC_POOL;
380 CM_INET_FD_ZERO(&e2PollParams.readFd);
382 DU_LOG("\nINFO --> SCTP : Polling started at RIC\n");
385 /* Receiving SCTP data */
386 for(assocIdx = 0; assocIdx < sctpCb.numAssoc; assocIdx++)
388 if((ret = processPolling(&e2PollParams, &sctpCb.assocCb[assocIdx], timeoutPtr, &memInfo)) != ROK)
390 DU_LOG("\nERROR --> SCTP : Failed to RecvMsg for E2 at RIC \n");
395 }/* End of sctpSockPoll() */
397 /*******************************************************************
399 * @brief checks for valid readFd and process the InetSctpRecvMsg
404 * Function : processPolling
407 * checks for valid readFd and process the InetSctpRecvMsg
410 * @params[in] Params required for polling
411 * @params[in] SockFd for file descriptor
412 * @params[in] timeoutPtr indicates the timeout value
413 * @params[in] MemInfo indicates memory region
415 * @return ROK - success
418 * ****************************************************************/
421 uint8_t processPolling(sctpSockPollParams *pollParams, RicSctpAssocCb *assocCb, uint32_t *timeoutPtr, CmInetMemInfo *memInfo)
425 CM_INET_FD_SET(&assocCb->sockFd, &pollParams->readFd);
426 ret = cmInetSelect(&pollParams->readFd, NULLP, timeoutPtr, &pollParams->numFd);
427 if(CM_INET_FD_ISSET(&assocCb->sockFd, &pollParams->readFd))
429 CM_INET_FD_CLR(&assocCb->sockFd, &pollParams->readFd);
430 ret = cmInetSctpRecvMsg(&assocCb->sockFd, &pollParams->addr, &pollParams->port, memInfo, &pollParams->mBuf, \
431 &pollParams->bufLen, &pollParams->info, &pollParams->flag, &pollParams->ntfy);
432 if(assocCb->connUp & (ret != ROK))
434 assocCb->bReadFdSet = RFAILED;
438 if(((pollParams->flag & CM_INET_SCTP_MSG_NOTIFICATION) != 0) && (ret == ROK))
440 ret = sctpNtfyHdlr(assocCb, &pollParams->ntfy);
443 DU_LOG("\nERROR --> SCTP : Failed to process sctp notify msg\n");
446 else if(assocCb->connUp)
448 E2APMsgHdlr(&assocCb->duId, pollParams->mBuf);
449 ODU_PUT_MSG_BUF(pollParams->mBuf);
453 ODU_PUT_MSG_BUF(pollParams->mBuf);
458 }/* End of sctpSockPoll() */
460 /*******************************************************************
462 * @brief Send message on SCTP socket
466 * Function : sctpSend
469 * Send message on SCTP socket
472 * @return ROK - success
475 * ****************************************************************/
476 uint8_t sctpSend(uint32_t duId, Buffer *mBuf)
480 MsgLen len; /* number of actually sent octets */
481 CmInetMemInfo memInfo;
483 memInfo.region = RIC_APP_MEM_REG;
484 memInfo.pool = RIC_POOL;
486 for(assocIdx = 0; assocIdx < sctpCb.numAssoc; assocIdx++)
488 if(sctpCb.assocCb[assocIdx].duId == duId)
490 ret = cmInetSctpSendMsg(&sctpCb.assocCb[assocIdx].sockFd, &sctpCb.assocCb[assocIdx].destIpNetAddr, \
491 sctpCb.assocCb[assocIdx].destPort, &memInfo, mBuf, &len, 0, FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
493 if(ret != ROK && ret != RWOULDBLOCK)
495 DU_LOG("\nERROR --> SCTP : Send message failed");
501 } /* End of sctpSend */
502 /**********************************************************************
504 **********************************************************************/