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