send/recv function is tested for only 1 eNB.

This commit is contained in:
Sukchan Lee 2017-10-19 13:42:07 +09:00
parent cca9f6d521
commit 36985520f9
3 changed files with 287 additions and 116 deletions

View File

@ -31,9 +31,9 @@ status_t s1ap_open(void)
struct socket *psock = NULL;
struct sockaddr_in local_addr;
const int on = 1;
struct sctp_event event;
c_uint16_t event_types[] = {
const int on = 1;
struct sctp_event event;
c_uint16_t event_types[] = {
SCTP_ASSOC_CHANGE,
SCTP_PEER_ADDR_CHANGE,
SCTP_REMOTE_ERROR,
@ -41,7 +41,7 @@ status_t s1ap_open(void)
SCTP_ADAPTATION_INDICATION,
SCTP_PARTIAL_DELIVERY_EVENT
};
int i;
int i;
usrsctp_init(LOCAL_UDP_PORT, NULL, debug_printf);
#ifdef SCTP_DEBUG
@ -60,26 +60,26 @@ status_t s1ap_open(void)
mme_self()->s1ap_sock = (net_sock_t *)psock;
if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_RECVRCVINFO,
if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_RECVRCVINFO,
&on, sizeof(int)) < 0)
{
d_error("usrsctp_setsockopt SCTP_RECVRCVINFO");
d_error("usrsctp_setsockopt SCTP_RECVRCVINFO");
return CORE_ERROR;
}
}
memset(&event, 0, sizeof(event));
event.se_assoc_id = SCTP_FUTURE_ASSOC;
event.se_on = 1;
for (i = 0; i < (int)(sizeof(event_types)/sizeof(c_uint16_t)); i++)
memset(&event, 0, sizeof(event));
event.se_assoc_id = SCTP_FUTURE_ASSOC;
event.se_on = 1;
for (i = 0; i < (int)(sizeof(event_types)/sizeof(c_uint16_t)); i++)
{
event.se_type = event_types[i];
if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_EVENT,
event.se_type = event_types[i];
if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_EVENT,
&event, sizeof(struct sctp_event)) < 0)
{
d_error("usrsctp_setsockopt SCTP_EVENT");
d_error("usrsctp_setsockopt SCTP_EVENT");
return CORE_ERROR;
}
}
}
}
memset((void *)&local_addr, 0, sizeof(struct sockaddr_in));
local_addr.sin_family = AF_INET;
@ -132,7 +132,7 @@ status_t s1ap_sendto(net_sock_t *s, pkbuf_t *pkbuf,
ssize_t sent;
struct socket *psock = (struct socket *)s;
struct sockaddr_in remote_addr;
struct sctp_sndinfo sndinfo;
struct sctp_sndinfo sndinfo;
d_assert(s, return CORE_ERROR, "Null param");
d_assert(pkbuf, return CORE_ERROR, "Null param");
@ -144,7 +144,7 @@ status_t s1ap_sendto(net_sock_t *s, pkbuf_t *pkbuf,
remote_addr.sin_addr.s_addr = addr;
memset((void *)&sndinfo, 0, sizeof(struct sctp_sndinfo));
sndinfo.snd_ppid = SCTP_S1AP_PPID;
sndinfo.snd_ppid = htonl(SCTP_S1AP_PPID);
sent = usrsctp_sendv(psock, pkbuf->payload, pkbuf->len,
(struct sockaddr *)&remote_addr, 1,
(void *)&sndinfo, (socklen_t)sizeof(struct sctp_sndinfo),
@ -164,89 +164,248 @@ status_t s1ap_sendto(net_sock_t *s, pkbuf_t *pkbuf,
return CORE_OK;
}
static void
handle_association_change_event(struct sctp_assoc_change *sac)
{
unsigned int i, n;
printf("Association change ");
switch (sac->sac_state) {
case SCTP_COMM_UP:
printf("SCTP_COMM_UP");
break;
case SCTP_COMM_LOST:
printf("SCTP_COMM_LOST");
break;
case SCTP_RESTART:
printf("SCTP_RESTART");
break;
case SCTP_SHUTDOWN_COMP:
printf("SCTP_SHUTDOWN_COMP");
break;
case SCTP_CANT_STR_ASSOC:
printf("SCTP_CANT_STR_ASSOC");
break;
default:
printf("UNKNOWN");
break;
}
printf(", streams (in/out) = (%u/%u)",
sac->sac_inbound_streams, sac->sac_outbound_streams);
n = sac->sac_length - sizeof(struct sctp_assoc_change);
if (((sac->sac_state == SCTP_COMM_UP) ||
(sac->sac_state == SCTP_RESTART)) && (n > 0)) {
printf(", supports");
for (i = 0; i < n; i++) {
switch (sac->sac_info[i]) {
case SCTP_ASSOC_SUPPORTS_PR:
printf(" PR");
break;
case SCTP_ASSOC_SUPPORTS_AUTH:
printf(" AUTH");
break;
case SCTP_ASSOC_SUPPORTS_ASCONF:
printf(" ASCONF");
break;
case SCTP_ASSOC_SUPPORTS_MULTIBUF:
printf(" MULTIBUF");
break;
case SCTP_ASSOC_SUPPORTS_RE_CONFIG:
printf(" RE-CONFIG");
break;
default:
printf(" UNKNOWN(0x%02x)", sac->sac_info[i]);
break;
}
}
} else if (((sac->sac_state == SCTP_COMM_LOST) ||
(sac->sac_state == SCTP_CANT_STR_ASSOC)) && (n > 0)) {
printf(", ABORT =");
for (i = 0; i < n; i++) {
printf(" 0x%02x", sac->sac_info[i]);
}
}
printf(".\n");
if ((sac->sac_state == SCTP_CANT_STR_ASSOC) ||
(sac->sac_state == SCTP_SHUTDOWN_COMP) ||
(sac->sac_state == SCTP_COMM_LOST)) {
exit(0);
}
return;
}
static void
handle_peer_address_change_event(struct sctp_paddr_change *spc)
{
char addr_buf[INET6_ADDRSTRLEN];
const char *addr;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
struct sockaddr_conn *sconn;
switch (spc->spc_aaddr.ss_family) {
case AF_INET:
sin = (struct sockaddr_in *)&spc->spc_aaddr;
addr = inet_ntop(AF_INET, &sin->sin_addr, addr_buf, INET_ADDRSTRLEN);
break;
case AF_INET6:
sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr;
addr = inet_ntop(AF_INET6, &sin6->sin6_addr, addr_buf, INET6_ADDRSTRLEN);
break;
case AF_CONN:
sconn = (struct sockaddr_conn *)&spc->spc_aaddr;
#ifdef _WIN32
_snprintf(addr_buf, INET6_ADDRSTRLEN, "%p", sconn->sconn_addr);
#else
snprintf(addr_buf, INET6_ADDRSTRLEN, "%p", sconn->sconn_addr);
#endif
addr = addr_buf;
break;
default:
#ifdef _WIN32
_snprintf(addr_buf, INET6_ADDRSTRLEN, "Unknown family %d", spc->spc_aaddr.ss_family);
#else
snprintf(addr_buf, INET6_ADDRSTRLEN, "Unknown family %d", spc->spc_aaddr.ss_family);
#endif
addr = addr_buf;
break;
}
printf("Peer address %s is now ", addr);
switch (spc->spc_state) {
case SCTP_ADDR_AVAILABLE:
printf("SCTP_ADDR_AVAILABLE");
break;
case SCTP_ADDR_UNREACHABLE:
printf("SCTP_ADDR_UNREACHABLE");
break;
case SCTP_ADDR_REMOVED:
printf("SCTP_ADDR_REMOVED");
break;
case SCTP_ADDR_ADDED:
printf("SCTP_ADDR_ADDED");
break;
case SCTP_ADDR_MADE_PRIM:
printf("SCTP_ADDR_MADE_PRIM");
break;
case SCTP_ADDR_CONFIRMED:
printf("SCTP_ADDR_CONFIRMED");
break;
default:
printf("UNKNOWN");
break;
}
printf(" (error = 0x%08x).\n", spc->spc_error);
return;
}
static void
handle_send_failed_event(struct sctp_send_failed_event *ssfe)
{
size_t i, n;
if (ssfe->ssfe_flags & SCTP_DATA_UNSENT) {
printf("Unsent ");
}
if (ssfe->ssfe_flags & SCTP_DATA_SENT) {
printf("Sent ");
}
if (ssfe->ssfe_flags & ~(SCTP_DATA_SENT | SCTP_DATA_UNSENT)) {
printf("(flags = %x) ", ssfe->ssfe_flags);
}
printf("message with PPID = %u, SID = %u, flags: 0x%04x due to error = 0x%08x",
ntohl(ssfe->ssfe_info.snd_ppid), ssfe->ssfe_info.snd_sid,
ssfe->ssfe_info.snd_flags, ssfe->ssfe_error);
n = ssfe->ssfe_length - sizeof(struct sctp_send_failed_event);
for (i = 0; i < n; i++) {
printf(" 0x%02x", ssfe->ssfe_data[i]);
}
printf(".\n");
return;
}
static void
handle_notification(union sctp_notification *notif, size_t n)
{
if (notif->sn_header.sn_length != (uint32_t)n) {
return;
}
switch (notif->sn_header.sn_type) {
case SCTP_ASSOC_CHANGE:
handle_association_change_event(&(notif->sn_assoc_change));
break;
case SCTP_PEER_ADDR_CHANGE:
handle_peer_address_change_event(&(notif->sn_paddr_change));
break;
case SCTP_REMOTE_ERROR:
break;
case SCTP_SHUTDOWN_EVENT:
break;
case SCTP_ADAPTATION_INDICATION:
break;
case SCTP_PARTIAL_DELIVERY_EVENT:
break;
case SCTP_AUTHENTICATION_EVENT:
break;
case SCTP_SENDER_DRY_EVENT:
break;
case SCTP_NOTIFICATIONS_STOPPED_EVENT:
break;
case SCTP_SEND_FAILED_EVENT:
handle_send_failed_event(&(notif->sn_send_failed_event));
break;
case SCTP_STREAM_RESET_EVENT:
break;
case SCTP_ASSOC_RESET_EVENT:
break;
case SCTP_STREAM_CHANGE_EVENT:
break;
default:
break;
}
}
static int s1ap_usrsctp_recv_cb(struct socket *sock,
union sctp_sockstore addr, void *data, size_t datalen,
struct sctp_rcvinfo rcv, int flags, void *ulp_info)
{
#if 0
event_t e;
pkbuf_t *pkbuf;
if (data) {
if (flags & MSG_NOTIFICATION) {
handle_notification((union sctp_notification *)data, datalen);
} else {
event_t e;
pkbuf_t *pkbuf;
c_uint32_t sin_addr = addr.sin.sin_addr.s_addr;
c_uint16_t sin_port = ntohs(addr.sin.sin_port);
c_uint32_t ppid = ntohl(rcv.rcv_ppid);
if (data == NULL)
{
return 1;
if (ppid == SCTP_S1AP_PPID)
{
/* FIXME : we need to find when eNB connects MME firstly */
mme_enb_t *enb = mme_enb_find_by_sock((net_sock_t *)sock);
if (!enb)
{
event_set(&e, MME_EVT_S1AP_LO_ACCEPT);
event_set_param1(&e, (c_uintptr_t)sock);
event_set_param2(&e, (c_uintptr_t)&sin_addr);
event_set_param3(&e, (c_uintptr_t)&sin_port);
mme_event_send(&e);
}
pkbuf = pkbuf_alloc(0, MAX_SDU_LEN);
d_assert(pkbuf, return 1, );
pkbuf->len = datalen;
memcpy(pkbuf->payload, data, pkbuf->len);
event_set(&e, MME_EVT_S1AP_MESSAGE);
event_set_param1(&e, (c_uintptr_t)sock);
event_set_param2(&e, (c_uintptr_t)pkbuf);
mme_event_send(&e);
}
}
free(data);
}
if (datalen == 0)
{
return 1;
}
pkbuf = pkbuf_alloc(0, MAX_SDU_LEN);
d_assert(pkbuf, return 1, );
pkbuf->len = datalen;
memcpy(pkbuf->payload, data, pkbuf->len);
d_print_hex(pkbuf->payload, pkbuf->len);
event_set(&e, MME_EVT_S1AP_MESSAGE);
event_set_param1(&e, (c_uintptr_t)sock);
event_set_param2(&e, (c_uintptr_t)pkbuf);
mme_event_send(&e);
free(data);
return 1;
#else
char namebuf[INET6_ADDRSTRLEN];
const char *name;
uint16_t port;
if (data) {
if (flags & MSG_NOTIFICATION) {
printf("Notification of length %d received.\n", (int)datalen);
} else {
switch (addr.sa.sa_family) {
#ifdef INET
case AF_INET:
name = inet_ntop(AF_INET, &addr.sin.sin_addr, namebuf, INET_ADDRSTRLEN);
port = ntohs(addr.sin.sin_port);
break;
#endif
#ifdef INET6
case AF_INET6:
name = inet_ntop(AF_INET6, &addr.sin6.sin6_addr, namebuf, INET6_ADDRSTRLEN),
port = ntohs(addr.sin6.sin6_port);
break;
#endif
case AF_CONN:
#ifdef _WIN32
_snprintf(namebuf, INET6_ADDRSTRLEN, "%p", addr.sconn.sconn_addr);
#else
snprintf(namebuf, INET6_ADDRSTRLEN, "%p", addr.sconn.sconn_addr);
#endif
name = namebuf;
port = ntohs(addr.sconn.sconn_port);
break;
default:
name = NULL;
port = 0;
break;
}
printf("Msg of length %d received from %s:%u on stream %u with SSN %u and TSN %u, PPID %u, context %u.\n",
(int)datalen,
name,
port,
rcv.rcv_sid,
rcv.rcv_ssn,
rcv.rcv_tsn,
ntohl(rcv.rcv_ppid),
rcv.rcv_context);
}
free(data);
}
return (1);
#endif
return (1);
}
static void debug_printf(const char *format, ...)

View File

@ -36,7 +36,6 @@ static void s1setup_test1(abts_case *tc, void *data)
rv = tests1ap_enb_send(sock[i], sendbuf);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
#if 0
rc = tests1ap_enb_read(sock[i], recvbuf);
ABTS_INT_NEQUAL(tc, 0, rc);
@ -44,11 +43,8 @@ static void s1setup_test1(abts_case *tc, void *data)
ABTS_INT_EQUAL(tc, CORE_OK, rv);
s1ap_free_pdu(&message);
#endif
}
core_sleep(time_from_msec(1000));
for (i = 0; i < NUM_OF_TEST_DUPLICATED_ENB; i++)
{
rv = tests1ap_enb_close(sock[i]);

View File

@ -88,24 +88,40 @@ int tests1ap_enb_read(net_sock_t *sock, pkbuf_t *recvbuf)
{
int rc = 0;
while(1)
{
rc = net_read(sock, recvbuf->payload, recvbuf->len, 0);
if (rc == -2)
{
continue;
}
else if (rc <= 0)
{
if (sock->sndrcv_errno == EAGAIN)
{
continue;
struct socket *psock = (struct socket *)sock;
struct sockaddr_in addr;
char name[INET6_ADDRSTRLEN];
ssize_t n;
int flags;
socklen_t from_len;
socklen_t infolen;
struct sctp_rcvinfo rcv_info;
unsigned int infotype;
n = usrsctp_recvv(psock, recvbuf->payload, MAX_SDU_LEN,
(struct sockaddr *)&addr, &from_len, (void *)&rcv_info,
&infolen, &infotype, &flags);
if (n > 0) {
if (flags & MSG_NOTIFICATION) {
printf("Notification of length %llu received.\n",
(unsigned long long)n);
} else {
if (infotype == SCTP_RECVV_RCVINFO) {
printf("Msg of length %llu received from %s:%u"
"on stream %u with SSN %u and TSN %u, PPID %u,"
"context %u, complete %d.\n",
(unsigned long long)n,
inet_ntop(AF_INET, &addr.sin_addr,
name, INET_ADDRSTRLEN), ntohs(addr.sin_port),
rcv_info.rcv_sid,
rcv_info.rcv_ssn,
rcv_info.rcv_tsn,
ntohl(rcv_info.rcv_ppid),
rcv_info.rcv_context,
(flags & MSG_EOR) ? 1 : 0);
} else {
rc = n;
}
break;
}
else
{
break;
}
}