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"
27 #include "du_app_mac_inf.h"
33 /**************************************************************************
34 * @brief Task Initiation callback function.
38 * Function : sctpActvInit
41 * This function is supplied as one of parameters during SCTP's
42 * task registration. SSI will invoke this function once, after
43 * it creates and attaches this TAPA Task to a system task.
45 * @param[in] Ent entity, the entity ID of this task.
46 * @param[in] Inst inst, the instance ID of this task.
47 * @param[in] Region region, the region ID registered for memory
49 * @param[in] Reason reason.
50 * @return ROK - success
52 ***************************************************************************/
53 uint8_t sctpActvInit(Ent entity, Inst inst, Region region, Reason reason)
55 DU_LOG("\n\nSCTP : Initializing");
56 ODU_SET_PROC_ID(DU_PROC);
58 f1Params.assocId = -1;
59 ricParams.assocId = -1;
65 /**************************************************************************
66 * @brief Task Activation callback function.
70 * Function : sctpActvTsk
73 * This function handles all SCTP messages received
74 * This API is registered with SSI during the
75 * Task Registration of DU APP.
77 * @param[in] Pst *pst, Post structure of the primitive.
78 * @param[in] Buffer *mBuf, Packed primitive parameters in the
80 * @return ROK - success
83 ***************************************************************************/
84 uint8_t sctpActvTsk(Pst *pst, Buffer *mBuf)
104 /*******************************************************************
106 * @brief Checks the status of the received information
110 * Function : duCheckReqStatus
113 * Checks the status of the received information
115 * @params[in] Confirm status
116 * @return ROK - success
119 ******************************************************************/
120 uint8_t duCheckReqStatus(CmStatus *cfm)
123 if(cfm->status != LCM_PRIM_OK)
125 DU_LOG("\nDU_APP : Failed to process the request successfully");
131 /**************************************************************************
132 * @brief Function to configure the Sctp Params during config Request
136 * Function : duSctpCfgReq
139 * This function configures SCTP Params during the config Request
141 * @param[in] SctpParams sctpCfg, common structure which has all the configuration
142 * @param[in] CmStatus cfm, Builds the cfm status and reason
145 * @return ROK - success
148 ***************************************************************************/
150 uint8_t duSctpCfgReq(SctpParams sctpCfg)
156 f1Params.destIpAddr.ipV4Pres = sctpCfg.cuIpAddr.ipV4Pres;
157 f1Params.destIpAddr.ipV4Addr = sctpCfg.cuIpAddr.ipV4Addr;
158 f1Params.destPort = sctpCfg.cuPort;
159 f1Params.itfState = DU_SCTP_DOWN;
160 f1Params.srcPort = sctpCfg.duPort[F1_INTERFACE];
161 f1Params.recvMsgSet = ROK;
162 memset (&f1Params.sockFd, -1, sizeof(CmInetFd));
163 fillDestNetAddr(&f1Params.destIpNetAddr, &f1Params.destIpAddr);
164 fillAddrLst(&f1Params.destAddrLst, &f1Params.destIpAddr);
166 /* Fill RIC Params */
167 ricParams.destIpAddr.ipV4Pres = sctpCfg.ricIpAddr.ipV4Pres;
168 ricParams.destIpAddr.ipV4Addr = sctpCfg.ricIpAddr.ipV4Addr;
169 ricParams.destPort = sctpCfg.ricPort;
170 ricParams.itfState = DU_SCTP_DOWN;
171 ricParams.srcPort = sctpCfg.duPort[E2_INTERFACE];
172 ricParams.recvMsgSet = ROK;
173 memset (&ricParams.sockFd, -1, sizeof(CmInetFd));
174 fillDestNetAddr(&ricParams.destIpNetAddr, &ricParams.destIpAddr);
175 fillAddrLst(&ricParams.destAddrLst, &ricParams.destIpAddr);
177 /* Fill AddressList */
178 fillAddrLst(&localAddrLst, &sctpCfg.duIpAddr);
180 /* Set polling to FALSE */
181 pollingState = FALSE;
183 /* Fill Cfm Status */
184 cfm.status = LCM_PRIM_OK;
185 cfm.reason = LCM_REASON_NOT_APPL;
187 ret = duCheckReqStatus(&cfm);
192 /*******************************************************************
194 * @brief Fills the address List of the source Ip Address
198 * Function : fillAddrLst
201 * Fills the address List of source Ip Address
203 * @params[in] CmInetNetAddrLst *addrLstPtr, Address List pointer
204 * @params[in] F1IpAddr *srcIpAddr, src Ip Adrress to be filled in the Address List
206 * @return ROK - success
209 ******************************************************************/
211 uint8_t fillAddrLst(CmInetNetAddrLst *addrLstPtr, F1IpAddr *ipAddr)
214 addrLstPtr->addrs[(addrLstPtr->count - 1)].type = CM_INET_IPV4ADDR_TYPE;
215 addrLstPtr->addrs[(addrLstPtr->count - 1)].u.ipv4NetAddr = CM_INET_NTOH_U32(ipAddr->ipV4Addr);
220 /******************************************************************************
222 * @brief Fills the address List of the source Ip Address
226 * Function : fillDestNetAddr
229 * Fills the address List of destinatoion Ip Address
231 * @params[in] CmInetNetAddr *destAddrPtr, Address List pointer
232 * @params[in] F1IpAddr *dstIpAddr, destIp Address to be filled in the Address List
234 * @return ROK - success
237 *******************************************************************************/
238 uint8_t fillDestNetAddr(CmInetNetAddr *destAddrPtr, F1IpAddr *dstIpPtr)
240 /* Filling destination address */
241 destAddrPtr->type = CM_INET_IPV4ADDR_TYPE;
242 destAddrPtr->u.ipv4NetAddr = CM_INET_NTOH_U32(dstIpPtr->ipV4Addr);
246 /******************************************************************************
248 * @brief Establishes the Assoc Req for the received interface type
252 * Function : establishAssocReq
255 * Eastablishes the Assoc Req for the received interface type
257 * @params[in] DuSctpDestCb *paramPtr
259 * @return ROK - success
262 *******************************************************************************/
264 uint8_t establishReq(DuSctpDestCb *paramPtr)
268 socket_type = CM_INET_STREAM;
270 if((ret = cmInetSocket(socket_type, ¶mPtr->sockFd, IPPROTO_SCTP)) != ROK)
272 DU_LOG("\nSCTP : Failed while opening a socket in ODU");
274 else if((ret = cmInetSctpBindx(¶mPtr->sockFd, &localAddrLst, paramPtr->srcPort)) != ROK)
276 DU_LOG("\nSCTP: Failed during Binding in ODU");
278 else if((ret = sctpSetSockOpts(¶mPtr->sockFd)) != ROK)
280 DU_LOG("\nSCTP : Failed to set Socket Opt in ODU");
286 DU_LOG("\nSCTP : Failed while establishing Req at DU");
291 ret = cmInetSctpConnectx(¶mPtr->sockFd, ¶mPtr->destIpNetAddr, ¶mPtr->destAddrLst, paramPtr->destPort);
292 /* 115 error_code indicates that Operation is in progress and hence ignored if SctpConnect failed due to this */
299 if((ret == ROK) & (paramPtr->itfState == DU_SCTP_DOWN))
301 paramPtr->itfState = DU_SCTP_CONNECTING;
304 /* Post the EVTSTARTPOLL Msg */
308 duFillSctpPst(&pst, EVTSTARTPOLL);
314 /******************************************************************************
316 * @brief Processes the assoc Req for the received interface type
320 * Function : duSctpAssocReq
323 * Processes the Assoc Req for the received interface type
325 * @params[in] itfType interface Type,
326 * @params[in] cfm , represents the status of request
328 * @return ROK - success
331 *******************************************************************************/
333 uint8_t duSctpAssocReq(uint8_t itfType)
337 DuSctpDestCb *paramPtr = NULLP;
339 DU_ALLOC(paramPtr, sizeof(DuSctpDestCb));
340 if(paramPtr == NULLP)
342 printf("\nDU_APP : Failed to allocate memory");
349 paramPtr = &f1Params;
350 ret = establishReq(paramPtr);
355 paramPtr = &ricParams;
356 ret = establishReq(paramPtr);
361 DU_LOG("\nSCTP : Invalid Interface Type");
367 DU_LOG("\nSCTP : ASSOC Req Failed.");
368 cfm.status = LCM_PRIM_NOK;
369 cfm.reason = LCM_REASON_NOT_APPL;
373 cfm.status = LCM_PRIM_OK;
374 cfm.reason = LCM_REASON_NOT_APPL;
376 ret = duCheckReqStatus(&cfm);
380 /*******************************************************************
382 * @brief Fills Pst struct for ENTSCTP
386 * Function : duFillSctpPst
389 * Fills Pst struct for ENTSCTP
392 * @return ROK - success
395 * ****************************************************************/
396 uint8_t duFillSctpPst(Pst *pst, Event event)
399 if(ODU_GET_MSG_BUF(DFLT_REGION, DU_POOL, &mBuf) != ROK)
401 printf("\nDU_APP : Failed to allocate memory");
404 memset(pst, 0, sizeof(Pst));
405 pst->srcEnt = (Ent)ENTDUAPP;
406 pst->srcInst = (Inst)DU_INST;
407 pst->srcProcId = DU_PROC;
408 pst->dstEnt = (Ent)ENTSCTP;
409 pst->dstInst = (Inst)SCTP_INST;
410 pst->dstProcId = pst->srcProcId;
412 pst->selector = ODU_SELECTOR_LC;
414 ODU_POST_TASK(pst, mBuf);
419 /*******************************************************************
421 * @brief Sets socket options as per requirement
425 * Function : sctpSetSockOpts
428 * Sets socket options as per requirement
430 * @params[in] sock_Fd determines the sockFd to be set
431 * @return ROK - success
434 * ****************************************************************/
435 uint8_t sctpSetSockOpts(CmInetFd *sock_Fd)
438 CmSctpEvent sctpEvent;
440 sctpEvent.dataIoEvent = TRUE;
441 sctpEvent.associationEvent = TRUE;
442 sctpEvent.addressEvent = TRUE;
443 sctpEvent.sendFailureEvent = TRUE;
444 sctpEvent.peerErrorEvent = TRUE;
445 sctpEvent.shutdownEvent = TRUE;
446 sctpEvent.partialDeliveryEvent = TRUE;
447 sctpEvent.adaptationLayerEvent = TRUE;
449 if((ret = cmInetSetOpt(sock_Fd, CM_SOCKOPT_LEVEL_SCTP, CM_SOCKOPT_OPT_SCTP_EVENTS, &sctpEvent) != ROK))
457 /*******************************************************************
459 * @brief Post received data/notification to DU APP
463 * Function : sendToDuApp
466 * Post received data/notification to DU APP
468 * @params[in] Message buffer
471 * @return ROK - success
474 * ****************************************************************/
475 void sendToDuApp(Buffer *mBuf, Event event)
478 DU_LOG("\nSCTP : Forwarding received message to duApp");
479 ODU_PRINT_MSG(mBuf, 0, 0);
482 memset(&(pst), 0, sizeof(Pst));
483 pst.srcEnt = (Ent)ENTSCTP;
484 pst.srcInst = (Inst)SCTP_INST;
485 pst.srcProcId = DU_PROC;
486 pst.dstEnt = (Ent)ENTDUAPP;
487 pst.dstInst = (Inst)DU_INST;
488 pst.dstProcId = pst.srcProcId;
490 pst.selector = ODU_SELECTOR_LC;
492 pst.region = DFLT_REGION;
494 if (ODU_POST_TASK(&pst, mBuf) != ROK)
496 DU_LOG("\nSCTP : ODU_POST_TASK failed in duReadCfg");
500 /*******************************************************************
502 * @brief Handles an SCTP notification message
505 * Function : sctpNtfyHdlr
508 * Handles an SCTP notification message
510 * @params[in] Notify message
512 * @return ROK - success
515 * ****************************************************************/
516 uint8_t sctpNtfyHdlr(CmInetSctpNotification *ntfy, uint8_t *itfState)
520 switch(ntfy->header.nType)
522 case CM_INET_SCTP_ASSOC_CHANGE :
523 DU_LOG("\nSCTP : Assoc change notification received");
524 switch(ntfy->u.assocChange.state)
526 case CM_INET_SCTP_COMM_UP:
527 DU_LOG("Event : COMMUNICATION UP");
528 *itfState = DU_SCTP_UP;
530 case CM_INET_SCTP_COMM_LOST:
531 DU_LOG("Event : COMMUNICATION LOST");
532 *itfState = DU_SCTP_DOWN;
534 case CM_INET_SCTP_RESTART:
535 DU_LOG("Event : SCTP RESTART");
536 *itfState = DU_SCTP_DOWN;
538 case CM_INET_SCTP_SHUTDOWN_COMP: /* association gracefully shutdown */
539 DU_LOG("Event : SHUTDOWN COMPLETE");
540 *itfState = DU_SCTP_DOWN;
542 case CM_INET_SCTP_CANT_STR_ASSOC:
543 DU_LOG("Event : CANT START ASSOC");
544 *itfState = DU_SCTP_DOWN;
547 DU_LOG("\nInvalid event");
551 case CM_INET_SCTP_PEER_ADDR_CHANGE :
552 DU_LOG("\nSCTP : Peer Address Change notificarion received");
553 /* Need to add handler */
555 case CM_INET_SCTP_REMOTE_ERROR :
556 DU_LOG("\nSCTP : Remote Error notification received");
558 case CM_INET_SCTP_SEND_FAILED :
559 DU_LOG("\nSCTP : Send Failed notification received\n");
561 case CM_INET_SCTP_SHUTDOWN_EVENT : /* peer socket gracefully closed */
562 DU_LOG("\nSCTP : Shutdown Event notification received\n");
563 *itfState = DU_SCTP_DOWN;
566 case CM_INET_SCTP_ADAPTATION_INDICATION :
567 DU_LOG("\nSCTP : Adaptation Indication received\n");
569 case CM_INET_SCTP_PARTIAL_DELIVERY_EVENT:
570 DU_LOG("\nSCTP : Partial Delivery Event received\n");
573 DU_LOG("\nSCTP : Invalid sctp notification type\n");
577 /* Pack notification and send to APP */
578 DU_LOG("\nSCTP : Forwarding received message to duApp");
580 memset(&(pst), 0, sizeof(Pst));
581 pst.srcEnt = (Ent)ENTSCTP;
582 pst.srcInst = (Inst)SCTP_INST;
583 pst.srcProcId = DU_PROC;
584 pst.dstEnt = (Ent)ENTDUAPP;
585 pst.dstInst = (Inst)DU_INST;
586 pst.dstProcId = pst.srcProcId;
587 pst.event = EVENT_SCTP_NTFY;
588 pst.selector = ODU_SELECTOR_LC;
590 pst.region = DU_APP_MEM_REGION;
592 if(cmPkSctpNtfy(&pst, ntfy) != ROK)
594 DU_LOG("\nSCTP : Failed to pack SCTP notification");
600 /*******************************************************************
602 * @brief checks for valid readFd and process the InetSctpRecvMsg
607 * Function : processPolling
610 * checks for valid readFd and process the InetSctpRecvMsg
613 * @params[in] Params required for polling
614 * @params[in] SockFd for file descriptor
615 * @params[in] timeoutPtr indicates the timeout value
616 * @params[in] MemInfo, recvMsgSet
618 * @return ROK - success
621 * ****************************************************************/
623 uint8_t processPolling(sctpSockPollParams *pollParams, CmInetFd *sockFd, uint32_t *timeoutPtr, CmInetMemInfo *memInfo, bool recvMsgSet)
626 CM_INET_FD_SET(sockFd, &pollParams->readFd);
627 ret = cmInetSelect(&pollParams->readFd, NULLP, timeoutPtr, (int16_t *)&pollParams->numFd);
628 if(CM_INET_FD_ISSET(sockFd, &pollParams->readFd))
630 CM_INET_FD_CLR(sockFd, &pollParams->readFd);
631 ret = cmInetSctpRecvMsg(sockFd, &pollParams->addr, &pollParams->port, memInfo, &(pollParams->mBuf), &pollParams->bufLen, &pollParams->info, &pollParams->flag, &pollParams->ntfy);
635 DU_LOG("\n SCTP: Failed to receive sctp msg for sockFd[%d]\n", sockFd->fd);
636 recvMsgSet = RFAILED;
640 if((((pollParams->flag & CM_INET_SCTP_MSG_NOTIFICATION) != 0)) && ret == ROK)
642 if(pollParams->port == f1Params.destPort)
644 f1Params.assocId = pollParams->ntfy.u.assocChange.assocId;
645 DU_LOG("\nSCTP : AssocId assigned to F1Params from PollParams [%d]\n", f1Params.assocId);
646 ret = sctpNtfyHdlr(&pollParams->ntfy, &f1Params.itfState);
648 else if(pollParams->port == ricParams.destPort)
650 ricParams.assocId = pollParams->ntfy.u.assocChange.assocId;
651 DU_LOG("\nSCTP : AssocId assigned to ricParams from PollParams [%d]\n", ricParams.assocId);
652 ret = sctpNtfyHdlr(&pollParams->ntfy, &ricParams.itfState);
656 DU_LOG("\nSCTP : Failed to fill AssocId\n");
661 DU_LOG("\nSCTP : Failed to process sctp notify msg\n");
664 else if(f1Params.itfState & (pollParams->port == f1Params.destPort))
666 sendToDuApp(pollParams->mBuf, EVENT_CU_DATA);
668 else if(ricParams.itfState & (pollParams->port == ricParams.destPort))
670 sendToDuApp(pollParams->mBuf, EVENT_RIC_DATA);
675 ODU_PUT_MSG_BUF(pollParams->mBuf);
681 /*******************************************************************
683 * @brief Receives message on the socket
687 * Function : sctpSockPoll
690 * Receives message on the socket
693 * @return ROK - success
696 * ****************************************************************/
697 uint8_t sctpSockPoll()
701 uint32_t *timeout_Ptr;
702 CmInetMemInfo memInfo;
703 sctpSockPollParams f1PollParams, e2PollParams;
705 memset(&f1PollParams, 0, sizeof(sctpSockPollParams));
706 memset(&e2PollParams, 0, sizeof(sctpSockPollParams));
708 if (f1Params.sockFd.blocking & ricParams.sockFd.blocking)
717 timeout_Ptr = &timeout;
719 memInfo.region = DU_APP_MEM_REGION;
720 memInfo.pool = DU_POOL;
722 CM_INET_FD_ZERO(&f1PollParams.readFd);
723 CM_INET_FD_ZERO(&e2PollParams.readFd);
725 DU_LOG("\nSCTP : Polling started at DU\n");
728 if(f1Params.itfState)
730 if((ret = processPolling(&f1PollParams, &f1Params.sockFd, timeout_Ptr, &memInfo, f1Params.recvMsgSet)) != ROK)
732 DU_LOG("\nSCTP : Failed to RecvMsg for F1\n");
735 if(ricParams.itfState)
737 if((ret = processPolling(&e2PollParams, &ricParams.sockFd, timeout_Ptr, &memInfo, ricParams.recvMsgSet)) != ROK)
739 DU_LOG("\nSCTP : Failed to RecvMsg for E2\n");
744 }/* End of sctpSockPoll() */
746 /*******************************************************************
748 * @brief Send message on SCTP socket
752 * Function : sctpSend
755 * Send message on SCTP socket
758 * @return ROK - success
761 * ****************************************************************/
762 uint8_t sctpSend(Buffer *mBuf, uint8_t itfType)
765 MsgLen len; /* number of actually sent octets */
766 CmInetMemInfo memInfo;
768 memInfo.region = DU_APP_MEM_REGION;
769 memInfo.pool = DU_POOL;
771 if(itfType == F1_INTERFACE)
773 DU_LOG("\nSCTP : sending the message to DuApp");
774 ret = cmInetSctpSendMsg(&f1Params.sockFd, &f1Params.destIpNetAddr, f1Params.destPort, &memInfo, mBuf, &len, 0, FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
777 if(itfType == E2_INTERFACE)
779 DU_LOG("\nSCTP : sending the message to ric");
780 ret = cmInetSctpSendMsg(&ricParams.sockFd, &ricParams.destIpNetAddr, ricParams.destPort, &memInfo, mBuf, &len, 0, FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
783 if(ret != ROK && ret != RWOULDBLOCK)
785 DU_LOG("\nSCTP : Failed sending the message");
790 } /* End of sctpSend */
792 /**********************************************************************
794 **********************************************************************/