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