summaryrefslogtreecommitdiffstats
path: root/src/vnet/sctp/sctp_output.c
diff options
context:
space:
mode:
authorMarco Varlese <marco.varlese@suse.com>2018-03-05 12:31:45 +0100
committerDamjan Marion <dmarion.lists@gmail.com>2018-03-05 13:46:32 +0000
commit9e09ff394ac0e731b5b33caf4d0cddff8de570b4 (patch)
tree5fdb5784570dadce34afc4cfe824f51a3f00e948 /src/vnet/sctp/sctp_output.c
parenteac3b11b67a9ee2d5b85c3e2e90220a04cd5db61 (diff)
SCTP: retransmission in INIT/SHUTDOWN phase
This patch addresses the need to handle timers timeouts (e.g. sent chunks not being acked) for both the INIT and SHUTDOWN phases. The INIT phase requires the handling of two timers the T1-init and T1-cookie timers whilst the SHUTDOWN phase requires the handling of the T2-shutdown timer only for the retransmission case. Left to be implemented is the handling of the DATA chunks retransmission (e.g. T3-rxtx expiration) but that will be submitted with a separate patch. Change-Id: I2b2e13dce11000aea3c7d965f02b27b76c97e605 Signed-off-by: Marco Varlese <marco.varlese@suse.com>
Diffstat (limited to 'src/vnet/sctp/sctp_output.c')
-rw-r--r--src/vnet/sctp/sctp_output.c82
1 files changed, 78 insertions, 4 deletions
diff --git a/src/vnet/sctp/sctp_output.c b/src/vnet/sctp/sctp_output.c
index 0c2fee1bb69..41fa1b31709 100644
--- a/src/vnet/sctp/sctp_output.c
+++ b/src/vnet/sctp/sctp_output.c
@@ -556,12 +556,12 @@ sctp_prepare_cookie_ack_chunk (sctp_connection_t * sctp_conn, u8 idx,
void
sctp_prepare_cookie_echo_chunk (sctp_connection_t * sctp_conn, u8 idx,
- vlib_buffer_t * b,
- sctp_state_cookie_param_t * sc)
+ vlib_buffer_t * b, u8 reuse_buffer)
{
vlib_main_t *vm = vlib_get_main ();
- sctp_reuse_buffer (vm, b);
+ if (reuse_buffer)
+ sctp_reuse_buffer (vm, b);
/* The minimum size of the message is given by the sctp_init_ack_chunk_t */
u16 alloc_bytes = sizeof (sctp_cookie_echo_chunk_t);
@@ -580,7 +580,7 @@ sctp_prepare_cookie_echo_chunk (sctp_connection_t * sctp_conn, u8 idx,
cookie_echo_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
vnet_sctp_set_chunk_type (&cookie_echo_chunk->chunk_hdr, COOKIE_ECHO);
vnet_sctp_set_chunk_length (&cookie_echo_chunk->chunk_hdr, chunk_len);
- clib_memcpy (&(cookie_echo_chunk->cookie), sc,
+ clib_memcpy (&(cookie_echo_chunk->cookie), &sctp_conn->cookie_param,
sizeof (sctp_state_cookie_param_t));
vnet_buffer (b)->sctp.connection_index =
@@ -588,6 +588,52 @@ sctp_prepare_cookie_echo_chunk (sctp_connection_t * sctp_conn, u8 idx,
vnet_buffer (b)->sctp.subconn_idx = idx;
}
+
+/*
+ * Send COOKIE_ECHO
+ */
+void
+sctp_send_cookie_echo (sctp_connection_t * sctp_conn)
+{
+ vlib_buffer_t *b;
+ u32 bi;
+ sctp_main_t *tm = vnet_get_sctp_main ();
+ vlib_main_t *vm = vlib_get_main ();
+
+ if (PREDICT_FALSE (sctp_conn->init_retransmit_err > SCTP_MAX_INIT_RETRANS))
+ {
+ clib_warning ("Reached MAX_INIT_RETRANS times. Aborting connection.");
+
+ session_stream_connect_notify (&sctp_conn->sub_conn
+ [MAIN_SCTP_SUB_CONN_IDX].connection, 1);
+
+ sctp_connection_timers_reset (sctp_conn);
+
+ sctp_connection_cleanup (sctp_conn);
+ }
+
+ if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
+ return;
+
+ b = vlib_get_buffer (vm, bi);
+ u8 idx = MAIN_SCTP_SUB_CONN_IDX;
+
+ sctp_init_buffer (vm, b);
+ sctp_prepare_cookie_echo_chunk (sctp_conn, idx, b, 0);
+ sctp_enqueue_to_output_now (vm, b, bi, sctp_conn->sub_conn[idx].c_is_ip4);
+
+ /* Start the T1_INIT timer */
+ sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T1_INIT,
+ sctp_conn->sub_conn[idx].RTO);
+
+ /* Change state to COOKIE_WAIT */
+ sctp_conn->state = SCTP_STATE_COOKIE_WAIT;
+
+ /* Measure RTT with this */
+ sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now ();
+}
+
+
/**
* Convert buffer to ERROR
*/
@@ -1270,6 +1316,20 @@ sctp_send_init (sctp_connection_t * sctp_conn)
sctp_main_t *tm = vnet_get_sctp_main ();
vlib_main_t *vm = vlib_get_main ();
+ if (PREDICT_FALSE (sctp_conn->init_retransmit_err > SCTP_MAX_INIT_RETRANS))
+ {
+ clib_warning ("Reached MAX_INIT_RETRANS times. Aborting connection.");
+
+ session_stream_connect_notify (&sctp_conn->sub_conn
+ [MAIN_SCTP_SUB_CONN_IDX].connection, 1);
+
+ sctp_connection_timers_reset (sctp_conn);
+
+ sctp_connection_cleanup (sctp_conn);
+
+ return;
+ }
+
if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
return;
@@ -1389,6 +1449,20 @@ sctp_push_header (transport_connection_t * trans_conn, vlib_buffer_t * b)
return 0;
}
+void
+sctp_data_retransmit (sctp_connection_t * sctp_conn)
+{
+ /* TODO: requires use of PEEK/SEND */
+ SCTP_DBG_OUTPUT
+ ("SCTP_CONN = %p, IDX = %u, S_INDEX = %u, C_INDEX = %u, sctp_conn->[...].LCL_PORT = %u, sctp_conn->[...].RMT_PORT = %u",
+ sctp_conn, idx, sctp_conn->sub_conn[idx].connection.s_index,
+ sctp_conn->sub_conn[idx].connection.c_index,
+ sctp_conn->sub_conn[idx].connection.lcl_port,
+ sctp_conn->sub_conn[idx].connection.rmt_port);
+
+ return;
+}
+
#if SCTP_DEBUG_STATE_MACHINE
always_inline u8
sctp_validate_output_state_machine (sctp_connection_t * sctp_conn,