18 #include <openssl/hmac.h> 23 typedef enum _sctp_output_next
30 #define foreach_sctp4_output_next \ 31 _ (DROP, "error-drop") \ 32 _ (IP_LOOKUP, "ip4-lookup") 34 #define foreach_sctp6_output_next \ 35 _ (DROP, "error-drop") \ 36 _ (IP_LOOKUP, "ip6-lookup") 39 #define sctp_error(n,s) s, 56 if (
sctp_main.tx_frames[!is_ip4][thread_index])
61 sctp_main.tx_frames[!is_ip4][thread_index]);
62 sctp_main.tx_frames[!is_ip4][thread_index] = 0;
72 if (
sctp_main.ip_lookup_tx_frames[!is_ip4][thread_index])
79 sctp_main.ip_lookup_tx_frames[!is_ip4][thread_index] = 0;
101 u32 ip_header_length, payload_length_host_byte_order;
102 u32 n_this_buffer, n_bytes_left, n_ip_bytes_this_buffer;
103 void *data_this_buffer;
107 payload_length_host_byte_order =
108 clib_net_to_host_u16 (ip0->
length) - ip_header_length;
110 clib_host_to_net_u32 (payload_length_host_byte_order +
127 n_bytes_left = n_this_buffer = payload_length_host_byte_order;
128 data_this_buffer = (
void *) ip0 + ip_header_length;
129 n_ip_bytes_this_buffer =
131 if (n_this_buffer + ip_header_length > n_ip_bytes_this_buffer)
133 n_this_buffer = n_ip_bytes_this_buffer > ip_header_length ?
134 n_ip_bytes_this_buffer - ip_header_length : 0;
140 n_bytes_left -= n_this_buffer;
141 if (n_bytes_left == 0)
158 u16 payload_length_host_byte_order;
159 u32 i, n_this_buffer, n_bytes_left;
160 u32 headers_size =
sizeof (ip0[0]);
161 void *data_this_buffer;
168 payload_length_host_byte_order = clib_net_to_host_u16 (ip0->
payload_length);
169 data_this_buffer = (
void *) (ip0 + 1);
188 ip6_hop_by_hop_ext_t *ext_hdr =
189 (ip6_hop_by_hop_ext_t *) data_this_buffer;
194 skip_bytes = 8 * (1 + ext_hdr->n_data_u64s);
195 data_this_buffer = (
void *) ((
u8 *) data_this_buffer + skip_bytes);
197 payload_length_host_byte_order -= skip_bytes;
198 headers_size += skip_bytes;
201 n_bytes_left = n_this_buffer = payload_length_host_byte_order;
210 n_bytes_left -= n_this_buffer;
211 if (n_bytes_left == 0)
214 if (!(p0->
flags & VLIB_BUFFER_NEXT_PRESENT))
233 if (sctp_sub_conn->c_is_ip4)
256 if (b->
flags & VLIB_BUFFER_NEXT_PRESENT)
259 b->
flags &= VLIB_BUFFER_NEXT_PRESENT - 1;
273 ASSERT ((b->
flags & VLIB_BUFFER_NEXT_PRESENT) == 0);
274 b->
flags &= VLIB_BUFFER_NON_DEFAULT_FREELIST;
275 b->
flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
288 u32 current_length =
vec_len (tm->tx_buffers[thread_index]);
292 current_length + n_free_buffers - 1);
296 _vec_len (tm->tx_buffers[thread_index]) = current_length + n_allocated;
298 if (
vec_len (tm->tx_buffers[thread_index]) == 0)
316 my_tx_buffers = tm->tx_buffers[thread_index];
317 *bidx = my_tx_buffers[
vec_len (my_tx_buffers) - 1];
318 _vec_len (my_tx_buffers) -= 1;
328 u32 *to_next, next_index;
331 b->
flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
339 f = tm->tx_frames[!is_ip4][thread_index];
344 tm->tx_frames[!is_ip4][thread_index] = f;
352 tm->tx_frames[!is_ip4][thread_index] = 0;
365 u8 is_ip4,
u32 fib_index,
u8 flush)
369 u32 *to_next, next_index;
372 b->
flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
386 f = tm->ip_lookup_tx_frames[!is_ip4][thread_index];
391 tm->ip_lookup_tx_frames[!is_ip4][thread_index] = f;
400 tm->ip_lookup_tx_frames[!is_ip4][thread_index] = 0;
406 u8 is_ip4,
u32 fib_index)
427 if (sub_conn->c_is_ip4)
441 u16 pointer_offset =
sizeof (init_chunk);
442 if (sub_conn->c_is_ip4)
452 ip6_param->
address.
as_u64[0] = sub_conn->c_lcl_ip.ip6.as_u64[0];
453 ip6_param->
address.
as_u64[1] = sub_conn->c_lcl_ip.ip6.as_u64[1];
470 init_chunk->
a_rwnd = clib_host_to_net_u32 (sctp_conn->sub_conn[idx].cwnd);
478 clib_host_to_net_u32 (sctp_conn->local_initial_tsn);
480 sctp_conn->local_initial_tsn);
484 vnet_buffer (b)->sctp.connection_index = sub_conn->c_c_index;
489 "SRC_PORT = %u, DST_PORT = %u",
490 sub_conn->connection.c_index,
502 #if OPENSSL_VERSION_NUMBER >= 0x10100000L 507 unsigned int len = 0;
508 const EVP_MD *md = EVP_sha1 ();
509 #if OPENSSL_VERSION_NUMBER >= 0x10100000L 510 ctx = HMAC_CTX_new ();
513 HMAC_Update (ctx, (
const unsigned char *) &sctp_conn,
sizeof (sctp_conn));
514 HMAC_Final (ctx, state_cookie->
mac, &len);
516 HMAC_CTX_init (&ctx);
519 HMAC_Update (&ctx, (
const unsigned char *) &sctp_conn,
sizeof (sctp_conn));
520 HMAC_Final (&ctx, state_cookie->
mac, &len);
521 HMAC_CTX_cleanup (&ctx);
549 sctp_conn->sub_conn[idx].connection.lcl_port;
551 sctp_conn->sub_conn[idx].connection.rmt_port;
557 sctp_conn->sub_conn[idx].connection.c_index;
581 sctp_conn->sub_conn[idx].connection.lcl_port;
583 sctp_conn->sub_conn[idx].connection.rmt_port;
591 sctp_conn->sub_conn[idx].connection.c_index;
609 clib_warning (
"Reached MAX_INIT_RETRANS times. Aborting connection.");
631 sctp_conn->sub_conn[idx].RTO);
634 sctp_conn->state = SCTP_STATE_COOKIE_WAIT;
668 err_chunk->
sctp_hdr.
src_port = sctp_conn->sub_conn[idx].connection.lcl_port;
669 err_chunk->
sctp_hdr.
dst_port = sctp_conn->sub_conn[idx].connection.rmt_port;
682 sctp_conn->sub_conn[idx].connection.c_index;
713 sctp_conn->sub_conn[idx].connection.lcl_port;
715 sctp_conn->sub_conn[idx].connection.rmt_port;
723 sctp_conn->sub_conn[idx].connection.c_index;
757 if (sctp_conn->sub_conn[idx].connection.is_ip4)
818 if (sctp_conn->sub_conn[idx].connection.is_ip4)
822 sctp_conn->sub_conn[idx].connection.lcl_ip.ip4.as_u32;
830 sctp_conn->sub_conn[idx].connection.lcl_ip.ip6.as_u64[0];
832 sctp_conn->sub_conn[idx].connection.lcl_ip.ip6.as_u64[1];
840 sctp_conn->sub_conn[idx].connection.lcl_port;
842 sctp_conn->sub_conn[idx].connection.rmt_port;
846 clib_host_to_net_u32 (sctp_conn->local_initial_tsn);
856 clib_host_to_net_u32 (sctp_conn->sub_conn[idx].cwnd);
863 sctp_conn->sub_conn[idx].connection.c_index;
897 if (sctp_conn->sub_conn[idx].connection.is_ip4)
958 if (sctp_conn->sub_conn[idx].connection.is_ip4)
962 sctp_conn->sub_conn[idx].connection.lcl_ip.ip4.as_u32;
970 sctp_conn->sub_conn[idx].connection.lcl_ip.ip6.as_u64[0];
972 sctp_conn->sub_conn[idx].connection.lcl_ip.ip6.as_u64[1];
980 sctp_conn->sub_conn[idx].connection.lcl_port;
982 sctp_conn->sub_conn[idx].connection.rmt_port;
986 clib_host_to_net_u32 (sctp_conn->local_initial_tsn);
994 clib_host_to_net_u32 (
random_u32 (&random_seed));
997 clib_host_to_net_u32 (sctp_conn->sub_conn[idx].cwnd);
1006 sctp_conn->sub_conn[idx].connection.c_index;
1032 sctp_conn->sub_conn[idx].connection.lcl_port;
1034 sctp_conn->sub_conn[idx].connection.rmt_port;
1042 sctp_conn->sub_conn[idx].connection.c_index;
1070 sctp_conn->sub_conn[idx].connection.is_ip4);
1091 sctp_conn->sub_conn[idx].connection.lcl_port;
1093 sctp_conn->sub_conn[idx].connection.rmt_port;
1100 sctp_conn->sub_conn[idx].connection.c_index;
1152 sctp_conn->ack_state = 0;
1155 sctp_conn->sub_conn[idx].connection.c_index;
1194 sctp_conn->sub_conn[idx].connection.c_index;
1229 sctp_conn->sub_conn[idx].connection.c_index;
1259 sctp_conn->sub_conn[i].
1262 sctp_conn->sub_conn[
i].unacknowledged_hb += 1;
1285 sctp_conn->sub_conn[idx].connection.lcl_port;
1287 sctp_conn->sub_conn[idx].connection.rmt_port;
1294 sctp_conn->sub_conn[idx].connection.c_index;
1325 clib_warning (
"Reached MAX_INIT_RETRANS times. Aborting connection.");
1348 sctp_conn->sub_conn[idx].c_fib_index);
1352 sctp_conn->sub_conn[idx].RTO);
1355 sctp_conn->state = SCTP_STATE_COOKIE_WAIT;
1371 || (b->
flags & VLIB_BUFFER_NEXT_PRESENT));
1374 "b->current_data = %p " 1388 (
"SCTP_CONN = %p, IDX = %u, S_INDEX = %u, C_INDEX = %u, sctp_conn->[...].LCL_PORT = %u, sctp_conn->[...].RMT_PORT = %u",
1389 sctp_conn, idx, sctp_conn->sub_conn[idx].connection.s_index,
1390 sctp_conn->sub_conn[idx].connection.c_index,
1391 sctp_conn->sub_conn[idx].connection.lcl_port,
1392 sctp_conn->sub_conn[idx].connection.rmt_port);
1395 sctp_conn->sub_conn[idx].connection.lcl_port;
1397 sctp_conn->sub_conn[idx].connection.rmt_port;
1400 data_chunk->
tsn = clib_host_to_net_u32 (sctp_conn->next_tsn);
1401 data_chunk->
stream_id = clib_host_to_net_u16 (0);
1402 data_chunk->
stream_seq = clib_host_to_net_u16 (0);
1416 sctp_conn->last_unacked_tsn = sctp_conn->next_tsn;
1419 sctp_conn->next_tsn += data_len;
1421 u32 inflight = sctp_conn->next_tsn - sctp_conn->last_unacked_tsn;
1423 if (sctp_conn->sub_conn[idx].partially_acked_bytes >=
1424 sctp_conn->sub_conn[idx].cwnd
1425 && inflight >= sctp_conn->sub_conn[idx].cwnd)
1427 sctp_conn->sub_conn[idx].cwnd += sctp_conn->sub_conn[idx].PMTU;
1428 sctp_conn->sub_conn[idx].partially_acked_bytes -=
1429 sctp_conn->sub_conn[idx].cwnd;
1435 sctp_conn->sub_conn[idx].connection.c_index;
1447 "S_INDEX = %u, C_INDEX = %u," 1448 "trans_conn->LCL_PORT = %u, trans_conn->RMT_PORT = %u",
1451 trans_conn->s_index,
1452 trans_conn->c_index,
1453 trans_conn->lcl_port, trans_conn->rmt_port);
1471 u32 bi, available_bytes, seg_size;
1474 ASSERT (sctp_conn->state >= SCTP_STATE_ESTABLISHED);
1475 ASSERT (max_deq_bytes != 0);
1482 ASSERT (available_bytes >= offset);
1483 available_bytes -=
offset;
1484 if (!available_bytes)
1486 max_deq_bytes =
clib_min (sctp_conn->sub_conn[idx].cwnd, max_deq_bytes);
1487 max_deq_bytes =
clib_min (available_bytes, max_deq_bytes);
1489 seg_size = max_deq_bytes;
1505 offset, max_deq_bytes);
1506 ASSERT (n_bytes == max_deq_bytes);
1519 u32 bi, n_bytes = 0;
1522 (
"SCTP_CONN = %p, IDX = %u, S_INDEX = %u, C_INDEX = %u, sctp_conn->[...].LCL_PORT = %u, sctp_conn->[...].RMT_PORT = %u",
1523 sctp_conn, idx, sctp_conn->sub_conn[idx].connection.s_index,
1524 sctp_conn->sub_conn[idx].connection.c_index,
1525 sctp_conn->sub_conn[idx].connection.lcl_port,
1526 sctp_conn->sub_conn[idx].connection.rmt_port);
1528 if (sctp_conn->state >= SCTP_STATE_ESTABLISHED)
1537 sctp_conn->sub_conn[idx].cwnd, &b);
1544 sctp_conn->sub_conn[idx].connection.is_ip4);
1549 #if SCTP_DEBUG_STATE_MACHINE 1555 switch (sctp_conn->state)
1557 case SCTP_STATE_CLOSED:
1561 case SCTP_STATE_ESTABLISHED:
1567 case SCTP_STATE_COOKIE_WAIT:
1571 case SCTP_STATE_SHUTDOWN_SENT:
1575 case SCTP_STATE_SHUTDOWN_RECEIVED:
1587 return sctp_conn->sub_conn[idx].is_retransmitting;
1595 u32 n_left_from, next_index, *from, *to_next;
1603 while (n_left_from > 0)
1609 while (n_left_from > 0 && n_left_to_next > 0)
1617 u32 error0 = SCTP_ERROR_PKTS_SENT, next0 =
1620 #if SCTP_DEBUG_STATE_MACHINE 1621 u16 packet_length = 0;
1629 n_left_to_next -= 1;
1639 error0 = SCTP_ERROR_INVALID_CONNECTION;
1652 &sctp_conn->sub_conn
1669 packet_length = clib_net_to_host_u16 (iph4->
length);
1676 &sctp_conn->sub_conn
1680 &sctp_conn->sub_conn
1706 (
"Trying to send an unrecognized chunk... something is really bad.");
1707 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
1712 #if SCTP_DEBUG_STATE_MACHINE 1714 (sctp_conn->sub_conn[idx].connection.lcl_port ==
1716 || sctp_conn->sub_conn[idx].connection.lcl_port ==
1718 && (sctp_conn->sub_conn[idx].connection.rmt_port ==
1720 || sctp_conn->sub_conn[idx].connection.rmt_port ==
1726 "packet_length = %u, " 1727 "chunk_type = %u [%s], " 1728 "connection.lcl_port = %u, sctp_hdr->src_port = %u, " 1729 "connection.rmt_port = %u, sctp_hdr->dst_port = %u",
1730 sctp_conn->sub_conn[idx].
1731 connection.c_index, packet_length,
1734 sctp_conn->sub_conn[idx].
1735 connection.lcl_port, sctp_hdr->
src_port,
1736 sctp_conn->sub_conn[idx].
1737 connection.rmt_port,
1740 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
1746 (
"SESSION_INDEX = %u, CONN_INDEX = %u, CURR_CONN_STATE = %u (%s), " 1747 "CHUNK_TYPE = %s, " "SRC_PORT = %u, DST_PORT = %u",
1748 sctp_conn->sub_conn[idx].connection.s_index,
1749 sctp_conn->sub_conn[idx].connection.c_index,
1755 #if SCTP_DEBUG_STATE_MACHINE 1756 if (sctp_validate_output_state_machine (sctp_conn, chunk_type) != 0)
1759 (
"Sending the wrong chunk (%s) based on state-machine status (%s)",
1763 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
1776 if (chunk_type ==
DATA 1777 && sctp_conn->sub_conn[idx].RTO_pending == 0)
1779 sctp_conn->sub_conn[idx].RTO_pending = 1;
1791 sctp_conn->state = SCTP_STATE_COOKIE_ECHOED;
1799 sctp_conn->sub_conn[idx].RTO);
1806 sctp_conn->sub_conn[idx].RTO);
1807 sctp_conn->state = SCTP_STATE_SHUTDOWN_SENT;
1814 sctp_conn->sub_conn[idx].RTO);
1815 sctp_conn->state = SCTP_STATE_SHUTDOWN_ACK_SENT;
1820 sctp_conn->state = SCTP_STATE_CLOSED;
1827 sctp_conn->sub_conn[idx].c_fib_index;
1829 b0->
flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
1832 (
"SESSION_INDEX = %u, CONNECTION_INDEX = %u, " "NEW_STATE = %s, " 1833 "CHUNK_SENT = %s", sctp_conn->sub_conn[idx].connection.s_index,
1834 sctp_conn->sub_conn[idx].connection.c_index,
1859 n_left_to_next, bi0, next0);
1887 .vector_size =
sizeof (
u32),
1892 #define _(s,n) [SCTP_OUTPUT_NEXT_##s] = n, 1907 .name =
"sctp6-output",
1909 .vector_size =
sizeof (
u32),
1914 #define _(s,n) [SCTP_OUTPUT_NEXT_##s] = n, #define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
void sctp_prepare_heartbeat_ack_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to HEARTBEAT_ACK.
static void sctp_enqueue_to_ip_lookup(vlib_main_t *vm, vlib_buffer_t *b, u32 bi, u8 is_ip4, u32 fib_index)
void sctp_connection_timers_reset(sctp_connection_t *sctp_conn)
Stop all connection timers.
sctp_chunks_common_hdr_t chunk_hdr
u16 sctp_check_outstanding_data_chunks(sctp_connection_t *sctp_conn)
struct _sctp_main sctp_main_t
static void sctp_timer_set(sctp_connection_t *tc, u8 conn_idx, u8 timer_id, u32 interval)
void session_flush_frames_main_thread(vlib_main_t *vm)
static void vnet_sctp_set_ebit(sctp_chunks_common_hdr_t *h)
sctp_state_cookie_param_t cookie
static char * sctp_error_strings[]
static uword random_default_seed(void)
Default random seed (unix/linux user-mode)
void sctp_flush_frames_to_output(u8 thread_index)
Flush v4 and v6 sctp and ip-lookup tx frames for thread index.
struct _transport_connection transport_connection_t
void sctp_prepare_cookie_ack_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
#define SCTP_ADV_DBG_OUTPUT(_fmt, _args...)
static uword sctp46_output_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame, int is_ip4)
#define SCTP_IPV4_ADDRESS_TYPE_LENGTH
struct _sctp_sub_connection sctp_sub_connection_t
static int ip4_header_bytes(ip4_header_t *i)
#define foreach_sctp4_output_next
#define INBOUND_STREAMS_COUNT
vlib_node_registration_t sctp6_output_node
(constructor) VLIB_REGISTER_NODE (sctp6_output_node)
sctp_chunks_common_hdr_t chunk_hdr
static u64 sctp_time_now(void)
void sctp_prepare_initack_chunk_for_collision(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b, ip4_address_t *ip4_addr, ip6_address_t *ip6_addr)
Convert buffer to INIT-ACK.
sctp_chunks_common_hdr_t chunk_hdr
static ip_csum_t ip_csum_with_carry(ip_csum_t sum, ip_csum_t x)
sctp_chunks_common_hdr_t chunk_hdr
vlib_error_t * errors
Vector of errors for this node.
void sctp_compute_mac(sctp_connection_t *sctp_conn, sctp_state_cookie_param_t *state_cookie)
static uword sctp6_output(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
sctp_chunks_common_hdr_t chunk_hdr
VLIB_NODE_FUNCTION_MULTIARCH(sctp4_output_node, sctp4_output)
uword as_uword[16/sizeof(uword)]
static sctp_main_t * vnet_get_sctp_main()
static void vnet_sctp_common_hdr_params_host_to_net(sctp_chunks_common_hdr_t *h)
vlib_node_registration_t ip4_lookup_node
(constructor) VLIB_REGISTER_NODE (ip4_lookup_node)
void sctp_send_shutdown_ack(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
void sctp_prepare_sack_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to SACK.
sctp_chunks_common_hdr_t chunk_hdr
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
static void sctp_init_cwnd(sctp_connection_t *sctp_conn)
static void vnet_sctp_set_chunk_type(sctp_chunks_common_hdr_t *h, sctp_chunk_type t)
static void sctp_enqueue_to_ip_lookup_i(vlib_main_t *vm, vlib_buffer_t *b, u32 bi, u8 is_ip4, u32 fib_index, u8 flush)
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
u8 pre_data[VLIB_BUFFER_PRE_DATA_SIZE]
Space for inserting data before buffer start.
static void * ip4_next_header(ip4_header_t *i)
static void sctp_enqueue_to_output_now(vlib_main_t *vm, vlib_buffer_t *b, u32 bi, u8 is_ip4)
#define SCTP_STATE_COOKIE_TYPE
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
static void sctp_push_hdr_i(sctp_connection_t *sctp_conn, vlib_buffer_t *b, sctp_state_t next_state)
Push SCTP header and update connection variables.
#define SCTP_DBG_OUTPUT(_fmt, _args...)
void sctp_data_retransmit(sctp_connection_t *sctp_conn)
void sctp_prepare_init_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to INIT.
static sctp_connection_t * sctp_get_connection_from_transport(transport_connection_t *tconn)
void sctp_prepare_abort_for_collision(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b, ip4_address_t *ip4_addr, ip6_address_t *ip6_addr)
Convert buffer to ABORT.
u16 current_length
Nbytes between current data and the end of this buffer.
static void * vlib_buffer_make_headroom(vlib_buffer_t *b, u8 size)
Make head room, typically for packet headers.
sctp_init_chunk_t sctp_init_ack_chunk_t
sctp_opt_params_hdr_t param_hdr
u8 * format_sctp_tx_trace(u8 *s, va_list *args)
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
static void sctp_enqueue_to_output_i(vlib_main_t *vm, vlib_buffer_t *b, u32 bi, u8 is_ip4, u8 flush)
#define OUTBOUND_STREAMS_COUNT
struct _sctp_connection sctp_connection_t
#define SCTP_IPV6_ADDRESS_TYPE
static u64 sctp_set_time_now(u32 thread_index)
static void * sctp_reuse_buffer(vlib_main_t *vm, vlib_buffer_t *b)
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
#define MAX_SCTP_CONNECTIONS
static void sctp_flush_frame_to_ip_lookup(vlib_main_t *vm, u8 thread_index, u8 is_ip4)
Flush ip lookup tx frames populated by timer pops.
vlib_error_t error
Error code for buffers to be enqueued to error handler.
static char * sctp_state_to_string(u8 state)
static u8 vnet_sctp_get_chunk_type(sctp_chunks_common_hdr_t *h)
sctp_hb_req_chunk_t sctp_hb_ack_chunk_t
sctp_chunks_common_hdr_t common_hdr
#define VLIB_REGISTER_NODE(x,...)
enum _sctp_state sctp_state_t
unsigned char mac[SHA1_OUTPUT_LENGTH]
static_always_inline uword vlib_get_thread_index(void)
void sctp_push_ip_hdr(sctp_main_t *tm, sctp_sub_connection_t *sctp_sub_conn, vlib_buffer_t *b)
sctp_chunks_common_hdr_t chunk_hdr
static ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
void sctp_send_init(sctp_connection_t *sctp_conn)
#define clib_warning(format, args...)
#define clib_memcpy(a, b, c)
#define VLIB_BUFFER_TRACE_TRAJECTORY
Compile time buffer trajectory tracing option Turn this on if you run into "bad monkey" contexts...
void sctp_send_cookie_echo(sctp_connection_t *sctp_conn)
void sctp_prepare_shutdown_ack_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to SHUTDOWN_ACK.
static int sctp_alloc_tx_buffers(sctp_main_t *tm, u8 thread_index, u32 n_free_buffers)
#define sctp_trajectory_add_start(b, start)
void sctp_prepare_shutdown_complete_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to SHUTDOWN_COMPLETE.
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
sctp_opt_params_hdr_t param_hdr
static void * ip6_next_header(ip6_header_t *i)
u32 ip4_sctp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip4_header_t *ip0)
enum _sctp_output_next sctp_output_next_t
vlib_node_registration_t ip6_lookup_node
(constructor) VLIB_REGISTER_NODE (ip6_lookup_node)
void sctp_prepare_shutdown_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to SHUTDOWN.
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
sctp_opt_params_hdr_t param_hdr
u32 session_tx_fifo_max_dequeue(transport_connection_t *tc)
#define SCTP_PRIMARY_PATH_IDX
static u8 sctp_is_retransmitting(sctp_connection_t *sctp_conn, u8 idx)
sctp_connection_t sctp_connection
static u16 vnet_sctp_calculate_padding(u16 base_length)
u32 next_buffer
Next buffer for this linked-list of buffers.
#define SCTP_CONN_TRACKING_DBG(_fmt, _args...)
static void * sctp_init_buffer(vlib_main_t *vm, vlib_buffer_t *b)
#define clib_mem_unaligned(pointer, type)
sctp_chunks_common_hdr_t chunk_hdr
void sctp_connection_cleanup(sctp_connection_t *sctp_conn)
Cleans up connection state.
sctp_header_t sctp_header
static vlib_main_t * vlib_get_main(void)
static void sctp_timer_update(sctp_connection_t *tc, u8 conn_idx, u8 timer_id, u32 interval)
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
sctp_hb_info_param_t hb_info
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
struct _vlib_node_registration vlib_node_registration_t
template key/value backing page structure
void sctp_prepare_heartbeat_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to HEARTBEAT.
void sctp_send_shutdown_complete(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b0)
static void * vlib_buffer_push_uninit(vlib_buffer_t *b, u8 size)
Prepend uninitialized data to buffer.
static sctp_connection_t * sctp_connection_get(u32 conn_index, u32 thread_index)
#define SCTP_IPV4_ADDRESS_TYPE
u32 ip6_sctp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip6_header_t *ip0, int *bogus_lengthp)
u32 sctp_prepare_data_retransmit(sctp_connection_t *sctp_conn, u8 idx, u32 offset, u32 max_deq_bytes, vlib_buffer_t **b)
static void * vlib_buffer_push_ip6(vlib_main_t *vm, vlib_buffer_t *b, ip6_address_t *src, ip6_address_t *dst, int proto)
Push IPv6 header to buffer.
void sctp_send_heartbeat(sctp_connection_t *sctp_conn)
void sctp_flush_frame_to_output(vlib_main_t *vm, u8 thread_index, u8 is_ip4)
Flush tx frame populated by retransmits and timer pops.
void sctp_prepare_operation_error(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b, u8 err_cause)
Convert buffer to ERROR.
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
sctp_err_cause_param_t err_causes[]
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
#define SCTP_VALID_COOKIE_LIFE
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
#define SCTP_DEBUG_STATE_MACHINE
Linear Congruential Random Number Generator.
sctp_chunks_common_hdr_t chunk_hdr
struct clib_bihash_value offset
template key/value backing page structure
u32 sctp_push_header(transport_connection_t *trans_conn, vlib_buffer_t *b)
void sctp_prepare_cookie_echo_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b, u8 reuse_buffer)
static char * sctp_chunk_to_string(u8 type)
static u32 random_u32(u32 *seed)
32-bit random number generator
int session_stream_connect_notify(transport_connection_t *tc, u8 is_fail)
static uword sctp4_output(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
#define ENDIANESS_SWAP(x)
static u32 vlib_num_workers()
sctp_opt_params_hdr_t param_hdr
u16 outbound_streams_count
static void vlib_buffer_free_one(vlib_main_t *vm, u32 buffer_index)
Free one buffer Shorthand to free a single buffer chain.
static int sctp_get_free_buffer_index(sctp_main_t *tm, u32 *bidx)
static void vnet_sctp_set_bbit(sctp_chunks_common_hdr_t *h)
static u8 sctp_data_subconn_select(sctp_connection_t *sctp_conn)
#define SCTP_IPV6_ADDRESS_TYPE_LENGTH
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
static u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
sctp_chunks_common_hdr_t chunk_hdr
int stream_session_peek_bytes(transport_connection_t *tc, u8 *buffer, u32 offset, u32 max_bytes)
sctp_opt_params_hdr_t param_hdr
#define foreach_sctp6_output_next
static void vnet_sctp_set_chunk_length(sctp_chunks_common_hdr_t *h, u16 length)
static void * vlib_buffer_push_ip4(vlib_main_t *vm, vlib_buffer_t *b, ip4_address_t *src, ip4_address_t *dst, int proto, u8 csum_offload)
Push IPv4 header to buffer.
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
vlib_node_registration_t sctp4_output_node
(constructor) VLIB_REGISTER_NODE (sctp4_output_node)
#define SCTP_DBG_STATE_MACHINE(_fmt, _args...)
#define SCTP_MAX_INIT_RETRANS
void sctp_prepare_initack_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b, ip4_address_t *ip4_addr, u8 add_ip4, ip6_address_t *ip6_addr, u8 add_ip6)
Convert buffer to INIT-ACK.
void sctp_send_shutdown(sctp_connection_t *sctp_conn)
sctp_chunks_common_hdr_t chunk_hdr