SCTP: API to add a sub-connection
This patch adds an API to add a sub-connection following a SRC/DST IP mapping as required by the RFC4960. At the same time, it changes the way the next available sub-connection is being calculated: rather than having an index in the parent connection which is prone to many issues at run-time, the next available sub-connection is being calculated by looking at the state of the set sub-connections and if marked as DOWN it means that is an available slot to be used. Change-Id: I662be6a247bfbbe8bf9aaf3f485183c07ef862fe Signed-off-by: Marco Varlese <marco.varlese@suse.com>
This commit is contained in:

committed by
Damjan Marion

parent
afddd83ca1
commit
3c6a976325
@ -542,6 +542,7 @@ API_FILES += vnet/udp/udp.api
|
||||
# Layer 4 protocol: sctp
|
||||
########################################
|
||||
libvnet_la_SOURCES += \
|
||||
vnet/sctp/sctp_api.c \
|
||||
vnet/sctp/sctp.c \
|
||||
vnet/sctp/sctp_pg.c \
|
||||
vnet/sctp/sctp_input.c \
|
||||
@ -552,7 +553,10 @@ nobase_include_HEADERS += \
|
||||
vnet/sctp/sctp_error.def \
|
||||
vnet/sctp/sctp_packet.h \
|
||||
vnet/sctp/sctp_timer.h \
|
||||
vnet/sctp/sctp.h
|
||||
vnet/sctp/sctp.h \
|
||||
vnet/sctp/sctp.api.h
|
||||
|
||||
API_FILES += vnet/sctp/sctp.api
|
||||
|
||||
########################################
|
||||
# Tunnel protocol: gre
|
||||
|
36
src/vnet/sctp/sctp.api
Normal file
36
src/vnet/sctp/sctp.api
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2018 SUSE LLC.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
option version = "1.0.0";
|
||||
|
||||
/** \brief Configure SCTP source addresses, for active-open SCTP sessions
|
||||
|
||||
SCTP src/dst ports are 16 bits
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param is_ipv6 - 1 for ipv6, 0 for ipv4
|
||||
@param vrf_id - fib table / vrf id for local adjacencies
|
||||
@param src_address - src address that SCTP will use for this sub-conn
|
||||
@param dst_address - dst address that SCTP will use for this sub-conn
|
||||
*/
|
||||
autoreply define sctp_add_src_dst_connection {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u8 is_ipv6;
|
||||
u32 vrf_id;
|
||||
u8 src_address[16];
|
||||
u8 dst_address[16];
|
||||
};
|
||||
|
@ -270,42 +270,62 @@ sctp_sub_connection_add (u8 thread_index)
|
||||
sctp_main_t *tm = vnet_get_sctp_main ();
|
||||
sctp_connection_t *sctp_conn = tm->connections[thread_index];
|
||||
|
||||
sctp_conn->sub_conn[sctp_conn->next_avail_sub_conn].connection.c_index =
|
||||
sctp_conn->sub_conn[MAIN_SCTP_SUB_CONN_IDX].connection.c_index;
|
||||
sctp_conn->sub_conn[sctp_conn->next_avail_sub_conn].
|
||||
connection.thread_index = thread_index;
|
||||
sctp_conn->sub_conn[sctp_conn->next_avail_sub_conn].subconn_idx =
|
||||
sctp_conn->next_avail_sub_conn;
|
||||
u8 subconn_idx = sctp_next_avail_subconn (sctp_conn);
|
||||
|
||||
sctp_conn->next_avail_sub_conn += 1;
|
||||
ASSERT (subconn_idx < MAX_SCTP_CONNECTIONS);
|
||||
|
||||
sctp_conn->sub_conn[subconn_idx].connection.c_index =
|
||||
sctp_conn->sub_conn[MAIN_SCTP_SUB_CONN_IDX].connection.c_index;
|
||||
sctp_conn->sub_conn[subconn_idx].connection.thread_index = thread_index;
|
||||
sctp_conn->sub_conn[subconn_idx].subconn_idx = subconn_idx;
|
||||
|
||||
return sctp_conn;
|
||||
}
|
||||
|
||||
void
|
||||
sctp_sub_connection_add_ip4 (u8 thread_index,
|
||||
sctp_ipv4_addr_param_t * ipv4_addr)
|
||||
u8
|
||||
sctp_sub_connection_add_ip4 (vlib_main_t * vm,
|
||||
ip4_address_t * lcl_addr,
|
||||
ip4_address_t * rmt_addr)
|
||||
{
|
||||
sctp_connection_t *sctp_conn = sctp_sub_connection_add (thread_index);
|
||||
sctp_connection_t *sctp_conn = sctp_sub_connection_add (vm->thread_index);
|
||||
|
||||
clib_memcpy (&sctp_conn->
|
||||
sub_conn[sctp_conn->next_avail_sub_conn].connection.lcl_ip.ip4,
|
||||
&ipv4_addr->address, sizeof (ipv4_addr->address));
|
||||
u8 subconn_idx = sctp_next_avail_subconn (sctp_conn);
|
||||
|
||||
if (subconn_idx == MAX_SCTP_CONNECTIONS)
|
||||
return SCTP_ERROR_MAX_CONNECTIONS;
|
||||
|
||||
clib_memcpy (&sctp_conn->sub_conn[subconn_idx].connection.lcl_ip,
|
||||
&lcl_addr, sizeof (lcl_addr));
|
||||
|
||||
clib_memcpy (&sctp_conn->sub_conn[subconn_idx].connection.rmt_ip,
|
||||
&rmt_addr, sizeof (rmt_addr));
|
||||
|
||||
sctp_conn->forming_association_changed = 1;
|
||||
|
||||
return SCTP_ERROR_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
sctp_sub_connection_add_ip6 (u8 thread_index,
|
||||
sctp_ipv6_addr_param_t * ipv6_addr)
|
||||
u8
|
||||
sctp_sub_connection_add_ip6 (vlib_main_t * vm,
|
||||
ip6_address_t * lcl_addr,
|
||||
ip6_address_t * rmt_addr)
|
||||
{
|
||||
sctp_connection_t *sctp_conn = sctp_sub_connection_add (thread_index);
|
||||
sctp_connection_t *sctp_conn = sctp_sub_connection_add (vm->thread_index);
|
||||
|
||||
clib_memcpy (&sctp_conn->
|
||||
sub_conn[sctp_conn->next_avail_sub_conn].connection.lcl_ip.ip6,
|
||||
&ipv6_addr->address, sizeof (ipv6_addr->address));
|
||||
u8 subconn_idx = sctp_next_avail_subconn (sctp_conn);
|
||||
|
||||
if (subconn_idx == MAX_SCTP_CONNECTIONS)
|
||||
return SCTP_ERROR_MAX_CONNECTIONS;
|
||||
|
||||
clib_memcpy (&sctp_conn->sub_conn[subconn_idx].connection.lcl_ip,
|
||||
&lcl_addr, sizeof (lcl_addr));
|
||||
|
||||
clib_memcpy (&sctp_conn->sub_conn[subconn_idx].connection.rmt_ip,
|
||||
&rmt_addr, sizeof (rmt_addr));
|
||||
|
||||
sctp_conn->forming_association_changed = 1;
|
||||
|
||||
return SCTP_ERROR_NONE;
|
||||
}
|
||||
|
||||
sctp_connection_t *
|
||||
@ -322,7 +342,6 @@ sctp_connection_new (u8 thread_index)
|
||||
sctp_conn - sctp_main->connections[thread_index];
|
||||
sctp_conn->sub_conn[MAIN_SCTP_SUB_CONN_IDX].c_thread_index = thread_index;
|
||||
sctp_conn->local_tag = 0;
|
||||
sctp_conn->next_avail_sub_conn = 1;
|
||||
|
||||
return sctp_conn;
|
||||
}
|
||||
@ -842,6 +861,8 @@ sctp_init (vlib_main_t * vm)
|
||||
transport_register_protocol (TRANSPORT_PROTO_SCTP, &sctp_proto,
|
||||
FIB_PROTOCOL_IP6, sctp6_output_node.index);
|
||||
|
||||
sctp_api_reference ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -235,8 +235,6 @@ typedef struct _sctp_connection
|
||||
|
||||
sctp_options_t snd_opts;
|
||||
|
||||
u8 next_avail_sub_conn; /**< Represent the index of the next free slot in sub_conn */
|
||||
|
||||
u8 forming_association_changed; /**< This is a flag indicating whether the original association has been modified during
|
||||
the life-span of the association itself. For instance, a new sub-connection might have been added. */
|
||||
|
||||
@ -245,10 +243,17 @@ typedef struct _sctp_connection
|
||||
typedef void (sctp_timer_expiration_handler) (u32 conn_index, u32 timer_id);
|
||||
|
||||
sctp_connection_t *sctp_connection_new (u8 thread_index);
|
||||
void sctp_sub_connection_add_ip4 (u8 thread_index,
|
||||
sctp_ipv4_addr_param_t * ipv4_addr);
|
||||
void sctp_sub_connection_add_ip6 (u8 thread_index,
|
||||
sctp_ipv6_addr_param_t * ipv6_addr);
|
||||
|
||||
u8
|
||||
sctp_sub_connection_add_ip4 (vlib_main_t * vm,
|
||||
ip4_address_t * lcl_addr,
|
||||
ip4_address_t * rmt_addr);
|
||||
|
||||
u8
|
||||
sctp_sub_connection_add_ip6 (vlib_main_t * vm,
|
||||
ip6_address_t * lcl_addr,
|
||||
ip6_address_t * rmt_addr);
|
||||
|
||||
void sctp_connection_close (sctp_connection_t * sctp_conn);
|
||||
void sctp_connection_cleanup (sctp_connection_t * sctp_conn);
|
||||
void sctp_connection_del (sctp_connection_t * sctp_conn);
|
||||
@ -307,6 +312,8 @@ void sctp_prepare_heartbeat_ack_chunk (sctp_connection_t * sctp_conn, u8 idx,
|
||||
|
||||
u16 sctp_check_outstanding_data_chunks (sctp_connection_t * sctp_conn);
|
||||
|
||||
void sctp_api_reference (void);
|
||||
|
||||
#define IP_PROTOCOL_SCTP 132
|
||||
|
||||
/** SSCTP FSM state definitions as per RFC4960. */
|
||||
@ -830,6 +837,19 @@ vlib_buffer_push_sctp (vlib_buffer_t * b, u16 sp_net, u16 dp_net,
|
||||
sctp_hdr_opts_len);
|
||||
}
|
||||
|
||||
always_inline u8
|
||||
sctp_next_avail_subconn (sctp_connection_t * sctp_conn)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
|
||||
{
|
||||
if (sctp_conn->sub_conn[i].state == SCTP_SUBCONN_STATE_DOWN)
|
||||
return i;
|
||||
}
|
||||
return MAX_SCTP_CONNECTIONS;
|
||||
}
|
||||
|
||||
always_inline void
|
||||
update_smallest_pmtu_idx (sctp_connection_t * sctp_conn)
|
||||
{
|
||||
|
114
src/vnet/sctp/sctp_api.c
Normal file
114
src/vnet/sctp/sctp_api.c
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
*------------------------------------------------------------------
|
||||
* sctp_api.c - vnet sctp-layer API
|
||||
*
|
||||
* Copyright (c) 2018 SUSE LLC.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <vnet/vnet.h>
|
||||
#include <vlibmemory/api.h>
|
||||
|
||||
#include <vnet/sctp/sctp.h>
|
||||
|
||||
#include <vnet/vnet_msg_enum.h>
|
||||
|
||||
#define vl_typedefs /* define message structures */
|
||||
#include <vnet/vnet_all_api_h.h>
|
||||
#undef vl_typedefs
|
||||
|
||||
#define vl_endianfun /* define message structures */
|
||||
#include <vnet/vnet_all_api_h.h>
|
||||
#undef vl_endianfun
|
||||
|
||||
/* instantiate all the print functions we know about */
|
||||
#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
|
||||
#define vl_printfun
|
||||
#include <vnet/vnet_all_api_h.h>
|
||||
#undef vl_printfun
|
||||
|
||||
#include <vlibapi/api_helper_macros.h>
|
||||
|
||||
#define foreach_sctp_api_msg \
|
||||
_(SCTP_ADD_SRC_DST_CONNECTION, sctp_add_src_dst_connection)
|
||||
|
||||
static void
|
||||
vl_api_sctp_add_src_dst_connection_t_handler
|
||||
(vl_api_sctp_add_src_dst_connection_t * mp)
|
||||
{
|
||||
vlib_main_t *vm = vlib_get_main ();
|
||||
vl_api_sctp_add_src_dst_connection_reply_t *rmp;
|
||||
int rv;
|
||||
|
||||
if (mp->is_ipv6)
|
||||
rv = sctp_sub_connection_add_ip6
|
||||
(vm,
|
||||
(ip6_address_t *) mp->src_address, (ip6_address_t *) mp->dst_address);
|
||||
else
|
||||
rv = sctp_sub_connection_add_ip4
|
||||
(vm,
|
||||
(ip4_address_t *) mp->src_address, (ip4_address_t *) mp->dst_address);
|
||||
|
||||
REPLY_MACRO (VL_API_SCTP_ADD_SRC_DST_CONNECTION_REPLY);
|
||||
}
|
||||
|
||||
#define vl_msg_name_crc_list
|
||||
#include <vnet/sctp/sctp.api.h>
|
||||
#undef vl_msg_name_crc_list
|
||||
|
||||
static void
|
||||
setup_message_id_table (api_main_t * am)
|
||||
{
|
||||
#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
|
||||
foreach_vl_msg_name_crc_sctp;
|
||||
#undef _
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
sctp_api_hookup (vlib_main_t * vm)
|
||||
{
|
||||
api_main_t *am = &api_main;
|
||||
|
||||
#define _(N,n) \
|
||||
vl_msg_api_set_handlers(VL_API_##N, #n, \
|
||||
vl_api_##n##_t_handler, \
|
||||
vl_noop_handler, \
|
||||
vl_api_##n##_t_endian, \
|
||||
vl_api_##n##_t_print, \
|
||||
sizeof(vl_api_##n##_t), 1);
|
||||
foreach_sctp_api_msg;
|
||||
#undef _
|
||||
|
||||
/*
|
||||
* Set up the (msg_name, crc, message-id) table
|
||||
*/
|
||||
setup_message_id_table (am);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VLIB_API_INIT_FUNCTION (sctp_api_hookup);
|
||||
|
||||
void
|
||||
sctp_api_reference (void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
@ -23,7 +23,7 @@ sctp_error (CREATE_EXISTS, "Connection already exists")
|
||||
sctp_error (INITS_RCVD, "INITs received")
|
||||
sctp_error (CREATE_SESSION_FAIL, "Sessions couldn't be allocated")
|
||||
sctp_error (NO_LISTENER, "no listener for dst port")
|
||||
sctp_error (LENGTH, "inconsistent ip/tcp lengths")
|
||||
sctp_error (LENGTH, "inconsistent ip/sctp lengths")
|
||||
sctp_error (DISPATCH, "Dispatch error")
|
||||
sctp_error (ACK_DUP, "Duplicate ACK")
|
||||
sctp_error (DATA_CHUNK_VIOLATION, "DATA chunk received in invalid state")
|
||||
@ -47,4 +47,5 @@ sctp_error (EVENT_FIFO_FULL, "Events not sent for lack of event fifo space")
|
||||
sctp_error (UNKOWN_CHUNK, "Unrecognized / unknown chunk or chunk-state mismatch")
|
||||
sctp_error (BUNDLING_VIOLATION, "Bundling not allowed")
|
||||
sctp_error (PUNT, "Packets punted")
|
||||
sctp_error (FILTERED, "Packets filtered")
|
||||
sctp_error (FILTERED, "Packets filtered")
|
||||
sctp_error (MAX_CONNECTIONS, "Reached max supported subconnection")
|
@ -399,7 +399,10 @@ sctp_handle_init (sctp_header_t * sctp_hdr,
|
||||
clib_memcpy (ip4_addr, &ipv4->address,
|
||||
sizeof (ip4_address_t));
|
||||
|
||||
sctp_sub_connection_add_ip4 (vlib_get_thread_index (), ipv4);
|
||||
sctp_sub_connection_add_ip4 (vlib_get_main (),
|
||||
&sctp_conn->sub_conn
|
||||
[MAIN_SCTP_SUB_CONN_IDX].connection.
|
||||
lcl_ip.ip4, &ipv4->address);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -410,7 +413,10 @@ sctp_handle_init (sctp_header_t * sctp_hdr,
|
||||
clib_memcpy (ip6_addr, &ipv6->address,
|
||||
sizeof (ip6_address_t));
|
||||
|
||||
sctp_sub_connection_add_ip6 (vlib_get_thread_index (), ipv6);
|
||||
sctp_sub_connection_add_ip6 (vlib_get_main (),
|
||||
&sctp_conn->sub_conn
|
||||
[MAIN_SCTP_SUB_CONN_IDX].connection.
|
||||
lcl_ip.ip6, &ipv6->address);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -528,7 +534,10 @@ sctp_handle_init_ack (sctp_header_t * sctp_hdr,
|
||||
sctp_ipv4_addr_param_t *ipv4 =
|
||||
(sctp_ipv4_addr_param_t *) opt_params_hdr;
|
||||
|
||||
sctp_sub_connection_add_ip4 (vlib_get_thread_index (), ipv4);
|
||||
sctp_sub_connection_add_ip4 (vlib_get_main (),
|
||||
&sctp_conn->sub_conn
|
||||
[MAIN_SCTP_SUB_CONN_IDX].connection.
|
||||
lcl_ip.ip4, &ipv4->address);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -537,7 +546,10 @@ sctp_handle_init_ack (sctp_header_t * sctp_hdr,
|
||||
sctp_ipv6_addr_param_t *ipv6 =
|
||||
(sctp_ipv6_addr_param_t *) opt_params_hdr;
|
||||
|
||||
sctp_sub_connection_add_ip6 (vlib_get_thread_index (), ipv6);
|
||||
sctp_sub_connection_add_ip6 (vlib_get_main (),
|
||||
&sctp_conn->sub_conn
|
||||
[MAIN_SCTP_SUB_CONN_IDX].connection.
|
||||
lcl_ip.ip6, &ipv6->address);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -1541,16 +1553,16 @@ sctp_handle_heartbeat_ack (sctp_hb_ack_chunk_t * sctp_hb_ack_chunk,
|
||||
}
|
||||
|
||||
always_inline void
|
||||
sctp_node_inc_counter (vlib_main_t * vm, u32 tcp4_node, u32 tcp6_node,
|
||||
sctp_node_inc_counter (vlib_main_t * vm, u32 sctp4_node, u32 sctp6_node,
|
||||
u8 is_ip4, u8 evt, u8 val)
|
||||
{
|
||||
if (PREDICT_TRUE (!val))
|
||||
return;
|
||||
|
||||
if (is_ip4)
|
||||
vlib_node_increment_counter (vm, tcp4_node, evt, val);
|
||||
vlib_node_increment_counter (vm, sctp4_node, evt, val);
|
||||
else
|
||||
vlib_node_increment_counter (vm, tcp6_node, evt, val);
|
||||
vlib_node_increment_counter (vm, sctp6_node, evt, val);
|
||||
}
|
||||
|
||||
always_inline uword
|
||||
@ -2073,7 +2085,7 @@ sctp46_input_dispatcher (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
n_left_to_next -= 1;
|
||||
|
||||
b0 = vlib_get_buffer (vm, bi0);
|
||||
vnet_buffer (b0)->tcp.flags = 0;
|
||||
vnet_buffer (b0)->sctp.flags = 0;
|
||||
fib_index0 = vnet_buffer (b0)->ip.fib_index;
|
||||
|
||||
/* Checksum computed by ipx_local no need to compute again */
|
||||
|
@ -68,6 +68,7 @@
|
||||
#include <vnet/ip/punt.api.h>
|
||||
#include <vnet/pg/pg.api.h>
|
||||
#include <vnet/feature/feature.api.h>
|
||||
#include <vnet/sctp/sctp.api.h>
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
|
Reference in New Issue
Block a user