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 ***************************************************************************/
107 for(destIdx=0; destIdx < sctpCb.sctpCfg.numDu; destIdx++)
109 sctpCb.destCb[destIdx].destPort = sctpCb.sctpCfg.sctpAssoc[destIdx].duPort;
110 sctpCb.destCb[destIdx].srcPort = sctpCb.sctpCfg.sctpAssoc[destIdx].cuPort;
111 sctpCb.destCb[destIdx].bReadFdSet = ROK;
112 memset(&sctpCb.destCb[destIdx].sockFd, -1, sizeof(CmInetFd));
113 memset(&sctpCb.destCb[destIdx].lstnSockFd, -1, sizeof(CmInetFd));
114 fillDestNetAddr(&sctpCb.destCb[destIdx].destIpNetAddr, &sctpCb.sctpCfg.sctpAssoc[destIdx].duIpAddr);
115 fillAddrLst(&sctpCb.destCb[destIdx].localAddrLst, &sctpCb.sctpCfg.sctpAssoc[destIdx].cuIpAddr);
117 sctpCb.numDu = sctpCb.sctpCfg.numDu;
122 /*******************************************************************
124 * @brief Fills the address List of the source Ip Address
128 * Function : fillAddrLst
131 * Fills the address List of source Ip Address
133 * @params[in] CmInetNetAddrLst *addrLstPtr, Address List pointer
134 * @params[in] F1IpAddr *srcIpAddr, src Ip Adrress to be filled in the Address List
135 * @return ROK - success
138 ******************************************************************/
140 uint8_t fillAddrLst(CmInetNetAddrLst *addrLstPtr, SctpIpAddr *ipAddr)
142 addrLstPtr->addrs[addrLstPtr->count].type = CM_INET_IPV4ADDR_TYPE;
143 addrLstPtr->addrs[addrLstPtr->count].u.ipv4NetAddr = CM_INET_NTOH_UINT32(ipAddr->ipV4Addr);
148 /******************************************************************************
150 * @brief Fills the address List of the source Ip Address
154 * Function : fillDestNetAddr
157 * Fills the address List of destinatoion Ip Address
159 * @params[in] CmInetNetAddr *destAddrPtr, Address List pointer
160 * @params[in] F1IpAddr *dstIpAddr, destIp Address to be filled in the Address List
161 * @return ROK - success
164 *******************************************************************************/
165 uint8_t fillDestNetAddr(CmInetNetAddr *destAddrPtr, SctpIpAddr *dstIpPtr)
167 /* Filling destination address */
168 destAddrPtr->type = CM_INET_IPV4ADDR_TYPE;
169 destAddrPtr->u.ipv4NetAddr = CM_INET_NTOH_UINT32(dstIpPtr->ipV4Addr);
173 /******************************************************************************
175 * @brief Eastablishes the Assoc Req for the received interface type
179 * Function : sctpStartReq
182 * Eastablishes the Assoc Req for the received interface type
184 * @params[in] DuSctpDestCb *paramPtr
185 * @return ROK - success
188 *******************************************************************************/
190 uint8_t sctpStartReq()
195 socket_type = CM_INET_STREAM;
196 for(destIdx=0; destIdx < sctpCb.numDu; destIdx++)
198 if((ret = cmInetSocket(socket_type, &sctpCb.destCb[destIdx].lstnSockFd, IPPROTO_SCTP) != ROK))
200 DU_LOG("\nERROR --> SCTP : Socket[%d] coudnt open for listening", sctpCb.destCb[destIdx].lstnSockFd.fd);
202 else if((ret = cmInetSctpBindx(&sctpCb.destCb[destIdx].lstnSockFd, &sctpCb.destCb[destIdx].localAddrLst, \
203 sctpCb.destCb[destIdx].srcPort)) != ROK)
205 DU_LOG("\nERROR --> SCTP: Binding failed at CU");
207 else if((ret = sctpAccept(&sctpCb.destCb[destIdx])) != ROK)
209 DU_LOG("\nERROR --> SCTP: Unable to accept the connection at CU");
213 if(sctpSockPoll() != ROK)
215 DU_LOG("\nERROR --> SCTP: Polling failed to start at CU");
219 /*******************************************************************
221 * @brief Sets socket options as per requirement
225 * Function : sctpSetSockOpts
228 * Sets socket options as per requirement
231 * @return ROK - success
234 * ****************************************************************/
235 uint8_t sctpSetSockOpts(CmInetFd *sock_Fd)
238 CmSctpEvent sctpEvent;
240 sctpEvent.dataIoEvent = TRUE;
241 sctpEvent.associationEvent = TRUE;
242 sctpEvent.addressEvent = TRUE;
243 sctpEvent.sendFailureEvent = TRUE;
244 sctpEvent.peerErrorEvent = TRUE;
245 sctpEvent.shutdownEvent = TRUE;
246 sctpEvent.partialDeliveryEvent = TRUE;
247 sctpEvent.adaptationLayerEvent = TRUE;
249 if((ret = cmInetSetOpt(sock_Fd, CM_SOCKOPT_LEVEL_SCTP, CM_SOCKOPT_OPT_SCTP_EVENTS, &sctpEvent)) != ROK)
257 /*******************************************************************
259 * @brief Initiates connection with peer SCTP
263 * Function : sctpAccept
266 * Establishes SCTP connection with peer.
267 * Here, DU-SCTP will initate connection towards CU-SCTP
270 * @return ROK - success
273 * ****************************************************************/
274 uint8_t sctpAccept(CuSctpDestCb *destCb)
278 ret = cmInetListen(&destCb->lstnSockFd, 1);
281 DU_LOG("\nERROR --> SCTP : Listening on socket failed");
282 cmInetClose(&destCb->lstnSockFd);
286 DU_LOG("\nINFO --> SCTP : Connecting");
288 while(!destCb->connUp)
290 ret = cmInetAccept(&destCb->lstnSockFd, &destCb->peerAddr, &destCb->sockFd);
297 DU_LOG("\nERROR --> SCTP : Failed to accept connection");
302 destCb->connUp = TRUE;
303 sctpSetSockOpts(&destCb->sockFd);
307 DU_LOG("\nINFO --> SCTP : Connection established");
312 /*******************************************************************
314 * @brief Handles an SCTP notification message
318 * Function : sctpNtfyHdlr
321 * Handles an SCTP notification message
323 * @params[in] Notify message
325 * @return ROK - success
328 * ****************************************************************/
329 uint8_t sctpNtfyHdlr(CuSctpDestCb *destCb, CmInetSctpNotification *ntfy)
331 switch(ntfy->header.nType)
333 case CM_INET_SCTP_ASSOC_CHANGE :
334 DU_LOG("\nINFO --> SCTP : Assoc change notification received");
335 switch(ntfy->u.assocChange.state)
337 case CM_INET_SCTP_COMM_UP:
338 DU_LOG("DEBUG --> Event : COMMUNICATION UP");
339 destCb->connUp = TRUE;
341 case CM_INET_SCTP_COMM_LOST:
342 DU_LOG("DEBUG --> Event : COMMUNICATION LOST");
343 destCb->connUp = FALSE;
345 case CM_INET_SCTP_RESTART:
346 DU_LOG("DEBUG --> Event : SCTP RESTART");
347 destCb->connUp = FALSE;
349 case CM_INET_SCTP_SHUTDOWN_COMP: /* association gracefully shutdown */
350 DU_LOG("DEBUG --> Event : SHUTDOWN COMPLETE");
351 destCb->connUp = FALSE;
353 case CM_INET_SCTP_CANT_STR_ASSOC:
354 DU_LOG("DEBUG --> Event : CANT START ASSOC");
355 destCb->connUp = FALSE;
358 DU_LOG("\nERROR --> Invalid event");
362 case CM_INET_SCTP_PEER_ADDR_CHANGE :
363 DU_LOG("\nINFO --> SCTP : Peer Address Change notificarion received");
364 /* Need to add handler */
366 case CM_INET_SCTP_REMOTE_ERROR :
367 DU_LOG("\nINFO --> SCTP : Remote Error notification received");
369 case CM_INET_SCTP_SEND_FAILED :
370 DU_LOG("\nINFO --> SCTP : Send Failed notification received\n");
372 case CM_INET_SCTP_SHUTDOWN_EVENT : /* peer socket gracefully closed */
373 DU_LOG("\nINFO --> SCTP : Shutdown Event notification received\n");
374 destCb->connUp = FALSE;
377 case CM_INET_SCTP_ADAPTATION_INDICATION :
378 DU_LOG("\nINFO --> SCTP : Adaptation Indication received\n");
380 case CM_INET_SCTP_PARTIAL_DELIVERY_EVENT:
381 DU_LOG("\nINFO --> SCTP : Partial Delivery Event received\n");
384 DU_LOG("\nERROR --> SCTP : Invalid notification type\n");
390 }/* End of sctpNtfyHdlr */
392 /*******************************************************************
394 * @brief Receives message on the socket
398 * Function : sctpSockPoll
401 * Receives message on the socket
404 * @return ROK - success
407 * ****************************************************************/
408 uint8_t sctpSockPoll()
413 uint32_t *timeoutPtr;
416 CmInetAddr egtpFromAddr;
417 CmInetMemInfo memInfo;
418 sctpSockPollParams f1PollParams;
419 uint64_t numMsgRcvd = 0;
421 memset(&f1PollParams, 0, sizeof(sctpSockPollParams));
423 egtpFromAddr.port = egtpCb.dstCb.dstPort;
424 egtpFromAddr.address = egtpCb.dstCb.dstIp;
426 /* All sockets are non-blocking */
428 timeoutPtr = &timeout;
429 memInfo.region = CU_APP_MEM_REG;
430 memInfo.pool = CU_POOL;
432 CM_INET_FD_ZERO(&f1PollParams.readFd);
436 /* Receiving SCTP data */
437 for(destIdx = 0; destIdx < sctpCb.numDu; destIdx++)
439 if((ret = processPolling(&f1PollParams, &sctpCb.destCb[destIdx], timeoutPtr, &memInfo)) != ROK)
441 DU_LOG("\nERROR --> SCTP : Failed to RecvMsg for F1 at CU\n");
445 /* Receiving EGTP data */
447 ret = cmInetRecvMsg(&(egtpCb.recvTptSrvr.sockFd), &egtpFromAddr, &memInfo, &egtpBuf, &egtpBufLen, CM_INET_NO_FLAG);
448 if(ret == ROK && egtpBuf != NULLP)
450 DU_LOG("\nINFO --> EGTP : Received UL Message [%ld]\n", numMsgRcvd+1);
452 //ODU_PRINT_MSG(egtpBuf, 0 ,0);
453 cuEgtpHdlRecvMsg(egtpBuf);
458 }/* End of sctpSockPoll() */
460 /*******************************************************************
462 * @brief checks for valid readFd and process the InetSctpRecvMsg
467 * Function : processPolling
470 * checks for valid readFd and process the InetSctpRecvMsg
473 * @params[in] Params required for polling
474 * @params[in] SockFd for file descriptor
475 * @params[in] timeoutPtr indicates the timeout value
476 * @params[in] MemInfo indicates memory region
478 * @return ROK - success
481 * ****************************************************************/
483 uint8_t processPolling(sctpSockPollParams *pollParams, CuSctpDestCb *destCb, uint32_t *timeoutPtr, CmInetMemInfo *memInfo)
486 CM_INET_FD_SET(&destCb->sockFd, &pollParams->readFd);
487 ret = cmInetSelect(&pollParams->readFd, NULLP, timeoutPtr, &pollParams->numFd);
488 if(CM_INET_FD_ISSET(&destCb->sockFd, &pollParams->readFd))
490 CM_INET_FD_CLR(&destCb->sockFd, &pollParams->readFd);
491 ret = cmInetSctpRecvMsg(&destCb->sockFd, &pollParams->addr, &pollParams->port, memInfo, &pollParams->mBuf, \
492 &pollParams->bufLen, &pollParams->info, &pollParams->flag, &pollParams->ntfy);
493 if(destCb->connUp & (ret != ROK))
495 destCb->bReadFdSet = RFAILED;
499 if(((pollParams->flag & CM_INET_SCTP_MSG_NOTIFICATION) != 0) && (ret == ROK))
501 ret = sctpNtfyHdlr(destCb, &pollParams->ntfy);
504 DU_LOG("\nERROR --> SCTP : Failed to process sctp notify msg\n");
507 else if(destCb->connUp & (pollParams->port == destCb->destPort))
509 F1APMsgHdlr(&destCb->duId, pollParams->mBuf);
510 ODU_PUT_MSG_BUF(pollParams->mBuf);
514 ODU_PUT_MSG_BUF(pollParams->mBuf);
519 }/* End of sctpSockPoll() */
521 /*******************************************************************
523 * @brief Send message on SCTP socket
527 * Function : sctpSend
530 * Send message on SCTP socket
533 * @return ROK - success
536 * ****************************************************************/
537 uint8_t sctpSend(uint32_t duId, Buffer *mBuf)
539 uint8_t ret = ROK, destIdx = 0;
540 MsgLen len = 0; /* number of actually sent octets */
541 CmInetMemInfo memInfo;
543 memset(&memInfo , 0, sizeof(CmInetMemInfo));
544 memInfo.region = CU_APP_MEM_REG;
545 memInfo.pool = CU_POOL;
547 for(destIdx=0; destIdx < sctpCb.numDu; destIdx++)
549 if(sctpCb.destCb[destIdx].duId == duId)
551 ret = cmInetSctpSendMsg(&sctpCb.destCb[destIdx].sockFd, &sctpCb.destCb[destIdx].destIpNetAddr, \
552 sctpCb.destCb[destIdx].destPort, &memInfo, mBuf, &len, 0, FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
554 if(ret != ROK && ret != RWOULDBLOCK)
556 DU_LOG("\nERROR --> SCTP : Send message failed");
562 DU_LOG("\nERROR --> SCTP : DU ID [%d] not found in SCTP DestCb list. Failed to send message", duId);
564 } /* End of sctpSend */
566 /**********************************************************************
568 **********************************************************************/