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 */
25 /* Global variable declaration */
26 F1SctpParams sctpCfg; /* SCTP configurations at DU */
28 /**************************************************************************
29 * @brief Task Initiation callback function.
33 * Function : sctpActvInit
36 * This function is supplied as one of parameters during SCTP's
37 * task registration. SSI will invoke this function once, after
38 * it creates and attaches this TAPA Task to a system task.
40 * @param[in] Ent entity, the entity ID of this task.
41 * @param[in] Inst inst, the instance ID of this task.
42 * @param[in] Region region, the region ID registered for memory
44 * @param[in] Reason reason.
45 * @return ROK - success
47 ***************************************************************************/
48 S16 sctpActvInit(Ent entity, Inst inst, Region region, Reason reason)
50 DU_LOG("\n\nSCTP : Initializing");
59 /**************************************************************************
60 * @brief Task Activation callback function.
64 * Function : sctpActvTsk
67 * This function handles all SCTP messages received
68 * This API is registered with SSI during the
69 * Task Registration of DU APP.
71 * @param[in] Pst *pst, Post structure of the primitive.
72 * @param[in] Buffer *mBuf, Packed primitive parameters in the
74 * @return ROK - success
77 ***************************************************************************/
78 S16 sctpActvTsk(Pst *pst, Buffer *mBuf)
88 cmUnpkSctpAssocReq(mBuf);
101 /*******************************************************************
103 * @brief Opens a non-blocking socket and binds to local address
107 * Function : openSctpEndp
110 * Opens a non-blocking socket and binds to local address
113 * @return ROK - success
116 * ****************************************************************/
122 /* Opening a non-blocking SCTP socket */
123 socket_type = CM_INET_STREAM;
126 ret = cmInetSocket(socket_type, &sockFd, IPPROTO_SCTP);
130 if(numRetry >= MAX_RETRY)
132 DU_LOG("\nSCTP : All attempts to open socket failed.");
133 /* Send indication to du_app */
138 DU_LOG("\nSCTP : Retrying socket opening");
143 DU_LOG("\nSCTP : Socket[%d] open",sockFd.fd);
146 }while(numRetry < MAX_RETRY);
149 } /* End of openSctpEndp */
152 /*******************************************************************
154 * @brief Bind socket to local Ip address and port
158 * Function : bindSctpEndp
161 * -Bind socket to local Ip address and port
164 * @return ROK - success
167 * ****************************************************************/
174 /* Binding the socket with local address */
175 localAddrLst.count = 1;
176 if(sctpCfg.duIpAddr.ipV4Pres)
178 localAddrLst.addrs[0].type = CM_INET_IPV4ADDR_TYPE;
179 localAddrLst.addrs[0].u.ipv4NetAddr = CM_INET_NTOH_U32(sctpCfg.duIpAddr.ipV4Addr);
183 localAddrLst.addrs[0].type = CM_INET_IPV4ADDR_TYPE;
184 localAddrLst.addrs[0].u.ipv4NetAddr = 0;
188 ret = cmInetSctpBindx(&sockFd, &localAddrLst, sctpCfg.duPort);
192 if(numRetry >= MAX_RETRY)
194 DU_LOG("\nSCTP : All attempts to bind socket failed.");
195 cmInetClose(&sockFd);
196 /* Send indication to du_app */
201 DU_LOG("\nSCTP : Retrying socket binding");
206 DU_LOG("\nSCTP : Socket bind successful");
209 }while(numRetry < MAX_RETRY);
213 } /* End of bindSctpEndp() */
215 /*******************************************************************
217 * @brief Sets socket options as per requirement
221 * Function : sctpSetSockOpts
224 * Sets socket options as per requirement
227 * @return ROK - success
230 * ****************************************************************/
231 S16 sctpSetSockOpts()
233 CmSctpEvent sctpEvent;
235 sctpEvent.dataIoEvent = TRUE;
236 sctpEvent.associationEvent = TRUE;
237 sctpEvent.addressEvent = TRUE;
238 sctpEvent.sendFailureEvent = TRUE;
239 sctpEvent.peerErrorEvent = TRUE;
240 sctpEvent.shutdownEvent = TRUE;
241 sctpEvent.partialDeliveryEvent = TRUE;
242 sctpEvent.adaptationLayerEvent = TRUE;
244 cmInetSetOpt(&sockFd, CM_SOCKOPT_LEVEL_SCTP, CM_SOCKOPT_OPT_SCTP_EVENTS, &sctpEvent);
250 /*******************************************************************
252 * @brief Initiates connection with peer SCTP
256 * Function : sctpConnect
259 * Establishes SCTP connection with peer.
260 * Here, DU-SCTP will initate connection towards CU-SCTP
263 * @return ROK - success
266 * ****************************************************************/
271 CmInetNetAddr primDstAddr; /* primary destination address */
273 /* Filling primary destination address */
274 if(sctpCfg.cuIpAddr.ipV4Pres)
276 primDstAddr.type = CM_INET_IPV4ADDR_TYPE;
277 primDstAddr.u.ipv4NetAddr = CM_INET_NTOH_U32(sctpCfg.cuIpAddr.ipV4Addr);
281 primDstAddr.type = CM_INET_IPV4ADDR_TYPE;
282 primDstAddr.u.ipv4NetAddr = 0;
285 /* Filling destination address list */
286 remoteAddrLst.count = 1;
287 if(sctpCfg.cuIpAddr.ipV4Pres)
289 remoteAddrLst.addrs[0].type = CM_INET_IPV4ADDR_TYPE;
290 remoteAddrLst.addrs[0].u.ipv4NetAddr = CM_INET_NTOH_U32(sctpCfg.cuIpAddr.ipV4Addr);
294 remoteAddrLst.addrs[0].type = CM_INET_IPV4ADDR_TYPE;
295 remoteAddrLst.addrs[0].u.ipv4NetAddr = 0;
298 /* Sending connect request to remote */
300 ret = cmInetSctpConnectx(&sockFd, &primDstAddr, &remoteAddrLst, sctpCfg.cuPort);
301 if (ret == RFAILED || ret == ROKDNA || ret == RCLOSED)
304 if(numRetry >= MAX_RETRY)
306 DU_LOG("\nSCTP : All attempts to connect failed.");
307 cmInetClose(&sockFd);
308 /* Send indication to du_app */
313 DU_LOG("\nSCTP : Retrying connection");
316 else if(ret == RINPROGRESS)
318 DU_LOG("\nSCTP : Connection in progess");
324 DU_LOG("\nSCTP : Connect successful");
327 }while(numRetry < MAX_RETRY);
330 }/* End of sctpConnect() */
332 /*******************************************************************
334 * @brief Post received data/notification to DU APP
338 * Function : sendToDuApp
341 * Post received data/notification to DU APP
343 * @params[in] Message buffer
346 * @return ROK - success
349 * ****************************************************************/
350 void sendToDuApp(Buffer *mBuf, Event event)
353 DU_LOG("\nSCTP : Forwarding received message to duApp");
354 SPrntMsg(mBuf, 0, 0);
357 cmMemset((U8 *)&(pst), 0, sizeof(Pst));
358 pst.srcEnt = (Ent)ENTSCTP;
359 pst.srcInst = (Inst)SCTP_INST;
360 pst.srcProcId = DU_PROC;
361 pst.dstEnt = (Ent)ENTDUAPP;
362 pst.dstInst = (Inst)DU_INST;
363 pst.dstProcId = pst.srcProcId;
365 pst.selector = DU_SELECTOR_LC;
367 pst.region = DFLT_REGION;
369 if (SPstTsk(&pst, mBuf) != ROK)
371 DU_LOG("\nSCTP : SPstTsk failed in duReadCfg");
375 /*******************************************************************
377 * @brief Handles an SCTP notification message
380 * Function : sctpNtfyHdlr
383 * Handles an SCTP notification message
385 * @params[in] Notify message
387 * @return ROK - success
390 * ****************************************************************/
391 S16 sctpNtfyHdlr(CmInetSctpNotification *ntfy)
395 switch(ntfy->header.nType)
397 case CM_INET_SCTP_ASSOC_CHANGE :
398 DU_LOG("\nSCTP : Assoc change notification received");
399 switch(ntfy->u.assocChange.state)
401 case CM_INET_SCTP_COMM_UP:
402 DU_LOG("Event : COMMUNICATION UP");
405 case CM_INET_SCTP_COMM_LOST:
406 DU_LOG("Event : COMMUNICATION LOST");
409 case CM_INET_SCTP_RESTART:
410 DU_LOG("Event : SCTP RESTART");
413 case CM_INET_SCTP_SHUTDOWN_COMP: /* association gracefully shutdown */
414 DU_LOG("Event : SHUTDOWN COMPLETE");
417 case CM_INET_SCTP_CANT_STR_ASSOC:
418 DU_LOG("Event : CANT START ASSOC");
422 DU_LOG("\nInvalid event");
426 case CM_INET_SCTP_PEER_ADDR_CHANGE :
427 DU_LOG("\nSCTP : Peer Address Change notificarion received");
428 /* Need to add handler */
430 case CM_INET_SCTP_REMOTE_ERROR :
431 DU_LOG("\nSCTP : Remote Error notification received");
433 case CM_INET_SCTP_SEND_FAILED :
434 DU_LOG("\nSCTP : Send Failed notification received\n");
436 case CM_INET_SCTP_SHUTDOWN_EVENT : /* peer socket gracefully closed */
437 DU_LOG("\nSCTP : Shutdown Event notification received\n");
440 case CM_INET_SCTP_ADAPTATION_INDICATION :
441 DU_LOG("\nSCTP : Adaptation Indication received\n");
443 case CM_INET_SCTP_PARTIAL_DELIVERY_EVENT:
444 DU_LOG("\nSCTP : Partial Delivery Event received\n");
447 DU_LOG("\nSCTP : Invalid sctp notification type\n");
451 /* Pack notification and send to APP */
452 DU_LOG("\nSCTP : Forwarding received message to duApp");
454 cmMemset((U8 *)&(pst), 0, sizeof(Pst));
455 pst.srcEnt = (Ent)ENTSCTP;
456 pst.srcInst = (Inst)SCTP_INST;
457 pst.srcProcId = DU_PROC;
458 pst.dstEnt = (Ent)ENTDUAPP;
459 pst.dstInst = (Inst)DU_INST;
460 pst.dstProcId = pst.srcProcId;
461 pst.event = EVTSCTPNTFY;
462 pst.selector = DU_SELECTOR_LC;
464 pst.region = DFLT_REGION;
466 if(cmPkSctpNtfy(&pst, ntfy) != ROK)
468 DU_LOG("\nSCTP : Failed to pack SCTP notification");
474 /*******************************************************************
476 * @brief Receives message on the socket
480 * Function : sctpSockPoll
483 * Receives message on the socket
486 * @return ROK - success
489 * ****************************************************************/
496 U32 timeout; /* timeout for cmInetSelect() */
497 U32 *timeoutPtr; /* pointer to timeout */
501 CmInetMemInfo memInfo; /* buffer allocation info */
503 CmInetSctpSndRcvInfo info;
504 CmInetSctpNotification ntfy;
515 timeoutPtr = &timeout;
517 memInfo.region = DU_APP_MEM_REGION;
518 memInfo.pool = DU_POOL;
519 CM_INET_FD_ZERO(&readFd);
523 CM_INET_FD_SET(&sockFd, &readFd);
524 ret = cmInetSelect(&readFd, NULLP, timeoutPtr, &numFds);
525 if (CM_INET_FD_ISSET(&sockFd, &readFd))
527 CM_INET_FD_CLR(&sockFd, &readFd);
528 ret = cmInetSctpRecvMsg(&sockFd, &addr, &port, &memInfo, &mBuf, &bufLen, &info, &flag, &ntfy);
529 if (connUp && ret != ROK)
531 DU_LOG("\nFailed to receive sctp msg\n");
535 /* If SCTP notification received */
536 if ((flag & CM_INET_SCTP_MSG_NOTIFICATION) != 0)
538 ret = sctpNtfyHdlr(&ntfy);
541 DU_LOG("\nSCTP : Failed to process sctp notify msg\n");
544 else if(connUp) /* If data received */
546 sendToDuApp(mBuf, EVTSCTPDATA);
557 }/* End of sctpSockPoll() */
559 /*******************************************************************
561 * @brief Send message on SCTP socket
565 * Function : sctpSend
568 * Send message on SCTP socket
571 * @return ROK - success
574 * ****************************************************************/
575 S16 sctpSend(Buffer *mBuf)
578 MsgLen len; /* number of actually sent octets */
579 CmInetNetAddr peerAddr; /* destination port address */
580 CmInetNetAddr *dstAddr;
581 CmInetMemInfo memInfo;
583 memInfo.region = DU_APP_MEM_REGION;
584 memInfo.pool = DU_POOL;
587 if(sctpCfg.cuIpAddr.ipV4Pres)
589 peerAddr.type = CM_INET_IPV4ADDR_TYPE;
590 peerAddr.u.ipv4NetAddr = CM_INET_NTOH_U32(sctpCfg.cuIpAddr.ipV4Addr);
598 ret = cmInetSctpSendMsg(&sockFd, dstAddr, sctpCfg.cuPort, &memInfo, mBuf, &len, 0, FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
599 if(ret != ROK && ret != RWOULDBLOCK)
601 DU_LOG("\nSCTP : Failed sending the message");
606 } /* End of sctpSend */
608 /*******************************************************************
610 * @brief SCTP Assoc establishment request from DU
614 * Function : sctpAssocReq
617 * This function opens a socket at DU and
618 * intiates SCTP connection.
621 * @return ROK - success
624 * ****************************************************************/
627 if(openSctpEndp() != ROK)
629 DU_LOG("\nSCTP : Failed while opening socket");
631 else if(bindSctpEndp() != ROK)
633 DU_LOG("\nSCTP : Failed while binding socket");
635 else if(sctpSetSockOpts() != ROK)
637 DU_LOG("\nSCTP : Failed while setting socket options");
639 else if(sctpConnect() != ROK)
641 DU_LOG("\nSCTP : Failed while connecting to peer");
643 else if(sctpSockPoll() != ROK)
645 DU_LOG("\nSCTP : Failed while polling");
647 } /* End of sctpAssocReq */
649 /**********************************************************************
651 **********************************************************************/