[Epic-ID: ODUHIGH-516][Task-ID: ODUHIGH-553] Transid fixes in E2AP procedures
[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 = 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          deleteE2NodeInfo(&ricCb.duInfo[0]);
327          exit(0);
328          break;
329       case CM_INET_SCTP_ADAPTATION_INDICATION :
330          DU_LOG("\nINFO   -->  SCTP : Adaptation Indication received\n");
331          break;
332       case CM_INET_SCTP_PARTIAL_DELIVERY_EVENT:
333          DU_LOG("\nINFO   -->  SCTP : Partial Delivery Event received\n");
334          break;
335       default:
336          DU_LOG("\nERROR   -->  SCTP : Invalid notification type\n");
337          break;
338    }
339
340    sctpNtfyInd(ntfy);
341    return ROK;
342 }/* End of sctpNtfyHdlr */
343
344 /*******************************************************************
345  *
346  * @brief Receives message on the socket
347  *
348  * @details
349  *
350  *    Function : sctpSockPoll
351  *
352  *    Functionality:
353  *      Receives message on the socket
354  *
355  * @params[in] 
356  * @return ROK     - success
357  *         RFAILED - failure
358  *
359  * ****************************************************************/
360 uint8_t sctpSockPoll()
361 {
362    uint8_t            assocIdx;
363    uint16_t           ret = ROK;
364    uint32_t           timeout;
365    uint32_t           *timeoutPtr;
366    CmInetMemInfo      memInfo;
367    sctpSockPollParams e2PollParams;
368
369    memset(&e2PollParams, 0, sizeof(sctpSockPollParams));
370     
371    /* All sockets are non-blocking */
372    timeout = 0;
373    timeoutPtr = &timeout;
374    memInfo.region = RIC_APP_MEM_REG;
375    memInfo.pool   = RIC_POOL;
376
377    CM_INET_FD_ZERO(&e2PollParams.readFd);
378
379    DU_LOG("\nINFO  -->  SCTP : Polling started at RIC\n");
380    while(1)
381    {
382       /* Receiving SCTP data */
383       for(assocIdx = 0; assocIdx < sctpCb.numAssoc; assocIdx++)
384       {
385          if((ret = processPolling(&e2PollParams, &sctpCb.assocCb[assocIdx], timeoutPtr, &memInfo)) != ROK)
386          {
387             DU_LOG("\nERROR  -->  SCTP : Failed to RecvMsg for E2 at RIC \n");
388          }
389       }
390    };
391    return (ret);
392 }/* End of sctpSockPoll() */
393
394 /*******************************************************************
395  *
396  * @brief checks for valid readFd and process the InetSctpRecvMsg
397  * during polling 
398  *
399  * @details
400  *
401  *    Function : processPolling
402  *
403  *    Functionality:
404  *         checks for valid readFd and process the InetSctpRecvMsg
405  *         during polling
406  *
407  * @params[in]  Params required for polling
408  * @params[in]  SockFd for file descriptor
409  * @params[in]  timeoutPtr indicates the timeout value
410  * @params[in]  MemInfo indicates memory region
411  *
412  * @return ROK     - success
413  *         RFAILED - failure
414  *
415  * ****************************************************************/
416
417  
418 uint8_t processPolling(sctpSockPollParams *pollParams, RicSctpAssocCb *assocCb, uint32_t *timeoutPtr, CmInetMemInfo *memInfo)
419 {
420    uint16_t ret = ROK;
421
422    CM_INET_FD_SET(&assocCb->sockFd, &pollParams->readFd);
423    ret = cmInetSelect(&pollParams->readFd, NULLP, timeoutPtr, &pollParams->numFd);
424    if(CM_INET_FD_ISSET(&assocCb->sockFd, &pollParams->readFd))
425    {
426       CM_INET_FD_CLR(&assocCb->sockFd, &pollParams->readFd);
427       ret = cmInetSctpRecvMsg(&assocCb->sockFd, &pollParams->addr, &pollParams->port, memInfo, &pollParams->mBuf, \
428           &pollParams->bufLen, &pollParams->info, &pollParams->flag, &pollParams->ntfy);
429       if(assocCb->connUp & (ret != ROK))
430       {
431          assocCb->bReadFdSet = RFAILED;
432       }
433       else
434       {
435          if(((pollParams->flag & CM_INET_SCTP_MSG_NOTIFICATION) != 0) && (ret == ROK))
436          {
437             ret = sctpNtfyHdlr(assocCb, &pollParams->ntfy);
438             if(ret != ROK)
439             {
440                DU_LOG("\nERROR  -->  SCTP : Failed to process sctp notify msg\n");
441             }
442          }
443          else if(assocCb->connUp)
444          {  
445             E2APMsgHdlr(&assocCb->duId, pollParams->mBuf);
446             ODU_PUT_MSG_BUF(pollParams->mBuf);
447          }
448          else
449          {
450             ODU_PUT_MSG_BUF(pollParams->mBuf);
451          }
452       } 
453   }
454   return ROK;
455 }/* End of sctpSockPoll() */
456
457 /*******************************************************************
458  *
459  * @brief Send message on SCTP socket
460  *
461  * @details
462  *
463  *    Function : sctpSend 
464  *
465  *    Functionality:
466  *        Send message on SCTP socket
467  *
468  * @params[in] 
469  * @return ROK     - success
470  *         RFAILED - failure
471  *
472  * ****************************************************************/
473 uint8_t sctpSend(uint32_t duId, Buffer *mBuf)
474 {
475    uint8_t          assocIdx;
476    uint8_t          ret;
477    MsgLen           len;          /* number of actually sent octets */
478    CmInetMemInfo    memInfo;                        
479    
480    memInfo.region = RIC_APP_MEM_REG;               
481    memInfo.pool   = RIC_POOL;
482
483    for(assocIdx = 0; assocIdx < sctpCb.numAssoc; assocIdx++)
484    {
485       if(sctpCb.assocCb[assocIdx].duId == duId)
486       {
487          ret = cmInetSctpSendMsg(&sctpCb.assocCb[assocIdx].sockFd, &sctpCb.assocCb[assocIdx].destIpNetAddr, \
488                sctpCb.assocCb[assocIdx].destPort, &memInfo, mBuf, &len, 0, FALSE, 0, 0/*SCT_PROTID_NONE*/, RWOULDBLOCK);
489
490          if(ret != ROK && ret != RWOULDBLOCK)
491          {
492             DU_LOG("\nERROR  -->  SCTP : Send message failed");
493             return RFAILED;
494          }
495       }
496    }
497    return ROK;
498 } /* End of sctpSend */
499 /**********************************************************************
500          End of file
501 **********************************************************************/