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"
28 #include "du_app_mac_inf.h"
29 #include "du_e2ap_mgr.h"
33 #include "du_app_rlc_inf.h"
37 /**************************************************************************
38 * @brief Task Initiation callback function.
42 * Function : sctpActvInit
45 * This function is supplied as one of parameters during SCTP's
46 * task registration. SSI will invoke this function once, after
47 * it creates and attaches this TAPA Task to a system task.
49 * @param[in] Ent entity, the entity ID of this task.
50 * @param[in] Inst inst, the instance ID of this task.
51 * @param[in] Region region, the region ID registered for memory
53 * @param[in] Reason reason.
54 * @return ROK - success
56 ***************************************************************************/
57 uint8_t sctpActvInit(Ent entity, Inst inst, Region region, Reason reason)
59 DU_LOG("\n\nDEBUG --> SCTP : Initializing");
60 ODU_SET_PROC_ID(DU_PROC);
63 memset(&f1Params, 0, sizeof(DuSctpDestCb));
64 f1Params.assocId = -1;
65 memset(&ricParams, 0, sizeof(DuSctpDestCb));
66 ricParams.assocId = -1;
72 /**************************************************************************
73 * @brief Function prints src, dest, msg infor about all the msgs that received.
77 * Function : callFlowSctpActvTsk
79 * Function prints src, dest, msg infor about all the msgs that received
81 * @param[in] Pst *pst, Post structure of the primitive.
84 ***************************************************************************/
85 void callFlowSctpActvTsk(Pst *pst)
88 char destTask[50]="ENTSCTP";
95 strcpy(sourceTask,"ENTDUAPP");
100 strcpy(message,"EVTSTARTPOLL");
107 DU_LOG("\nCall Flow: %s -> %s : %s\n", sourceTask, destTask, message);
110 /**************************************************************************
111 * @brief Task Activation callback function.
115 * Function : sctpActvTsk
118 * This function handles all SCTP messages received
119 * This API is registered with SSI during the
120 * Task Registration of DU APP.
122 * @param[in] Pst *pst, Post structure of the primitive.
123 * @param[in] Buffer *mBuf, Packed primitive parameters in the
125 * @return ROK - success
128 ***************************************************************************/
129 uint8_t sctpActvTsk(Pst *pst, Buffer *mBuf)
132 #ifdef CALL_FLOW_DEBUG_LOG
133 callFlowSctpActvTsk(pst);
155 /*******************************************************************
157 * @brief Checks the status of the received information
161 * Function : duCheckReqStatus
164 * Checks the status of the received information
166 * @params[in] Confirm status
167 * @return ROK - success
170 ******************************************************************/
171 uint8_t duCheckReqStatus(CmStatus *cfm)
174 if(cfm->status != LCM_PRIM_OK)
176 DU_LOG("\nERROR --> DU_APP : Failed to process the request successfully");
182 /**************************************************************************
183 * @brief Function to configure the Sctp Params during config Request
187 * Function : duSctpCfgReq
190 * This function configures SCTP Params during the config Request
192 * @param[in] SctpParams sctpCfg, common structure which has all the configuration
193 * @param[in] CmStatus cfm, Builds the cfm status and reason
196 * @return ROK - success
199 ***************************************************************************/
201 uint8_t duSctpCfgReq(SctpParams sctpCfg)
206 #ifdef CALL_FLOW_DEBUG_LOG
207 DU_LOG("\nCall Flow: ENTDUAPP -> ENTSCTP : EVENT_CFG_REQ_TO_SCTP\n");
210 f1Params.destIpAddr.ipV4Pres = sctpCfg.cuIpAddr.ipV4Pres;
211 f1Params.destIpAddr.ipV4Addr = sctpCfg.cuIpAddr.ipV4Addr;
212 f1Params.destPort = sctpCfg.cuPort;
213 f1Params.itfState = DU_SCTP_DOWN;
214 f1Params.srcPort = sctpCfg.duPort[F1_INTERFACE];
215 f1Params.recvMsgSet = ROK;
216 memset (&f1Params.sockFd, -1, sizeof(CmInetFd));
217 fillDestNetAddr(&f1Params.destIpNetAddr, &f1Params.destIpAddr);
218 fillAddrLst(&f1Params.destAddrLst, &f1Params.destIpAddr);
220 /* Fill RIC Params */
221 ricParams.destIpAddr.ipV4Pres = sctpCfg.ricIpAddr.ipV4Pres;
222 ricParams.destIpAddr.ipV4Addr = sctpCfg.ricIpAddr.ipV4Addr;
223 ricParams.destPort = sctpCfg.ricPort;
224 ricParams.itfState = DU_SCTP_DOWN;
225 ricParams.srcPort = sctpCfg.duPort[E2_INTERFACE];
226 ricParams.recvMsgSet = ROK;
227 memset (&ricParams.sockFd, -1, sizeof(CmInetFd));
228 fillDestNetAddr(&ricParams.destIpNetAddr, &ricParams.destIpAddr);
229 fillAddrLst(&ricParams.destAddrLst, &ricParams.destIpAddr);
231 /* Fill AddressList */
232 fillAddrLst(&localAddrLst, &sctpCfg.duIpAddr);
234 /* Set polling to FALSE */
235 pollingState = FALSE;
237 /* Fill Cfm Status */
238 cfm.status = LCM_PRIM_OK;
239 cfm.reason = LCM_REASON_NOT_APPL;
241 ret = duCheckReqStatus(&cfm);
246 /*******************************************************************
248 * @brief Fills the address List of the source Ip Address
252 * Function : fillAddrLst
255 * Fills the address List of source Ip Address
257 * @params[in] CmInetNetAddrLst *addrLstPtr, Address List pointer
258 * @params[in] F1IpAddr *srcIpAddr, src Ip Adrress to be filled in the Address List
260 * @return ROK - success
263 ******************************************************************/
265 uint8_t fillAddrLst(CmInetNetAddrLst *addrLstPtr, F1IpAddr *ipAddr)
268 addrLstPtr->addrs[(addrLstPtr->count - 1)].type = CM_INET_IPV4ADDR_TYPE;
269 addrLstPtr->addrs[(addrLstPtr->count - 1)].u.ipv4NetAddr = CM_INET_NTOH_UINT32(ipAddr->ipV4Addr);
274 /******************************************************************************
276 * @brief Fills the address List of the source Ip Address
280 * Function : fillDestNetAddr
283 * Fills the address List of destinatoion Ip Address
285 * @params[in] CmInetNetAddr *destAddrPtr, Address List pointer
286 * @params[in] F1IpAddr *dstIpAddr, destIp Address to be filled in the Address List
288 * @return ROK - success
291 *******************************************************************************/
292 uint8_t fillDestNetAddr(CmInetNetAddr *destAddrPtr, F1IpAddr *dstIpPtr)
294 /* Filling destination address */
295 destAddrPtr->type = CM_INET_IPV4ADDR_TYPE;
296 destAddrPtr->u.ipv4NetAddr = CM_INET_NTOH_UINT32(dstIpPtr->ipV4Addr);
300 /******************************************************************************
302 * @brief Establishes the Assoc Req for the received interface type
306 * Function : establishAssocReq
309 * Eastablishes the Assoc Req for the received interface type
311 * @params[in] DuSctpDestCb *paramPtr
313 * @return ROK - success
316 *******************************************************************************/
318 uint8_t establishReq(DuSctpDestCb *paramPtr)
322 socket_type = CM_INET_STREAM;
324 if((ret = cmInetSocket(socket_type, ¶mPtr->sockFd, IPPROTO_SCTP)) != ROK)
326 DU_LOG("\nERROR --> SCTP : Failed while opening a socket in ODU");
328 else if((ret = cmInetSctpBindx(¶mPtr->sockFd, &localAddrLst, paramPtr->srcPort)) != ROK)
330 DU_LOG("\nERROR --> SCTP: Failed during Binding in ODU");
332 else if((ret = sctpSetSockOpts(¶mPtr->sockFd)) != ROK)
334 DU_LOG("\nERROR --> SCTP : Failed to set Socket Opt in ODU");
340 DU_LOG("\nERROR --> SCTP : Failed while establishing Req at DU");
345 ret = cmInetSctpConnectx(¶mPtr->sockFd, ¶mPtr->destIpNetAddr, ¶mPtr->destAddrLst, paramPtr->destPort);
346 /* 115 error_code indicates that Operation is in progress and hence ignored if SctpConnect failed due to this */
353 if((ret == ROK) & (paramPtr->itfState == DU_SCTP_DOWN))
355 paramPtr->itfState = DU_SCTP_CONNECTING;
358 /* Post the EVTSTARTPOLL Msg */
362 duFillSctpPst(&pst, EVTSTARTPOLL);
368 /******************************************************************************
370 * @brief Processes the assoc Req for the received interface type
374 * Function : duSctpAssocReq
377 * Processes the Assoc Req for the received interface type
379 * @params[in] itfType interface Type,
380 * @params[in] cfm , represents the status of request
382 * @return ROK - success
385 *******************************************************************************/
387 uint8_t duSctpAssocReq(uint8_t itfType)
391 DuSctpDestCb *paramPtr = NULLP;
393 #ifdef CALL_FLOW_DEBUG_LOG
394 DU_LOG("\nCall Flow: ENTDUAPP -> ENTSCTP : EVENT_ASSOC_REQ_TO_SCTP\n");
397 DU_ALLOC(paramPtr, sizeof(DuSctpDestCb));
398 if(paramPtr == NULLP)
400 DU_LOG("\nERROR --> DU_APP : Failed to allocate memory");
407 paramPtr = &f1Params;
408 ret = establishReq(paramPtr);
413 paramPtr = &ricParams;
414 ret = establishReq(paramPtr);
419 DU_LOG("\nERROR --> SCTP : Invalid Interface Type %d", itfType);
425 DU_LOG("\nERROR --> SCTP : ASSOC Req Failed.");
426 cfm.status = LCM_PRIM_NOK;
427 cfm.reason = LCM_REASON_NOT_APPL;
431 cfm.status = LCM_PRIM_OK;
432 cfm.reason = LCM_REASON_NOT_APPL;
434 ret = duCheckReqStatus(&cfm);
438 /*******************************************************************
440 * @brief Fills Pst struct for ENTSCTP
444 * Function : duFillSctpPst
447 * Fills Pst struct for ENTSCTP
450 * @return ROK - success
453 * ****************************************************************/
454 uint8_t duFillSctpPst(Pst *pst, Event event)
457 if(ODU_GET_MSG_BUF(DFLT_REGION, DU_POOL, &mBuf) != ROK)
459 DU_LOG("\nERROR --> DU_APP : Failed to allocate memory");
462 memset(pst, 0, sizeof(Pst));
463 pst->srcEnt = (Ent)ENTDUAPP;
464 pst->srcInst = (Inst)DU_INST;
465 pst->srcProcId = DU_PROC;
466 pst->dstEnt = (Ent)ENTSCTP;
467 pst->dstInst = (Inst)SCTP_INST;
468 pst->dstProcId = pst->srcProcId;
470 pst->selector = ODU_SELECTOR_LC;
472 ODU_POST_TASK(pst, mBuf);
477 /*******************************************************************
479 * @brief Sets socket options as per requirement
483 * Function : sctpSetSockOpts
486 * Sets socket options as per requirement
488 * @params[in] sock_Fd determines the sockFd to be set
489 * @return ROK - success
492 * ****************************************************************/
493 uint8_t sctpSetSockOpts(CmInetFd *sock_Fd)
496 CmSctpEvent sctpEvent;
498 sctpEvent.dataIoEvent = TRUE;
499 sctpEvent.associationEvent = TRUE;
500 sctpEvent.addressEvent = TRUE;
501 sctpEvent.sendFailureEvent = TRUE;
502 sctpEvent.peerErrorEvent = TRUE;
503 sctpEvent.shutdownEvent = TRUE;
504 sctpEvent.partialDeliveryEvent = TRUE;
505 sctpEvent.adaptationLayerEvent = TRUE;
507 if((ret = cmInetSetOpt(sock_Fd, CM_SOCKOPT_LEVEL_SCTP, CM_SOCKOPT_OPT_SCTP_EVENTS, &sctpEvent) != ROK))
515 /*******************************************************************
517 * @brief Post received data/notification to DU APP
521 * Function : sendToDuApp
524 * Post received data/notification to DU APP
526 * @params[in] Message buffer
529 * @return ROK - success
532 * ****************************************************************/
533 void sendToDuApp(Buffer *mBuf, Event event)
536 DU_LOG("\nDEBUG --> SCTP : Forwarding received message to duApp");
537 ODU_PRINT_MSG(mBuf, 0, 0);
540 memset(&(pst), 0, sizeof(Pst));
541 pst.srcEnt = (Ent)ENTSCTP;
542 pst.srcInst = (Inst)SCTP_INST;
543 pst.srcProcId = DU_PROC;
544 pst.dstEnt = (Ent)ENTDUAPP;
545 pst.dstInst = (Inst)DU_INST;
546 pst.dstProcId = pst.srcProcId;
548 pst.selector = ODU_SELECTOR_LC;
550 pst.region = DFLT_REGION;
552 if (ODU_POST_TASK(&pst, mBuf) != ROK)
554 DU_LOG("\nERROR --> SCTP : ODU_POST_TASK failed in duReadCfg");
558 /*******************************************************************
560 * @brief Handles an SCTP notification message
563 * Function : sctpNtfyHdlr
566 * Handles an SCTP notification message
568 * @params[in] Notify message
570 * @return ROK - success
573 * ****************************************************************/
574 uint8_t sctpNtfyHdlr(CmInetSctpNotification *ntfy, uint8_t *itfState)
578 switch(ntfy->header.nType)
580 case CM_INET_SCTP_ASSOC_CHANGE :
581 DU_LOG("\nDEBUG --> SCTP : Assoc change notification received");
582 switch(ntfy->u.assocChange.state)
584 case CM_INET_SCTP_COMM_UP:
585 DU_LOG("INFO --> Event : COMMUNICATION UP");
586 *itfState = DU_SCTP_UP;
588 case CM_INET_SCTP_COMM_LOST:
589 DU_LOG("INFO --> Event : COMMUNICATION LOST");
590 *itfState = DU_SCTP_DOWN;
592 case CM_INET_SCTP_RESTART:
593 DU_LOG("INFO --> Event : SCTP RESTART");
594 *itfState = DU_SCTP_DOWN;
596 case CM_INET_SCTP_SHUTDOWN_COMP: /* association gracefully shutdown */
597 DU_LOG("INFO --> Event : SHUTDOWN COMPLETE");
598 *itfState = DU_SCTP_DOWN;
600 case CM_INET_SCTP_CANT_STR_ASSOC:
601 DU_LOG("INFO --> Event : CANT START ASSOC");
602 *itfState = DU_SCTP_DOWN;
605 DU_LOG("\nERROR --> Invalid event %d", ntfy->u.assocChange.state);
609 case CM_INET_SCTP_PEER_ADDR_CHANGE :
610 DU_LOG("\nINFO --> SCTP : Peer Address Change notificarion received");
611 /* Need to add handler */
613 case CM_INET_SCTP_REMOTE_ERROR :
614 DU_LOG("\nINFO --> SCTP : Remote Error notification received");
616 case CM_INET_SCTP_SEND_FAILED :
617 DU_LOG("\nINFO --> SCTP : Send Failed notification received\n");
619 case CM_INET_SCTP_SHUTDOWN_EVENT : /* peer socket gracefully closed */
620 DU_LOG("\nINFO --> SCTP : Shutdown Event notification received\n");
621 *itfState = DU_SCTP_DOWN;
624 case CM_INET_SCTP_ADAPTATION_INDICATION :
625 DU_LOG("\nINFO --> SCTP : Adaptation Indication received\n");
627 case CM_INET_SCTP_PARTIAL_DELIVERY_EVENT:
628 DU_LOG("\nINFO --> SCTP : Partial Delivery Event received\n");
631 DU_LOG("\nERROR --> SCTP : Invalid sctp notification type %d", ntfy->header.nType);
635 /* Pack notification and send to APP */
636 DU_LOG("\nDEBUG --> SCTP : Forwarding received message to duApp");
638 memset(&(pst), 0, sizeof(Pst));
639 pst.srcEnt = (Ent)ENTSCTP;
640 pst.srcInst = (Inst)SCTP_INST;
641 pst.srcProcId = DU_PROC;
642 pst.dstEnt = (Ent)ENTDUAPP;
643 pst.dstInst = (Inst)DU_INST;
644 pst.dstProcId = pst.srcProcId;
645 pst.event = EVENT_SCTP_NTFY;
646 pst.selector = ODU_SELECTOR_LC;
648 pst.region = DU_APP_MEM_REGION;
650 if(cmPkSctpNtfy(&pst, ntfy) != ROK)
652 DU_LOG("\nERROR --> SCTP : Failed to pack SCTP notification");
658 /*******************************************************************
660 * @brief checks for valid readFd and process the InetSctpRecvMsg
665 * Function : processPolling
668 * checks for valid readFd and process the InetSctpRecvMsg
671 * @params[in] Params required for polling
672 * @params[in] SockFd for file descriptor
673 * @params[in] timeoutPtr indicates the timeout value
674 * @params[in] MemInfo, recvMsgSet
676 * @return ROK - success
679 * ****************************************************************/
681 uint8_t processPolling(sctpSockPollParams *pollParams, CmInetFd *sockFd, uint32_t *timeoutPtr, CmInetMemInfo *memInfo, bool recvMsgSet)
684 CM_INET_FD_SET(sockFd, &pollParams->readFd);
685 ret = cmInetSelect(&pollParams->readFd, NULLP, timeoutPtr, (int16_t *)&pollParams->numFd);
686 if(CM_INET_FD_ISSET(sockFd, &pollParams->readFd))
688 CM_INET_FD_CLR(sockFd, &pollParams->readFd);
689 ret = cmInetSctpRecvMsg(sockFd, &pollParams->addr, &pollParams->port, memInfo, &(pollParams->mBuf), &pollParams->bufLen, &pollParams->info, &pollParams->flag, &pollParams->ntfy);
693 DU_LOG("\nERROR --> SCTP: Failed to receive sctp msg for sockFd[%d]\n", sockFd->fd);
694 recvMsgSet = RFAILED;
698 #ifdef CALL_FLOW_DEBUG_LOG
699 if(pollParams->port == f1Params.destPort)
700 DU_LOG("\nCall Flow: CU -> ENTSCTP : EVENT_SCTP_MSG\n");
702 DU_LOG("\nCall Flow: RIC -> ENTSCTP : EVENT_SCTP_MSG\n");
704 if((((pollParams->flag & CM_INET_SCTP_MSG_NOTIFICATION) != 0)) && ret == ROK)
706 if(pollParams->port == f1Params.destPort)
708 f1Params.assocId = pollParams->ntfy.u.assocChange.assocId;
709 DU_LOG("\nDEBUG --> SCTP : AssocId assigned to F1Params from PollParams [%d]\n", f1Params.assocId);
710 ret = sctpNtfyHdlr(&pollParams->ntfy, &f1Params.itfState);
712 else if(pollParams->port == ricParams.destPort)
714 ricParams.assocId = pollParams->ntfy.u.assocChange.assocId;
715 DU_LOG("\nDEBUG --> SCTP : AssocId assigned to ricParams from PollParams [%d]\n", ricParams.assocId);
716 ret = sctpNtfyHdlr(&pollParams->ntfy, &ricParams.itfState);
720 DU_LOG("\nERROR --> SCTP : Failed to fill AssocId\n");
725 DU_LOG("\nERROR --> SCTP : Failed to process sctp notify msg\n");
728 else if(f1Params.itfState & (pollParams->port == f1Params.destPort))
730 sendToDuApp(pollParams->mBuf, EVENT_CU_DATA);
732 else if(ricParams.itfState & (pollParams->port == ricParams.destPort))
734 sendToDuApp(pollParams->mBuf, EVENT_RIC_DATA);
739 ODU_PUT_MSG_BUF(pollParams->mBuf);
745 /*******************************************************************
747 * @brief Receives message on the socket
751 * Function : sctpSockPoll
754 * Receives message on the socket
757 * @return ROK - success
760 * ****************************************************************/
761 uint8_t sctpSockPoll()
765 uint32_t *timeout_Ptr;
766 CmInetMemInfo memInfo;
767 sctpSockPollParams f1PollParams, e2PollParams;
769 memset(&f1PollParams, 0, sizeof(sctpSockPollParams));
770 memset(&e2PollParams, 0, sizeof(sctpSockPollParams));
772 if (f1Params.sockFd.blocking & ricParams.sockFd.blocking)
781 timeout_Ptr = &timeout;
783 memInfo.region = DU_APP_MEM_REGION;
784 memInfo.pool = DU_POOL;
786 CM_INET_FD_ZERO(&f1PollParams.readFd);
787 CM_INET_FD_ZERO(&e2PollParams.readFd);
789 DU_LOG("\nINFO --> SCTP : Polling started at DU\n");
792 if(f1Params.itfState)
794 if((ret = processPolling(&f1PollParams, &f1Params.sockFd, timeout_Ptr, &memInfo, f1Params.recvMsgSet)) != ROK)
796 DU_LOG("\nERROR --> SCTP : Failed to RecvMsg for F1\n");
799 if(ricParams.itfState)
801 if((ret = processPolling(&e2PollParams, &ricParams.sockFd, timeout_Ptr, &memInfo, ricParams.recvMsgSet)) != ROK)
803 DU_LOG("\nERROR --> SCTP : Failed to RecvMsg for E2\n");
808 }/* End of sctpSockPoll() */
810 /*******************************************************************
812 * @brief Send message on SCTP socket
816 * Function : sctpSend
819 * Send message on SCTP socket
822 * @return ROK - success
825 * ****************************************************************/
826 uint8_t sctpSend(Buffer *mBuf, uint8_t itfType)
829 MsgLen len =0; /* number of actually sent octets */
830 CmInetMemInfo memInfo;
832 memInfo.region = DU_APP_MEM_REGION;
833 memInfo.pool = DU_POOL;
835 #ifdef CALL_FLOW_DEBUG_LOG
836 if(itfType == F1_INTERFACE)
838 DU_LOG("\nCall Flow: ENTDUAPP -> ENTSCTP : EVENT_F1AP_MSG_TO_SCTP\n");
842 DU_LOG("\nCall Flow: ENTDUAPP -> ENTSCTP : EVENT_E2AP_MSG_TO_SCTP\n");
846 if(itfType == F1_INTERFACE)
848 DU_LOG("\nDEBUG --> SCTP : sending the message to CU");
849 #ifdef CALL_FLOW_DEBUG_LOG
850 DU_LOG("\nCall Flow: ENTSCTP -> CU : EVENT_F1AP_MSG_TO_CU\n");
852 ret = cmInetSctpSendMsg(&f1Params.sockFd, &f1Params.destIpNetAddr, f1Params.destPort, &memInfo, mBuf, &len, 0, FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
855 if(itfType == E2_INTERFACE)
857 DU_LOG("\nDEBUG --> SCTP : sending the message to ric");
858 #ifdef CALL_FLOW_DEBUG_LOG
859 DU_LOG("\nCall Flow: ENTSCTP -> RIC : EVENT_E2AP_MSG_TO_RIC\n");
861 ret = cmInetSctpSendMsg(&ricParams.sockFd, &ricParams.destIpNetAddr, ricParams.destPort, &memInfo, mBuf, &len, 0, FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
864 if(ret != ROK && ret != RWOULDBLOCK)
866 DU_LOG("\nERROR --> SCTP : Failed sending the message");
871 } /* End of sctpSend */
873 /**********************************************************************
875 **********************************************************************/