diff options
Diffstat (limited to 'src/vnet/sctp/sctp_output.c')
-rw-r--r-- | src/vnet/sctp/sctp_output.c | 183 |
1 files changed, 79 insertions, 104 deletions
diff --git a/src/vnet/sctp/sctp_output.c b/src/vnet/sctp/sctp_output.c index 7657d0cd1e9..bb8332f5732 100644 --- a/src/vnet/sctp/sctp_output.c +++ b/src/vnet/sctp/sctp_output.c @@ -554,9 +554,6 @@ sctp_prepare_cookie_ack_chunk (sctp_connection_t * sctp_conn, vnet_sctp_set_chunk_type (&cookie_ack_chunk->chunk_hdr, COOKIE_ACK); vnet_sctp_set_chunk_length (&cookie_ack_chunk->chunk_hdr, chunk_len); - /* Measure RTT with this */ - sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now (); - vnet_buffer (b)->sctp.connection_index = sctp_conn->sub_conn[idx].connection.c_index; } @@ -591,9 +588,6 @@ sctp_prepare_cookie_echo_chunk (sctp_connection_t * sctp_conn, clib_memcpy (&(cookie_echo_chunk->cookie), sc, sizeof (sctp_state_cookie_param_t)); - /* Measure RTT with this */ - sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now (); - vnet_buffer (b)->sctp.connection_index = sctp_conn->sub_conn[idx].connection.c_index; } @@ -736,9 +730,6 @@ sctp_prepare_initack_chunk (sctp_connection_t * sctp_conn, vlib_buffer_t * b, sctp_conn->local_tag = init_ack_chunk->initiate_tag; - /* Measure RTT with this */ - sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now (); - vnet_buffer (b)->sctp.connection_index = sctp_conn->sub_conn[idx].connection.c_index; } @@ -802,9 +793,6 @@ sctp_send_shutdown (sctp_connection_t * sctp_conn) u8 idx = sctp_pick_conn_idx_on_chunk (SHUTDOWN); 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 (); } /** @@ -852,11 +840,6 @@ sctp_send_shutdown_ack (sctp_connection_t * sctp_conn, vlib_buffer_t * b) sctp_reuse_buffer (vm, b); sctp_prepare_shutdown_ack_chunk (sctp_conn, b); - - u8 idx = sctp_pick_conn_idx_on_chunk (SHUTDOWN_ACK); - - /* Measure RTT with this */ - sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now (); } /** @@ -1041,8 +1024,6 @@ sctp_send_shutdown_complete (sctp_connection_t * sctp_conn) u8 idx = sctp_pick_conn_idx_on_chunk (SHUTDOWN_COMPLETE); sctp_enqueue_to_output (vm, b, bi, sctp_conn->sub_conn[idx].connection.is_ip4); - - sctp_conn->state = SCTP_STATE_CLOSED; } @@ -1069,15 +1050,15 @@ sctp_send_init (sctp_connection_t * sctp_conn) sctp_push_ip_hdr (tm, &sctp_conn->sub_conn[idx], b); sctp_enqueue_to_ip_lookup (vm, b, bi, sctp_conn->sub_conn[idx].c_is_ip4); - /* Measure RTT with this */ - sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now (); - /* 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 (); } /** @@ -1156,18 +1137,51 @@ sctp_push_header (transport_connection_t * trans_conn, vlib_buffer_t * b) sctp_push_hdr_i (sctp_conn, idx, b, SCTP_STATE_ESTABLISHED); - if (sctp_conn->sub_conn[idx].RTO_pending == 0) - { - sctp_conn->sub_conn[idx].RTO_pending = 1; - sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now (); - } - sctp_trajectory_add_start (b0, 3); return 0; } +always_inline u8 +sctp_validate_output_state_machine (sctp_connection_t * sctp_conn, + u8 chunk_type) +{ + u8 result = 0; + switch (sctp_conn->state) + { + case SCTP_STATE_CLOSED: + if (chunk_type != INIT && chunk_type != INIT_ACK) + result = 1; + break; + case SCTP_STATE_ESTABLISHED: + if (chunk_type != DATA && chunk_type != HEARTBEAT && + chunk_type != HEARTBEAT_ACK && chunk_type != SACK && + chunk_type != COOKIE_ACK && chunk_type != SHUTDOWN) + result = 1; + break; + case SCTP_STATE_COOKIE_WAIT: + if (chunk_type != COOKIE_ECHO) + result = 1; + break; + case SCTP_STATE_SHUTDOWN_SENT: + if (chunk_type != SHUTDOWN_COMPLETE) + result = 1; + break; + case SCTP_STATE_SHUTDOWN_RECEIVED: + if (chunk_type != SHUTDOWN_ACK) + result = 1; + break; + } + return result; +} + +always_inline u8 +sctp_is_retransmitting (sctp_connection_t * sctp_conn, u8 idx) +{ + return sctp_conn->sub_conn[idx].is_retransmitting; +} + always_inline uword sctp46_output_inline (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -1322,93 +1336,49 @@ sctp46_output_inline (vlib_main_t * vm, sctp_chunk_to_string (chunk_type), full_hdr->hdr.src_port, full_hdr->hdr.dst_port); - if (chunk_type == DATA) - SCTP_ADV_DBG_OUTPUT ("PACKET_LENGTH = %u", packet_length); - /* Let's make sure the state-machine does not send anything crazy */ - switch (sctp_conn->state) +#if SCTP_DEBUG_STATE_MACHINE + if (sctp_validate_output_state_machine (sctp_conn, chunk_type) != 0) { - case SCTP_STATE_CLOSED: - { - if (chunk_type != INIT && chunk_type != INIT_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; - } - break; - } - case SCTP_STATE_ESTABLISHED: - if (chunk_type != DATA && chunk_type != HEARTBEAT && - chunk_type != HEARTBEAT_ACK && chunk_type != SACK && - chunk_type != COOKIE_ACK && chunk_type != SHUTDOWN) - { - 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; - } - break; - case SCTP_STATE_COOKIE_WAIT: - if (chunk_type != COOKIE_ECHO) - { - 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; - } - /* 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)", + ("Sending the wrong chunk (%s) based on state-machine status (%s)", sctp_chunk_to_string (chunk_type), sctp_state_to_string (sctp_conn->state)); - break; + + error0 = SCTP_ERROR_UNKOWN_CHUNK; + next0 = SCTP_OUTPUT_NEXT_DROP; + goto done; + } +#endif + + /* Karn's algorithm: RTT measurements MUST NOT be made using + * packets that were retransmitted + */ + if (!sctp_is_retransmitting (sctp_conn, idx)) + { + /* Measure RTT with this */ + if (chunk_type == DATA + && sctp_conn->sub_conn[idx].RTO_pending == 0) + { + sctp_conn->sub_conn[idx].RTO_pending = 1; + sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now (); + } + else + sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now (); } + /* Let's take care of TIMERS */ switch (chunk_type) { + case COOKIE_ECHO: + { + sctp_conn->state = SCTP_STATE_COOKIE_ECHOED; + break; + } case DATA: { + SCTP_ADV_DBG_OUTPUT ("PACKET_LENGTH = %u", packet_length); + sctp_timer_update (sctp_conn, idx, SCTP_TIMER_T3_RXTX, sctp_conn->sub_conn[idx].RTO); break; @@ -1429,6 +1399,11 @@ sctp46_output_inline (vlib_main_t * vm, sctp_conn->state = SCTP_STATE_SHUTDOWN_ACK_SENT; break; } + case SHUTDOWN_COMPLETE: + { + sctp_conn->state = SCTP_STATE_CLOSED; + break; + } } vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0; |