- 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
This commit is contained in:
@@ -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);
|
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 cnx_id, enum sctp_state_e state,
|
||||||
uint16_t out_streams, uint16_t in_streams);
|
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_ */
|
#endif /* SCTP_ITTI_MESSAGING_H_ */
|
||||||
|
|||||||
@@ -49,12 +49,25 @@
|
|||||||
#include "sctp_common.h"
|
#include "sctp_common.h"
|
||||||
#include "sctp_eNB_itti_messaging.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 {
|
struct sctp_cnx_list_elm_s {
|
||||||
STAILQ_ENTRY(sctp_cnx_list_elm_s) entries;
|
STAILQ_ENTRY(sctp_cnx_list_elm_s) entries;
|
||||||
|
|
||||||
|
/* Type of this association
|
||||||
|
*/
|
||||||
|
enum sctp_connection_type_e connection_type;
|
||||||
|
|
||||||
/* Socket descriptor of connection */
|
/* Socket descriptor of connection */
|
||||||
int sd;
|
int sd;
|
||||||
|
|
||||||
|
/* local port used */
|
||||||
|
uint16_t local_port;
|
||||||
|
|
||||||
/* IN/OUT streams */
|
/* IN/OUT streams */
|
||||||
uint16_t in_streams;
|
uint16_t in_streams;
|
||||||
uint16_t out_streams;
|
uint16_t out_streams;
|
||||||
@@ -113,6 +126,7 @@ void sctp_handle_new_association_req(
|
|||||||
struct sctp_event_subscribe events;
|
struct sctp_event_subscribe events;
|
||||||
|
|
||||||
struct sctp_cnx_list_elm_s *sctp_cnx = NULL;
|
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
|
/* Prepare a new SCTP association as requested by upper layer and try to connect
|
||||||
* to remote host.
|
* to remote host.
|
||||||
@@ -166,6 +180,8 @@ void sctp_handle_new_association_req(
|
|||||||
* address and port.
|
* address and port.
|
||||||
* Only use IPv4 for the first connection attempt
|
* 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 address_index = 0;
|
||||||
uint8_t used_address = sctp_new_association_req_p->remote_address.ipv6 +
|
uint8_t used_address = sctp_new_association_req_p->remote_address.ipv6 +
|
||||||
@@ -228,10 +244,31 @@ void sctp_handle_new_association_req(
|
|||||||
return;
|
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 = calloc(1, sizeof(*sctp_cnx));
|
||||||
|
|
||||||
|
sctp_cnx->connection_type = connection_type;
|
||||||
|
|
||||||
sctp_cnx->sd = sd;
|
sctp_cnx->sd = sd;
|
||||||
sctp_cnx->task_id = requestor;
|
sctp_cnx->task_id = requestor;
|
||||||
sctp_cnx->cnx_id = sctp_new_association_req_p->ulp_cnx_id;
|
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);
|
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
|
static
|
||||||
inline void sctp_eNB_read_from_socket(struct sctp_cnx_list_elm_s *sctp_cnx)
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
SCTP_DEBUG("Found data for descriptor %d\n", events[i].data.fd);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
MESSAGE_DEF(SCTP_NEW_ASSOCIATION_REQ , MESSAGE_PRIORITY_MED, sctp_new_association_req_t , sctp_new_association_req)
|
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_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_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_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)
|
MESSAGE_DEF(SCTP_DATA_IND, MESSAGE_PRIORITY_MED, sctp_data_ind_t , sctp_data_ind)
|
||||||
@@ -23,6 +23,18 @@ typedef struct {
|
|||||||
net_ip_address_t remote_address;
|
net_ip_address_t remote_address;
|
||||||
} sctp_new_association_req_t;
|
} 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 {
|
typedef struct {
|
||||||
/* Upper layer connexion identifier */
|
/* Upper layer connexion identifier */
|
||||||
uint16_t ulp_cnx_id;
|
uint16_t ulp_cnx_id;
|
||||||
|
|||||||
Reference in New Issue
Block a user