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 ***************************************************************************/
44 int destIdx = 0, assocIdx = 0;
46 sctpCb.sctpCfg = ricCb.ricCfgParams.sctpParams;
47 fillAddrLst(&sctpCb.localAddrLst, &sctpCb.sctpCfg.localIpAddr);
48 memset(&sctpCb.e2LstnSockFd, -1, sizeof(CmInetFd));
49 for(destIdx=0; destIdx < sctpCb.sctpCfg.numDestNode; destIdx++)
51 sctpCb.assocCb[assocIdx].destPort = sctpCb.sctpCfg.destCb[destIdx].destPort;
52 sctpCb.assocCb[assocIdx].bReadFdSet = ROK;
53 memset(&sctpCb.assocCb[assocIdx].sockFd, -1, sizeof(CmInetFd));
54 fillDestNetAddr(&sctpCb.assocCb[assocIdx].destIpNetAddr, &sctpCb.sctpCfg.destCb[destIdx].destIpAddr);
55 sctpCb.assocCb[assocIdx].connUp = false;
58 sctpCb.numAssoc = assocIdx;
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()
133 uint8_t assocIdx = 0;
136 socket_type = CM_INET_STREAM;
141 if((ret = cmInetSocket(socket_type, &sctpCb.e2LstnSockFd, IPPROTO_SCTP) != ROK))
143 DU_LOG("\nERROR --> SCTP : Socket[%d] coudnt open for listening", sctpCb.e2LstnSockFd.fd);
145 else if((ret = cmInetSctpBindx(&sctpCb.e2LstnSockFd, &sctpCb.localAddrLst, sctpCb.sctpCfg.e2SctpPort)) != ROK)
147 DU_LOG("\nERROR --> SCTP: Binding failed at RIC");
149 else if(ret = cmInetListen(&sctpCb.e2LstnSockFd, 1) != ROK)
151 DU_LOG("\nERROR --> SCTP: Unable to accept the connection at CU");
152 DU_LOG("\nERROR --> SCTP : Listening on socket failed");
153 cmInetClose(&sctpCb.e2LstnSockFd);
158 for(assocIdx=0; assocIdx < sctpCb.numAssoc; assocIdx++)
160 if((ret = sctpAccept(&sctpCb.assocCb[assocIdx])) != ROK)
162 DU_LOG("\nERROR --> SCTP: Unable to accept the connection at RIC");
170 if(sctpSockPoll() != ROK)
172 DU_LOG("\nERROR --> SCTP: Polling failed to start at RIC");
178 /*******************************************************************
180 * @brief Sets socket options as per requirement
184 * Function : sctpSetSockOpts
187 * Sets socket options as per requirement
190 * @return ROK - success
193 * ****************************************************************/
194 uint8_t sctpSetSockOpts(CmInetFd *sock_Fd)
197 CmSctpEvent sctpEvent;
199 sctpEvent.dataIoEvent = TRUE;
200 sctpEvent.associationEvent = TRUE;
201 sctpEvent.addressEvent = TRUE;
202 sctpEvent.sendFailureEvent = TRUE;
203 sctpEvent.peerErrorEvent = TRUE;
204 sctpEvent.shutdownEvent = TRUE;
205 sctpEvent.partialDeliveryEvent = TRUE;
206 sctpEvent.adaptationLayerEvent = TRUE;
208 if((ret = cmInetSetOpt(sock_Fd, CM_SOCKOPT_LEVEL_SCTP, CM_SOCKOPT_OPT_SCTP_EVENTS, &sctpEvent)) != ROK)
216 /*******************************************************************
218 * @brief Initiates connection with peer SCTP
222 * Function : sctpAccept
225 * Establishes SCTP connection with peer.
226 * Here, DU-SCTP will initate connection towards RIC-SCTP
229 * @return ROK - success
232 * ****************************************************************/
233 uint8_t sctpAccept(RicSctpAssocCb *assocCb)
237 DU_LOG("\nINFO --> SCTP : Connecting");
239 while(!assocCb->connUp)
241 ret = cmInetAccept(&sctpCb.e2LstnSockFd, &assocCb->peerAddr, &assocCb->sockFd);
248 DU_LOG("\nERROR --> SCTP : Failed to accept connection");
253 assocCb->connUp = TRUE;
254 sctpSetSockOpts(&assocCb->sockFd);
258 DU_LOG("\nINFO --> SCTP : Connection established");
263 /*******************************************************************
265 * @brief Handles an SCTP notification message
269 * Function : sctpNtfyHdlr
272 * Handles an SCTP notification message
274 * @params[in] Notify message
276 * @return ROK - success
279 * ****************************************************************/
280 uint8_t sctpNtfyHdlr(RicSctpAssocCb *assocCb, CmInetSctpNotification *ntfy)
282 switch(ntfy->header.nType)
284 case CM_INET_SCTP_ASSOC_CHANGE :
285 DU_LOG("\nINFO --> SCTP : Assoc change notification received");
286 switch(ntfy->u.assocChange.state)
288 case CM_INET_SCTP_COMM_UP:
289 DU_LOG("\nINFO --> Event : COMMUNICATION UP");
290 assocCb->connUp = TRUE;
292 case CM_INET_SCTP_COMM_LOST:
293 DU_LOG("\nINFO --> Event : COMMUNICATION LOST");
294 assocCb->connUp = FALSE;
296 case CM_INET_SCTP_RESTART:
297 DU_LOG("\nINFO --> Event : SCTP RESTART");
298 assocCb->connUp = FALSE;
300 case CM_INET_SCTP_SHUTDOWN_COMP: /* association gracefully shutdown */
301 DU_LOG("\nINFO --> Event : SHUTDOWN COMPLETE");
302 assocCb->connUp = FALSE;
304 case CM_INET_SCTP_CANT_STR_ASSOC:
305 DU_LOG("\nINFO --> Event : CANT START ASSOC");
306 assocCb->connUp = FALSE;
309 DU_LOG("\nERROR --> Invalid event");
313 case CM_INET_SCTP_PEER_ADDR_CHANGE :
314 DU_LOG("\nINFO --> SCTP : Peer Address Change notificarion received");
315 /* Need to add handler */
317 case CM_INET_SCTP_REMOTE_ERROR :
318 DU_LOG("\nINFO --> SCTP : Remote Error notification received");
320 case CM_INET_SCTP_SEND_FAILED :
321 DU_LOG("\nINFO --> SCTP : Send Failed notification received\n");
323 case CM_INET_SCTP_SHUTDOWN_EVENT : /* peer socket gracefully closed */
324 DU_LOG("\nINFO --> SCTP : Shutdown Event notification received\n");
325 assocCb->connUp = FALSE;
328 case CM_INET_SCTP_ADAPTATION_INDICATION :
329 DU_LOG("\nINFO --> SCTP : Adaptation Indication received\n");
331 case CM_INET_SCTP_PARTIAL_DELIVERY_EVENT:
332 DU_LOG("\nINFO --> SCTP : Partial Delivery Event received\n");
335 DU_LOG("\nERROR --> SCTP : Invalid notification type\n");
341 }/* End of sctpNtfyHdlr */
343 /*******************************************************************
345 * @brief Receives message on the socket
349 * Function : sctpSockPoll
352 * Receives message on the socket
355 * @return ROK - success
358 * ****************************************************************/
359 uint8_t sctpSockPoll()
364 uint32_t *timeoutPtr;
365 CmInetMemInfo memInfo;
366 sctpSockPollParams e2PollParams;
368 memset(&e2PollParams, 0, sizeof(sctpSockPollParams));
370 /* All sockets are non-blocking */
372 timeoutPtr = &timeout;
373 memInfo.region = RIC_APP_MEM_REG;
374 memInfo.pool = RIC_POOL;
376 CM_INET_FD_ZERO(&e2PollParams.readFd);
378 DU_LOG("\nINFO --> SCTP : Polling started at RIC\n");
381 /* Receiving SCTP data */
382 for(assocIdx = 0; assocIdx < sctpCb.numAssoc; assocIdx++)
384 if((ret = processPolling(&e2PollParams, &sctpCb.assocCb[assocIdx], timeoutPtr, &memInfo)) != ROK)
386 DU_LOG("\nERROR --> SCTP : Failed to RecvMsg for E2 at RIC \n");
391 }/* End of sctpSockPoll() */
393 /*******************************************************************
395 * @brief checks for valid readFd and process the InetSctpRecvMsg
400 * Function : processPolling
403 * checks for valid readFd and process the InetSctpRecvMsg
406 * @params[in] Params required for polling
407 * @params[in] SockFd for file descriptor
408 * @params[in] timeoutPtr indicates the timeout value
409 * @params[in] MemInfo indicates memory region
411 * @return ROK - success
414 * ****************************************************************/
417 uint8_t processPolling(sctpSockPollParams *pollParams, RicSctpAssocCb *assocCb, uint32_t *timeoutPtr, CmInetMemInfo *memInfo)
421 CM_INET_FD_SET(&assocCb->sockFd, &pollParams->readFd);
422 ret = cmInetSelect(&pollParams->readFd, NULLP, timeoutPtr, &pollParams->numFd);
423 if(CM_INET_FD_ISSET(&assocCb->sockFd, &pollParams->readFd))
425 CM_INET_FD_CLR(&assocCb->sockFd, &pollParams->readFd);
426 ret = cmInetSctpRecvMsg(&assocCb->sockFd, &pollParams->addr, &pollParams->port, memInfo, &pollParams->mBuf, \
427 &pollParams->bufLen, &pollParams->info, &pollParams->flag, &pollParams->ntfy);
428 if(assocCb->connUp & (ret != ROK))
430 assocCb->bReadFdSet = RFAILED;
434 if(((pollParams->flag & CM_INET_SCTP_MSG_NOTIFICATION) != 0) && (ret == ROK))
436 ret = sctpNtfyHdlr(assocCb, &pollParams->ntfy);
439 DU_LOG("\nERROR --> SCTP : Failed to process sctp notify msg\n");
442 else if(assocCb->connUp)
444 E2APMsgHdlr(&assocCb->duId, pollParams->mBuf);
445 ODU_PUT_MSG_BUF(pollParams->mBuf);
449 ODU_PUT_MSG_BUF(pollParams->mBuf);
454 }/* End of sctpSockPoll() */
456 /*******************************************************************
458 * @brief Send message on SCTP socket
462 * Function : sctpSend
465 * Send message on SCTP socket
468 * @return ROK - success
471 * ****************************************************************/
472 uint8_t sctpSend(uint32_t duId, Buffer *mBuf)
476 MsgLen len; /* number of actually sent octets */
477 CmInetMemInfo memInfo;
479 memInfo.region = RIC_APP_MEM_REG;
480 memInfo.pool = RIC_POOL;
482 for(assocIdx = 0; assocIdx < sctpCb.numAssoc; assocIdx++)
484 if(sctpCb.assocCb[assocIdx].duId == duId)
486 ret = cmInetSctpSendMsg(&sctpCb.assocCb[assocIdx].sockFd, &sctpCb.assocCb[assocIdx].destIpNetAddr, \
487 sctpCb.assocCb[assocIdx].destPort, &memInfo, mBuf, &len, 0, FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
489 if(ret != ROK && ret != RWOULDBLOCK)
491 DU_LOG("\nERROR --> SCTP : Send message failed");
497 } /* End of sctpSend */
498 /**********************************************************************
500 **********************************************************************/