diff options
author | Marco Varlese <marco.varlese@suse.com> | 2018-02-15 17:01:56 +0100 |
---|---|---|
committer | Damjan Marion <dmarion.lists@gmail.com> | 2018-02-17 09:45:28 +0000 |
commit | 54432f8c0ac1f680198afa6047ce74bc4a126f21 (patch) | |
tree | 472bcb2609160a17e285d97d0d1b484baa332af8 /src/vnet/sctp/sctp_output.c | |
parent | a250882b8fbc3f75d919bffaea10809a37205204 (diff) |
SCTP: 'multi-home' support
This patch addresses the SCTP requirement for multiple sub-connections
to implement the so called 'multi-homed' scenario.
Change-Id: Ibce18f216e9d2bebe318992c441bf278e16aad17
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.c | 120 |
1 files changed, 62 insertions, 58 deletions
diff --git a/src/vnet/sctp/sctp_output.c b/src/vnet/sctp/sctp_output.c index 6012e50b908..459b33d46bc 100644 --- a/src/vnet/sctp/sctp_output.c +++ b/src/vnet/sctp/sctp_output.c @@ -261,6 +261,7 @@ sctp_reuse_buffer (vlib_main_t * vm, vlib_buffer_t * b) b->current_length = 0; b->total_length_not_including_first_buffer = 0; vnet_buffer (b)->sctp.flags = 0; + vnet_buffer (b)->sctp.conn_idx = MAX_SCTP_CONNECTIONS; /* Leave enough space for headers */ return vlib_buffer_make_headroom (b, MAX_HDRS_LEN); @@ -274,6 +275,7 @@ sctp_init_buffer (vlib_main_t * vm, vlib_buffer_t * b) b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; b->total_length_not_including_first_buffer = 0; vnet_buffer (b)->sctp.flags = 0; + vnet_buffer (b)->sctp.conn_idx = MAX_SCTP_CONNECTIONS; VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b); /* Leave enough space for headers */ return vlib_buffer_make_headroom (b, MAX_HDRS_LEN); @@ -410,12 +412,12 @@ sctp_enqueue_to_ip_lookup (vlib_main_t * vm, vlib_buffer_t * b, u32 bi, * Convert buffer to INIT */ void -sctp_prepare_init_chunk (sctp_connection_t * sctp_conn, vlib_buffer_t * b) +sctp_prepare_init_chunk (sctp_connection_t * sctp_conn, u8 idx, + vlib_buffer_t * b) { u32 random_seed = random_default_seed (); u16 alloc_bytes = sizeof (sctp_init_chunk_t); - sctp_sub_connection_t *sub_conn = - &sctp_conn->sub_conn[sctp_pick_conn_idx_on_chunk (INIT)]; + sctp_sub_connection_t *sub_conn = &sctp_conn->sub_conn[idx]; sctp_ipv4_addr_param_t *ip4_param = 0; sctp_ipv6_addr_param_t *ip6_param = 0; @@ -476,6 +478,7 @@ sctp_prepare_init_chunk (sctp_connection_t * sctp_conn, vlib_buffer_t * b) sctp_conn->local_tag = init_chunk->initiate_tag; vnet_buffer (b)->sctp.connection_index = sub_conn->c_c_index; + vnet_buffer (b)->sctp.conn_idx = idx; SCTP_DBG_STATE_MACHINE ("CONN_INDEX = %u, CURR_CONN_STATE = %u (%s), " "CHUNK_TYPE = %s, " @@ -518,11 +521,10 @@ sctp_compute_mac (sctp_connection_t * sctp_conn, } void -sctp_prepare_cookie_ack_chunk (sctp_connection_t * sctp_conn, +sctp_prepare_cookie_ack_chunk (sctp_connection_t * sctp_conn, u8 idx, vlib_buffer_t * b) { vlib_main_t *vm = vlib_get_main (); - u8 idx = sctp_pick_conn_idx_on_chunk (COOKIE_ACK); sctp_reuse_buffer (vm, b); @@ -549,15 +551,15 @@ sctp_prepare_cookie_ack_chunk (sctp_connection_t * sctp_conn, vnet_buffer (b)->sctp.connection_index = sctp_conn->sub_conn[idx].connection.c_index; + vnet_buffer (b)->sctp.conn_idx = idx; } void -sctp_prepare_cookie_echo_chunk (sctp_connection_t * sctp_conn, +sctp_prepare_cookie_echo_chunk (sctp_connection_t * sctp_conn, u8 idx, vlib_buffer_t * b, sctp_state_cookie_param_t * sc) { vlib_main_t *vm = vlib_get_main (); - u8 idx = sctp_pick_conn_idx_on_chunk (COOKIE_ECHO); sctp_reuse_buffer (vm, b); @@ -583,20 +585,20 @@ sctp_prepare_cookie_echo_chunk (sctp_connection_t * sctp_conn, vnet_buffer (b)->sctp.connection_index = sctp_conn->sub_conn[idx].connection.c_index; + vnet_buffer (b)->sctp.conn_idx = idx; } /** * Convert buffer to INIT-ACK */ void -sctp_prepare_initack_chunk (sctp_connection_t * sctp_conn, vlib_buffer_t * b, - ip4_address_t * ip4_addr, +sctp_prepare_initack_chunk (sctp_connection_t * sctp_conn, u8 idx, + vlib_buffer_t * b, ip4_address_t * ip4_addr, ip6_address_t * ip6_addr) { vlib_main_t *vm = vlib_get_main (); sctp_ipv4_addr_param_t *ip4_param = 0; sctp_ipv6_addr_param_t *ip6_param = 0; - u8 idx = sctp_pick_conn_idx_on_chunk (INIT_ACK); u32 random_seed = random_default_seed (); sctp_reuse_buffer (vm, b); @@ -725,15 +727,16 @@ sctp_prepare_initack_chunk (sctp_connection_t * sctp_conn, vlib_buffer_t * b, vnet_buffer (b)->sctp.connection_index = sctp_conn->sub_conn[idx].connection.c_index; + vnet_buffer (b)->sctp.conn_idx = idx; } /** * Convert buffer to SHUTDOWN */ void -sctp_prepare_shutdown_chunk (sctp_connection_t * sctp_conn, vlib_buffer_t * b) +sctp_prepare_shutdown_chunk (sctp_connection_t * sctp_conn, u8 idx, + vlib_buffer_t * b) { - u8 idx = sctp_pick_conn_idx_on_chunk (SHUTDOWN); u16 alloc_bytes = sizeof (sctp_shutdown_association_chunk_t); /* As per RFC 4960 the chunk_length value does NOT contemplate @@ -760,6 +763,7 @@ sctp_prepare_shutdown_chunk (sctp_connection_t * sctp_conn, vlib_buffer_t * b) vnet_buffer (b)->sctp.connection_index = sctp_conn->sub_conn[idx].connection.c_index; + vnet_buffer (b)->sctp.conn_idx = idx; } /* @@ -779,11 +783,12 @@ sctp_send_shutdown (sctp_connection_t * sctp_conn) if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi))) return; + u8 idx = MAIN_SCTP_SUB_CONN_IDX; + b = vlib_get_buffer (vm, bi); sctp_init_buffer (vm, b); - sctp_prepare_shutdown_chunk (sctp_conn, b); + sctp_prepare_shutdown_chunk (sctp_conn, idx, b); - 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); } @@ -792,10 +797,9 @@ sctp_send_shutdown (sctp_connection_t * sctp_conn) * Convert buffer to SHUTDOWN_ACK */ void -sctp_prepare_shutdown_ack_chunk (sctp_connection_t * sctp_conn, +sctp_prepare_shutdown_ack_chunk (sctp_connection_t * sctp_conn, u8 idx, vlib_buffer_t * b) { - u8 idx = sctp_pick_conn_idx_on_chunk (SHUTDOWN_ACK); u16 alloc_bytes = sizeof (sctp_shutdown_association_chunk_t); alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes); @@ -817,13 +821,15 @@ sctp_prepare_shutdown_ack_chunk (sctp_connection_t * sctp_conn, vnet_buffer (b)->sctp.connection_index = sctp_conn->sub_conn[idx].connection.c_index; + vnet_buffer (b)->sctp.conn_idx = idx; } /* * Send SHUTDOWN_ACK */ void -sctp_send_shutdown_ack (sctp_connection_t * sctp_conn, vlib_buffer_t * b) +sctp_send_shutdown_ack (sctp_connection_t * sctp_conn, u8 idx, + vlib_buffer_t * b) { vlib_main_t *vm = vlib_get_main (); @@ -832,17 +838,17 @@ 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); + sctp_prepare_shutdown_ack_chunk (sctp_conn, idx, b); } /** * Convert buffer to SACK */ void -sctp_prepare_sack_chunk (sctp_connection_t * sctp_conn, vlib_buffer_t * b) +sctp_prepare_sack_chunk (sctp_connection_t * sctp_conn, u8 idx, + vlib_buffer_t * b) { vlib_main_t *vm = vlib_get_main (); - u8 idx = sctp_pick_conn_idx_on_chunk (SACK); sctp_reuse_buffer (vm, b); @@ -870,18 +876,18 @@ sctp_prepare_sack_chunk (sctp_connection_t * sctp_conn, vlib_buffer_t * b) vnet_buffer (b)->sctp.connection_index = sctp_conn->sub_conn[idx].connection.c_index; + vnet_buffer (b)->sctp.conn_idx = idx; } /** * Convert buffer to HEARTBEAT_ACK */ void -sctp_prepare_heartbeat_ack_chunk (sctp_connection_t * sctp_conn, +sctp_prepare_heartbeat_ack_chunk (sctp_connection_t * sctp_conn, u8 idx, vlib_buffer_t * b) { vlib_main_t *vm = vlib_get_main (); - u8 idx = sctp_pick_conn_idx_on_chunk (HEARTBEAT_ACK); u16 alloc_bytes = sizeof (sctp_hb_ack_chunk_t); sctp_reuse_buffer (vm, b); @@ -909,16 +915,16 @@ sctp_prepare_heartbeat_ack_chunk (sctp_connection_t * sctp_conn, vnet_buffer (b)->sctp.connection_index = sctp_conn->sub_conn[idx].connection.c_index; + vnet_buffer (b)->sctp.conn_idx = idx; } /** * Convert buffer to HEARTBEAT */ void -sctp_prepare_heartbeat_chunk (sctp_connection_t * sctp_conn, +sctp_prepare_heartbeat_chunk (sctp_connection_t * sctp_conn, u8 idx, vlib_buffer_t * b) { - u8 idx = sctp_pick_conn_idx_on_chunk (HEARTBEAT); u16 alloc_bytes = sizeof (sctp_hb_req_chunk_t); /* As per RFC 4960 the chunk_length value does NOT contemplate @@ -944,6 +950,7 @@ sctp_prepare_heartbeat_chunk (sctp_connection_t * sctp_conn, vnet_buffer (b)->sctp.connection_index = sctp_conn->sub_conn[idx].connection.c_index; + vnet_buffer (b)->sctp.conn_idx = idx; } void @@ -954,28 +961,39 @@ sctp_send_heartbeat (sctp_connection_t * sctp_conn) sctp_main_t *tm = vnet_get_sctp_main (); vlib_main_t *vm = vlib_get_main (); - if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi))) - return; + u8 i; + u32 now = sctp_time_now (); - b = vlib_get_buffer (vm, bi); - sctp_init_buffer (vm, b); - sctp_prepare_heartbeat_chunk (sctp_conn, b); + for (i = 0; i < MAX_SCTP_CONNECTIONS; i++) + { + if (sctp_conn->sub_conn[i].state == SCTP_SUBCONN_STATE_DOWN) + continue; - u8 idx = sctp_pick_conn_idx_on_state (SCTP_STATE_ESTABLISHED); - sctp_enqueue_to_output_now (vm, b, bi, - sctp_conn->sub_conn[idx].connection.is_ip4); + if (now > (sctp_conn->sub_conn[i].last_seen + SCTP_HB_INTERVAL)) + { + if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi))) + return; + + b = vlib_get_buffer (vm, bi); + sctp_init_buffer (vm, b); + sctp_prepare_heartbeat_chunk (sctp_conn, i, b); + + sctp_enqueue_to_output_now (vm, b, bi, + sctp_conn->sub_conn[i]. + connection.is_ip4); - sctp_conn->sub_conn[idx].unacknowledged_hb += 1; + sctp_conn->sub_conn[i].unacknowledged_hb += 1; + } + } } /** * Convert buffer to SHUTDOWN_COMPLETE */ void -sctp_prepare_shutdown_complete_chunk (sctp_connection_t * sctp_conn, +sctp_prepare_shutdown_complete_chunk (sctp_connection_t * sctp_conn, u8 idx, vlib_buffer_t * b) { - u8 idx = sctp_pick_conn_idx_on_chunk (SHUTDOWN_COMPLETE); u16 alloc_bytes = sizeof (sctp_shutdown_association_chunk_t); alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes); @@ -997,10 +1015,11 @@ sctp_prepare_shutdown_complete_chunk (sctp_connection_t * sctp_conn, vnet_buffer (b)->sctp.connection_index = sctp_conn->sub_conn[idx].connection.c_index; + vnet_buffer (b)->sctp.conn_idx = idx; } void -sctp_send_shutdown_complete (sctp_connection_t * sctp_conn, +sctp_send_shutdown_complete (sctp_connection_t * sctp_conn, u8 idx, vlib_buffer_t * b0) { vlib_main_t *vm = vlib_get_main (); @@ -1010,12 +1029,11 @@ sctp_send_shutdown_complete (sctp_connection_t * sctp_conn, sctp_reuse_buffer (vm, b0); - sctp_prepare_shutdown_complete_chunk (sctp_conn, b0); + sctp_prepare_shutdown_complete_chunk (sctp_conn, idx, b0); sctp_conn->state = SCTP_STATE_CLOSED; } - /* * Send INIT */ @@ -1031,10 +1049,10 @@ sctp_send_init (sctp_connection_t * sctp_conn) return; b = vlib_get_buffer (vm, bi); - u8 idx = sctp_pick_conn_idx_on_chunk (INIT); + u8 idx = MAIN_SCTP_SUB_CONN_IDX; sctp_init_buffer (vm, b); - sctp_prepare_init_chunk (sctp_conn, b); + sctp_prepare_init_chunk (sctp_conn, idx, b); 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); @@ -1099,6 +1117,8 @@ sctp_push_hdr_i (sctp_connection_t * sctp_conn, u8 idx, vlib_buffer_t * b, vnet_buffer (b)->sctp.connection_index = sctp_conn->sub_conn[idx].connection.c_index; + + vnet_buffer (b)->sctp.conn_idx = idx; } u32 @@ -1107,29 +1127,13 @@ sctp_push_header (transport_connection_t * trans_conn, vlib_buffer_t * b) sctp_connection_t *sctp_conn = sctp_get_connection_from_transport (trans_conn); - u8 idx = sctp_pick_conn_idx_on_chunk (DATA); - - if (sctp_conn->sub_conn[idx].unacknowledged_hb > - SCTP_ASSOCIATION_MAX_RETRANS) - { - // The remote-peer is considered to be unreachable hence shutting down - - /* Start cleanup. App wasn't notified yet so use delete notify as - * opposed to delete to cleanup session layer state. */ - stream_session_delete_notify (&sctp_conn->sub_conn - [MAIN_SCTP_SUB_CONN_IDX].connection); - - sctp_connection_timers_reset (sctp_conn); - - sctp_connection_cleanup (sctp_conn); - } + u8 idx = sctp_data_subconn_select (sctp_conn); sctp_push_hdr_i (sctp_conn, idx, b, SCTP_STATE_ESTABLISHED); sctp_trajectory_add_start (b0, 3); return 0; - } #if SCTP_DEBUG_STATE_MACHINE @@ -1227,7 +1231,7 @@ sctp46_output_inline (vlib_main_t * vm, goto done; } - u8 idx = sctp_pick_conn_idx_on_state (sctp_conn->state); + u8 idx = vnet_buffer (b0)->sctp.conn_idx; th0 = vlib_buffer_get_current (b0); |