#include <vppinfra/random.h>
#include <openssl/hmac.h>
-vlib_node_registration_t sctp4_output_node;
-vlib_node_registration_t sctp6_output_node;
-
-typedef enum _sctp_output_next
-{
- SCTP_OUTPUT_NEXT_DROP,
- SCTP_OUTPUT_NEXT_IP_LOOKUP,
- SCTP_OUTPUT_N_NEXT
-} sctp_output_next_t;
-
-#define foreach_sctp4_output_next \
- _ (DROP, "error-drop") \
- _ (IP_LOOKUP, "ip4-lookup")
-
-#define foreach_sctp6_output_next \
- _ (DROP, "error-drop") \
- _ (IP_LOOKUP, "ip6-lookup")
-
-static char *sctp_error_strings[] = {
-#define sctp_error(n,s) s,
-#include <vnet/sctp/sctp_error.def>
-#undef sctp_error
-};
-
-typedef struct
-{
- sctp_header_t sctp_header;
- sctp_connection_t sctp_connection;
-} sctp_tx_trace_t;
-
/**
* Flush tx frame populated by retransmits and timer pops
*/
vnet_buffer (b)->sctp.subconn_idx = MAX_SCTP_CONNECTIONS;
/* Leave enough space for headers */
- return vlib_buffer_make_headroom (b, MAX_HDRS_LEN);
+ return vlib_buffer_make_headroom (b, TRANSPORT_MAX_HDRS_LEN);
}
always_inline void *
sctp_init_buffer (vlib_main_t * vm, vlib_buffer_t * b)
{
ASSERT ((b->flags & VLIB_BUFFER_NEXT_PRESENT) == 0);
- b->flags &= VLIB_BUFFER_NON_DEFAULT_FREELIST;
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.subconn_idx = MAX_SCTP_CONNECTIONS;
VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b);
/* Leave enough space for headers */
- return vlib_buffer_make_headroom (b, MAX_HDRS_LEN);
+ return vlib_buffer_make_headroom (b, TRANSPORT_MAX_HDRS_LEN);
}
always_inline int
always_inline void
sctp_enqueue_to_ip_lookup_i (vlib_main_t * vm, vlib_buffer_t * b, u32 bi,
- u8 is_ip4, u8 flush)
+ u8 is_ip4, u32 fib_index, u8 flush)
{
sctp_main_t *tm = vnet_get_sctp_main ();
u32 thread_index = vlib_get_thread_index ();
b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
b->error = 0;
- /* Default FIB for now */
- vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
+ vnet_buffer (b)->sw_if_index[VLIB_TX] = fib_index;
+ vnet_buffer (b)->sw_if_index[VLIB_RX] = 0;
/* Send to IP lookup */
next_index = is_ip4 ? ip4_lookup_node.index : ip6_lookup_node.index;
always_inline void
sctp_enqueue_to_ip_lookup (vlib_main_t * vm, vlib_buffer_t * b, u32 bi,
- u8 is_ip4)
+ u8 is_ip4, u32 fib_index)
{
- sctp_enqueue_to_ip_lookup_i (vm, b, bi, is_ip4, 0);
+ sctp_enqueue_to_ip_lookup_i (vm, b, bi, is_ip4, fib_index, 0);
+ if (vm->thread_index == 0 && vlib_num_workers ())
+ session_flush_frames_main_thread (vm);
}
/**
vnet_sctp_set_chunk_length (&init_chunk->chunk_hdr, chunk_len);
vnet_sctp_common_hdr_params_host_to_net (&init_chunk->chunk_hdr);
+ sctp_init_cwnd (sctp_conn);
+
init_chunk->a_rwnd = clib_host_to_net_u32 (sctp_conn->sub_conn[idx].cwnd);
init_chunk->initiate_tag = clib_host_to_net_u32 (random_u32 (&random_seed));
init_chunk->inboud_streams_count =
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), &sctp_conn->cookie_param,
- sizeof (sctp_state_cookie_param_t));
+ clib_memcpy_fast (&(cookie_echo_chunk->cookie), &sctp_conn->cookie_param,
+ sizeof (sctp_state_cookie_param_t));
vnet_buffer (b)->sctp.connection_index =
sctp_conn->sub_conn[idx].connection.c_index;
clib_host_to_net_u16 (SCTP_STATE_COOKIE_TYPE);
state_cookie_param->param_hdr.length =
clib_host_to_net_u16 (sizeof (sctp_state_cookie_param_t));
- state_cookie_param->creation_time = clib_host_to_net_u32 (sctp_time_now ());
+ state_cookie_param->creation_time = clib_host_to_net_u64 (sctp_time_now ());
state_cookie_param->cookie_lifespan =
clib_host_to_net_u32 (SCTP_VALID_COOKIE_LIFE);
void
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)
+ u8 add_ip4, ip6_address_t * ip6_addr, u8 add_ip6)
{
vlib_main_t *vm = vlib_get_main ();
sctp_ipv4_addr_param_t *ip4_param = 0;
u16 alloc_bytes =
sizeof (sctp_init_ack_chunk_t) + sizeof (sctp_state_cookie_param_t);
- if (PREDICT_TRUE (ip4_addr != NULL))
+ if (PREDICT_FALSE (add_ip4 == 1))
{
/* Create room for variable-length fields in the INIT_ACK chunk */
alloc_bytes += SCTP_IPV4_ADDRESS_TYPE_LENGTH;
}
- if (PREDICT_TRUE (ip6_addr != NULL))
+ if (PREDICT_FALSE (add_ip6 == 1))
{
/* Create room for variable-length fields in the INIT_ACK chunk */
alloc_bytes += SCTP_IPV6_ADDRESS_TYPE_LENGTH;
clib_host_to_net_u16 (SCTP_STATE_COOKIE_TYPE);
state_cookie_param->param_hdr.length =
clib_host_to_net_u16 (sizeof (sctp_state_cookie_param_t));
- state_cookie_param->creation_time = clib_host_to_net_u32 (sctp_time_now ());
+ state_cookie_param->creation_time = clib_host_to_net_u64 (sctp_time_now ());
state_cookie_param->cookie_lifespan =
clib_host_to_net_u32 (SCTP_VALID_COOKIE_LIFE);
vlib_main_t *vm = vlib_get_main ();
u8 i;
- u32 now = sctp_time_now ();
+ u64 now = sctp_time_now ();
for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
{
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);
+ sctp_enqueue_to_ip_lookup (vm, b, bi, sctp_conn->sub_conn[idx].c_is_ip4,
+ sctp_conn->sub_conn[idx].c_fib_index);
/* Start the T1_INIT timer */
sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T1_INIT,
sctp_push_hdr_i (sctp_connection_t * sctp_conn, vlib_buffer_t * b,
sctp_state_t next_state)
{
- u16 data_len =
- b->current_length + b->total_length_not_including_first_buffer;
+ u16 data_len = b->current_length;
+
+ if (b->flags & VLIB_BUFFER_TOTAL_LENGTH_VALID)
+ data_len += b->total_length_not_including_first_buffer;
+
ASSERT (!b->total_length_not_including_first_buffer
|| (b->flags & VLIB_BUFFER_NEXT_PRESENT));
"data_len = %u",
b->current_length, b->current_data, data_len);
+ u16 data_padding = vnet_sctp_calculate_padding (b->current_length);
+ if (data_padding > 0)
+ {
+ u8 *p_tail = vlib_buffer_put_uninit (b, data_padding);
+ clib_memset_u8 (p_tail, 0, data_padding);
+ }
+
u16 bytes_to_add = sizeof (sctp_payload_data_chunk_t);
u16 chunk_length = data_len + bytes_to_add - sizeof (sctp_header_t);
- bytes_to_add += vnet_sctp_calculate_padding (bytes_to_add + data_len);
-
sctp_payload_data_chunk_t *data_chunk =
vlib_buffer_push_uninit (b, bytes_to_add);
SCTP_ADV_DBG_OUTPUT ("POINTER_WITH_DATA = %p, DATA_OFFSET = %u",
b->data, b->current_data);
- sctp_conn->last_unacked_tsn = sctp_conn->next_tsn;
+ if (sctp_conn->sub_conn[idx].state != SCTP_SUBCONN_AWAITING_SACK)
+ {
+ sctp_conn->sub_conn[idx].state = SCTP_SUBCONN_AWAITING_SACK;
+ sctp_conn->last_unacked_tsn = sctp_conn->next_tsn;
+ }
+
sctp_conn->next_tsn += data_len;
u32 inflight = sctp_conn->next_tsn - sctp_conn->last_unacked_tsn;
return 0;
}
+u32
+sctp_prepare_data_retransmit (sctp_connection_t * sctp_conn,
+ u8 idx,
+ u32 offset,
+ u32 max_deq_bytes, vlib_buffer_t ** b)
+{
+ sctp_main_t *tm = vnet_get_sctp_main ();
+ vlib_main_t *vm = vlib_get_main ();
+ int n_bytes = 0;
+ u32 bi, available_bytes, seg_size;
+ u8 *data;
+
+ ASSERT (sctp_conn->state >= SCTP_STATE_ESTABLISHED);
+ ASSERT (max_deq_bytes != 0);
+
+ /*
+ * Make sure we can retransmit something
+ */
+ available_bytes =
+ transport_max_tx_dequeue (&sctp_conn->sub_conn[idx].connection);
+ ASSERT (available_bytes >= offset);
+ available_bytes -= offset;
+ if (!available_bytes)
+ return 0;
+ max_deq_bytes = clib_min (sctp_conn->sub_conn[idx].cwnd, max_deq_bytes);
+ max_deq_bytes = clib_min (available_bytes, max_deq_bytes);
+
+ seg_size = max_deq_bytes;
+
+ /*
+ * Allocate and fill in buffer(s)
+ */
+
+ if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
+ return 0;
+ *b = vlib_get_buffer (vm, bi);
+ data = sctp_init_buffer (vm, *b);
+
+ /* Easy case, buffer size greater than mss */
+ if (PREDICT_TRUE (seg_size <= tm->bytes_per_buffer))
+ {
+ n_bytes =
+ session_tx_fifo_peek_bytes (&sctp_conn->sub_conn[idx].connection,
+ data, offset, max_deq_bytes);
+ ASSERT (n_bytes == max_deq_bytes);
+ b[0]->current_length = n_bytes;
+ sctp_push_hdr_i (sctp_conn, *b, sctp_conn->state);
+ }
+
+ return n_bytes;
+}
+
void
sctp_data_retransmit (sctp_connection_t * sctp_conn)
{
- /* TODO: requires use of PEEK/SEND */
+ vlib_main_t *vm = vlib_get_main ();
+ vlib_buffer_t *b = 0;
+ u32 bi, n_bytes = 0;
+
+ u8 idx = sctp_data_subconn_select (sctp_conn);
+
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.lcl_port,
sctp_conn->sub_conn[idx].connection.rmt_port);
+ if (sctp_conn->state >= SCTP_STATE_ESTABLISHED)
+ {
+ return;
+ }
+
+ n_bytes =
+ sctp_prepare_data_retransmit (sctp_conn, idx, 0,
+ sctp_conn->sub_conn[idx].cwnd, &b);
+ if (n_bytes > 0)
+ SCTP_DBG_OUTPUT ("We have data (%u bytes) to retransmit", n_bytes);
+
+ bi = vlib_get_buffer_index (vm, b);
+
+ sctp_enqueue_to_output_now (vm, b, bi,
+ sctp_conn->sub_conn[idx].connection.is_ip4);
+
return;
}
}
#endif
-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,
- vlib_frame_t * from_frame, int is_ip4)
-{
- u32 n_left_from, next_index, *from, *to_next;
- u32 my_thread_index = vm->thread_index;
-
- from = vlib_frame_vector_args (from_frame);
- n_left_from = from_frame->n_vectors;
- next_index = node->cached_next_index;
- sctp_set_time_now (my_thread_index);
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- u32 bi0;
- vlib_buffer_t *b0;
- sctp_header_t *sctp_hdr = 0;
- sctp_connection_t *sctp_conn;
- sctp_tx_trace_t *t0;
- sctp_header_t *th0 = 0;
- u32 error0 = SCTP_ERROR_PKTS_SENT, next0 =
- SCTP_OUTPUT_NEXT_IP_LOOKUP;
-
-#if SCTP_DEBUG_STATE_MACHINE
- u16 packet_length = 0;
-#endif
-
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- 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);
-
- if (PREDICT_FALSE (sctp_conn == 0))
- {
- error0 = SCTP_ERROR_INVALID_CONNECTION;
- next0 = SCTP_OUTPUT_NEXT_DROP;
- goto done;
- }
-
- u8 idx = vnet_buffer (b0)->sctp.subconn_idx;
-
- th0 = vlib_buffer_get_current (b0);
-
- if (is_ip4)
- {
- ip4_header_t *iph4 = vlib_buffer_push_ip4 (vm,
- b0,
- &sctp_conn->sub_conn
- [idx].connection.
- lcl_ip.ip4,
- &sctp_conn->
- sub_conn
- [idx].connection.
- rmt_ip.ip4,
- IP_PROTOCOL_SCTP, 1);
-
- u32 checksum = ip4_sctp_compute_checksum (vm, b0, iph4);
-
- sctp_hdr = ip4_next_header (iph4);
- sctp_hdr->checksum = checksum;
-
- vnet_buffer (b0)->l4_hdr_offset = (u8 *) th0 - b0->data;
-
-#if SCTP_DEBUG_STATE_MACHINE
- packet_length = clib_net_to_host_u16 (iph4->length);
-#endif
- }
- else
- {
- ip6_header_t *iph6 = vlib_buffer_push_ip6 (vm,
- b0,
- &sctp_conn->sub_conn
- [idx].
- connection.lcl_ip.
- ip6,
- &sctp_conn->sub_conn
- [idx].
- connection.rmt_ip.
- ip6,
- IP_PROTOCOL_SCTP);
-
- int bogus = ~0;
- u32 checksum = ip6_sctp_compute_checksum (vm, b0, iph6, &bogus);
- ASSERT (!bogus);
-
- sctp_hdr = ip6_next_header (iph6);
- sctp_hdr->checksum = checksum;
-
- vnet_buffer (b0)->l3_hdr_offset = (u8 *) iph6 - b0->data;
- vnet_buffer (b0)->l4_hdr_offset = (u8 *) th0 - b0->data;
-
-#if SCTP_DEBUG_STATE_MACHINE
- packet_length = clib_net_to_host_u16 (iph6->payload_length);
-#endif
- }
-
- sctp_full_hdr_t *full_hdr = (sctp_full_hdr_t *) sctp_hdr;
- u8 chunk_type = vnet_sctp_get_chunk_type (&full_hdr->common_hdr);
- if (chunk_type >= UNKNOWN)
- {
- clib_warning
- ("Trying to send an unrecognized chunk... something is really bad.");
- error0 = SCTP_ERROR_UNKOWN_CHUNK;
- next0 = SCTP_OUTPUT_NEXT_DROP;
- goto done;
- }
-
-#if SCTP_DEBUG_STATE_MACHINE
- u8 is_valid =
- (sctp_conn->sub_conn[idx].connection.lcl_port ==
- sctp_hdr->src_port
- || sctp_conn->sub_conn[idx].connection.lcl_port ==
- sctp_hdr->dst_port)
- && (sctp_conn->sub_conn[idx].connection.rmt_port ==
- sctp_hdr->dst_port
- || sctp_conn->sub_conn[idx].connection.rmt_port ==
- sctp_hdr->src_port);
-
- if (!is_valid)
- {
- SCTP_DBG_STATE_MACHINE ("BUFFER IS INCORRECT: conn_index = %u, "
- "packet_length = %u, "
- "chunk_type = %u [%s], "
- "connection.lcl_port = %u, sctp_hdr->src_port = %u, "
- "connection.rmt_port = %u, sctp_hdr->dst_port = %u",
- sctp_conn->sub_conn[idx].
- connection.c_index, packet_length,
- chunk_type,
- sctp_chunk_to_string (chunk_type),
- sctp_conn->sub_conn[idx].
- connection.lcl_port, sctp_hdr->src_port,
- sctp_conn->sub_conn[idx].
- connection.rmt_port,
- sctp_hdr->dst_port);
-
- error0 = SCTP_ERROR_UNKOWN_CHUNK;
- next0 = SCTP_OUTPUT_NEXT_DROP;
- goto done;
- }
-#endif
- SCTP_DBG_STATE_MACHINE
- ("SESSION_INDEX = %u, CONN_INDEX = %u, CURR_CONN_STATE = %u (%s), "
- "CHUNK_TYPE = %s, " "SRC_PORT = %u, DST_PORT = %u",
- sctp_conn->sub_conn[idx].connection.s_index,
- sctp_conn->sub_conn[idx].connection.c_index,
- sctp_conn->state, sctp_state_to_string (sctp_conn->state),
- sctp_chunk_to_string (chunk_type), full_hdr->hdr.src_port,
- full_hdr->hdr.dst_port);
-
- /* Let's make sure the state-machine does not send anything crazy */
-#if SCTP_DEBUG_STATE_MACHINE
- if (sctp_validate_output_state_machine (sctp_conn, chunk_type) != 0)
- {
- 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;
-
- }
-#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;
- }
- 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;
- }
- case SHUTDOWN_COMPLETE:
- {
- sctp_conn->state = SCTP_STATE_CLOSED;
- break;
- }
- }
-
- vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
-
- b0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
-
- SCTP_DBG_STATE_MACHINE
- ("SESSION_INDEX = %u, CONNECTION_INDEX = %u, " "NEW_STATE = %s, "
- "CHUNK_SENT = %s", sctp_conn->sub_conn[idx].connection.s_index,
- sctp_conn->sub_conn[idx].connection.c_index,
- sctp_state_to_string (sctp_conn->state),
- sctp_chunk_to_string (chunk_type));
-
- vnet_sctp_common_hdr_params_host_to_net (&full_hdr->common_hdr);
-
- done:
- b0->error = node->errors[error0];
- if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
- {
- t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
- if (th0)
- {
- clib_memcpy (&t0->sctp_header, th0,
- sizeof (t0->sctp_header));
- }
- else
- {
- memset (&t0->sctp_header, 0, sizeof (t0->sctp_header));
- }
- clib_memcpy (&t0->sctp_connection, sctp_conn,
- sizeof (t0->sctp_connection));
- }
-
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
- n_left_to_next, bi0, next0);
- }
-
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
-
- return from_frame->n_vectors;
-}
-
-static uword
-sctp4_output (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * from_frame)
-{
- return sctp46_output_inline (vm, node, from_frame, 1 /* is_ip4 */ );
-}
-
-static uword
-sctp6_output (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * from_frame)
-{
- return sctp46_output_inline (vm, node, from_frame, 0 /* is_ip4 */ );
-}
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (sctp4_output_node) =
-{
- .function = sctp4_output,.name = "sctp4-output",
- /* Takes a vector of packets. */
- .vector_size = sizeof (u32),
- .n_errors = SCTP_N_ERROR,
- .error_strings = sctp_error_strings,
- .n_next_nodes = SCTP_OUTPUT_N_NEXT,
- .next_nodes = {
-#define _(s,n) [SCTP_OUTPUT_NEXT_##s] = n,
- foreach_sctp4_output_next
-#undef _
- },
- .format_buffer = format_sctp_header,
- .format_trace = format_sctp_tx_trace,
-};
-/* *INDENT-ON* */
-
-VLIB_NODE_FUNCTION_MULTIARCH (sctp4_output_node, sctp4_output);
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (sctp6_output_node) =
-{
- .function = sctp6_output,
- .name = "sctp6-output",
- /* Takes a vector of packets. */
- .vector_size = sizeof (u32),
- .n_errors = SCTP_N_ERROR,
- .error_strings = sctp_error_strings,
- .n_next_nodes = SCTP_OUTPUT_N_NEXT,
- .next_nodes = {
-#define _(s,n) [SCTP_OUTPUT_NEXT_##s] = n,
- foreach_sctp6_output_next
-#undef _
- },
- .format_buffer = format_sctp_header,
- .format_trace = format_sctp_tx_trace,
-};
-/* *INDENT-ON* */
-
-VLIB_NODE_FUNCTION_MULTIARCH (sctp6_output_node, sctp6_output);
-
/*
* fd.io coding-style-patch-verification: ON
*