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