Configure Outbound streams on SCTP_COMM_UP

This commit is contained in:
Sukchan Lee 2018-05-30 21:49:17 +09:00
parent 9aed43075c
commit 3b9b1108b1
5 changed files with 166 additions and 169 deletions

View File

@ -213,10 +213,6 @@ CORE_DECLARE(int) core_sctp_recvmsg(sock_id id, void *msg, size_t len,
c_sockaddr_t *from, sctp_info_t *sinfo, int *msg_flags);
CORE_DECLARE(int) core_sctp_recvdata(sock_id id, void *msg, size_t len,
c_sockaddr_t *from, sctp_info_t *sinfo);
#define CORE_SCTP_EAGAIN -2
#define CORE_SCTP_REMOTE_CLOSED -3
CORE_DECLARE(int) core_sctp_recvmsg2(sock_id id, void *msg, size_t len,
c_sockaddr_t *from, sctp_info_t *sinfo);
/*
* TUN Driver
*/

View File

@ -271,106 +271,6 @@ int core_sctp_recvdata(sock_id id, void *msg, size_t len,
return size;
}
int core_sctp_recvmsg2(sock_id id, void *msg, size_t len,
c_sockaddr_t *from, sctp_info_t *sinfo)
{
sock_t *sock = (sock_t *)id;
int size;
socklen_t addrlen = sizeof(struct sockaddr_storage);
int flags = 0;
struct sctp_sndrcvinfo sndrcvinfo;
d_assert(id, return -1,);
do
{
size = sctp_recvmsg(sock->fd, msg, len,
from ? &from->sa : NULL, from ? &addrlen : NULL,
&sndrcvinfo, &flags);
if (size < 0)
{
if (errno != EAGAIN)
{
d_error("sctp_recvmsg(%d) failed(%d:%s)",
size, errno, strerror(errno));
}
return size;
}
if (flags & MSG_NOTIFICATION)
{
union sctp_notification *not = (union sctp_notification *)msg;
switch(not->sn_header.sn_type)
{
case SCTP_ASSOC_CHANGE :
d_trace(3, "SCTP_ASSOC_CHANGE"
"(type:0x%x, flags:0x%x, state:0x%x)\n",
not->sn_assoc_change.sac_type,
not->sn_assoc_change.sac_flags,
not->sn_assoc_change.sac_state);
if (not->sn_assoc_change.sac_state ==
SCTP_SHUTDOWN_COMP ||
not->sn_assoc_change.sac_state ==
SCTP_COMM_LOST)
{
return CORE_SCTP_REMOTE_CLOSED;
}
if (not->sn_assoc_change.sac_state == SCTP_COMM_UP)
{
d_trace(3, "SCTP_COMM_UP : inboud:%d, outbound = %d\n",
not->sn_assoc_change.sac_inbound_streams,
not->sn_assoc_change.sac_outbound_streams);
}
if (sinfo)
{
sinfo->inbound_streams =
not->sn_assoc_change.sac_inbound_streams;
sinfo->outbound_streams =
not->sn_assoc_change.sac_outbound_streams;
}
break;
case SCTP_SEND_FAILED :
d_error("SCTP_SEND_FAILED"
"(type:0x%x, flags:0x%x, error:0x%x)\n",
not->sn_send_failed.ssf_type,
not->sn_send_failed.ssf_flags,
not->sn_send_failed.ssf_error);
break;
case SCTP_SHUTDOWN_EVENT :
d_trace(3, "SCTP_SHUTDOWN_EVENT\n");
return CORE_SCTP_REMOTE_CLOSED;
default :
d_error("Discarding event with unknown "
"flags = 0x%x, type 0x%x",
flags, not->sn_header.sn_type);
break;
}
}
else if (flags & MSG_EOR)
{
break;
}
else
{
return CORE_SCTP_EAGAIN;
}
} while(1);
if (sinfo)
{
sinfo->ppid = ntohl(sndrcvinfo.sinfo_ppid);
sinfo->stream_no = sndrcvinfo.sinfo_stream;
}
return size;
}
static status_t subscribe_to_events(sock_id id)
{
sock_t *sock = (sock_t *)id;

View File

@ -95,9 +95,6 @@ void mme_state_operational(fsm_t *s, event_t *e)
enb = mme_enb_find_by_addr(addr);
if (!enb)
{
mme_enb_t *enb = NULL;
c_uint16_t outbound_streams = 0;
#if USE_USRSCTP != 1
status_t rv;
@ -107,11 +104,6 @@ void mme_state_operational(fsm_t *s, event_t *e)
enb = mme_enb_add(sock, addr);
d_assert(enb, break, "Null param");
outbound_streams = (c_uint16_t)event_get_param3(e);
if (outbound_streams)
enb->outbound_streams =
c_min(outbound_streams, enb->outbound_streams);
}
else
{
@ -123,6 +115,39 @@ void mme_state_operational(fsm_t *s, event_t *e)
break;
}
case MME_EVT_S1AP_LO_SCTP_COMM_UP:
{
mme_enb_t *enb = NULL;
sock_id sock = 0;
c_sockaddr_t *addr = NULL;
c_uint16_t outbound_streams = 0;
sock = (sock_id)event_get_param1(e);
d_assert(sock, break, "Null param");
addr = (c_sockaddr_t *)event_get_param2(e);
d_assert(addr, break, "Null param");
outbound_streams = (c_uint16_t)event_get_param4(e);
d_trace(3, "eNB-S1 SCTP_COMM_UP[%s] Outbound Streams[%d]\n",
CORE_ADDR(addr, buf), outbound_streams);
enb = mme_enb_find_by_addr(addr);
if (!enb)
{
enb = mme_enb_add(sock, addr);
d_assert(enb, break, "Null param");
}
else
{
CORE_FREE(addr);
}
enb->outbound_streams =
c_min(outbound_streams, enb->outbound_streams);
break;
}
case MME_EVT_S1AP_LO_CONNREFUSED:
{
mme_enb_t *enb = NULL;
@ -139,8 +164,7 @@ void mme_state_operational(fsm_t *s, event_t *e)
if (enb)
{
d_trace(1, "eNB-S1[%x] connection refused!!!\n",
enb->enb_id);
d_trace(1, "eNB-S1[%x] connection refused!!!\n", enb->enb_id);
mme_enb_remove(enb);
}
else
@ -157,7 +181,6 @@ void mme_state_operational(fsm_t *s, event_t *e)
sock_id sock = 0;
c_sockaddr_t *addr = NULL;
pkbuf_t *pkbuf = NULL;
c_uint16_t outbound_streams = 0;
sock = (sock_id)event_get_param1(e);
d_assert(sock, break, "Null param");
@ -168,7 +191,6 @@ void mme_state_operational(fsm_t *s, event_t *e)
pkbuf = (pkbuf_t *)event_get_param3(e);
d_assert(pkbuf, break, "Null param");
outbound_streams = (c_uint16_t)event_get_param4(e);
enb = mme_enb_find_by_addr(addr);
CORE_FREE(addr);
@ -176,10 +198,6 @@ void mme_state_operational(fsm_t *s, event_t *e)
d_assert(FSM_STATE(&enb->sm), pkbuf_free(pkbuf); break,
"No S1AP State Machine");
if (outbound_streams)
enb->outbound_streams =
c_min(outbound_streams, enb->outbound_streams);
rv = s1ap_decode_pdu(&message, pkbuf);
if (rv != CORE_OK)
{

View File

@ -3,6 +3,10 @@
#include "core_debug.h"
#include "core_thread.h"
#if HAVE_NETINET_SCTP_H
#include <netinet/sctp.h>
#endif
#include "mme_event.h"
#include "s1ap_path.h"
@ -124,12 +128,12 @@ static int s1ap_accept_handler(sock_id id, void *data)
int s1ap_recv_handler(sock_id sock, void *data)
{
status_t rv;
pkbuf_t *pkbuf;
int size;
event_t e;
c_sockaddr_t *addr = NULL;
sctp_info_t sinfo;
int flags = 0;
d_assert(sock, return -1, "Null param");
@ -146,63 +150,141 @@ int s1ap_recv_handler(sock_id sock, void *data)
return -1;
}
size = core_sctp_recvmsg2(sock, pkbuf->payload, pkbuf->len, NULL, &sinfo);
if (size <= 0)
size = core_sctp_recvmsg(
sock, pkbuf->payload, pkbuf->len, NULL, &sinfo, &flags);
if (size < 0)
{
pkbuf_free(pkbuf);
d_error("core_sctp_recvmsg(%d) failed(%d:%s)",
size, errno, strerror(errno));
return size;
}
if (size == CORE_SCTP_EAGAIN)
if (flags & MSG_NOTIFICATION)
{
union sctp_notification *not =
(union sctp_notification *)pkbuf->payload;
switch(not->sn_header.sn_type)
{
return 0;
case SCTP_ASSOC_CHANGE :
d_trace(3, "SCTP_ASSOC_CHANGE"
"(type:0x%x, flags:0x%x, state:0x%x)\n",
not->sn_assoc_change.sac_type,
not->sn_assoc_change.sac_flags,
not->sn_assoc_change.sac_state);
if (not->sn_assoc_change.sac_state == SCTP_COMM_UP)
{
d_trace(3, "SCTP_COMM_UP : inbound:%d, outbound = %d\n",
not->sn_assoc_change.sac_inbound_streams,
not->sn_assoc_change.sac_outbound_streams);
addr = core_calloc(1, sizeof(c_sockaddr_t));
d_assert(addr, pkbuf_free(pkbuf); return 0,);
memcpy(addr, sock_remote_addr(sock), sizeof(c_sockaddr_t));
event_set(&e, MME_EVT_S1AP_LO_SCTP_COMM_UP);
event_set_param1(&e, (c_uintptr_t)sock);
event_set_param2(&e, (c_uintptr_t)addr);
event_set_param3(&e,
(c_uintptr_t)not->sn_assoc_change.sac_inbound_streams);
event_set_param4(&e,
(c_uintptr_t)not->sn_assoc_change.sac_outbound_streams);
if (mme_event_send(&e) != CORE_OK)
{
d_error("Event MME_EVT_S1AP_LO_CONNREFUSED failed");
CORE_FREE(addr);
}
pkbuf_free(pkbuf);
return 0;
}
if (not->sn_assoc_change.sac_state == SCTP_SHUTDOWN_COMP)
d_trace(3, "SCTP_SHUTDOWN_COMP\n");
if (not->sn_assoc_change.sac_state == SCTP_COMM_LOST)
d_trace(3, "SCTP_COMM_LOST\n");
if (not->sn_assoc_change.sac_state == SCTP_SHUTDOWN_COMP ||
not->sn_assoc_change.sac_state == SCTP_COMM_LOST)
{
addr = core_calloc(1, sizeof(c_sockaddr_t));
d_assert(addr, pkbuf_free(pkbuf); return 0,);
memcpy(addr, sock_remote_addr(sock), sizeof(c_sockaddr_t));
event_set(&e, MME_EVT_S1AP_LO_CONNREFUSED);
event_set_param1(&e, (c_uintptr_t)sock);
event_set_param2(&e, (c_uintptr_t)addr);
if (mme_event_send(&e) != CORE_OK)
{
d_error("Event MME_EVT_S1AP_LO_CONNREFUSED failed");
CORE_FREE(addr);
}
sock_delete(sock);
pkbuf_free(pkbuf);
return 0;
}
break;
case SCTP_SEND_FAILED :
d_error("SCTP_SEND_FAILED"
"(type:0x%x, flags:0x%x, error:0x%x)\n",
not->sn_send_failed.ssf_type,
not->sn_send_failed.ssf_flags,
not->sn_send_failed.ssf_error);
break;
case SCTP_SHUTDOWN_EVENT :
d_trace(3, "SCTP_SHUTDOWN_EVENT\n");
addr = core_calloc(1, sizeof(c_sockaddr_t));
d_assert(addr, pkbuf_free(pkbuf); return 0,);
memcpy(addr, sock_remote_addr(sock), sizeof(c_sockaddr_t));
event_set(&e, MME_EVT_S1AP_LO_CONNREFUSED);
event_set_param1(&e, (c_uintptr_t)sock);
event_set_param2(&e, (c_uintptr_t)addr);
if (mme_event_send(&e) != CORE_OK)
{
d_error("Event MME_EVT_S1AP_LO_CONNREFUSED failed");
CORE_FREE(addr);
}
sock_delete(sock);
pkbuf_free(pkbuf);
return 0;
default :
d_error("Discarding event with unknown flags:0x%x type:0x%x",
flags, not->sn_header.sn_type);
break;
}
if (size == CORE_SCTP_REMOTE_CLOSED)
}
else if (flags & MSG_EOR)
{
addr = core_calloc(1, sizeof(c_sockaddr_t));
d_assert(addr, pkbuf_free(pkbuf); return 0,);
memcpy(addr, sock_remote_addr(sock), sizeof(c_sockaddr_t));
event_set(&e, MME_EVT_S1AP_MESSAGE);
event_set_param1(&e, (c_uintptr_t)sock);
event_set_param2(&e, (c_uintptr_t)addr);
event_set_param3(&e, (c_uintptr_t)pkbuf);
if (mme_event_send(&e) != CORE_OK)
{
addr = core_calloc(1, sizeof(c_sockaddr_t));
d_assert(addr, return -1,);
memcpy(addr, sock_remote_addr(sock), sizeof(c_sockaddr_t));
event_set(&e, MME_EVT_S1AP_LO_CONNREFUSED);
event_set_param1(&e, (c_uintptr_t)sock);
event_set_param2(&e, (c_uintptr_t)addr);
sock_delete(sock);
if (mme_event_send(&e) != CORE_OK)
{
d_error("Event MME_EVT_S1AP_LO_CONNREFUSED failed");
CORE_FREE(addr);
}
return 0;
}
if (errno != EAGAIN)
{
d_error("core_sctp_recvmsg(%d) failed(%d:%s)",
size, errno, strerror(errno));
pkbuf_free(pkbuf);
CORE_FREE(addr);
}
return 0;
}
pkbuf->len = size;
d_trace(50, "[S1AP] RECV : ");
d_trace_hex(50, pkbuf->payload, pkbuf->len);
addr = core_calloc(1, sizeof(c_sockaddr_t));
d_assert(addr, return -1,);
memcpy(addr, sock_remote_addr(sock), sizeof(c_sockaddr_t));
event_set(&e, MME_EVT_S1AP_MESSAGE);
event_set_param1(&e, (c_uintptr_t)sock);
event_set_param2(&e, (c_uintptr_t)addr);
event_set_param3(&e, (c_uintptr_t)pkbuf);
event_set_param4(&e, (c_uintptr_t)sinfo.outbound_streams);
rv = mme_event_send(&e);
if (rv != CORE_OK)
else
{
pkbuf_free(pkbuf);
CORE_FREE(addr);
d_assert(0, pkbuf_free(pkbuf); return 0, "Unknown flags : 0x%x", flags);
}
pkbuf_free(pkbuf);
return 0;
}

View File

@ -440,6 +440,8 @@ static int s1ap_usrsctp_recv_handler(struct socket *sock,
event_set_param1(&e, (c_uintptr_t)sock);
event_set_param2(&e, (c_uintptr_t)addr);
event_set_param3(&e, (c_uintptr_t)
not->sn_assoc_change.sac_inbound_streams);
event_set_param4(&e, (c_uintptr_t)
not->sn_assoc_change.sac_outbound_streams);
if (mme_event_send(&e) != CORE_OK)
{
@ -510,7 +512,6 @@ static int s1ap_usrsctp_recv_handler(struct socket *sock,
event_set_param1(&e, (c_uintptr_t)sock);
event_set_param2(&e, (c_uintptr_t)addr);
event_set_param3(&e, (c_uintptr_t)pkbuf);
event_set_param4(&e, (c_uintptr_t)0);
if (mme_event_send(&e) != CORE_OK)
{
pkbuf_free(pkbuf);