[Epic-ID: ODUHIGH-405][Task-ID: ODUHIGH-414] Support at CU and RIC stub for SCTP...
[o-du/l2.git] / src / ric_stub / 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;
45
46    sctpCb.sctpCfg = ricCfgParams.sctpParams;   
47    for(destIdx=0; destIdx < sctpCb.sctpCfg.numDu; destIdx++)
48    {   
49       sctpCb.destCb[destIdx].destPort = sctpCb.sctpCfg.sctpAssoc[destIdx].duPort;
50       sctpCb.destCb[destIdx].srcPort  = sctpCb.sctpCfg.sctpAssoc[destIdx].ricPort;
51       sctpCb.destCb[destIdx].bReadFdSet = ROK;
52       memset(&sctpCb.destCb[destIdx].sockFd, -1, sizeof(CmInetFd));
53       memset(&sctpCb.destCb[destIdx].lstnSockFd, -1, sizeof(CmInetFd));
54       fillDestNetAddr(&sctpCb.destCb[destIdx].destIpNetAddr, &sctpCb.sctpCfg.sctpAssoc[destIdx].duIpAddr);
55       fillAddrLst(&sctpCb.destCb[destIdx].localAddrLst, &sctpCb.sctpCfg.sctpAssoc[destIdx].ricIpAddr);
56       sctpCb.destCb[destIdx].connUp = false;
57    }   
58    sctpCb.numDu = sctpCb.sctpCfg.numDu;
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 destIdx  = 0;
134    uint8_t ret = ROK;
135
136    socket_type = CM_INET_STREAM;
137
138    for(destIdx=0; destIdx < sctpCb.numDu; destIdx++)
139    {
140       if((ret = cmInetSocket(socket_type, &sctpCb.destCb[destIdx].lstnSockFd, IPPROTO_SCTP) != ROK))
141       {
142          DU_LOG("\nERROR  -->  SCTP : Socket[%d] coudnt open for listening", sctpCb.destCb[destIdx].lstnSockFd.fd);
143       } 
144       else if((ret = cmInetSctpBindx(&sctpCb.destCb[destIdx].lstnSockFd, &sctpCb.destCb[destIdx].localAddrLst, \
145          sctpCb.destCb[destIdx].srcPort)) != ROK)
146       {
147          DU_LOG("\nERROR  -->  SCTP: Binding failed at RIC");
148       }
149       else if((ret = sctpAccept(&sctpCb.destCb[destIdx])) != ROK)
150       {
151          DU_LOG("\nERROR  -->  SCTP: Unable to accept the connection at RIC");
152       }
153    }
154
155    if(sctpSockPoll() != ROK)
156    {
157       DU_LOG("\nERROR  -->  SCTP: Polling failed to start at RIC");
158    }
159    return (ret);
160 }
161 /*******************************************************************
162  *
163  * @brief Sets socket options as per requirement
164  *
165  * @details
166  *
167  *    Function : sctpSetSockOpts
168  *
169  *    Functionality: 
170  *       Sets socket options as per requirement
171  *
172  * @params[in] 
173  * @return ROK     - success
174  *         RFAILED - failure
175  *
176  * ****************************************************************/
177 uint8_t sctpSetSockOpts(CmInetFd *sock_Fd)
178 {
179    S16 ret = ROK;
180    CmSctpEvent sctpEvent;
181   
182    sctpEvent.dataIoEvent          = TRUE;
183    sctpEvent.associationEvent     = TRUE;
184    sctpEvent.addressEvent         = TRUE;
185    sctpEvent.sendFailureEvent     = TRUE;
186    sctpEvent.peerErrorEvent       = TRUE;
187    sctpEvent.shutdownEvent        = TRUE;
188    sctpEvent.partialDeliveryEvent = TRUE;
189    sctpEvent.adaptationLayerEvent = TRUE;
190
191    if((ret = cmInetSetOpt(sock_Fd, CM_SOCKOPT_LEVEL_SCTP, CM_SOCKOPT_OPT_SCTP_EVENTS, &sctpEvent)) != ROK)
192    {
193      ret = RFAILED;
194    }
195   
196    return (ret);
197 }
198
199 /*******************************************************************
200  *
201  * @brief Initiates connection with peer SCTP
202  *
203  * @details
204  *
205  *    Function : sctpAccept
206  *
207  *    Functionality:
208  *       Establishes SCTP connection with peer.
209  *       Here, DU-SCTP will initate connection towards RIC-SCTP
210  *
211  * @params[in] 
212  * @return ROK     - success
213  *         RFAILED - failure
214  *
215  * ****************************************************************/
216 uint8_t sctpAccept(RicSctpDestCb *destCb)
217 {
218    uint8_t  ret;
219
220    ret = cmInetListen(&destCb->lstnSockFd, 1);
221    if (ret != ROK)
222    {
223       DU_LOG("\nERROR   -->  SCTP : Listening on socket failed");
224       cmInetClose(&destCb->lstnSockFd);
225       return RFAILED;
226    }
227    
228    DU_LOG("\nINFO   -->  SCTP : Connecting");
229
230    while(!destCb->connUp)
231    {
232       ret = cmInetAccept(&destCb->lstnSockFd, &destCb->peerAddr, &destCb->sockFd);
233       if (ret == ROKDNA)
234       {
235          continue;
236       }
237       else if(ret != ROK)
238       {
239          DU_LOG("\nERROR  -->  SCTP : Failed to accept connection");
240          return RFAILED;
241       }
242       else
243       {
244          destCb->connUp = TRUE;
245          sctpSetSockOpts(&destCb->sockFd);
246          break;
247       }
248    }
249    DU_LOG("\nINFO   -->  SCTP : Connection established");
250
251    return ROK;
252 }
253
254 /*******************************************************************
255  *
256  * @brief Handles an SCTP notification message
257  *
258  * @details
259  *
260  *    Function : sctpNtfyHdlr
261  *
262  *    Functionality:
263  *      Handles an SCTP notification message
264  *
265  * @params[in] Notify message
266  *
267  * @return ROK     - success
268  *         RFAILED - failure
269  *
270  * ****************************************************************/
271 uint8_t sctpNtfyHdlr(RicSctpDestCb *destCb, CmInetSctpNotification *ntfy)
272 {
273    switch(ntfy->header.nType)
274    {
275       case CM_INET_SCTP_ASSOC_CHANGE :
276          DU_LOG("\nINFO   -->  SCTP : Assoc change notification received");
277          switch(ntfy->u.assocChange.state)
278          {
279             case CM_INET_SCTP_COMM_UP:
280                DU_LOG("\nINFO   -->  Event : COMMUNICATION UP");
281                destCb->connUp = TRUE;
282                break;
283             case CM_INET_SCTP_COMM_LOST:
284                DU_LOG("\nINFO   -->  Event : COMMUNICATION LOST");
285                destCb->connUp = FALSE;
286                break;
287             case CM_INET_SCTP_RESTART:
288                DU_LOG("\nINFO   -->  Event : SCTP RESTART");
289                destCb->connUp = FALSE;
290                break;
291             case CM_INET_SCTP_SHUTDOWN_COMP: /* association gracefully shutdown */
292                DU_LOG("\nINFO   -->  Event : SHUTDOWN COMPLETE");
293                destCb->connUp = FALSE;
294                break;
295             case CM_INET_SCTP_CANT_STR_ASSOC:
296                DU_LOG("\nINFO   -->  Event : CANT START ASSOC");
297                destCb->connUp = FALSE;
298                break;
299             default:
300                DU_LOG("\nERROR   -->  Invalid event");
301                break;
302          }
303          break;
304       case CM_INET_SCTP_PEER_ADDR_CHANGE :
305          DU_LOG("\nINFO   -->  SCTP : Peer Address Change notificarion received");
306          /* Need to add handler */
307          break;
308       case CM_INET_SCTP_REMOTE_ERROR :
309          DU_LOG("\nINFO   -->  SCTP : Remote Error notification received");
310          break;
311       case CM_INET_SCTP_SEND_FAILED :
312          DU_LOG("\nINFO   -->  SCTP : Send Failed notification received\n");
313          break;
314       case CM_INET_SCTP_SHUTDOWN_EVENT : /* peer socket gracefully closed */
315          DU_LOG("\nINFO   -->  SCTP : Shutdown Event notification received\n");
316          destCb->connUp = FALSE;
317          exit(0);
318          break;
319       case CM_INET_SCTP_ADAPTATION_INDICATION :
320          DU_LOG("\nINFO   -->  SCTP : Adaptation Indication received\n");
321          break;
322       case CM_INET_SCTP_PARTIAL_DELIVERY_EVENT:
323          DU_LOG("\nINFO   -->  SCTP : Partial Delivery Event received\n");
324          break;
325       default:
326          DU_LOG("\nERROR   -->  SCTP : Invalid notification type\n");
327          break;
328    }
329
330    sctpNtfyInd(ntfy);
331    return ROK;
332 }/* End of sctpNtfyHdlr */
333
334 /*******************************************************************
335  *
336  * @brief Receives message on the socket
337  *
338  * @details
339  *
340  *    Function : sctpSockPoll
341  *
342  *    Functionality:
343  *      Receives message on the socket
344  *
345  * @params[in] 
346  * @return ROK     - success
347  *         RFAILED - failure
348  *
349  * ****************************************************************/
350 uint8_t sctpSockPoll()
351 {
352    uint8_t            destIdx;
353    uint16_t           ret = ROK;
354    uint32_t           timeout;
355    uint32_t           *timeoutPtr;
356    CmInetMemInfo      memInfo;
357    sctpSockPollParams e2PollParams;
358
359    memset(&e2PollParams, 0, sizeof(sctpSockPollParams));
360     
361    /* All sockets are non-blocking */
362    timeout = 0;
363    timeoutPtr = &timeout;
364    memInfo.region = RIC_APP_MEM_REG;
365    memInfo.pool   = RIC_POOL;
366
367    CM_INET_FD_ZERO(&e2PollParams.readFd);
368
369    DU_LOG("\nINFO  -->  SCTP : Polling started at RIC\n");
370    while(1)
371    {
372       /* Receiving SCTP data */
373       for(destIdx = 0; destIdx < sctpCb.numDu; destIdx++)
374       {
375
376          if((ret = processPolling(&e2PollParams, &sctpCb.destCb[destIdx], timeoutPtr, &memInfo)) != ROK)
377          {
378             DU_LOG("\nERROR  -->  SCTP : Failed to RecvMsg for E2 at RIC \n");
379          }
380       }
381    };
382    return (ret);
383 }/* End of sctpSockPoll() */
384
385 /*******************************************************************
386  *
387  * @brief checks for valid readFd and process the InetSctpRecvMsg
388  * during polling 
389  *
390  * @details
391  *
392  *    Function : processPolling
393  *
394  *    Functionality:
395  *         checks for valid readFd and process the InetSctpRecvMsg
396  *         during polling
397  *
398  * @params[in]  Params required for polling
399  * @params[in]  SockFd for file descriptor
400  * @params[in]  timeoutPtr indicates the timeout value
401  * @params[in]  MemInfo indicates memory region
402  *
403  * @return ROK     - success
404  *         RFAILED - failure
405  *
406  * ****************************************************************/
407
408  
409 uint8_t processPolling(sctpSockPollParams *pollParams, RicSctpDestCb *destCb, uint32_t *timeoutPtr, CmInetMemInfo *memInfo)
410 {
411    uint16_t ret = ROK;
412
413    CM_INET_FD_SET(&destCb->sockFd, &pollParams->readFd);
414    ret = cmInetSelect(&pollParams->readFd, NULLP, timeoutPtr, &pollParams->numFd);
415    if(CM_INET_FD_ISSET(&destCb->sockFd, &pollParams->readFd))
416    {
417       CM_INET_FD_CLR(&destCb->sockFd, &pollParams->readFd);
418       ret = cmInetSctpRecvMsg(&destCb->sockFd, &pollParams->addr, &pollParams->port, memInfo, &pollParams->mBuf, \
419           &pollParams->bufLen, &pollParams->info, &pollParams->flag, &pollParams->ntfy);
420       if(destCb->connUp & (ret != ROK))
421       {
422          destCb->bReadFdSet = RFAILED;
423       }
424       else
425       {
426          if(((pollParams->flag & CM_INET_SCTP_MSG_NOTIFICATION) != 0) && (ret == ROK))
427          {
428             ret = sctpNtfyHdlr(destCb, &pollParams->ntfy);
429             if(ret != ROK)
430             {
431                DU_LOG("\nERROR  -->  SCTP : Failed to process sctp notify msg\n");
432             }
433          }
434          else if(destCb->connUp & (pollParams->port == destCb->destPort))
435          {  
436             E2APMsgHdlr(pollParams->mBuf);
437             ODU_PUT_MSG_BUF(pollParams->mBuf);
438          }
439          else
440          {
441             ODU_PUT_MSG_BUF(pollParams->mBuf);
442          }
443       } 
444   }
445   return ROK;
446 }/* End of sctpSockPoll() */
447
448 /*******************************************************************
449  *
450  * @brief Send message on SCTP socket
451  *
452  * @details
453  *
454  *    Function : sctpSend 
455  *
456  *    Functionality:
457  *        Send message on SCTP socket
458  *
459  * @params[in] 
460  * @return ROK     - success
461  *         RFAILED - failure
462  *
463  * ****************************************************************/
464 uint8_t sctpSend(Buffer *mBuf)
465 {
466    uint8_t          ret;
467    MsgLen           len;          /* number of actually sent octets */
468    CmInetMemInfo    memInfo;                        
469    
470    memInfo.region = RIC_APP_MEM_REG;               
471    memInfo.pool   = RIC_POOL;
472
473    ret = cmInetSctpSendMsg(&sctpCb.destCb[0].sockFd, &sctpCb.destCb[0].destIpNetAddr, sctpCb.destCb[0].destPort, &memInfo, \
474       mBuf, &len, 0, FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
475
476    if(ret != ROK && ret != RWOULDBLOCK)
477    {
478       DU_LOG("\nERROR  -->  SCTP : Send message failed");
479       return RFAILED;
480    }
481
482    return ROK;
483 } /* End of sctpSend */
484 /**********************************************************************
485          End of file
486 **********************************************************************/