[Epic-ID: ODUHIGH-463][Task-ID: ODUHIGH-496] Dummy Xn Setup Request/Response
[o-du/l2.git] / src / cu_stub / cu_stub_sctp.c
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2017-2019] [Radisys]                                        #
4 #                                                                              #
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                                    #
8 #                                                                              #
9 #       http://www.apache.org/licenses/LICENSE-2.0                             #
10 #                                                                              #
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 *******************************************************************************/
18
19 /* This file contains all SCTP related functionality */
20
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"
26 #include "cu_stub.h"
27 #include "cm_inet.h"
28 #include "cm_tpt.h"
29
30 #include "cm_inet.x"
31 #include "cm_tpt.x"
32
33
34 /**************************************************************************
35  * @brief Task Initiation callback function. 
36  *
37  * @details
38  *
39  *     Function : sctpActvInit 
40  *    
41  *     Functionality:
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.
45  *     
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 
49  *              usage of this task.
50  * @param[in]  Reason reason.
51  * @return ROK     - success
52  *         RFAILED - failure
53  ***************************************************************************/
54 uint8_t sctpActvInit()
55 {
56    DU_LOG("\n\nDEBUG  -->  SCTP : Initializing");
57    memset(&sctpCb, 0, sizeof(SctpGlobalCb));
58    sctpCb.sctpCfg = cuCb.cuCfgParams.sctpParams;
59    return ROK;
60 }
61
62 /**************************************************************************
63  * @brief Task Activation callback function. 
64  *
65  * @details
66  *
67  *      Function : sctpActvTsk 
68  * 
69  *      Functionality:
70  *           This function handles all SCTP messages received
71  *           This API is registered with SSI during the 
72  *           Task Registration of DU APP.
73  *     
74  * @param[in]  Pst     *pst, Post structure of the primitive.     
75  * @param[in]  Buffer *mBuf, Packed primitive parameters in the
76  *  buffer.
77  * @return ROK     - success
78  *         RFAILED - failure
79  *
80  ***************************************************************************/
81 uint8_t sctpActvTsk(Pst *pst, Buffer *mBuf)
82 {
83
84 //TODO: TBD
85    return ROK;
86 }
87
88 /**************************************************************************
89  * @brief Function to configure the Sctp Params during config Request
90  *
91  * @details
92  *
93  *      Function : duSctpCfgReq
94  * 
95  *      Functionality:
96  *           This function configures SCTP Params during the config Request
97  *     
98  * @return ROK     - success
99  *         RFAILED - failure
100  *
101  ***************************************************************************/
102
103 uint8_t sctpCfgReq()
104 {
105    int destIdx = 0, assocIdx = 0;
106    
107    fillAddrLst(&sctpCb.localAddrLst, &sctpCb.sctpCfg.localIpAddr);
108    memset(&sctpCb.f1LstnSockFd, -1, sizeof(CmInetFd));
109
110    for(destIdx=0; destIdx < sctpCb.sctpCfg.f1SctpInfo.numDestNode; destIdx++)
111    {
112       sctpCb.assocCb[assocIdx].intf = F1_INTERFACE;
113       sctpCb.assocCb[assocIdx].destPort = sctpCb.sctpCfg.f1SctpInfo.destCb[destIdx].destPort;
114       sctpCb.assocCb[assocIdx].bReadFdSet = ROK;
115       memset(&sctpCb.assocCb[assocIdx].sockFd, -1, sizeof(CmInetFd));
116       fillDestNetAddr(&sctpCb.assocCb[assocIdx].destIpNetAddr, &sctpCb.sctpCfg.f1SctpInfo.destCb[destIdx].destIpAddr);
117       assocIdx++;
118    }
119
120    sctpCb.localXnNodeType = sctpCb.sctpCfg.xnSctpInfo.localNodeType;
121    for(destIdx=0; destIdx < sctpCb.sctpCfg.xnSctpInfo.numDestNode; destIdx++)
122    {
123       sctpCb.assocCb[assocIdx].intf = XN_INTERFACE;
124       sctpCb.assocCb[assocIdx].destPort = sctpCb.sctpCfg.xnSctpInfo.destCb[destIdx].destPort;
125       sctpCb.assocCb[assocIdx].bReadFdSet = ROK;
126       memset(&sctpCb.assocCb[assocIdx].sockFd, -1, sizeof(CmInetFd));
127       fillDestNetAddr(&sctpCb.assocCb[assocIdx].destIpNetAddr, &sctpCb.sctpCfg.xnSctpInfo.destCb[destIdx].destIpAddr);
128       assocIdx++;
129    }
130    sctpCb.numAssoc = assocIdx;
131    return ROK;
132 }
133
134
135 /*******************************************************************
136  *
137  * @brief Fills the address List of the source Ip Address
138  *
139  * @details
140  *
141  *    Function : fillAddrLst
142  *
143  *    Functionality:
144  *       Fills the address List of source Ip Address
145  *
146  * @params[in] CmInetNetAddrLst *addrLstPtr, Address List pointer
147  * @params[in] F1IpAddr *srcIpAddr, src Ip Adrress to be filled in the Address List
148  * @return ROK     - success
149  *         RFAILED - failure
150  *
151  ******************************************************************/
152
153 uint8_t fillAddrLst(CmInetNetAddrLst *addrLstPtr, SctpIpAddr *ipAddr)
154
155    addrLstPtr->addrs[addrLstPtr->count].type = CM_INET_IPV4ADDR_TYPE;
156    addrLstPtr->addrs[addrLstPtr->count].u.ipv4NetAddr = CM_INET_NTOH_UINT32(ipAddr->ipV4Addr);
157    addrLstPtr->count++;
158    return ROK;
159 }
160
161 /******************************************************************************
162  *
163  * @brief Fills the address List of the source Ip Address
164  *
165  * @details
166  *
167  *    Function : fillDestNetAddr
168  *
169  *    Functionality:
170  *       Fills the address List of destinatoion Ip Address
171  *
172  * @params[in] CmInetNetAddr *destAddrPtr, Address List pointer
173  * @params[in] F1IpAddr *dstIpAddr, destIp Address to be filled in the Address List
174  * @return ROK     - success
175  *         RFAILED - failure
176  *
177  *******************************************************************************/
178 uint8_t fillDestNetAddr(CmInetNetAddr *destAddrPtr, SctpIpAddr *dstIpPtr)
179 {
180    /* Filling destination address */
181    destAddrPtr->type = CM_INET_IPV4ADDR_TYPE;
182    destAddrPtr->u.ipv4NetAddr = CM_INET_NTOH_UINT32(dstIpPtr->ipV4Addr);
183    return ROK;
184 }
185
186 /******************************************************************************
187  *
188  * @brief Eastablishes the Assoc Req for the received interface type
189  *
190  * @details
191  *
192  *    Function : sctpStartReq
193  *
194  *    Functionality:
195  *       Eastablishes the Assoc Req for the received interface type
196  *
197  * @params[in] DuSctpDestCb *paramPtr
198  * @return ROK     - success
199  *         RFAILED - failure
200  *
201  *******************************************************************************/
202
203 uint8_t sctpStartReq()
204 {
205    uint8_t assocIdx;
206    uint8_t ret = ROK;
207    CmInetFd sockFd;
208
209    socket_type = CM_INET_STREAM;
210
211    /* Establish SCTP association at XN interface */
212    if(sctpCb.sctpCfg.xnSctpInfo.numDestNode)
213    {
214       if(sctpCb.localXnNodeType == SERVER)
215       {
216          if((ret = cmInetSocket(socket_type, &sctpCb.xnLstnSockFd, IPPROTO_SCTP) != ROK))
217          {   
218             DU_LOG("\nERROR  -->  SCTP : Socket[%d] coudnt open for listening", sctpCb.f1LstnSockFd.fd);
219          }   
220          else if((ret = cmInetSctpBindx(&sctpCb.xnLstnSockFd, &sctpCb.localAddrLst, sctpCb.sctpCfg.xnSctpInfo.port)) != ROK)
221          {   
222             DU_LOG("\nERROR  -->  SCTP: Binding failed at CU");
223          }   
224          else if(ret = cmInetListen(&sctpCb.xnLstnSockFd, 1) != ROK)
225          {   
226             DU_LOG("\nERROR  -->  SCTP : Listening on socket failed");
227             cmInetClose(&sctpCb.xnLstnSockFd);
228             return RFAILED;
229          }   
230          else
231          {   
232             for(assocIdx=0; assocIdx < sctpCb.numAssoc; assocIdx++)
233             {   
234                if(sctpCb.assocCb[assocIdx].intf == XN_INTERFACE)
235                {   
236                   if((ret = sctpAccept(&sctpCb.xnLstnSockFd, &sctpCb.assocCb[assocIdx])) != ROK)
237                   {
238                      DU_LOG("\nERROR  -->  SCTP: Unable to accept the connection at CU");
239                   }
240                }
241             }
242          }
243       }
244       else if(sctpCb.localXnNodeType == CLIENT)
245       {
246          for(assocIdx=0; assocIdx < sctpCb.numAssoc; assocIdx++)
247          {
248             if(sctpCb.assocCb[assocIdx].intf == XN_INTERFACE)
249             {
250                if((ret = cmInetSocket(socket_type, &sctpCb.assocCb[assocIdx].sockFd, IPPROTO_SCTP)) != ROK)
251                {   
252                   DU_LOG("\nERROR  -->  SCTP : Failed while opening a socket in ODU");
253                }   
254                else if((ret = cmInetSctpBindx(&sctpCb.assocCb[assocIdx].sockFd, &sctpCb.localAddrLst, sctpCb.sctpCfg.xnSctpInfo.port)) != ROK)
255                {   
256                   DU_LOG("\nERROR  -->  SCTP:  Failed during Binding in ODU");
257                }   
258                else if((ret = sctpSetSockOpts(&sctpCb.assocCb[assocIdx].sockFd)) != ROK)
259                {   
260                   DU_LOG("\nERROR  -->  SCTP : Failed to set Socket Opt in ODU");
261                }    
262                else
263                {   
264                   if(ret != ROK)
265                   {   
266                      DU_LOG("\nERROR  -->  SCTP : Failed while establishing Req at DU");
267                      ret = RFAILED;
268                   }   
269                   else 
270                   {   
271                      ret = cmInetSctpConnectx(&sctpCb.assocCb[assocIdx].sockFd, &sctpCb.assocCb[assocIdx].destIpNetAddr, \
272                               &sctpCb.assocCb[assocIdx].destAddrLst, sctpCb.assocCb[assocIdx].destPort);
273                      /* 115 error_code indicates that Operation is in progress and hence ignored if SctpConnect failed due to this */
274                      if(ret == 18)    
275                      {
276                         ret = ROK; 
277                      }
278                   }   
279                }
280             }
281          }
282       }
283    }
284
285    /* Establish SCTP association at F1 interface */
286    if(sctpCb.sctpCfg.f1SctpInfo.numDestNode)
287    {
288       if((ret = cmInetSocket(socket_type, &sctpCb.f1LstnSockFd, IPPROTO_SCTP) != ROK))
289       {
290          DU_LOG("\nERROR  -->  SCTP : Socket[%d] coudnt open for listening", sctpCb.f1LstnSockFd.fd);
291       } 
292       else if((ret = cmInetSctpBindx(&sctpCb.f1LstnSockFd, &sctpCb.localAddrLst, sctpCb.sctpCfg.f1SctpInfo.port)) != ROK)
293       {
294          DU_LOG("\nERROR  -->  SCTP: Binding failed at CU");
295       }
296       else if(ret = cmInetListen(&sctpCb.f1LstnSockFd, 1) != ROK)
297       {
298          DU_LOG("\nERROR  -->  SCTP : Listening on socket failed");
299          cmInetClose(&sctpCb.f1LstnSockFd);
300          return RFAILED;
301       }
302       else
303       {
304          for(assocIdx=0; assocIdx < sctpCb.numAssoc; assocIdx++)
305          {
306             if(sctpCb.assocCb[assocIdx].intf == F1_INTERFACE)
307             {
308                if((ret = sctpAccept(&sctpCb.f1LstnSockFd, &sctpCb.assocCb[assocIdx])) != ROK)
309                {
310                   DU_LOG("\nERROR  -->  SCTP: Unable to accept the connection at CU");
311                }
312             }
313          }
314       }
315    }
316
317    if(ret == ROK)
318    {
319       if(sctpSockPoll() != ROK)
320       {
321          DU_LOG("\nERROR  -->  SCTP: Polling failed to start at CU");
322       }
323    }
324    return (ret);
325 }
326
327 /*******************************************************************
328  *
329  * @brief Sets socket options as per requirement
330  *
331  * @details
332  *
333  *    Function : sctpSetSockOpts
334  *
335  *    Functionality: 
336  *       Sets socket options as per requirement
337  *
338  * @params[in] 
339  * @return ROK     - success
340  *         RFAILED - failure
341  *
342  * ****************************************************************/
343 uint8_t sctpSetSockOpts(CmInetFd *sock_Fd)
344 {
345    S16 ret = ROK;
346    CmSctpEvent sctpEvent;
347   
348    sctpEvent.dataIoEvent          = TRUE;
349    sctpEvent.associationEvent     = TRUE;
350    sctpEvent.addressEvent         = TRUE;
351    sctpEvent.sendFailureEvent     = TRUE;
352    sctpEvent.peerErrorEvent       = TRUE;
353    sctpEvent.shutdownEvent        = TRUE;
354    sctpEvent.partialDeliveryEvent = TRUE;
355    sctpEvent.adaptationLayerEvent = TRUE;
356
357    if((ret = cmInetSetOpt(sock_Fd, CM_SOCKOPT_LEVEL_SCTP, CM_SOCKOPT_OPT_SCTP_EVENTS, &sctpEvent)) != ROK)
358    {
359      ret = RFAILED;
360    }
361   
362    return (ret);
363 }
364
365 /*******************************************************************
366  *
367  * @brief Initiates connection with peer SCTP
368  *
369  * @details
370  *
371  *    Function : sctpAccept
372  *
373  *    Functionality:
374  *       Establishes SCTP connection with peer.
375  *       Here, DU-SCTP will initate connection towards CU-SCTP
376  *
377  * @params[in] 
378  * @return ROK     - success
379  *         RFAILED - failure
380  *
381  * ****************************************************************/
382 uint8_t sctpAccept(CmInetFd *lstnSockFd, CuSctpAssocCb *assocCb)
383 {
384    uint8_t  ret;
385
386    DU_LOG("\nINFO  -->  SCTP : Connecting");
387
388    while(!assocCb->connUp)
389    {
390       ret = cmInetAccept(lstnSockFd, &assocCb->peerAddr, &assocCb->sockFd);
391       if (ret == ROKDNA)
392       {
393          continue;
394       }
395       else if(ret != ROK)
396       {
397          DU_LOG("\nERROR  -->  SCTP : Failed to accept connection");
398          return RFAILED;
399       }
400       else
401       {
402          assocCb->connUp = TRUE;
403          sctpSetSockOpts(&assocCb->sockFd);
404          break;
405       }
406    }
407    DU_LOG("\nINFO  -->  SCTP : Connection established");
408
409    return ROK;
410 }
411
412 /*******************************************************************
413  *
414  * @brief Handles an SCTP notification message
415  *
416  * @details
417  *
418  *    Function : sctpNtfyHdlr
419  *
420  *    Functionality:
421  *      Handles an SCTP notification message
422  *
423  * @params[in] Notify message
424  *
425  * @return ROK     - success
426  *         RFAILED - failure
427  *
428  * ****************************************************************/
429 uint8_t sctpNtfyHdlr(CuSctpAssocCb *assocCb, CmInetSctpNotification *ntfy)
430 {
431    switch(ntfy->header.nType)
432    {
433       case CM_INET_SCTP_ASSOC_CHANGE :
434          DU_LOG("\nINFO  -->  SCTP : Assoc change notification received");
435          switch(ntfy->u.assocChange.state)
436          {
437             case CM_INET_SCTP_COMM_UP:
438                DU_LOG("DEBUG  -->  Event : COMMUNICATION UP");
439                assocCb->connUp = TRUE;
440                break;
441             case CM_INET_SCTP_COMM_LOST:
442                DU_LOG("DEBUG  -->  Event : COMMUNICATION LOST");
443                assocCb->connUp = FALSE;
444                break;
445             case CM_INET_SCTP_RESTART:
446                DU_LOG("DEBUG  -->  Event : SCTP RESTART");
447                assocCb->connUp = FALSE;
448                break;
449             case CM_INET_SCTP_SHUTDOWN_COMP: /* association gracefully shutdown */
450                DU_LOG("DEBUG  -->  Event : SHUTDOWN COMPLETE");
451                assocCb->connUp = FALSE;
452                break;
453             case CM_INET_SCTP_CANT_STR_ASSOC:
454                DU_LOG("DEBUG  -->  Event : CANT START ASSOC");
455                assocCb->connUp = FALSE;
456                break;
457             default:
458                DU_LOG("\nERROR  -->  Invalid event");
459                break;
460          }
461          break;
462       case CM_INET_SCTP_PEER_ADDR_CHANGE :
463          DU_LOG("\nINFO  -->  SCTP : Peer Address Change notificarion received");
464          /* Need to add handler */
465          break;
466       case CM_INET_SCTP_REMOTE_ERROR :
467          DU_LOG("\nINFO  -->  SCTP : Remote Error notification received");
468          break;
469       case CM_INET_SCTP_SEND_FAILED :
470          DU_LOG("\nINFO  -->  SCTP : Send Failed notification received\n");
471          break;
472       case CM_INET_SCTP_SHUTDOWN_EVENT : /* peer socket gracefully closed */
473          DU_LOG("\nINFO  -->  SCTP : Shutdown Event notification received\n");
474          assocCb->connUp = FALSE;
475          exit(0);
476          break;
477       case CM_INET_SCTP_ADAPTATION_INDICATION :
478          DU_LOG("\nINFO  -->  SCTP : Adaptation Indication received\n");
479          break;
480       case CM_INET_SCTP_PARTIAL_DELIVERY_EVENT:
481          DU_LOG("\nINFO  -->  SCTP : Partial Delivery Event received\n");
482          break;
483       default:
484          DU_LOG("\nERROR  -->  SCTP : Invalid notification type\n");
485          break;
486    }
487
488    sctpNtfyInd(ntfy);
489    return ROK;
490 }/* End of sctpNtfyHdlr */
491
492 /*******************************************************************
493  *
494  * @brief Receives message on the socket
495  *
496  * @details
497  *
498  *    Function : sctpSockPoll
499  *
500  *    Functionality:
501  *      Receives message on the socket
502  *
503  * @params[in] 
504  * @return ROK     - success
505  *         RFAILED - failure
506  *
507  * ****************************************************************/
508 uint8_t sctpSockPoll()
509 {
510    uint8_t       assocIdx = 0, destIdx = 0;
511    uint16_t      ret = ROK;
512    uint32_t      timeout;
513    uint32_t      *timeoutPtr;
514    Buffer        *egtpBuf;
515    MsgLen        egtpBufLen;
516    CmInetMemInfo memInfo;
517    sctpSockPollParams pollParams;
518    uint64_t      numMsgRcvd = 0;
519    CmInetAddr    fromAddr;
520
521    memset(&pollParams, 0, sizeof(sctpSockPollParams));
522     
523
524    /* All sockets are non-blocking */
525    timeout = 0;
526    timeoutPtr = &timeout;
527    memInfo.region = CU_APP_MEM_REG;
528    memInfo.pool   = CU_POOL;
529    
530    CM_INET_FD_ZERO(&pollParams.readFd);
531
532    while(1)
533    {
534       /* Receiving SCTP data */
535       for(assocIdx = 0; assocIdx < sctpCb.numAssoc; assocIdx++)
536       {
537          if((ret = processPolling(&pollParams, &sctpCb.assocCb[assocIdx], timeoutPtr, &memInfo)) != ROK)
538          {
539             DU_LOG("\nERROR  -->  SCTP : Failed to RecvMsg for F1 at CU\n");
540          }
541       }
542
543       /* Receiving EGTP data */
544       egtpBufLen = -1;
545       ret = cmInetRecvMsg(&(egtpCb.sockFd), &fromAddr, &memInfo, &egtpBuf, &egtpBufLen, CM_INET_NO_FLAG);
546       if(ret == ROK && egtpBuf != NULLP)
547       {
548          for(destIdx = 0; destIdx < egtpCb.numDu; destIdx++)
549          {
550             if((fromAddr.port == egtpCb.dstCb[destIdx].dstAddr.port) && (fromAddr.address == egtpCb.dstCb[destIdx].dstAddr.address))
551             {
552                DU_LOG("\nINFO  -->  EGTP : Received UL Message [%ld] from DU Id [%d]\n", numMsgRcvd+1, egtpCb.dstCb[destIdx].duId);
553                numMsgRcvd++;
554                //ODU_PRINT_MSG(egtpBuf, 0 ,0);
555                cuEgtpHdlRecvMsg(egtpBuf);
556                break;
557             }
558
559          }
560       }
561    };
562    return (ret);
563 }/* End of sctpSockPoll() */
564
565 /*******************************************************************
566  *
567  * @brief checks for valid readFd and process the InetSctpRecvMsg
568  * during polling 
569  *
570  * @details
571  *
572  *    Function : processPolling
573  *
574  *    Functionality:
575  *         checks for valid readFd and process the InetSctpRecvMsg
576  *         during polling
577  *
578  * @params[in]  Params required for polling
579  * @params[in]  SockFd for file descriptor
580  * @params[in]  timeoutPtr indicates the timeout value
581  * @params[in]  MemInfo indicates memory region
582  *
583  * @return ROK     - success
584  *         RFAILED - failure
585  *
586  * ****************************************************************/
587
588 uint8_t processPolling(sctpSockPollParams *pollParams, CuSctpAssocCb *assocCb, uint32_t *timeoutPtr, CmInetMemInfo *memInfo)
589 {
590    uint16_t ret = ROK;
591    CM_INET_FD_SET(&assocCb->sockFd, &pollParams->readFd);
592    ret = cmInetSelect(&pollParams->readFd, NULLP, timeoutPtr, &pollParams->numFd);
593    if(CM_INET_FD_ISSET(&assocCb->sockFd, &pollParams->readFd))
594    {
595       CM_INET_FD_CLR(&assocCb->sockFd, &pollParams->readFd);
596       ret = cmInetSctpRecvMsg(&assocCb->sockFd, &pollParams->addr, &pollParams->port, memInfo, &pollParams->mBuf, \
597          &pollParams->bufLen, &pollParams->info, &pollParams->flag, &pollParams->ntfy);
598       if(assocCb->connUp & (ret != ROK))
599       {
600          assocCb->bReadFdSet = RFAILED;
601       }
602       else
603       {
604          if(((pollParams->flag & CM_INET_SCTP_MSG_NOTIFICATION) != 0) && (ret == ROK))
605          {
606             ret = sctpNtfyHdlr(assocCb, &pollParams->ntfy);
607             if(ret != ROK)
608             {
609                DU_LOG("\nERROR  -->  SCTP : Failed to process sctp notify msg\n");
610             }
611          }
612          else if(assocCb->connUp && assocCb->intf == F1_INTERFACE)
613          {  
614             F1APMsgHdlr(&assocCb->destId, pollParams->mBuf);
615             ODU_PUT_MSG_BUF(pollParams->mBuf);
616          }
617          else if(assocCb->connUp && assocCb->intf == XN_INTERFACE)
618          {
619             DU_LOG("\nDEBUG  -->  SCTP : Received message at XN interface");
620             ODU_PRINT_MSG(pollParams->mBuf, 0,0);
621             XNAPMsgHdlr(&assocCb->destId, pollParams->mBuf);
622             ODU_PUT_MSG_BUF(pollParams->mBuf);
623          }
624          else
625          {
626             ODU_PUT_MSG_BUF(pollParams->mBuf);
627          }
628       } 
629   }
630   return ROK;
631 }/* End of sctpSockPoll() */
632
633 /*******************************************************************
634  *
635  * @brief Send message on an SCTP Association
636  *
637  * @details
638  *
639  *    Function : sendOnSctpAssoc
640  *
641  *    Functionality:
642  *        Send message on SCTP association
643  *
644  * @params[in] 
645  * @return ROK     - success
646  *         RFAILED - failure
647  *
648  * ****************************************************************/
649 uint8_t sendOnSctpAssoc(CuSctpAssocCb *assocCb, Buffer *mBuf)
650 {
651    uint8_t          ret = ROK;
652    MsgLen           len = 0;          /* number of actually sent octets */
653    CmInetMemInfo    memInfo;
654    
655    memset(&memInfo , 0, sizeof(CmInetMemInfo));
656    memInfo.region = CU_APP_MEM_REG;    
657    memInfo.pool   = CU_POOL;
658
659    ret = cmInetSctpSendMsg(&assocCb->sockFd, &assocCb->destIpNetAddr, assocCb->destPort, &memInfo, mBuf, &len, 0, \
660       FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
661
662    if(ret != ROK && ret != RWOULDBLOCK)
663    {
664       DU_LOG("\nERROR  -->  SCTP : Send message failed");
665       return RFAILED;
666    }
667    return ROK;
668 }
669
670 /*******************************************************************
671  *
672  * @brief Send message on SCTP socket
673  *
674  * @details
675  *
676  *    Function : sctpSend 
677  *
678  *    Functionality:
679  *        Send message on SCTP socket
680  *
681  * @params[in] 
682  * @return ROK     - success
683  *         RFAILED - failure
684  *
685  * ****************************************************************/
686 uint8_t sctpSend(InterfaceType intf, uint32_t destId, Buffer *mBuf)
687 {
688    uint8_t  assocIdx = 0;
689
690    for(assocIdx=0; assocIdx < sctpCb.numAssoc; assocIdx++)
691    {
692       if((sctpCb.assocCb[assocIdx].intf == intf) && (sctpCb.assocCb[assocIdx].destId == destId))
693       {
694          if(sendOnSctpAssoc(&sctpCb.assocCb[assocIdx], mBuf) == ROK)
695             return ROK;
696          else
697             break;
698       }
699    }
700    DU_LOG("\nERROR  -->  SCTP : Dest ID [%d] at Interface [%d] not found in SCTP DestCb list. Failed to send message", destId, intf);
701    return RFAILED;
702 } /* End of sctpSend */
703
704 /**********************************************************************
705          End of file
706 **********************************************************************/