summaryrefslogtreecommitdiffstats
path: root/src/vnet/sctp/sctp_input.c
diff options
context:
space:
mode:
authorMarco Varlese <marco.varlese@suse.com>2018-02-19 15:23:13 +0100
committerFlorin Coras <florin.coras@gmail.com>2018-02-20 21:13:03 +0000
commitf3ab4896ed13733a22e9637395973fc1808823e1 (patch)
tree68fbdf6b914b73e1c9c526060d168a5ad99b4be0 /src/vnet/sctp/sctp_input.c
parent6525c7f9022fbed15c519872833097eb8607118b (diff)
SCTP: congestion control
This patch addresses the requirements depicted by section 7.1.1 and 7.1.2 of the RFC 4960. Specifically, it implements the Slow-start and Congestion-avoidance policies. The patch also took care of correctly implementing some 'formatting' functions required - for instance - in packet(s) tracing. Change-Id: I68eade1b30345de3acb3ac8a653a5ef76eb6d2ac Signed-off-by: Marco Varlese <marco.varlese@suse.com>
Diffstat (limited to 'src/vnet/sctp/sctp_input.c')
-rw-r--r--src/vnet/sctp/sctp_input.c61
1 files changed, 33 insertions, 28 deletions
diff --git a/src/vnet/sctp/sctp_input.c b/src/vnet/sctp/sctp_input.c
index 6c804880d7e..35218d5dd62 100644
--- a/src/vnet/sctp/sctp_input.c
+++ b/src/vnet/sctp/sctp_input.c
@@ -537,6 +537,8 @@ sctp_handle_init_ack (sctp_header_t * sctp_hdr,
sctp_timer_set (sctp_conn, idx,
SCTP_TIMER_T1_COOKIE, sctp_conn->sub_conn[idx].RTO);
+ stream_session_accept_notify (&sctp_conn->sub_conn[idx].connection);
+
return SCTP_ERROR_NONE;
}
@@ -804,8 +806,6 @@ sctp_handle_cookie_echo (sctp_header_t * sctp_hdr,
sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T4_HEARTBEAT,
sctp_conn->sub_conn[idx].RTO);
- stream_session_accept_notify (&sctp_conn->sub_conn[idx].connection);
-
return SCTP_ERROR_NONE;
}
@@ -834,8 +834,6 @@ sctp_handle_cookie_ack (sctp_header_t * sctp_hdr,
sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T4_HEARTBEAT,
sctp_conn->sub_conn[idx].RTO);
- stream_session_accept_notify (&sctp_conn->sub_conn[idx].connection);
-
return SCTP_ERROR_NONE;
}
@@ -870,7 +868,7 @@ sctp46_rcv_phase_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
ip6_header_t *ip6_hdr = 0;
sctp_connection_t *sctp_conn, *new_sctp_conn;
u16 sctp_implied_length = 0;
- u16 error0 = SCTP_ERROR_NONE, next0 = SCTP_RCV_PHASE_N_NEXT;
+ u16 error0 = SCTP_ERROR_NONE, next0 = sctp_next_drop (is_ip4);
u8 idx;
bi0 = from[0];
@@ -936,6 +934,8 @@ sctp46_rcv_phase_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
new_sctp_conn - tm->connections[my_thread_index];
new_sctp_conn->sub_conn[idx].c_thread_index =
my_thread_index;
+ new_sctp_conn->sub_conn[idx].PMTU =
+ sctp_conn->sub_conn[idx].PMTU;
new_sctp_conn->sub_conn[idx].parent = new_sctp_conn;
if (sctp_half_open_connection_cleanup (sctp_conn))
@@ -951,7 +951,7 @@ sctp46_rcv_phase_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
new_sctp_conn, idx, b0,
sctp_implied_length);
- sctp_init_mss (new_sctp_conn);
+ sctp_init_cwnd (new_sctp_conn);
if (session_stream_connect_notify
(&new_sctp_conn->sub_conn[idx].connection, 0))
@@ -962,8 +962,8 @@ sctp46_rcv_phase_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
sctp_connection_cleanup (new_sctp_conn);
goto drop;
}
+ next0 = sctp_next_output (is_ip4);
}
- next0 = sctp_next_output (is_ip4);
break;
/* All UNEXPECTED scenarios (wrong chunk received per state-machine)
@@ -1177,13 +1177,11 @@ sctp_handle_shutdown_complete (sctp_header_t * sctp_hdr,
if (sctp_is_bundling (sctp_implied_length, &shutdown_complete->chunk_hdr))
return SCTP_ERROR_BUNDLING_VIOLATION;
- sctp_timer_reset (sctp_conn, MAIN_SCTP_SUB_CONN_IDX,
- SCTP_TIMER_T2_SHUTDOWN);
+ sctp_timer_reset (sctp_conn, idx, SCTP_TIMER_T2_SHUTDOWN);
- sctp_conn->state = SCTP_STATE_CLOSED;
+ stream_session_disconnect_notify (&sctp_conn->sub_conn[idx].connection);
- stream_session_disconnect_notify (&sctp_conn->sub_conn
- [MAIN_SCTP_SUB_CONN_IDX].connection);
+ sctp_conn->state = SCTP_STATE_CLOSED;
*next0 = sctp_next_drop (sctp_conn->sub_conn[idx].c_is_ip4);
@@ -1422,6 +1420,17 @@ sctp_handle_sack (sctp_selective_ack_chunk_t * sack_chunk,
sctp_conn->sub_conn[idx].last_seen = sctp_time_now ();
+ /* Section 7.2.2; point (2) */
+ if (sctp_conn->sub_conn[idx].cwnd > sctp_conn->sub_conn[idx].ssthresh)
+ sctp_conn->sub_conn[idx].partially_acked_bytes =
+ sctp_conn->next_tsn - sack_chunk->cumulative_tsn_ack;
+
+ /* Section 7.2.2; point (5) */
+ if (sctp_conn->next_tsn - sack_chunk->cumulative_tsn_ack == 0)
+ sctp_conn->sub_conn[idx].partially_acked_bytes = 0;
+
+ sctp_conn->last_unacked_tsn = sack_chunk->cumulative_tsn_ack;
+
sctp_calculate_rto (sctp_conn, idx);
sctp_timer_update (sctp_conn, idx, SCTP_TIMER_T3_RXTX,
@@ -1510,7 +1519,7 @@ sctp46_listen_process_inline (vlib_main_t * vm,
ip6_header_t *ip6_hdr;
sctp_connection_t *child_conn;
sctp_connection_t *sctp_listener;
- u16 next0 = SCTP_LISTEN_PHASE_N_NEXT, error0 = SCTP_ERROR_ENQUEUED;
+ u16 next0 = sctp_next_drop (is_ip4), error0 = SCTP_ERROR_ENQUEUED;
bi0 = from[0];
to_next[0] = bi0;
@@ -1560,6 +1569,8 @@ sctp46_listen_process_inline (vlib_main_t * vm,
child_conn->sub_conn[MAIN_SCTP_SUB_CONN_IDX].c_is_ip4 = is_ip4;
child_conn->sub_conn[MAIN_SCTP_SUB_CONN_IDX].connection.proto =
sctp_listener->sub_conn[MAIN_SCTP_SUB_CONN_IDX].connection.proto;
+ child_conn->sub_conn[MAIN_SCTP_SUB_CONN_IDX].PMTU =
+ sctp_listener->sub_conn[MAIN_SCTP_SUB_CONN_IDX].PMTU;
child_conn->state = SCTP_STATE_CLOSED;
if (is_ip4)
@@ -1609,7 +1620,7 @@ sctp46_listen_process_inline (vlib_main_t * vm,
sctp_handle_init (sctp_hdr, sctp_chunk_hdr, child_conn, b0,
sctp_implied_length);
- sctp_init_mss (child_conn);
+ sctp_init_cwnd (child_conn);
if (error0 == SCTP_ERROR_NONE)
{
@@ -1624,8 +1635,8 @@ sctp46_listen_process_inline (vlib_main_t * vm,
error0 = SCTP_ERROR_CREATE_SESSION_FAIL;
goto drop;
}
+ next0 = sctp_next_output (is_ip4);
}
- next0 = sctp_next_output (is_ip4);
break;
/* Reception of a DATA chunk whilst in the CLOSED state is called
@@ -2058,9 +2069,6 @@ sctp46_input_dispatcher (vlib_main_t * vm, vlib_node_runtime_t * node,
goto done;
}
-#if SCTP_DEBUG_STATE_MACHINE
- u8 idx = sctp_pick_conn_idx_on_state (sctp_conn->state);
-#endif
vnet_buffer (b0)->sctp.hdr_offset =
(u8 *) sctp_hdr - (u8 *) vlib_buffer_get_current (b0);
@@ -2075,15 +2083,12 @@ sctp46_input_dispatcher (vlib_main_t * vm, vlib_node_runtime_t * node,
next0 = tm->dispatch_table[sctp_conn->state][chunk_type].next;
error0 = tm->dispatch_table[sctp_conn->state][chunk_type].error;
- SCTP_DBG_STATE_MACHINE ("CONNECTION_INDEX = %u: "
- "CURRENT_CONNECTION_STATE = %s,"
- "CHUNK_TYPE_RECEIVED = %s "
- "NEXT_PHASE = %s",
- sctp_conn->sub_conn
- [idx].connection.c_index,
- sctp_state_to_string (sctp_conn->state),
- sctp_chunk_to_string (chunk_type),
- phase_to_string (next0));
+ SCTP_DBG_STATE_MACHINE
+ ("SESSION_INDEX = %u, CURRENT_CONNECTION_STATE = %s,"
+ "CHUNK_TYPE_RECEIVED = %s " "NEXT_PHASE = %s",
+ sctp_conn->sub_conn[MAIN_SCTP_SUB_CONN_IDX].
+ connection.s_index, sctp_state_to_string (sctp_conn->state),
+ sctp_chunk_to_string (chunk_type), phase_to_string (next0));
if (chunk_type == DATA)
SCTP_ADV_DBG ("n_advance_bytes0 = %u, n_data_bytes0 = %u",
@@ -2223,7 +2228,7 @@ do { \
* _(SHUTDOWN_RECEIVED, "SHUTDOWN_RECEIVED") \
* _(SHUTDOWN_ACK_SENT, "SHUTDOWN_ACK_SENT")
*/
- _(CLOSED, DATA, SCTP_INPUT_NEXT_LISTEN_PHASE, SCTP_ERROR_NONE); /* UNEXPECTED DATA chunk which requires special handling */
+ //_(CLOSED, DATA, SCTP_INPUT_NEXT_LISTEN_PHASE, SCTP_ERROR_NONE); /* UNEXPECTED DATA chunk which requires special handling */
_(CLOSED, INIT, SCTP_INPUT_NEXT_LISTEN_PHASE, SCTP_ERROR_NONE);
_(CLOSED, INIT_ACK, SCTP_INPUT_NEXT_DROP, SCTP_ERROR_ACK_DUP); /* UNEXPECTED INIT_ACK chunk */
_(CLOSED, SACK, SCTP_INPUT_NEXT_DROP, SCTP_ERROR_SACK_CHUNK_VIOLATION); /* UNEXPECTED SACK chunk */