Commit be4a2b5b authored by Cedric Roux's avatar Cedric Roux

- Updated eNB SCTP task to accept new associations in case of "server", for X2AP for example

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4405 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent 69d84a6d
......@@ -45,3 +45,22 @@ int sctp_itti_send_association_resp(task_id_t task_id, instance_t instance,
return itti_send_msg_to_task(task_id, instance, message_p);
}
int sctp_itti_send_association_ind(task_id_t task_id, instance_t instance,
int32_t assoc_id, uint16_t port,
uint16_t out_streams, uint16_t in_streams)
{
MessageDef *message_p;
sctp_new_association_ind_t *sctp_new_association_ind_p;
message_p = itti_alloc_new_message(TASK_SCTP, SCTP_NEW_ASSOCIATION_IND);
sctp_new_association_ind_p = &message_p->msg.sctp_new_association_ind;
sctp_new_association_ind_p->assoc_id = assoc_id;
sctp_new_association_ind_p->port = port;
sctp_new_association_ind_p->out_streams = out_streams;
sctp_new_association_ind_p->in_streams = in_streams;
return itti_send_msg_to_task(task_id, instance, message_p);
}
......@@ -9,4 +9,8 @@ int sctp_itti_send_association_resp(task_id_t task_id, instance_t instance,
uint16_t cnx_id, enum sctp_state_e state,
uint16_t out_streams, uint16_t in_streams);
int sctp_itti_send_association_ind(task_id_t task_id, instance_t instance,
int32_t assoc_id, uint16_t port,
uint16_t out_streams, uint16_t in_streams);
#endif /* SCTP_ITTI_MESSAGING_H_ */
......@@ -49,12 +49,25 @@
#include "sctp_common.h"
#include "sctp_eNB_itti_messaging.h"
enum sctp_connection_type_e {
SCTP_TYPE_CLIENT,
SCTP_TYPE_SERVER,
SCTP_TYPE_MAX
};
struct sctp_cnx_list_elm_s {
STAILQ_ENTRY(sctp_cnx_list_elm_s) entries;
/* Type of this association
*/
enum sctp_connection_type_e connection_type;
/* Socket descriptor of connection */
int sd;
/* local port used */
uint16_t local_port;
/* IN/OUT streams */
uint16_t in_streams;
uint16_t out_streams;
......@@ -113,6 +126,7 @@ void sctp_handle_new_association_req(
struct sctp_event_subscribe events;
struct sctp_cnx_list_elm_s *sctp_cnx = NULL;
enum sctp_connection_type_e connection_type = SCTP_TYPE_CLIENT;
/* Prepare a new SCTP association as requested by upper layer and try to connect
* to remote host.
......@@ -166,6 +180,8 @@ void sctp_handle_new_association_req(
* address and port.
* Only use IPv4 for the first connection attempt
*/
if ((sctp_new_association_req_p->remote_address.ipv6 != 0) ||
(sctp_new_association_req_p->remote_address.ipv4 != 0))
{
uint8_t address_index = 0;
uint8_t used_address = sctp_new_association_req_p->remote_address.ipv6 +
......@@ -228,10 +244,31 @@ void sctp_handle_new_association_req(
return;
}
}
} else {
/* No remote address provided -> only bind the socket for now.
* Connection will be accepted in the main event loop
*/
struct sockaddr_in6 addr6;
connection_type = SCTP_TYPE_SERVER;
/* For now bind to any interface */
addr6.sin6_family = AF_INET6;
addr6.sin6_addr = in6addr_any;
addr6.sin6_port = htons(sctp_new_association_req_p->port);
if (bind(sd, (struct sockaddr*)&addr6, sizeof(addr6)) < 0) {
SCTP_ERROR("Failed to bind the socket %d to address any (v4/v6): %s\n",
strerror(errno));
close(sd);
return;
}
}
sctp_cnx = calloc(1, sizeof(*sctp_cnx));
sctp_cnx->connection_type = connection_type;
sctp_cnx->sd = sd;
sctp_cnx->task_id = requestor;
sctp_cnx->cnx_id = sctp_new_association_req_p->ulp_cnx_id;
......@@ -283,6 +320,72 @@ void sctp_send_data(instance_t instance, task_id_t task_id, sctp_data_req_t *sct
sctp_cnx->assoc_id);
}
static
inline void sctp_eNB_accept_associations(struct sctp_cnx_list_elm_s *sctp_cnx)
{
int client_sd;
struct sockaddr saddr;
socklen_t saddr_size;
DevAssert(sctp_cnx != NULL);
saddr_size = sizeof(saddr);
/* There is a new client connecting. Accept it...
*/
if ((client_sd = accept(sctp_cnx->sd, &saddr, &saddr_size)) < 0) {
SCTP_ERROR("[%d] accept failed: %s:%d\n", sctp_cnx->sd, strerror(errno), errno);
} else {
struct sctp_cnx_list_elm_s *new_cnx;
uint16_t port;
/* This is an ipv6 socket */
port = ((struct sockaddr_in6*)&saddr)->sin6_port;
/* Contrary to BSD, client socket does not inherit O_NONBLOCK option */
if (fcntl(client_sd, F_SETFL, O_NONBLOCK) < 0) {
SCTP_ERROR("fcntl F_SETFL O_NONBLOCK failed: %s\n",
strerror(errno));
close(client_sd);
return;
}
new_cnx = calloc(1, sizeof(*sctp_cnx));
DevAssert(new_cnx != NULL);
new_cnx->connection_type = SCTP_TYPE_CLIENT;
new_cnx->sd = client_sd;
new_cnx->task_id = sctp_cnx->task_id;
new_cnx->cnx_id = 0;
new_cnx->ppid = sctp_cnx->ppid;
new_cnx->instance = sctp_cnx->instance;
new_cnx->local_port = sctp_cnx->local_port;
if (sctp_get_sockinfo(client_sd, &new_cnx->in_streams, &new_cnx->out_streams,
&new_cnx->assoc_id) != 0)
{
SCTP_ERROR("sctp_get_sockinfo failed\n");
close(client_sd);
free(new_cnx);
return;
}
/* Insert new element at end of list */
STAILQ_INSERT_TAIL(&sctp_cnx_list, new_cnx, entries);
sctp_nb_cnx++;
/* Add the socket to list of fd monitored by ITTI */
itti_subscribe_event_fd(TASK_SCTP, client_sd);
sctp_itti_send_association_ind(new_cnx->task_id, new_cnx->instance,
new_cnx->assoc_id, port,
new_cnx->out_streams, new_cnx->in_streams);
}
}
static
inline void sctp_eNB_read_from_socket(struct sctp_cnx_list_elm_s *sctp_cnx)
{
......@@ -387,7 +490,11 @@ void sctp_eNB_flush_sockets(struct epoll_event *events, int nb_events)
continue;
}
SCTP_DEBUG("Found data for descriptor %d\n", events[i].data.fd);
sctp_eNB_read_from_socket(sctp_cnx);
if (sctp_cnx->connection_type == SCTP_TYPE_CLIENT) {
sctp_eNB_read_from_socket(sctp_cnx);
} else {
sctp_eNB_accept_associations(sctp_cnx);
}
}
}
......
MESSAGE_DEF(SCTP_NEW_ASSOCIATION_REQ , MESSAGE_PRIORITY_MED, sctp_new_association_req_t , sctp_new_association_req)
MESSAGE_DEF(SCTP_NEW_ASSOCIATION_RESP, MESSAGE_PRIORITY_MED, sctp_new_association_resp_t , sctp_new_association_resp)
MESSAGE_DEF(SCTP_NEW_ASSOCIATION_IND , MESSAGE_PRIORITY_MED, sctp_new_association_ind_t , sctp_new_association_ind)
MESSAGE_DEF(SCTP_REGISTER_UPPER_LAYER, MESSAGE_PRIORITY_MED, sctp_listener_register_upper_layer_t, sctp_listener_register_upper_layer)
MESSAGE_DEF(SCTP_DATA_REQ, MESSAGE_PRIORITY_MED, sctp_data_req_t , sctp_data_req)
MESSAGE_DEF(SCTP_DATA_IND, MESSAGE_PRIORITY_MED, sctp_data_ind_t , sctp_data_ind)
\ No newline at end of file
......@@ -23,6 +23,18 @@ typedef struct {
net_ip_address_t remote_address;
} sctp_new_association_req_t;
typedef struct {
/* Assoc id of the new association */
int32_t assoc_id;
/* The port used by remote host */
uint16_t port;
/* Number of streams used for this association */
uint16_t in_streams;
uint16_t out_streams;
} sctp_new_association_ind_t;
typedef struct {
/* Upper layer connexion identifier */
uint16_t ulp_cnx_id;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment