e8737f4b17aaca3db878d3e8c8f79cce62c646e0
[o-du/l2.git] / ric_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 "ric_stub_sctp.h"
23 #include "ric_stub.h"
24 #include "ric_e2ap_msg_hdl.h"
25 #include "E2AP-PDU.h"
26
27 /**************************************************************************
28  * @brief Function to configure the Sctp Params during config Request
29  *
30  * @details
31  *
32  *      Function : sctpCfgReq
33  * 
34  *      Functionality:
35  *           This function configures SCTP Params during the config Request
36  *     
37  * @return ROK     - success
38  *         RFAILED - failure
39  *
40  ***************************************************************************/
41
42 uint8_t sctpCfgReq()
43 {
44    int destIdx = 0, assocIdx = 0;
45
46    sctpCb.sctpCfg = ricCb.ricCfgParams.sctpParams;   
47    fillAddrLst(&sctpCb.localAddrLst, &sctpCb.sctpCfg.localIpAddr);
48    memset(&sctpCb.e2LstnSockFd, -1, sizeof(CmInetFd));
49    for(destIdx=0; destIdx < sctpCb.sctpCfg.numDestNode; destIdx++)
50    {   
51       sctpCb.assocCb[assocIdx].destPort = sctpCb.sctpCfg.destCb[destIdx].destPort;
52       sctpCb.assocCb[assocIdx].bReadFdSet = ROK;
53       memset(&sctpCb.assocCb[assocIdx].sockFd, -1, sizeof(CmInetFd));
54       fillDestNetAddr(&sctpCb.assocCb[assocIdx].destIpNetAddr, &sctpCb.sctpCfg.destCb[destIdx].destIpAddr);
55       sctpCb.assocCb[assocIdx].connUp = false;
56       assocIdx++;
57    }   
58    sctpCb.numAssoc = assocIdx;
59    return ROK;
60 }
61
62 /*******************************************************************
63  *
64  * @brief Fills the address List of the source Ip Address
65  *
66  * @details
67  *
68  *    Function : fillAddrLst
69  *
70  *    Functionality:
71  *       Fills the address List of source Ip Address
72  *
73  * @params[in] CmInetNetAddrLst *addrLstPtr, Address List pointer
74  * @params[in] F1IpAddr *srcIpAddr, src Ip Adrress to be filled in the Address List
75  * @return ROK     - success
76  *         RFAILED - failure
77  *
78  ******************************************************************/
79
80 uint8_t fillAddrLst(CmInetNetAddrLst *addrLstPtr, SctpIpAddr *ipAddr)
81
82    addrLstPtr->addrs[addrLstPtr->count].type = CM_INET_IPV4ADDR_TYPE;
83    addrLstPtr->addrs[addrLstPtr->count].u.ipv4NetAddr = CM_INET_NTOH_UINT32(ipAddr->ipV4Addr);
84    addrLstPtr->count++;
85
86    return ROK;
87 }
88
89 /******************************************************************************
90  *
91  * @brief Fills the address List of the source Ip Address
92  *
93  * @details
94  *
95  *    Function : fillDestNetAddr
96  *
97  *    Functionality:
98  *       Fills the address List of destinatoion Ip Address
99  *
100  * @params[in] CmInetNetAddr *destAddrPtr, Address List pointer
101  * @params[in] F1IpAddr *dstIpAddr, destIp Address to be filled in the Address List
102  * @return ROK     - success
103  *         RFAILED - failure
104  *
105  *******************************************************************************/
106 uint8_t fillDestNetAddr(CmInetNetAddr *destAddrPtr, SctpIpAddr *dstIpPtr)
107 {
108    /* Filling destination address */
109    destAddrPtr->type = CM_INET_IPV4ADDR_TYPE;
110    destAddrPtr->u.ipv4NetAddr = CM_INET_NTOH_UINT32(dstIpPtr->ipV4Addr);
111    return ROK;
112 }
113
114 /******************************************************************************
115  *
116  * @brief Eastablishes the Assoc Req for the received interface type
117  *
118  * @details
119  *
120  *    Function : sctpStartReq
121  *
122  *    Functionality:
123  *       Eastablishes the Assoc Req for the received interface type
124  *
125  * @params[in] DuSctpDestCb *paramPtr
126  * @return ROK     - success
127  *         RFAILED - failure
128  *
129  *******************************************************************************/
130
131 uint8_t sctpStartReq()
132 {
133    uint8_t assocIdx  = 0;
134    uint8_t ret = ROK;
135
136    socket_type = CM_INET_STREAM;
137
138    if(sctpCb.numAssoc)
139    {
140
141       if((ret = cmInetSocket(socket_type, &sctpCb.e2LstnSockFd, IPPROTO_SCTP) != ROK))
142       {
143          DU_LOG("\nERROR  -->  SCTP : Socket[%d] coudnt open for listening", sctpCb.e2LstnSockFd.fd);
144       } 
145       else if((ret = cmInetSctpBindx(&sctpCb.e2LstnSockFd, &sctpCb.localAddrLst, sctpCb.sctpCfg.e2SctpPort)) != ROK)
146       {
147          DU_LOG("\nERROR  -->  SCTP: Binding failed at RIC");
148       }
149       else if(ret = cmInetListen(&sctpCb.e2LstnSockFd, 1) != ROK)
150       {
151          DU_LOG("\nERROR  -->  SCTP: Unable to accept the connection at CU");
152          DU_LOG("\nERROR  -->  SCTP : Listening on socket failed");
153          cmInetClose(&sctpCb.e2LstnSockFd);
154          return RFAILED;
155       }
156       else
157       {
158          for(assocIdx=0; assocIdx < sctpCb.numAssoc; assocIdx++)
159          {
160             if((ret = sctpAccept(&sctpCb.assocCb[assocIdx])) != ROK)
161             {
162                DU_LOG("\nERROR  -->  SCTP: Unable to accept the connection at RIC");
163             }
164          }
165       }
166    }
167
168    if(ret == ROK)
169    {
170       if(sctpSockPoll() != ROK)
171       {
172          DU_LOG("\nERROR  -->  SCTP: Polling failed to start at RIC");
173       }
174    }
175    return (ret);
176 }
177
178 /*******************************************************************
179  *
180  * @brief Sets socket options as per requirement
181  *
182  * @details
183  *
184  *    Function : sctpSetSockOpts
185  *
186  *    Functionality: 
187  *       Sets socket options as per requirement
188  *
189  * @params[in] 
190  * @return ROK     - success
191  *         RFAILED - failure
192  *
193  * ****************************************************************/
194 uint8_t sctpSetSockOpts(CmInetFd *sock_Fd)
195 {
196    S16 ret = ROK;
197    CmSctpEvent sctpEvent;
198   
199    sctpEvent.dataIoEvent          = TRUE;
200    sctpEvent.associationEvent     = TRUE;
201    sctpEvent.addressEvent         = TRUE;
202    sctpEvent.sendFailureEvent     = TRUE;
203    sctpEvent.peerErrorEvent       = TRUE;
204    sctpEvent.shutdownEvent        = TRUE;
205    sctpEvent.partialDeliveryEvent = TRUE;
206    sctpEvent.adaptationLayerEvent = TRUE;
207
208    if((ret = cmInetSetOpt(sock_Fd, CM_SOCKOPT_LEVEL_SCTP, CM_SOCKOPT_OPT_SCTP_EVENTS, &sctpEvent)) != ROK)
209    {
210      ret = RFAILED;
211    }
212   
213    return (ret);
214 }
215
216 /*******************************************************************
217  *
218  * @brief Initiates connection with peer SCTP
219  *
220  * @details
221  *
222  *    Function : sctpAccept
223  *
224  *    Functionality:
225  *       Establishes SCTP connection with peer.
226  *       Here, DU-SCTP will initate connection towards RIC-SCTP
227  *
228  * @params[in] 
229  * @return ROK     - success
230  *         RFAILED - failure
231  *
232  * ****************************************************************/
233 uint8_t sctpAccept(RicSctpAssocCb *assocCb)
234 {
235    uint8_t  ret;
236
237    DU_LOG("\nINFO   -->  SCTP : Connecting");
238
239    while(!assocCb->connUp)
240    {
241       ret = cmInetAccept(&sctpCb.e2LstnSockFd, &assocCb->peerAddr, &assocCb->sockFd);
242       if (ret == ROKDNA)
243       {
244          continue;
245       }
246       else if(ret != ROK)
247       {
248          DU_LOG("\nERROR  -->  SCTP : Failed to accept connection");
249          return RFAILED;
250       }
251       else
252       {
253          assocCb->connUp = TRUE;
254          sctpSetSockOpts(&assocCb->sockFd);
255          break;
256       }
257    }
258    DU_LOG("\nINFO   -->  SCTP : Connection established");
259
260    return ROK;
261 }
262
263 /*******************************************************************
264  *
265  * @brief Handles an SCTP notification message
266  *
267  * @details
268  *
269  *    Function : sctpNtfyHdlr
270  *
271  *    Functionality:
272  *      Handles an SCTP notification message
273  *
274  * @params[in] Notify message
275  *
276  * @return ROK     - success
277  *         RFAILED - failure
278  *
279  * ****************************************************************/
280 uint8_t sctpNtfyHdlr(RicSctpAssocCb *assocCb, CmInetSctpNotification *ntfy)
281 {
282    switch(ntfy->header.nType)
283    {
284       case CM_INET_SCTP_ASSOC_CHANGE :
285          DU_LOG("\nINFO   -->  SCTP : Assoc change notification received");
286          switch(ntfy->u.assocChange.state)
287          {
288             case CM_INET_SCTP_COMM_UP:
289                DU_LOG("\nINFO   -->  Event : COMMUNICATION UP");
290                assocCb->connUp = TRUE;
291                break;
292             case CM_INET_SCTP_COMM_LOST:
293                DU_LOG("\nINFO   -->  Event : COMMUNICATION LOST");
294                assocCb->connUp = FALSE;
295                break;
296             case CM_INET_SCTP_RESTART:
297                DU_LOG("\nINFO   -->  Event : SCTP RESTART");
298                assocCb->connUp = FALSE;
299                break;
300             case CM_INET_SCTP_SHUTDOWN_COMP: /* association gracefully shutdown */
301                DU_LOG("\nINFO   -->  Event : SHUTDOWN COMPLETE");
302                assocCb->connUp = FALSE;
303                break;
304             case CM_INET_SCTP_CANT_STR_ASSOC:
305                DU_LOG("\nINFO   -->  Event : CANT START ASSOC");
306                assocCb->connUp = FALSE;
307                break;
308             default:
309                DU_LOG("\nERROR   -->  Invalid event");
310                break;
311          }
312          break;
313       case CM_INET_SCTP_PEER_ADDR_CHANGE :
314          DU_LOG("\nINFO   -->  SCTP : Peer Address Change notificarion received");
315          /* Need to add handler */
316          break;
317       case CM_INET_SCTP_REMOTE_ERROR :
318          DU_LOG("\nINFO   -->  SCTP : Remote Error notification received");
319          break;
320       case CM_INET_SCTP_SEND_FAILED :
321          DU_LOG("\nINFO   -->  SCTP : Send Failed notification received\n");
322          break;
323       case CM_INET_SCTP_SHUTDOWN_EVENT : /* peer socket gracefully closed */
324          DU_LOG("\nINFO   -->  SCTP : Shutdown Event notification received\n");
325          assocCb->connUp = FALSE;
326          exit(0);
327          break;
328       case CM_INET_SCTP_ADAPTATION_INDICATION :
329          DU_LOG("\nINFO   -->  SCTP : Adaptation Indication received\n");
330          break;
331       case CM_INET_SCTP_PARTIAL_DELIVERY_EVENT:
332          DU_LOG("\nINFO   -->  SCTP : Partial Delivery Event received\n");
333          break;
334       default:
335          DU_LOG("\nERROR   -->  SCTP : Invalid notification type\n");
336          break;
337    }
338
339    sctpNtfyInd(ntfy);
340    return ROK;
341 }/* End of sctpNtfyHdlr */
342
343 /*******************************************************************
344  *
345  * @brief Receives message on the socket
346  *
347  * @details
348  *
349  *    Function : sctpSockPoll
350  *
351  *    Functionality:
352  *      Receives message on the socket
353  *
354  * @params[in] 
355  * @return ROK     - success
356  *         RFAILED - failure
357  *
358  * ****************************************************************/
359 uint8_t sctpSockPoll()
360 {
361    uint8_t            assocIdx;
362    uint16_t           ret = ROK;
363    uint32_t           timeout;
364    uint32_t           *timeoutPtr;
365    CmInetMemInfo      memInfo;
366    sctpSockPollParams e2PollParams;
367
368    memset(&e2PollParams, 0, sizeof(sctpSockPollParams));
369     
370    /* All sockets are non-blocking */
371    timeout = 0;
372    timeoutPtr = &timeout;
373    memInfo.region = RIC_APP_MEM_REG;
374    memInfo.pool   = RIC_POOL;
375
376    CM_INET_FD_ZERO(&e2PollParams.readFd);
377
378    DU_LOG("\nINFO  -->  SCTP : Polling started at RIC\n");
379    while(1)
380    {
381       /* Receiving SCTP data */
382       for(assocIdx = 0; assocIdx < sctpCb.numAssoc; assocIdx++)
383       {
384          if((ret = processPolling(&e2PollParams, &sctpCb.assocCb[assocIdx], timeoutPtr, &memInfo)) != ROK)
385          {
386             DU_LOG("\nERROR  -->  SCTP : Failed to RecvMsg for E2 at RIC \n");
387          }
388       }
389    };
390    return (ret);
391 }/* End of sctpSockPoll() */
392
393 /*******************************************************************
394  *
395  * @brief checks for valid readFd and process the InetSctpRecvMsg
396  * during polling 
397  *
398  * @details
399  *
400  *    Function : processPolling
401  *
402  *    Functionality:
403  *         checks for valid readFd and process the InetSctpRecvMsg
404  *         during polling
405  *
406  * @params[in]  Params required for polling
407  * @params[in]  SockFd for file descriptor
408  * @params[in]  timeoutPtr indicates the timeout value
409  * @params[in]  MemInfo indicates memory region
410  *
411  * @return ROK     - success
412  *         RFAILED - failure
413  *
414  * ****************************************************************/
415
416  
417 uint8_t processPolling(sctpSockPollParams *pollParams, RicSctpAssocCb *assocCb, uint32_t *timeoutPtr, CmInetMemInfo *memInfo)
418 {
419    uint16_t ret = ROK;
420
421    CM_INET_FD_SET(&assocCb->sockFd, &pollParams->readFd);
422    ret = cmInetSelect(&pollParams->readFd, NULLP, timeoutPtr, &pollParams->numFd);
423    if(CM_INET_FD_ISSET(&assocCb->sockFd, &pollParams->readFd))
424    {
425       CM_INET_FD_CLR(&assocCb->sockFd, &pollParams->readFd);
426       ret = cmInetSctpRecvMsg(&assocCb->sockFd, &pollParams->addr, &pollParams->port, memInfo, &pollParams->mBuf, \
427           &pollParams->bufLen, &pollParams->info, &pollParams->flag, &pollParams->ntfy);
428       if(assocCb->connUp & (ret != ROK))
429       {
430          assocCb->bReadFdSet = RFAILED;
431       }
432       else
433       {
434          if(((pollParams->flag & CM_INET_SCTP_MSG_NOTIFICATION) != 0) && (ret == ROK))
435          {
436             ret = sctpNtfyHdlr(assocCb, &pollParams->ntfy);
437             if(ret != ROK)
438             {
439                DU_LOG("\nERROR  -->  SCTP : Failed to process sctp notify msg\n");
440             }
441          }
442          else if(assocCb->connUp)
443          {  
444             E2APMsgHdlr(&assocCb->duId, pollParams->mBuf);
445             ODU_PUT_MSG_BUF(pollParams->mBuf);
446          }
447          else
448          {
449             ODU_PUT_MSG_BUF(pollParams->mBuf);
450          }
451       } 
452   }
453   return ROK;
454 }/* End of sctpSockPoll() */
455
456 /*******************************************************************
457  *
458  * @brief Send message on SCTP socket
459  *
460  * @details
461  *
462  *    Function : sctpSend 
463  *
464  *    Functionality:
465  *        Send message on SCTP socket
466  *
467  * @params[in] 
468  * @return ROK     - success
469  *         RFAILED - failure
470  *
471  * ****************************************************************/
472 uint8_t sctpSend(uint32_t duId, Buffer *mBuf)
473 {
474    uint8_t          assocIdx;
475    uint8_t          ret;
476    MsgLen           len;          /* number of actually sent octets */
477    CmInetMemInfo    memInfo;                        
478    
479    memInfo.region = RIC_APP_MEM_REG;               
480    memInfo.pool   = RIC_POOL;
481
482    for(assocIdx = 0; assocIdx < sctpCb.numAssoc; assocIdx++)
483    {
484       if(sctpCb.assocCb[assocIdx].duId == duId)
485       {
486          ret = cmInetSctpSendMsg(&sctpCb.assocCb[assocIdx].sockFd, &sctpCb.assocCb[assocIdx].destIpNetAddr, \
487                sctpCb.assocCb[assocIdx].destPort, &memInfo, mBuf, &len, 0, FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
488
489          if(ret != ROK && ret != RWOULDBLOCK)
490          {
491             DU_LOG("\nERROR  -->  SCTP : Send message failed");
492             return RFAILED;
493          }
494       }
495    }
496    return ROK;
497 } /* End of sctpSend */
498 /**********************************************************************
499          End of file
500 **********************************************************************/