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