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));
424 /* All sockets are non-blocking */
426 timeoutPtr = &timeout;
427 memInfo.region = CU_APP_MEM_REG;
428 memInfo.pool = CU_POOL;
430 CM_INET_FD_ZERO(&f1PollParams.readFd);
434 /* Receiving SCTP data */
435 for(destIdx = 0; destIdx < sctpCb.numDu; destIdx++)
437 if((ret = processPolling(&f1PollParams, &sctpCb.destCb[destIdx], timeoutPtr, &memInfo)) != ROK)
439 DU_LOG("\nERROR --> SCTP : Failed to RecvMsg for F1 at CU\n");
443 /* Receiving EGTP data */
444 for(destIdx = 0; destIdx < egtpCb.numDu; destIdx++)
447 egtpFromAddr.port = egtpCb.dstCb[destIdx].dstPort;
448 egtpFromAddr.address = egtpCb.dstCb[destIdx].dstIp;
450 ret = cmInetRecvMsg(&(egtpCb.recvTptSrvr.sockFd), &egtpFromAddr, &memInfo, &egtpBuf, &egtpBufLen, CM_INET_NO_FLAG);
451 if(ret == ROK && egtpBuf != NULLP)
453 DU_LOG("\nINFO --> EGTP : Received UL Message [%ld] from DUid %d\n", numMsgRcvd+1, egtpCb.dstCb[destIdx].duId);
455 //ODU_PRINT_MSG(egtpBuf, 0 ,0);
456 cuEgtpHdlRecvMsg(egtpBuf);
462 }/* End of sctpSockPoll() */
464 /*******************************************************************
466 * @brief checks for valid readFd and process the InetSctpRecvMsg
471 * Function : processPolling
474 * checks for valid readFd and process the InetSctpRecvMsg
477 * @params[in] Params required for polling
478 * @params[in] SockFd for file descriptor
479 * @params[in] timeoutPtr indicates the timeout value
480 * @params[in] MemInfo indicates memory region
482 * @return ROK - success
485 * ****************************************************************/
487 uint8_t processPolling(sctpSockPollParams *pollParams, CuSctpDestCb *destCb, uint32_t *timeoutPtr, CmInetMemInfo *memInfo)
490 CM_INET_FD_SET(&destCb->sockFd, &pollParams->readFd);
491 ret = cmInetSelect(&pollParams->readFd, NULLP, timeoutPtr, &pollParams->numFd);
492 if(CM_INET_FD_ISSET(&destCb->sockFd, &pollParams->readFd))
494 CM_INET_FD_CLR(&destCb->sockFd, &pollParams->readFd);
495 ret = cmInetSctpRecvMsg(&destCb->sockFd, &pollParams->addr, &pollParams->port, memInfo, &pollParams->mBuf, \
496 &pollParams->bufLen, &pollParams->info, &pollParams->flag, &pollParams->ntfy);
497 if(destCb->connUp & (ret != ROK))
499 destCb->bReadFdSet = RFAILED;
503 if(((pollParams->flag & CM_INET_SCTP_MSG_NOTIFICATION) != 0) && (ret == ROK))
505 ret = sctpNtfyHdlr(destCb, &pollParams->ntfy);
508 DU_LOG("\nERROR --> SCTP : Failed to process sctp notify msg\n");
511 else if(destCb->connUp & (pollParams->port == destCb->destPort))
513 F1APMsgHdlr(&destCb->duId, pollParams->mBuf);
514 ODU_PUT_MSG_BUF(pollParams->mBuf);
518 ODU_PUT_MSG_BUF(pollParams->mBuf);
523 }/* End of sctpSockPoll() */
525 /*******************************************************************
527 * @brief Send message on SCTP socket
531 * Function : sctpSend
534 * Send message on SCTP socket
537 * @return ROK - success
540 * ****************************************************************/
541 uint8_t sctpSend(uint32_t duId, Buffer *mBuf)
543 uint8_t ret = ROK, destIdx = 0;
544 MsgLen len = 0; /* number of actually sent octets */
545 CmInetMemInfo memInfo;
547 memset(&memInfo , 0, sizeof(CmInetMemInfo));
548 memInfo.region = CU_APP_MEM_REG;
549 memInfo.pool = CU_POOL;
551 for(destIdx=0; destIdx < sctpCb.numDu; destIdx++)
553 if(sctpCb.destCb[destIdx].duId == duId)
555 ret = cmInetSctpSendMsg(&sctpCb.destCb[destIdx].sockFd, &sctpCb.destCb[destIdx].destIpNetAddr, \
556 sctpCb.destCb[destIdx].destPort, &memInfo, mBuf, &len, 0, FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
558 if(ret != ROK && ret != RWOULDBLOCK)
560 DU_LOG("\nERROR --> SCTP : Send message failed");
566 DU_LOG("\nERROR --> SCTP : DU ID [%d] not found in SCTP DestCb list. Failed to send message", duId);
568 } /* End of sctpSend */
570 /**********************************************************************
572 **********************************************************************/