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 */
21 #include "common_def.h"
22 #include "OCTET_STRING.h"
23 #include "cu_f1ap_msg_hdl.h"
24 #include "cu_stub_sctp.h"
25 #include "cu_stub_egtp.h"
34 /**************************************************************************
35 * @brief Task Initiation callback function.
39 * Function : sctpActvInit
42 * This function is supplied as one of parameters during SCTP's
43 * task registration. SSI will invoke this function once, after
44 * it creates and attaches this TAPA Task to a system task.
46 * @param[in] Ent entity, the entity ID of this task.
47 * @param[in] Inst inst, the instance ID of this task.
48 * @param[in] Region region, the region ID registered for memory
50 * @param[in] Reason reason.
51 * @return ROK - success
53 ***************************************************************************/
54 uint8_t sctpActvInit()
56 DU_LOG("\n\nDEBUG --> SCTP : Initializing");
57 memset(&sctpCb, 0, sizeof(SctpGlobalCb));
58 sctpCb.sctpCfg = cuCb.cuCfgParams.sctpParams;
62 /**************************************************************************
63 * @brief Task Activation callback function.
67 * Function : sctpActvTsk
70 * This function handles all SCTP messages received
71 * This API is registered with SSI during the
72 * Task Registration of DU APP.
74 * @param[in] Pst *pst, Post structure of the primitive.
75 * @param[in] Buffer *mBuf, Packed primitive parameters in the
77 * @return ROK - success
80 ***************************************************************************/
81 uint8_t sctpActvTsk(Pst *pst, Buffer *mBuf)
88 /**************************************************************************
89 * @brief Function to configure the Sctp Params during config Request
93 * Function : duSctpCfgReq
96 * This function configures SCTP Params during the config Request
98 * @return ROK - success
101 ***************************************************************************/
105 int destIdx = 0, assocIdx = 0;
107 fillAddrLst(&sctpCb.localAddrLst, &sctpCb.sctpCfg.localIpAddr);
108 memset(&sctpCb.f1LstnSockFd, -1, sizeof(CmInetFd));
110 for(destIdx=0; destIdx < sctpCb.sctpCfg.numDestNode; destIdx++)
112 sctpCb.assocCb[assocIdx].destPort = sctpCb.sctpCfg.destCb[destIdx].destPort;
113 sctpCb.assocCb[assocIdx].bReadFdSet = ROK;
114 memset(&sctpCb.assocCb[assocIdx].sockFd, -1, sizeof(CmInetFd));
115 fillDestNetAddr(&sctpCb.assocCb[assocIdx].destIpNetAddr, &sctpCb.sctpCfg.destCb[destIdx].destIpAddr);
118 sctpCb.numAssoc = assocIdx;
123 /*******************************************************************
125 * @brief Fills the address List of the source Ip Address
129 * Function : fillAddrLst
132 * Fills the address List of source Ip Address
134 * @params[in] CmInetNetAddrLst *addrLstPtr, Address List pointer
135 * @params[in] F1IpAddr *srcIpAddr, src Ip Adrress to be filled in the Address List
136 * @return ROK - success
139 ******************************************************************/
141 uint8_t fillAddrLst(CmInetNetAddrLst *addrLstPtr, SctpIpAddr *ipAddr)
143 addrLstPtr->addrs[addrLstPtr->count].type = CM_INET_IPV4ADDR_TYPE;
144 addrLstPtr->addrs[addrLstPtr->count].u.ipv4NetAddr = CM_INET_NTOH_UINT32(ipAddr->ipV4Addr);
149 /******************************************************************************
151 * @brief Fills the address List of the source Ip Address
155 * Function : fillDestNetAddr
158 * Fills the address List of destinatoion Ip Address
160 * @params[in] CmInetNetAddr *destAddrPtr, Address List pointer
161 * @params[in] F1IpAddr *dstIpAddr, destIp Address to be filled in the Address List
162 * @return ROK - success
165 *******************************************************************************/
166 uint8_t fillDestNetAddr(CmInetNetAddr *destAddrPtr, SctpIpAddr *dstIpPtr)
168 /* Filling destination address */
169 destAddrPtr->type = CM_INET_IPV4ADDR_TYPE;
170 destAddrPtr->u.ipv4NetAddr = CM_INET_NTOH_UINT32(dstIpPtr->ipV4Addr);
174 /******************************************************************************
176 * @brief Eastablishes the Assoc Req for the received interface type
180 * Function : sctpStartReq
183 * Eastablishes the Assoc Req for the received interface type
185 * @params[in] DuSctpDestCb *paramPtr
186 * @return ROK - success
189 *******************************************************************************/
191 uint8_t sctpStartReq()
196 socket_type = CM_INET_STREAM;
200 if((ret = cmInetSocket(socket_type, &sctpCb.f1LstnSockFd, IPPROTO_SCTP) != ROK))
202 DU_LOG("\nERROR --> SCTP : Socket[%d] coudnt open for listening", sctpCb.f1LstnSockFd.fd);
204 else if((ret = cmInetSctpBindx(&sctpCb.f1LstnSockFd, &sctpCb.localAddrLst, sctpCb.sctpCfg.f1SctpPort)) != ROK)
206 DU_LOG("\nERROR --> SCTP: Binding failed at CU");
208 else if(ret = cmInetListen(&sctpCb.f1LstnSockFd, 1) != ROK)
210 DU_LOG("\nERROR --> SCTP : Listening on socket failed");
211 cmInetClose(&sctpCb.f1LstnSockFd);
216 for(assocIdx=0; assocIdx < sctpCb.numAssoc; assocIdx++)
218 if((ret = sctpAccept(&sctpCb.assocCb[assocIdx])) != ROK)
220 DU_LOG("\nERROR --> SCTP: Unable to accept the connection at CU");
228 if(sctpSockPoll() != ROK)
230 DU_LOG("\nERROR --> SCTP: Polling failed to start at CU");
235 /*******************************************************************
237 * @brief Sets socket options as per requirement
241 * Function : sctpSetSockOpts
244 * Sets socket options as per requirement
247 * @return ROK - success
250 * ****************************************************************/
251 uint8_t sctpSetSockOpts(CmInetFd *sock_Fd)
254 CmSctpEvent sctpEvent;
256 sctpEvent.dataIoEvent = TRUE;
257 sctpEvent.associationEvent = TRUE;
258 sctpEvent.addressEvent = TRUE;
259 sctpEvent.sendFailureEvent = TRUE;
260 sctpEvent.peerErrorEvent = TRUE;
261 sctpEvent.shutdownEvent = TRUE;
262 sctpEvent.partialDeliveryEvent = TRUE;
263 sctpEvent.adaptationLayerEvent = TRUE;
265 if((ret = cmInetSetOpt(sock_Fd, CM_SOCKOPT_LEVEL_SCTP, CM_SOCKOPT_OPT_SCTP_EVENTS, &sctpEvent)) != ROK)
273 /*******************************************************************
275 * @brief Initiates connection with peer SCTP
279 * Function : sctpAccept
282 * Establishes SCTP connection with peer.
283 * Here, DU-SCTP will initate connection towards CU-SCTP
286 * @return ROK - success
289 * ****************************************************************/
290 uint8_t sctpAccept(CuSctpAssocCb *assocCb)
294 DU_LOG("\nINFO --> SCTP : Connecting");
296 while(!assocCb->connUp)
298 ret = cmInetAccept(&sctpCb.f1LstnSockFd, &assocCb->peerAddr, &assocCb->sockFd);
305 DU_LOG("\nERROR --> SCTP : Failed to accept connection");
310 assocCb->connUp = TRUE;
311 sctpSetSockOpts(&assocCb->sockFd);
315 DU_LOG("\nINFO --> SCTP : Connection established");
320 /*******************************************************************
322 * @brief Handles an SCTP notification message
326 * Function : sctpNtfyHdlr
329 * Handles an SCTP notification message
331 * @params[in] Notify message
333 * @return ROK - success
336 * ****************************************************************/
337 uint8_t sctpNtfyHdlr(CuSctpAssocCb *assocCb, CmInetSctpNotification *ntfy)
339 switch(ntfy->header.nType)
341 case CM_INET_SCTP_ASSOC_CHANGE :
342 DU_LOG("\nINFO --> SCTP : Assoc change notification received");
343 switch(ntfy->u.assocChange.state)
345 case CM_INET_SCTP_COMM_UP:
346 DU_LOG("DEBUG --> Event : COMMUNICATION UP");
347 assocCb->connUp = TRUE;
349 case CM_INET_SCTP_COMM_LOST:
350 DU_LOG("DEBUG --> Event : COMMUNICATION LOST");
351 assocCb->connUp = FALSE;
353 case CM_INET_SCTP_RESTART:
354 DU_LOG("DEBUG --> Event : SCTP RESTART");
355 assocCb->connUp = FALSE;
357 case CM_INET_SCTP_SHUTDOWN_COMP: /* association gracefully shutdown */
358 DU_LOG("DEBUG --> Event : SHUTDOWN COMPLETE");
359 assocCb->connUp = FALSE;
361 case CM_INET_SCTP_CANT_STR_ASSOC:
362 DU_LOG("DEBUG --> Event : CANT START ASSOC");
363 assocCb->connUp = FALSE;
366 DU_LOG("\nERROR --> Invalid event");
370 case CM_INET_SCTP_PEER_ADDR_CHANGE :
371 DU_LOG("\nINFO --> SCTP : Peer Address Change notificarion received");
372 /* Need to add handler */
374 case CM_INET_SCTP_REMOTE_ERROR :
375 DU_LOG("\nINFO --> SCTP : Remote Error notification received");
377 case CM_INET_SCTP_SEND_FAILED :
378 DU_LOG("\nINFO --> SCTP : Send Failed notification received\n");
380 case CM_INET_SCTP_SHUTDOWN_EVENT : /* peer socket gracefully closed */
381 DU_LOG("\nINFO --> SCTP : Shutdown Event notification received\n");
382 assocCb->connUp = FALSE;
385 case CM_INET_SCTP_ADAPTATION_INDICATION :
386 DU_LOG("\nINFO --> SCTP : Adaptation Indication received\n");
388 case CM_INET_SCTP_PARTIAL_DELIVERY_EVENT:
389 DU_LOG("\nINFO --> SCTP : Partial Delivery Event received\n");
392 DU_LOG("\nERROR --> SCTP : Invalid notification type\n");
398 }/* End of sctpNtfyHdlr */
400 /*******************************************************************
402 * @brief Receives message on the socket
406 * Function : sctpSockPoll
409 * Receives message on the socket
412 * @return ROK - success
415 * ****************************************************************/
416 uint8_t sctpSockPoll()
418 uint8_t assocIdx = 0, destIdx = 0;
421 uint32_t *timeoutPtr;
424 CmInetMemInfo memInfo;
425 sctpSockPollParams f1PollParams;
426 uint64_t numMsgRcvd = 0;
429 memset(&f1PollParams, 0, sizeof(sctpSockPollParams));
432 /* All sockets are non-blocking */
434 timeoutPtr = &timeout;
435 memInfo.region = CU_APP_MEM_REG;
436 memInfo.pool = CU_POOL;
438 CM_INET_FD_ZERO(&f1PollParams.readFd);
442 /* Receiving SCTP data */
443 for(assocIdx = 0; assocIdx < sctpCb.numAssoc; assocIdx++)
445 if((ret = processPolling(&f1PollParams, &sctpCb.assocCb[assocIdx], timeoutPtr, &memInfo)) != ROK)
447 DU_LOG("\nERROR --> SCTP : Failed to RecvMsg for F1 at CU\n");
451 /* Receiving EGTP data */
453 ret = cmInetRecvMsg(&(egtpCb.sockFd), &fromAddr, &memInfo, &egtpBuf, &egtpBufLen, CM_INET_NO_FLAG);
454 if(ret == ROK && egtpBuf != NULLP)
456 for(destIdx = 0; destIdx < egtpCb.numDu; destIdx++)
458 if((fromAddr.port == egtpCb.dstCb[destIdx].dstAddr.port) && (fromAddr.address == egtpCb.dstCb[destIdx].dstAddr.address))
460 DU_LOG("\nINFO --> EGTP : Received UL Message [%ld] from DU Id [%d]\n", numMsgRcvd+1, egtpCb.dstCb[destIdx].duId);
462 //ODU_PRINT_MSG(egtpBuf, 0 ,0);
463 cuEgtpHdlRecvMsg(egtpBuf);
471 }/* End of sctpSockPoll() */
473 /*******************************************************************
475 * @brief checks for valid readFd and process the InetSctpRecvMsg
480 * Function : processPolling
483 * checks for valid readFd and process the InetSctpRecvMsg
486 * @params[in] Params required for polling
487 * @params[in] SockFd for file descriptor
488 * @params[in] timeoutPtr indicates the timeout value
489 * @params[in] MemInfo indicates memory region
491 * @return ROK - success
494 * ****************************************************************/
496 uint8_t processPolling(sctpSockPollParams *pollParams, CuSctpAssocCb *assocCb, uint32_t *timeoutPtr, CmInetMemInfo *memInfo)
499 CM_INET_FD_SET(&assocCb->sockFd, &pollParams->readFd);
500 ret = cmInetSelect(&pollParams->readFd, NULLP, timeoutPtr, &pollParams->numFd);
501 if(CM_INET_FD_ISSET(&assocCb->sockFd, &pollParams->readFd))
503 CM_INET_FD_CLR(&assocCb->sockFd, &pollParams->readFd);
504 ret = cmInetSctpRecvMsg(&assocCb->sockFd, &pollParams->addr, &pollParams->port, memInfo, &pollParams->mBuf, \
505 &pollParams->bufLen, &pollParams->info, &pollParams->flag, &pollParams->ntfy);
506 if(assocCb->connUp & (ret != ROK))
508 assocCb->bReadFdSet = RFAILED;
512 if(((pollParams->flag & CM_INET_SCTP_MSG_NOTIFICATION) != 0) && (ret == ROK))
514 ret = sctpNtfyHdlr(assocCb, &pollParams->ntfy);
517 DU_LOG("\nERROR --> SCTP : Failed to process sctp notify msg\n");
520 else if(assocCb->connUp)
522 F1APMsgHdlr(&assocCb->duId, pollParams->mBuf);
523 ODU_PUT_MSG_BUF(pollParams->mBuf);
527 ODU_PUT_MSG_BUF(pollParams->mBuf);
532 }/* End of sctpSockPoll() */
534 /*******************************************************************
536 * @brief Send message on SCTP socket
540 * Function : sctpSend
543 * Send message on SCTP socket
546 * @return ROK - success
549 * ****************************************************************/
550 uint8_t sctpSend(uint32_t duId, Buffer *mBuf)
552 uint8_t ret = ROK, assocIdx = 0;
553 MsgLen len = 0; /* number of actually sent octets */
554 CmInetMemInfo memInfo;
556 memset(&memInfo , 0, sizeof(CmInetMemInfo));
557 memInfo.region = CU_APP_MEM_REG;
558 memInfo.pool = CU_POOL;
560 for(assocIdx=0; assocIdx < sctpCb.numAssoc; assocIdx++)
562 if(sctpCb.assocCb[assocIdx].duId == duId)
564 ret = cmInetSctpSendMsg(&sctpCb.assocCb[assocIdx].sockFd, &sctpCb.assocCb[assocIdx].destIpNetAddr, \
565 sctpCb.assocCb[assocIdx].destPort, &memInfo, mBuf, &len, 0, FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
567 if(ret != ROK && ret != RWOULDBLOCK)
569 DU_LOG("\nERROR --> SCTP : Send message failed");
575 DU_LOG("\nERROR --> SCTP : DU ID [%d] not found in SCTP DestCb list. Failed to send message", duId);
577 } /* End of sctpSend */
579 /**********************************************************************
581 **********************************************************************/