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 */
20 #include "common_def.h"
25 #include "du_app_mac_inf.h"
31 /**************************************************************************
32 * @brief Task Initiation callback function.
36 * Function : sctpActvInit
39 * This function is supplied as one of parameters during SCTP's
40 * task registration. SSI will invoke this function once, after
41 * it creates and attaches this TAPA Task to a system task.
43 * @param[in] Ent entity, the entity ID of this task.
44 * @param[in] Inst inst, the instance ID of this task.
45 * @param[in] Region region, the region ID registered for memory
47 * @param[in] Reason reason.
48 * @return ROK - success
50 ***************************************************************************/
51 S16 sctpActvInit(Ent entity, Inst inst, Region region, Reason reason)
53 DU_LOG("\n\nSCTP : Initializing");
56 f1Params.assocId = -1;
57 ricParams.assocId = -1;
63 /**************************************************************************
64 * @brief Task Activation callback function.
68 * Function : sctpActvTsk
71 * This function handles all SCTP messages received
72 * This API is registered with SSI during the
73 * Task Registration of DU APP.
75 * @param[in] Pst *pst, Post structure of the primitive.
76 * @param[in] Buffer *mBuf, Packed primitive parameters in the
78 * @return ROK - success
81 ***************************************************************************/
82 S16 sctpActvTsk(Pst *pst, Buffer *mBuf)
102 /*******************************************************************
104 * @brief Checks the status of the received information
108 * Function : duCheckReqStatus
111 * Checks the status of the received information
113 * @params[in] Confirm status
114 * @return ROK - success
117 ******************************************************************/
118 S16 duCheckReqStatus(CmStatus *cfm)
121 if(cfm->status != LCM_PRIM_OK)
123 DU_LOG("\nDU_APP : Failed to process the request successfully");
129 /**************************************************************************
130 * @brief Function to configure the Sctp Params during config Request
134 * Function : duSctpCfgReq
137 * This function configures SCTP Params during the config Request
139 * @param[in] SctpParams sctpCfg, common structure which has all the configuration
140 * @param[in] CmStatus cfm, Builds the cfm status and reason
143 * @return ROK - success
146 ***************************************************************************/
148 S16 duSctpCfgReq(SctpParams sctpCfg)
154 f1Params.destIpAddr.ipV4Pres = sctpCfg.cuIpAddr.ipV4Pres;
155 f1Params.destIpAddr.ipV4Addr = sctpCfg.cuIpAddr.ipV4Addr;
156 f1Params.destPort = sctpCfg.cuPort;
157 f1Params.itfState = DU_SCTP_DOWN;
158 f1Params.srcPort = sctpCfg.duPort[F1_INTERFACE];
159 f1Params.recvMsgSet = ROK;
160 cmMemset ((U8 *)&f1Params.sockFd, -1, sizeof(CmInetFd));
161 fillDestNetAddr(&f1Params.destIpNetAddr, &f1Params.destIpAddr);
162 fillAddrLst(&f1Params.destAddrLst, &f1Params.destIpAddr);
164 /* Fill RIC Params */
165 ricParams.destIpAddr.ipV4Pres = sctpCfg.ricIpAddr.ipV4Pres;
166 ricParams.destIpAddr.ipV4Addr = sctpCfg.ricIpAddr.ipV4Addr;
167 ricParams.destPort = sctpCfg.ricPort;
168 ricParams.itfState = DU_SCTP_DOWN;
169 ricParams.srcPort = sctpCfg.duPort[E2_INTERFACE];
170 ricParams.recvMsgSet = ROK;
171 cmMemset ((U8 *)&ricParams.sockFd, -1, sizeof(CmInetFd));
172 fillDestNetAddr(&ricParams.destIpNetAddr, &ricParams.destIpAddr);
173 fillAddrLst(&ricParams.destAddrLst, &ricParams.destIpAddr);
175 /* Fill AddressList */
176 fillAddrLst(&localAddrLst, &sctpCfg.duIpAddr);
178 /* Set polling to FALSE */
179 pollingState = FALSE;
181 /* Fill Cfm Status */
182 cfm.status = LCM_PRIM_OK;
183 cfm.reason = LCM_REASON_NOT_APPL;
185 ret = duCheckReqStatus(&cfm);
190 /*******************************************************************
192 * @brief Fills the address List of the source Ip Address
196 * Function : fillAddrLst
199 * Fills the address List of source Ip Address
201 * @params[in] CmInetNetAddrLst *addrLstPtr, Address List pointer
202 * @params[in] F1IpAddr *srcIpAddr, src Ip Adrress to be filled in the Address List
204 * @return ROK - success
207 ******************************************************************/
209 S16 fillAddrLst(CmInetNetAddrLst *addrLstPtr, F1IpAddr *ipAddr)
212 addrLstPtr->addrs[(addrLstPtr->count - 1)].type = CM_INET_IPV4ADDR_TYPE;
213 addrLstPtr->addrs[(addrLstPtr->count - 1)].u.ipv4NetAddr = CM_INET_NTOH_U32(ipAddr->ipV4Addr);
218 /******************************************************************************
220 * @brief Fills the address List of the source Ip Address
224 * Function : fillDestNetAddr
227 * Fills the address List of destinatoion Ip Address
229 * @params[in] CmInetNetAddr *destAddrPtr, Address List pointer
230 * @params[in] F1IpAddr *dstIpAddr, destIp Address to be filled in the Address List
232 * @return ROK - success
235 *******************************************************************************/
236 S16 fillDestNetAddr(CmInetNetAddr *destAddrPtr, F1IpAddr *dstIpPtr)
238 /* Filling destination address */
239 destAddrPtr->type = CM_INET_IPV4ADDR_TYPE;
240 destAddrPtr->u.ipv4NetAddr = CM_INET_NTOH_U32(dstIpPtr->ipV4Addr);
244 /******************************************************************************
246 * @brief Establishes the Assoc Req for the received interface type
250 * Function : establishAssocReq
253 * Eastablishes the Assoc Req for the received interface type
255 * @params[in] DuSctpDestCb *paramPtr
257 * @return ROK - success
260 *******************************************************************************/
262 S16 establishReq(DuSctpDestCb *paramPtr)
266 socket_type = CM_INET_STREAM;
268 if((ret = cmInetSocket(socket_type, ¶mPtr->sockFd, IPPROTO_SCTP)) != ROK)
270 DU_LOG("\nSCTP : Failed while opening a socket in ODU");
272 else if((ret = cmInetSctpBindx(¶mPtr->sockFd, &localAddrLst, paramPtr->srcPort)) != ROK)
274 DU_LOG("\nSCTP: Failed during Binding in ODU");
276 else if((ret = sctpSetSockOpts(¶mPtr->sockFd)) != ROK)
278 DU_LOG("\nSCTP : Failed to set Socket Opt in ODU");
284 DU_LOG("\nSCTP : Failed while establishing Req at DU");
289 ret = cmInetSctpConnectx(¶mPtr->sockFd, ¶mPtr->destIpNetAddr, ¶mPtr->destAddrLst, paramPtr->destPort);
290 /* 115 error_code indicates that Operation is in progress and hence ignored if SctpConnect failed due to this */
297 if((ret == ROK) & (paramPtr->itfState == DU_SCTP_DOWN))
299 paramPtr->itfState = DU_SCTP_CONNECTING;
302 /* Post the EVTSTARTPOLL Msg */
306 duFillSctpPst(&pst, EVTSTARTPOLL);
312 /******************************************************************************
314 * @brief Processes the assoc Req for the received interface type
318 * Function : duSctpAssocReq
321 * Processes the Assoc Req for the received interface type
323 * @params[in] itfType interface Type,
324 * @params[in] cfm , represents the status of request
326 * @return ROK - success
329 *******************************************************************************/
331 S16 duSctpAssocReq(U8 itfType)
335 DuSctpDestCb *paramPtr = NULLP;
337 DU_ALLOC(paramPtr, sizeof(DuSctpDestCb));
338 if(paramPtr == NULLP)
340 printf("\nDU_APP : Failed to allocate memory");
347 paramPtr = &f1Params;
348 ret = establishReq(paramPtr);
353 paramPtr = &ricParams;
354 ret = establishReq(paramPtr);
359 DU_LOG("\nSCTP : Invalid Interface Type");
365 DU_LOG("\nSCTP : ASSOC Req Failed.");
366 cfm.status = LCM_PRIM_NOK;
367 cfm.reason = LCM_REASON_NOT_APPL;
371 cfm.status = LCM_PRIM_OK;
372 cfm.reason = LCM_REASON_NOT_APPL;
374 ret = duCheckReqStatus(&cfm);
378 /*******************************************************************
380 * @brief Fills Pst struct for ENTSCTP
384 * Function : duFillSctpPst
387 * Fills Pst struct for ENTSCTP
390 * @return ROK - success
393 * ****************************************************************/
394 S16 duFillSctpPst(Pst *pst, Event event)
397 if(SGetMsg(DFLT_REGION, DU_POOL, &mBuf) != ROK)
399 printf("\nDU_APP : Failed to allocate memory");
402 cmMemset((U8 *)pst, 0, sizeof(Pst));
403 pst->srcEnt = (Ent)ENTDUAPP;
404 pst->srcInst = (Inst)DU_INST;
405 pst->srcProcId = DU_PROC;
406 pst->dstEnt = (Ent)ENTSCTP;
407 pst->dstInst = (Inst)SCTP_INST;
408 pst->dstProcId = pst->srcProcId;
410 pst->selector = ODU_SELECTOR_LC;
417 /*******************************************************************
419 * @brief Sets socket options as per requirement
423 * Function : sctpSetSockOpts
426 * Sets socket options as per requirement
428 * @params[in] sock_Fd determines the sockFd to be set
429 * @return ROK - success
432 * ****************************************************************/
433 S16 sctpSetSockOpts(CmInetFd *sock_Fd)
436 CmSctpEvent sctpEvent;
438 sctpEvent.dataIoEvent = TRUE;
439 sctpEvent.associationEvent = TRUE;
440 sctpEvent.addressEvent = TRUE;
441 sctpEvent.sendFailureEvent = TRUE;
442 sctpEvent.peerErrorEvent = TRUE;
443 sctpEvent.shutdownEvent = TRUE;
444 sctpEvent.partialDeliveryEvent = TRUE;
445 sctpEvent.adaptationLayerEvent = TRUE;
447 if((ret = cmInetSetOpt(sock_Fd, CM_SOCKOPT_LEVEL_SCTP, CM_SOCKOPT_OPT_SCTP_EVENTS, &sctpEvent) != ROK))
455 /*******************************************************************
457 * @brief Post received data/notification to DU APP
461 * Function : sendToDuApp
464 * Post received data/notification to DU APP
466 * @params[in] Message buffer
469 * @return ROK - success
472 * ****************************************************************/
473 void sendToDuApp(Buffer *mBuf, Event event)
476 DU_LOG("\nSCTP : Forwarding received message to duApp");
477 SPrntMsg(mBuf, 0, 0);
480 cmMemset((U8 *)&(pst), 0, sizeof(Pst));
481 pst.srcEnt = (Ent)ENTSCTP;
482 pst.srcInst = (Inst)SCTP_INST;
483 pst.srcProcId = DU_PROC;
484 pst.dstEnt = (Ent)ENTDUAPP;
485 pst.dstInst = (Inst)DU_INST;
486 pst.dstProcId = pst.srcProcId;
488 pst.selector = ODU_SELECTOR_LC;
490 pst.region = DFLT_REGION;
492 if (SPstTsk(&pst, mBuf) != ROK)
494 DU_LOG("\nSCTP : SPstTsk failed in duReadCfg");
498 /*******************************************************************
500 * @brief Handles an SCTP notification message
503 * Function : sctpNtfyHdlr
506 * Handles an SCTP notification message
508 * @params[in] Notify message
510 * @return ROK - success
513 * ****************************************************************/
514 S16 sctpNtfyHdlr(CmInetSctpNotification *ntfy, U8 *itfState)
518 switch(ntfy->header.nType)
520 case CM_INET_SCTP_ASSOC_CHANGE :
521 DU_LOG("\nSCTP : Assoc change notification received");
522 switch(ntfy->u.assocChange.state)
524 case CM_INET_SCTP_COMM_UP:
525 DU_LOG("Event : COMMUNICATION UP");
526 *itfState = DU_SCTP_UP;
528 case CM_INET_SCTP_COMM_LOST:
529 DU_LOG("Event : COMMUNICATION LOST");
530 *itfState = DU_SCTP_DOWN;
532 case CM_INET_SCTP_RESTART:
533 DU_LOG("Event : SCTP RESTART");
534 *itfState = DU_SCTP_DOWN;
536 case CM_INET_SCTP_SHUTDOWN_COMP: /* association gracefully shutdown */
537 DU_LOG("Event : SHUTDOWN COMPLETE");
538 *itfState = DU_SCTP_DOWN;
540 case CM_INET_SCTP_CANT_STR_ASSOC:
541 DU_LOG("Event : CANT START ASSOC");
542 *itfState = DU_SCTP_DOWN;
545 DU_LOG("\nInvalid event");
549 case CM_INET_SCTP_PEER_ADDR_CHANGE :
550 DU_LOG("\nSCTP : Peer Address Change notificarion received");
551 /* Need to add handler */
553 case CM_INET_SCTP_REMOTE_ERROR :
554 DU_LOG("\nSCTP : Remote Error notification received");
556 case CM_INET_SCTP_SEND_FAILED :
557 DU_LOG("\nSCTP : Send Failed notification received\n");
559 case CM_INET_SCTP_SHUTDOWN_EVENT : /* peer socket gracefully closed */
560 DU_LOG("\nSCTP : Shutdown Event notification received\n");
561 *itfState = DU_SCTP_DOWN;
564 case CM_INET_SCTP_ADAPTATION_INDICATION :
565 DU_LOG("\nSCTP : Adaptation Indication received\n");
567 case CM_INET_SCTP_PARTIAL_DELIVERY_EVENT:
568 DU_LOG("\nSCTP : Partial Delivery Event received\n");
571 DU_LOG("\nSCTP : Invalid sctp notification type\n");
575 /* Pack notification and send to APP */
576 DU_LOG("\nSCTP : Forwarding received message to duApp");
578 cmMemset((U8 *)&(pst), 0, sizeof(Pst));
579 pst.srcEnt = (Ent)ENTSCTP;
580 pst.srcInst = (Inst)SCTP_INST;
581 pst.srcProcId = DU_PROC;
582 pst.dstEnt = (Ent)ENTDUAPP;
583 pst.dstInst = (Inst)DU_INST;
584 pst.dstProcId = pst.srcProcId;
585 pst.event = EVENT_SCTP_NTFY;
586 pst.selector = ODU_SELECTOR_LC;
588 pst.region = DU_APP_MEM_REGION;
590 if(cmPkSctpNtfy(&pst, ntfy) != ROK)
592 DU_LOG("\nSCTP : Failed to pack SCTP notification");
598 /*******************************************************************
600 * @brief checks for valid readFd and process the InetSctpRecvMsg
605 * Function : processPolling
608 * checks for valid readFd and process the InetSctpRecvMsg
611 * @params[in] Params required for polling
612 * @params[in] SockFd for file descriptor
613 * @params[in] timeoutPtr indicates the timeout value
614 * @params[in] MemInfo, recvMsgSet
616 * @return ROK - success
619 * ****************************************************************/
621 S16 processPolling(sctpSockPollParams *pollParams, CmInetFd *sockFd, U32 *timeoutPtr, CmInetMemInfo *memInfo, Bool recvMsgSet)
624 CM_INET_FD_SET(sockFd, &pollParams->readFd);
625 ret = cmInetSelect(&pollParams->readFd, NULLP, timeoutPtr, &pollParams->numFd);
626 if(CM_INET_FD_ISSET(sockFd, &pollParams->readFd))
628 CM_INET_FD_CLR(sockFd, &pollParams->readFd);
629 ret = cmInetSctpRecvMsg(sockFd, &pollParams->addr, &pollParams->port, memInfo, &(pollParams->mBuf), &pollParams->bufLen, &pollParams->info, &pollParams->flag, &pollParams->ntfy);
633 DU_LOG("\n SCTP: Failed to receive sctp msg for sockFd[%d]\n", sockFd->fd);
634 recvMsgSet = RFAILED;
638 if((((pollParams->flag & CM_INET_SCTP_MSG_NOTIFICATION) != 0)) && ret == ROK)
640 if(pollParams->port == f1Params.destPort)
642 f1Params.assocId = pollParams->ntfy.u.assocChange.assocId;
643 DU_LOG("\nSCTP : AssocId assigned to F1Params from PollParams [%d]\n", f1Params.assocId);
644 ret = sctpNtfyHdlr(&pollParams->ntfy, &f1Params.itfState);
646 else if(pollParams->port == ricParams.destPort)
648 ricParams.assocId = pollParams->ntfy.u.assocChange.assocId;
649 DU_LOG("\nSCTP : AssocId assigned to ricParams from PollParams [%d]\n", ricParams.assocId);
650 ret = sctpNtfyHdlr(&pollParams->ntfy, &ricParams.itfState);
654 DU_LOG("\nSCTP : Failed to fill AssocId\n");
659 DU_LOG("\nSCTP : Failed to process sctp notify msg\n");
662 else if(f1Params.itfState & (pollParams->port == f1Params.destPort))
664 sendToDuApp(pollParams->mBuf, EVENT_CU_DATA);
666 else if(ricParams.itfState & (pollParams->port == ricParams.destPort))
668 sendToDuApp(pollParams->mBuf, EVENT_RIC_DATA);
673 SPutMsg(pollParams->mBuf);
679 /*******************************************************************
681 * @brief Receives message on the socket
685 * Function : sctpSockPoll
688 * Receives message on the socket
691 * @return ROK - success
694 * ****************************************************************/
700 CmInetMemInfo memInfo;
701 sctpSockPollParams f1PollParams, e2PollParams;
703 memset(&f1PollParams, 0, sizeof(sctpSockPollParams));
704 memset(&e2PollParams, 0, sizeof(sctpSockPollParams));
706 if (f1Params.sockFd.blocking & ricParams.sockFd.blocking)
715 timeout_Ptr = &timeout;
717 memInfo.region = DU_APP_MEM_REGION;
718 memInfo.pool = DU_POOL;
720 CM_INET_FD_ZERO(&f1PollParams.readFd);
721 CM_INET_FD_ZERO(&e2PollParams.readFd);
723 DU_LOG("\nSCTP : Polling started at DU\n");
726 if(f1Params.itfState)
728 if((ret = processPolling(&f1PollParams, &f1Params.sockFd, timeout_Ptr, &memInfo, f1Params.recvMsgSet)) != ROK)
730 DU_LOG("\nSCTP : Failed to RecvMsg for F1\n");
733 if(ricParams.itfState)
735 if((ret = processPolling(&e2PollParams, &ricParams.sockFd, timeout_Ptr, &memInfo, ricParams.recvMsgSet)) != ROK)
737 DU_LOG("\nSCTP : Failed to RecvMsg for E2\n");
742 }/* End of sctpSockPoll() */
744 /*******************************************************************
746 * @brief Send message on SCTP socket
750 * Function : sctpSend
753 * Send message on SCTP socket
756 * @return ROK - success
759 * ****************************************************************/
760 S16 sctpSend(Buffer *mBuf, U8 itfType)
763 MsgLen len; /* number of actually sent octets */
764 CmInetMemInfo memInfo;
766 memInfo.region = DU_APP_MEM_REGION;
767 memInfo.pool = DU_POOL;
769 if(itfType == F1_INTERFACE)
771 DU_LOG("\nSCTP : sending the message to DuApp");
772 ret = cmInetSctpSendMsg(&f1Params.sockFd, &f1Params.destIpNetAddr, f1Params.destPort, &memInfo, mBuf, &len, 0, FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
775 if(itfType == E2_INTERFACE)
777 DU_LOG("\nSCTP : sending the message to ric");
778 ret = cmInetSctpSendMsg(&ricParams.sockFd, &ricParams.destIpNetAddr, ricParams.destPort, &memInfo, mBuf, &len, 0, FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
781 if(ret != ROK && ret != RWOULDBLOCK)
783 DU_LOG("\nSCTP : Failed sending the message");
788 } /* End of sctpSend */
790 /**********************************************************************
792 **********************************************************************/