summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarco Varlese <marco.varlese@suse.com>2018-02-07 12:22:41 +0100
committerDamjan Marion <dmarion.lists@gmail.com>2018-02-08 10:03:23 +0000
commitbe2251b0c5b10a3a556e75c9bfbea96df4799297 (patch)
treeacdcc931983211663b51df87e3d0b41672cce65f /src
parentc04cbf16ccfd9ef142937e4684af6093d812a866 (diff)
SCTP: shutdown phase
This patch addresses some bugs discovered with the shutdown phase which were causing the actual chunks not to leave the output_node. While fixing the issue some minor refactoring was also performed to align the internal functions to a 'common' design. Change-Id: Ieac4f6e78cffad2e6982536f8e9f190a66f328f7 Signed-off-by: Marco Varlese <marco.varlese@suse.com>
Diffstat (limited to 'src')
-rw-r--r--src/vnet/sctp/sctp.h3
-rw-r--r--src/vnet/sctp/sctp_input.c73
-rw-r--r--src/vnet/sctp/sctp_output.c83
3 files changed, 92 insertions, 67 deletions
diff --git a/src/vnet/sctp/sctp.h b/src/vnet/sctp/sctp.h
index 9129aa80682..60a195f47c1 100644
--- a/src/vnet/sctp/sctp.h
+++ b/src/vnet/sctp/sctp.h
@@ -247,7 +247,8 @@ void sctp_connection_del (sctp_connection_t * sctp_conn);
u32 sctp_push_header (transport_connection_t * tconn, vlib_buffer_t * b);
void sctp_send_init (sctp_connection_t * sctp_conn);
void sctp_send_shutdown (sctp_connection_t * sctp_conn);
-void sctp_send_shutdown_ack (sctp_connection_t * sctp_conn);
+void sctp_send_shutdown_ack (sctp_connection_t * sctp_conn,
+ vlib_buffer_t * b);
void sctp_send_shutdown_complete (sctp_connection_t * sctp_conn);
void sctp_send_heartbeat (sctp_connection_t * sctp_conn);
void sctp_flush_frame_to_output (vlib_main_t * vm, u8 thread_index,
diff --git a/src/vnet/sctp/sctp_input.c b/src/vnet/sctp/sctp_input.c
index 7d5e7555af5..8df95642ce4 100644
--- a/src/vnet/sctp/sctp_input.c
+++ b/src/vnet/sctp/sctp_input.c
@@ -686,11 +686,10 @@ sctp_is_connection_gapping (sctp_connection_t * sctp_conn, u32 tsn,
always_inline u16
sctp_handle_data (sctp_payload_data_chunk_t * sctp_data_chunk,
- sctp_connection_t * sctp_conn, vlib_buffer_t * b,
+ sctp_connection_t * sctp_conn, u8 idx, vlib_buffer_t * b,
u16 * next0)
{
u32 error = 0, n_data_bytes;
- u8 idx = sctp_pick_conn_idx_on_state (sctp_conn->state);
u8 is_gapping = 0;
/* Check that the LOCALLY generated tag is being used by the REMOTE peer as the verification tag */
@@ -758,13 +757,11 @@ sctp_handle_data (sctp_payload_data_chunk_t * sctp_data_chunk,
always_inline u16
sctp_handle_cookie_echo (sctp_header_t * sctp_hdr,
sctp_chunks_common_hdr_t * sctp_chunk_hdr,
- sctp_connection_t * sctp_conn, vlib_buffer_t * b0)
+ sctp_connection_t * sctp_conn, u8 idx,
+ vlib_buffer_t * b0, u16 * next0)
{
u32 now = sctp_time_now ();
- /* Build TCB */
- u8 idx = sctp_pick_conn_idx_on_chunk (COOKIE_ECHO);
-
sctp_cookie_echo_chunk_t *cookie_echo =
(sctp_cookie_echo_chunk_t *) sctp_hdr;
@@ -791,6 +788,7 @@ sctp_handle_cookie_echo (sctp_header_t * sctp_hdr,
/* Change state */
sctp_conn->state = SCTP_STATE_ESTABLISHED;
+ *next0 = sctp_next_output (sctp_conn->sub_conn[idx].c_is_ip4);
sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T4_HEARTBEAT,
sctp_conn->sub_conn[idx].RTO);
@@ -804,12 +802,9 @@ sctp_handle_cookie_echo (sctp_header_t * sctp_hdr,
always_inline u16
sctp_handle_cookie_ack (sctp_header_t * sctp_hdr,
sctp_chunks_common_hdr_t * sctp_chunk_hdr,
- sctp_connection_t * sctp_conn, vlib_buffer_t * b0)
+ sctp_connection_t * sctp_conn, u8 idx,
+ vlib_buffer_t * b0, u16 * next0)
{
-
- /* Stop T1_COOKIE timer */
- u8 idx = sctp_pick_conn_idx_on_chunk (COOKIE_ACK);
-
/* Check that the LOCALLY generated tag is being used by the REMOTE peer as the verification tag */
if (sctp_conn->local_tag != sctp_hdr->verification_tag)
{
@@ -821,6 +816,7 @@ sctp_handle_cookie_ack (sctp_header_t * sctp_hdr,
sctp_timer_reset (sctp_conn, idx, SCTP_TIMER_T1_COOKIE);
/* Change state */
sctp_conn->state = SCTP_STATE_ESTABLISHED;
+ *next0 = sctp_next_output (sctp_conn->sub_conn[idx].c_is_ip4);
sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T4_HEARTBEAT,
sctp_conn->sub_conn[idx].RTO);
@@ -1090,8 +1086,9 @@ vlib_node_registration_t sctp6_shutdown_phase_node;
always_inline u16
sctp_handle_shutdown (sctp_header_t * sctp_hdr,
sctp_chunks_common_hdr_t * sctp_chunk_hdr,
- sctp_connection_t * sctp_conn, vlib_buffer_t * b0,
- u16 sctp_implied_length)
+ sctp_connection_t * sctp_conn, u8 idx,
+ vlib_buffer_t * b0, u16 sctp_implied_length,
+ u16 * next0)
{
sctp_shutdown_association_chunk_t *shutdown_chunk =
(sctp_shutdown_association_chunk_t *) (sctp_hdr);
@@ -1113,21 +1110,25 @@ sctp_handle_shutdown (sctp_header_t * sctp_hdr,
case SCTP_STATE_ESTABLISHED:
if (sctp_check_outstanding_data_chunks (sctp_conn) == 0)
sctp_conn->state = SCTP_STATE_SHUTDOWN_RECEIVED;
+ sctp_send_shutdown_ack (sctp_conn, b0);
break;
case SCTP_STATE_SHUTDOWN_SENT:
- sctp_send_shutdown_ack (sctp_conn);
+ sctp_send_shutdown_ack (sctp_conn, b0);
break;
}
+ *next0 = sctp_next_output (sctp_conn->sub_conn[idx].c_is_ip4);
+
return SCTP_ERROR_NONE;
}
always_inline u16
sctp_handle_shutdown_ack (sctp_header_t * sctp_hdr,
sctp_chunks_common_hdr_t * sctp_chunk_hdr,
- sctp_connection_t * sctp_conn, vlib_buffer_t * b0,
- u16 sctp_implied_length)
+ sctp_connection_t * sctp_conn, u8 idx,
+ vlib_buffer_t * b0, u16 sctp_implied_length,
+ u16 * next0)
{
sctp_shutdown_ack_chunk_t *shutdown_ack_chunk =
(sctp_shutdown_ack_chunk_t *) (sctp_hdr);
@@ -1153,14 +1154,17 @@ sctp_handle_shutdown_ack (sctp_header_t * sctp_hdr,
SCTP_TIMER_T2_SHUTDOWN);
sctp_send_shutdown_complete (sctp_conn);
+ *next0 = sctp_next_output (sctp_conn->sub_conn[idx].c_is_ip4);
+
return SCTP_ERROR_NONE;
}
always_inline u16
sctp_handle_shutdown_complete (sctp_header_t * sctp_hdr,
sctp_chunks_common_hdr_t * sctp_chunk_hdr,
- sctp_connection_t * sctp_conn,
- vlib_buffer_t * b0, u16 sctp_implied_length)
+ sctp_connection_t * sctp_conn, u8 idx,
+ vlib_buffer_t * b0, u16 sctp_implied_length,
+ u16 * next0)
{
sctp_shutdown_complete_chunk_t *shutdown_complete =
(sctp_shutdown_complete_chunk_t *) (sctp_hdr);
@@ -1185,6 +1189,8 @@ sctp_handle_shutdown_complete (sctp_header_t * sctp_hdr,
stream_session_disconnect_notify (&sctp_conn->sub_conn
[MAIN_SCTP_SUB_CONN_IDX].connection);
+ *next0 = sctp_next_output (sctp_conn->sub_conn[idx].c_is_ip4);
+
return SCTP_ERROR_NONE;
}
@@ -1257,30 +1263,31 @@ sctp46_shutdown_phase_inline (vlib_main_t * vm,
sctp_implied_length =
sctp_calculate_implied_length (ip4_hdr, ip6_hdr, is_ip4);
- switch (vnet_sctp_get_chunk_type (sctp_chunk_hdr))
+ u8 idx = sctp_pick_conn_idx_on_state (sctp_conn->state);
+
+ u8 chunk_type = vnet_sctp_get_chunk_type (sctp_chunk_hdr);
+ switch (chunk_type)
{
case SHUTDOWN:
error0 =
- sctp_handle_shutdown (sctp_hdr, sctp_chunk_hdr, sctp_conn, b0,
- sctp_implied_length);
- next0 = sctp_next_output (is_ip4);
+ sctp_handle_shutdown (sctp_hdr, sctp_chunk_hdr, sctp_conn,
+ idx, b0, sctp_implied_length, &next0);
break;
case SHUTDOWN_ACK:
error0 =
sctp_handle_shutdown_ack (sctp_hdr, sctp_chunk_hdr, sctp_conn,
- b0, sctp_implied_length);
- next0 = sctp_next_output (is_ip4);
+ idx, b0, sctp_implied_length,
+ &next0);
break;
case SHUTDOWN_COMPLETE:
error0 =
sctp_handle_shutdown_complete (sctp_hdr, sctp_chunk_hdr,
- sctp_conn, b0,
- sctp_implied_length);
+ sctp_conn, idx, b0,
+ sctp_implied_length, &next0);
sctp_connection_cleanup (sctp_conn);
- next0 = sctp_next_output (is_ip4);
break;
/*
@@ -1290,8 +1297,7 @@ sctp46_shutdown_phase_inline (vlib_main_t * vm,
case DATA:
error0 =
sctp_handle_data ((sctp_payload_data_chunk_t *) sctp_hdr,
- sctp_conn, b0, &next0);
- next0 = sctp_next_output (is_ip4);
+ sctp_conn, idx, b0, &next0);
break;
/* All UNEXPECTED scenarios (wrong chunk received per state-machine)
@@ -1761,15 +1767,13 @@ sctp46_established_phase_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
case COOKIE_ECHO:
error0 =
sctp_handle_cookie_echo (sctp_hdr, sctp_chunk_hdr, sctp_conn,
- b0);
- next0 = sctp_next_output (is_ip4);
+ idx, b0, &next0);
break;
case COOKIE_ACK:
error0 =
sctp_handle_cookie_ack (sctp_hdr, sctp_chunk_hdr, sctp_conn,
- b0);
- next0 = sctp_next_output (is_ip4);
+ idx, b0, &next0);
break;
case SACK:
@@ -1793,7 +1797,7 @@ sctp46_established_phase_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
case DATA:
error0 =
sctp_handle_data ((sctp_payload_data_chunk_t *) sctp_hdr,
- sctp_conn, b0, &next0);
+ sctp_conn, idx, b0, &next0);
break;
/* All UNEXPECTED scenarios (wrong chunk received per state-machine)
@@ -2064,7 +2068,6 @@ sctp46_input_dispatcher (vlib_main_t * vm, vlib_node_runtime_t * node,
vnet_sctp_common_hdr_params_net_to_host (sctp_chunk_hdr);
u8 type = vnet_sctp_get_chunk_type (sctp_chunk_hdr);
-
#if SCTP_DEBUG_STATE_MACHINE
u8 idx = sctp_pick_conn_idx_on_state (sctp_conn->state);
#endif
diff --git a/src/vnet/sctp/sctp_output.c b/src/vnet/sctp/sctp_output.c
index dc78c0959ce..276d7e70213 100644
--- a/src/vnet/sctp/sctp_output.c
+++ b/src/vnet/sctp/sctp_output.c
@@ -751,12 +751,9 @@ sctp_prepare_initack_chunk (sctp_connection_t * sctp_conn, vlib_buffer_t * b,
void
sctp_prepare_shutdown_chunk (sctp_connection_t * sctp_conn, vlib_buffer_t * b)
{
- vlib_main_t *vm = vlib_get_main ();
u8 idx = sctp_pick_conn_idx_on_chunk (SHUTDOWN);
u16 alloc_bytes = sizeof (sctp_shutdown_association_chunk_t);
- b = sctp_reuse_buffer (vm, b);
-
/* As per RFC 4960 the chunk_length value does NOT contemplate
* the size of the first header (see sctp_header_t) and any padding
*/
@@ -805,8 +802,8 @@ sctp_send_shutdown (sctp_connection_t * sctp_conn)
sctp_prepare_shutdown_chunk (sctp_conn, b);
u8 idx = sctp_pick_conn_idx_on_chunk (SHUTDOWN);
- sctp_enqueue_to_output (vm, b, bi,
- sctp_conn->sub_conn[idx].connection.is_ip4);
+ sctp_enqueue_to_output_now (vm, b, bi,
+ sctp_conn->sub_conn[idx].connection.is_ip4);
/* Measure RTT with this */
sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now ();
@@ -847,34 +844,21 @@ sctp_prepare_shutdown_ack_chunk (sctp_connection_t * sctp_conn,
* Send SHUTDOWN_ACK
*/
void
-sctp_send_shutdown_ack (sctp_connection_t * sctp_conn)
+sctp_send_shutdown_ack (sctp_connection_t * sctp_conn, vlib_buffer_t * b)
{
- vlib_buffer_t *b;
- u32 bi;
- sctp_main_t *tm = vnet_get_sctp_main ();
vlib_main_t *vm = vlib_get_main ();
if (sctp_check_outstanding_data_chunks (sctp_conn) > 0)
return;
- if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
- return;
+ sctp_reuse_buffer (vm, b);
- b = vlib_get_buffer (vm, bi);
- sctp_init_buffer (vm, b);
sctp_prepare_shutdown_ack_chunk (sctp_conn, b);
u8 idx = sctp_pick_conn_idx_on_chunk (SHUTDOWN_ACK);
- sctp_enqueue_to_output (vm, b, bi,
- sctp_conn->sub_conn[idx].connection.is_ip4);
/* Measure RTT with this */
sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now ();
-
- /* Start the SCTP_TIMER_T2_SHUTDOWN timer */
- sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T2_SHUTDOWN,
- sctp_conn->sub_conn[idx].RTO);
- sctp_conn->state = SCTP_STATE_SHUTDOWN_ACK_SENT;
}
/**
@@ -1228,6 +1212,7 @@ sctp46_output_inline (vlib_main_t * vm,
n_left_to_next -= 1;
b0 = vlib_get_buffer (vm, bi0);
+
sctp_conn =
sctp_connection_get (vnet_buffer (b0)->sctp.connection_index,
my_thread_index);
@@ -1390,6 +1375,30 @@ sctp46_output_inline (vlib_main_t * vm,
/* Change state */
sctp_conn->state = SCTP_STATE_COOKIE_ECHOED;
break;
+ case SCTP_STATE_SHUTDOWN_SENT:
+ if (chunk_type != SHUTDOWN_COMPLETE)
+ {
+ SCTP_DBG_STATE_MACHINE
+ ("Sending the wrong chunk (%s) based on state-machine status (%s)",
+ sctp_chunk_to_string (chunk_type),
+ sctp_state_to_string (sctp_conn->state));
+
+ error0 = SCTP_ERROR_UNKOWN_CHUNK;
+ next0 = SCTP_OUTPUT_NEXT_DROP;
+ goto done;
+ }
+ case SCTP_STATE_SHUTDOWN_RECEIVED:
+ if (chunk_type != SHUTDOWN_ACK)
+ {
+ SCTP_DBG_STATE_MACHINE
+ ("Sending the wrong chunk (%s) based on state-machine status (%s)",
+ sctp_chunk_to_string (chunk_type),
+ sctp_state_to_string (sctp_conn->state));
+
+ error0 = SCTP_ERROR_UNKOWN_CHUNK;
+ next0 = SCTP_OUTPUT_NEXT_DROP;
+ goto done;
+ }
default:
SCTP_DBG_STATE_MACHINE
("Sending chunk (%s) based on state-machine status (%s)",
@@ -1398,18 +1407,30 @@ sctp46_output_inline (vlib_main_t * vm,
break;
}
- if (chunk_type == SHUTDOWN)
+ switch (chunk_type)
{
- /* Start the SCTP_TIMER_T2_SHUTDOWN timer */
- sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T2_SHUTDOWN,
- sctp_conn->sub_conn[idx].RTO);
- sctp_conn->state = SCTP_STATE_SHUTDOWN_SENT;
- }
-
- if (chunk_type == DATA)
- {
- sctp_timer_update (sctp_conn, idx, SCTP_TIMER_T3_RXTX,
- sctp_conn->sub_conn[idx].RTO);
+ case DATA:
+ {
+ sctp_timer_update (sctp_conn, idx, SCTP_TIMER_T3_RXTX,
+ sctp_conn->sub_conn[idx].RTO);
+ break;
+ }
+ case SHUTDOWN:
+ {
+ /* Start the SCTP_TIMER_T2_SHUTDOWN timer */
+ sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T2_SHUTDOWN,
+ sctp_conn->sub_conn[idx].RTO);
+ sctp_conn->state = SCTP_STATE_SHUTDOWN_SENT;
+ break;
+ }
+ case SHUTDOWN_ACK:
+ {
+ /* Start the SCTP_TIMER_T2_SHUTDOWN timer */
+ sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T2_SHUTDOWN,
+ sctp_conn->sub_conn[idx].RTO);
+ sctp_conn->state = SCTP_STATE_SHUTDOWN_ACK_SENT;
+ break;
+ }
}
vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;