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 */
23 #include "du_common.h"
25 /* Global variable declaration */
26 CmInetFd sockFd; /* Socket file descriptor */
27 U8 socket_type; /* Socket type */
28 Bool nonblocking; /* Blocking/Non-blocking socket */
29 Bool connUp; /* Is connection up */
30 int assocId; /* Assoc Id of connected assoc */
32 CmInetNetAddrLst localAddrLst;
33 CmInetNetAddrLst remoteAddrLst;
35 F1SctpParams *sctpCfg; /* SCTP configurations at DU */
36 S16 sctpOutMsgSend(Buffer *mBuf);
38 /**************************************************************************
39 * @brief Task Initiation callback function.
43 * Function : sctpActvInit
46 * This function is supplied as one of parameters during SCTP's
47 * task registration. SSI will invoke this function once, after
48 * it creates and attaches this TAPA Task to a system task.
50 * @param[in] Ent entity, the entity ID of this task.
51 * @param[in] Inst inst, the instance ID of this task.
52 * @param[in] Region region, the region ID registered for memory
54 * @param[in] Reason reason.
55 * @return ROK - success
57 ***************************************************************************/
58 S16 sctpActvInit(Ent entity, Inst inst, Region region, Reason reason)
64 sctpCfg = &(duCfgParam.sctpParams);
69 /**************************************************************************
70 * @brief Task Activation callback function.
74 * Function : sctpActvTsk
77 * This function handles all SCTP messages received
78 * This API is registered with SSI during the
79 * Task Registration of DU APP.
81 * @param[in] Pst *pst, Post structure of the primitive.
82 * @param[in] Buffer *mBuf, Packed primitive parameters in the
84 * @return ROK - success
87 ***************************************************************************/
88 S16 sctpActvTsk(Pst *pst, Buffer *mBuf)
110 /*******************************************************************
112 * @brief Opens a non-blocking socket and binds to local address
116 * Function : openSctpEndp
119 * Opens a non-blocking socket and binds to local address
122 * @return ROK - success
125 * ****************************************************************/
131 /* Opening a non-blocking SCTP socket */
132 socket_type = CM_INET_STREAM;
135 ret = cmInetSocket(socket_type, &sockFd, IPPROTO_SCTP,(sctpCfg->duIpAddr.ipV4Pres ? CM_INET_IPV4_DOMAIN : CM_INET_IPV6_DOMAIN));
139 if(numRetry >= MAX_RETRY)
141 printf("\nAll attempts to open socket failed.");
142 /* Send indication to du_app */
147 printf("\nRetrying socket opening");
152 printf("\nSocket[%d] opened successfully",sockFd.fd);
155 }while(numRetry < MAX_RETRY);
158 } /* End of openSctpEndp */
161 /*******************************************************************
163 * @brief Bind socket to local Ip address and port
167 * Function : bindSctpEndp
170 * -Bind socket to local Ip address and port
173 * @return ROK - success
176 * ****************************************************************/
183 /* Binding the socket with local address */
184 localAddrLst.count = 1;
185 if(sctpCfg->duIpAddr.ipV4Pres)
187 localAddrLst.addrs[0].type = CM_INET_IPV4ADDR_TYPE;
188 localAddrLst.addrs[0].u.ipv4NetAddr = CM_INET_NTOH_U32(sctpCfg->duIpAddr.ipV4Addr);
190 else if(sctpCfg->duIpAddr.ipV6Pres)
192 localAddrLst.addrs[0].type = CM_INET_IPV6ADDR_TYPE;
193 // CM_INET_COPY_IPV6ADDR(&(localAddrLst.addrs[0].u.ipv6NetAddr),&(sctpCfg->duIpAddr.ipV6Addr);
197 localAddrLst.addrs[0].type = CM_INET_IPV4ADDR_TYPE;
198 localAddrLst.addrs[0].u.ipv4NetAddr = 0;
202 ret = cmInetSctpBindx(&sockFd, &localAddrLst, sctpCfg->duPort);
206 if(numRetry >= MAX_RETRY)
208 printf("\nAll attempts to bind socket failed.");
209 cmInetClose(&sockFd);
210 /* Send indication to du_app */
215 printf("\nRetrying socket binding");
220 printf("\nSocket bind successful");
223 }while(numRetry < MAX_RETRY);
227 } /* End of bindSctpEndp() */
229 /*******************************************************************
231 * @brief Sets socket options as per requirement
235 * Function : sctpSetSockOpts
238 * Sets socket options as per requirement
241 * @return ROK - success
244 * ****************************************************************/
245 S16 sctpSetSockOpts()
247 CmSctpEvent sctpEvent;
249 sctpEvent.dataIoEvent = TRUE;
250 sctpEvent.associationEvent = TRUE;
251 sctpEvent.addressEvent = TRUE;
252 sctpEvent.sendFailureEvent = TRUE;
253 sctpEvent.peerErrorEvent = TRUE;
254 sctpEvent.shutdownEvent = TRUE;
255 sctpEvent.partialDeliveryEvent = TRUE;
256 sctpEvent.adaptationLayerEvent = TRUE;
258 cmInetSetOpt(&sockFd, CM_SOCKOPT_LEVEL_SCTP, CM_SOCKOPT_OPT_SCTP_EVENTS, &sctpEvent);
264 /*******************************************************************
266 * @brief Initiates connection with peer SCTP
270 * Function : sctpConnect
273 * Establishes SCTP connection with peer.
274 * Here, DU-SCTP will initate connection towards CU-SCTP
277 * @return ROK - success
280 * ****************************************************************/
285 CmInetNetAddr primDstAddr; /* primary destination address */
287 /* Filling primary destination address */
288 if(sctpCfg->cuIpAddr.ipV4Pres)
290 primDstAddr.type = CM_INET_IPV4ADDR_TYPE;
291 primDstAddr.u.ipv4NetAddr = CM_INET_NTOH_U32(sctpCfg->cuIpAddr.ipV4Addr);
293 else if(sctpCfg->cuIpAddr.ipV6Pres)
295 primDstAddr.type = CM_INET_IPV6ADDR_TYPE;
296 //CM_INET_COPY_IPV6ADDR(&(primDstAddr.u.ipv6NetAddr),&(sctpCfg->cuIpAddr.ipV6Addr);
300 primDstAddr.type = CM_INET_IPV4ADDR_TYPE;
301 primDstAddr.u.ipv4NetAddr = 0;
304 /* Filling destination address list */
305 remoteAddrLst.count = 1;
306 if(sctpCfg->cuIpAddr.ipV4Pres)
308 remoteAddrLst.addrs[0].type = CM_INET_IPV4ADDR_TYPE;
309 remoteAddrLst.addrs[0].u.ipv4NetAddr = CM_INET_NTOH_U32(sctpCfg->cuIpAddr.ipV4Addr);
311 else if(sctpCfg->cuIpAddr.ipV6Pres)
313 remoteAddrLst.addrs[0].type = CM_INET_IPV6ADDR_TYPE;
314 //CM_INET_COPY_IPV6ADDR(&(remoteAddrLst.addrs[0].u.ipv6NetAddr),&(sctpCfg->cuIpAddr.ipV6Addr);
318 remoteAddrLst.addrs[0].type = CM_INET_IPV4ADDR_TYPE;
319 remoteAddrLst.addrs[0].u.ipv4NetAddr = 0;
322 /* Sending connect request to remote */
324 ret = cmInetSctpConnectx(&sockFd, &primDstAddr, &remoteAddrLst, sctpCfg->cuPort);
325 if (ret == RFAILED || ret == ROKDNA || ret == RCLOSED)
328 if(numRetry >= MAX_RETRY)
330 printf("\nAll attempts to connect failed.");
331 cmInetClose(&sockFd);
332 /* Send indication to du_app */
337 printf("\nRetrying connection");
340 else if(ret == RINPROGRESS)
342 printf("\nConnection in progess");
348 printf("\nSCTP connect successful");
351 }while(numRetry < MAX_RETRY);
354 }/* End of sctpConnect() */
356 /*******************************************************************
358 * @brief Post received data/notification to DU APP
362 * Function : sendToDuApp
365 * Post received data/notification to DU APP
367 * @params[in] Message buffer
370 * @return ROK - success
373 * ****************************************************************/
374 void sendToDuApp(Buffer *mBuf, Event event)
377 printf("\nForwarding received message to duApp");
378 SPrntMsg(mBuf, 0, 0);
381 cmMemset((U8 *)&(pst), 0, sizeof(Pst));
382 pst.srcEnt = (Ent)ENTSCTP;
383 pst.srcInst = (Inst)SCTP_INST;
384 pst.srcProcId = DU_PROC;
385 pst.dstEnt = (Ent)ENTDUAPP;
386 pst.dstInst = (Inst)DU_INST;
387 pst.dstProcId = pst.srcProcId;
389 pst.selector = DU_SELECTOR_LC;
391 pst.region = DFLT_REGION;
393 if (SPstTsk(&pst, mBuf) != ROK)
395 printf("\nSPstTsk failed in duReadCfg");
400 /*******************************************************************
402 * @brief Handles an SCTP notification message
405 * Function : sctpNtfyHdlr
408 * Handles an SCTP notification message
410 * @params[in] Notify message
412 * @return ROK - success
415 * ****************************************************************/
416 S16 sctpNtfyHdlr(CmInetSctpNotification *ntfy)
419 switch(ntfy->header.nType)
421 case CM_INET_SCTP_ASSOC_CHANGE :
422 switch(ntfy->u.assocChange.state)
424 case CM_INET_SCTP_COMM_UP:
425 printf("\nSCTP notify assocchange(comm up) received");
428 case CM_INET_SCTP_COMM_LOST:
429 printf("\nSCTP notify assocchange(comm lost) received");
432 case CM_INET_SCTP_RESTART:
433 printf("\nSCTP notify assocchange(sctp restart) received");
436 case CM_INET_SCTP_SHUTDOWN_COMP: /* association gracefully shutdown */
437 printf("\nSCTP notify assocchange(shutdown complete) received\n");
440 case CM_INET_SCTP_CANT_STR_ASSOC:
441 printf("\nSCTP notify assocchange(cant str assoc) received\n");
445 printf("\nInvalid event");
449 case CM_INET_SCTP_PEER_ADDR_CHANGE :
450 printf("\nSCTP notify peer addr change received");
451 /* Need to add handler */
453 case CM_INET_SCTP_REMOTE_ERROR :
454 printf("\nSCTP notify remote error received");
456 case CM_INET_SCTP_SEND_FAILED :
457 printf("\nSCTP notify send failed received\n");
459 case CM_INET_SCTP_SHUTDOWN_EVENT : /* peer socket gracefully closed */
460 printf("\nSCTP notify shutdown event received\n");
463 case CM_INET_SCTP_ADAPTATION_INDICATION :
464 printf("\nSCTP notify adaptation indication received\n");
466 case CM_INET_SCTP_PARTIAL_DELIVERY_EVENT:
467 printf("\nSCTP notify partial delivery received\n");
470 printf("\nInvalid sctp notification type\n");
474 /* Pack notification and send to APP */
475 if(cmPkSctpNtfy(ntfy) != ROK)
477 printf("\nFailed to pack SCTP notification");
483 /*******************************************************************
485 * @brief Receives message on the socket
489 * Function : sctpSockPoll
492 * Receives message on the socket
495 * @return ROK - success
498 * ****************************************************************/
505 U32 timeout; /* timeout for cmInetSelect() */
506 U32 *timeoutPtr; /* pointer to timeout */
510 CmInetMemInfo memInfo; /* buffer allocation info */
512 CmInetSctpSndRcvInfo info;
513 CmInetSctpNotification ntfy;
524 timeoutPtr = &timeout;
526 memInfo.region = DU_APP_MEM_REGION;
527 memInfo.pool = DU_POOL;
528 CM_INET_FD_ZERO(&readFd);
532 CM_INET_FD_SET(&sockFd, &readFd);
533 ret = cmInetSelect(&readFd, NULLP, timeoutPtr, &numFds);
534 if (CM_INET_FD_ISSET(&sockFd, &readFd))
536 CM_INET_FD_CLR(&sockFd, &readFd);
537 ret = cmInetSctpRecvMsg(&sockFd, &addr, &port, &memInfo, &mBuf, &bufLen, &info, &flag, &ntfy);
538 if (connUp && ret != ROK)
540 printf("\nFailed to receive sctp msg\n");
544 /* If SCTP notification received */
545 if ((flag & CM_INET_SCTP_MSG_NOTIFICATION) != 0)
547 ret = sctpNtfyHdlr(&ntfy);
550 printf("\nFailed to process sctp notify msg\n");
553 else if(connUp) /* If data received */
555 sendToDuApp(mBuf, EVTSCTPDATA);
566 }/* End of sctpSockPoll() */
568 /*******************************************************************
570 * @brief Send message on SCTP socket
574 * Function : sctpOutMsgSend
577 * Send message on SCTP socket
580 * @return ROK - success
583 * ****************************************************************/
584 S16 sctpOutMsgSend(Buffer *mBuf)
587 MsgLen len; /* number of actually sent octets */
588 CmInetNetAddr peerAddr; /* destination port address */
589 CmInetNetAddr *dstAddr;
590 CmInetMemInfo memInfo;
592 memInfo.region = DU_APP_MEM_REGION;
593 memInfo.pool = DU_POOL;
596 if(sctpCfg->cuIpAddr.ipV4Pres)
598 peerAddr.type = CM_INET_IPV4ADDR_TYPE;
599 peerAddr.u.ipv4NetAddr = CM_INET_NTOH_U32(sctpCfg->cuIpAddr.ipV4Addr);
602 else if(sctpCfg->cuIpAddr.ipV6Pres)
604 peerAddr.type = CM_INET_IPV6ADDR_TYPE;
605 //CM_INET_COPY_IPV6ADDR(&(primDstAddr.u.ipv6NetAddr),&(sctpCfg->cuIpAddr.ipV6Addr);
613 ret = cmInetSctpSendMsg(&sockFd, dstAddr, sctpCfg->cuPort, &memInfo, mBuf, &len, 0, FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
614 if(ret != ROK && ret != RWOULDBLOCK)
616 printf("\nFailed sending the message");
621 } /* End of sctpOutMsgSend */
623 /*******************************************************************
625 * @brief SCTP Assoc establishment request from DU
629 * Function : sctpAssocReq
632 * This function opens a socket at DU and
633 * intiates SCTP connection.
636 * @return ROK - success
639 * ****************************************************************/
642 if(openSctpEndp() != ROK)
644 printf("\nFailed while opening socket");
646 else if(bindSctpEndp() != ROK)
648 printf("\nFailed while binding socket");
650 else if(sctpSetSockOpts() != ROK)
652 printf("\nFailed while setting socket options");
654 else if(sctpConnect() != ROK)
656 printf("\nFailed while connecting to peer");
658 else if(sctpSockPoll() != ROK)
660 printf("\nFailed while polling");
662 } /* End of sctpAssocReq */
664 /**********************************************************************
666 **********************************************************************/