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)
425 if (sub_conn->c_is_ip4)
439 u16 pointer_offset =
sizeof (init_chunk);
440 if (sub_conn->c_is_ip4)
450 ip6_param->
address.
as_u64[0] = sub_conn->c_lcl_ip.ip6.as_u64[0];
451 ip6_param->
address.
as_u64[1] = sub_conn->c_lcl_ip.ip6.as_u64[1];
468 init_chunk->
a_rwnd = clib_host_to_net_u32 (sctp_conn->sub_conn[idx].cwnd);
476 clib_host_to_net_u32 (sctp_conn->local_initial_tsn);
478 sctp_conn->local_initial_tsn);
482 vnet_buffer (b)->sctp.connection_index = sub_conn->c_c_index;
487 "SRC_PORT = %u, DST_PORT = %u",
488 sub_conn->connection.c_index,
500 #if OPENSSL_VERSION_NUMBER >= 0x10100000L 505 unsigned int len = 0;
506 const EVP_MD *md = EVP_sha1 ();
507 #if OPENSSL_VERSION_NUMBER >= 0x10100000L 508 ctx = HMAC_CTX_new ();
511 HMAC_Update (ctx, (
const unsigned char *) &sctp_conn,
sizeof (sctp_conn));
512 HMAC_Final (ctx, state_cookie->
mac, &len);
514 HMAC_CTX_init (&ctx);
517 HMAC_Update (&ctx, (
const unsigned char *) &sctp_conn,
sizeof (sctp_conn));
518 HMAC_Final (&ctx, state_cookie->
mac, &len);
519 HMAC_CTX_cleanup (&ctx);
547 sctp_conn->sub_conn[idx].connection.lcl_port;
549 sctp_conn->sub_conn[idx].connection.rmt_port;
555 sctp_conn->sub_conn[idx].connection.c_index;
579 sctp_conn->sub_conn[idx].connection.lcl_port;
581 sctp_conn->sub_conn[idx].connection.rmt_port;
589 sctp_conn->sub_conn[idx].connection.c_index;
607 clib_warning (
"Reached MAX_INIT_RETRANS times. Aborting connection.");
629 sctp_conn->sub_conn[idx].RTO);
632 sctp_conn->state = SCTP_STATE_COOKIE_WAIT;
666 err_chunk->
sctp_hdr.
src_port = sctp_conn->sub_conn[idx].connection.lcl_port;
667 err_chunk->
sctp_hdr.
dst_port = sctp_conn->sub_conn[idx].connection.rmt_port;
680 sctp_conn->sub_conn[idx].connection.c_index;
711 sctp_conn->sub_conn[idx].connection.lcl_port;
713 sctp_conn->sub_conn[idx].connection.rmt_port;
721 sctp_conn->sub_conn[idx].connection.c_index;
755 if (sctp_conn->sub_conn[idx].connection.is_ip4)
816 if (sctp_conn->sub_conn[idx].connection.is_ip4)
820 sctp_conn->sub_conn[idx].connection.lcl_ip.ip4.as_u32;
828 sctp_conn->sub_conn[idx].connection.lcl_ip.ip6.as_u64[0];
830 sctp_conn->sub_conn[idx].connection.lcl_ip.ip6.as_u64[1];
838 sctp_conn->sub_conn[idx].connection.lcl_port;
840 sctp_conn->sub_conn[idx].connection.rmt_port;
844 clib_host_to_net_u32 (sctp_conn->local_initial_tsn);
854 clib_host_to_net_u32 (sctp_conn->sub_conn[idx].cwnd);
861 sctp_conn->sub_conn[idx].connection.c_index;
895 if (sctp_conn->sub_conn[idx].connection.is_ip4)
956 if (sctp_conn->sub_conn[idx].connection.is_ip4)
960 sctp_conn->sub_conn[idx].connection.lcl_ip.ip4.as_u32;
968 sctp_conn->sub_conn[idx].connection.lcl_ip.ip6.as_u64[0];
970 sctp_conn->sub_conn[idx].connection.lcl_ip.ip6.as_u64[1];
978 sctp_conn->sub_conn[idx].connection.lcl_port;
980 sctp_conn->sub_conn[idx].connection.rmt_port;
984 clib_host_to_net_u32 (sctp_conn->local_initial_tsn);
992 clib_host_to_net_u32 (
random_u32 (&random_seed));
995 clib_host_to_net_u32 (sctp_conn->sub_conn[idx].cwnd);
1004 sctp_conn->sub_conn[idx].connection.c_index;
1030 sctp_conn->sub_conn[idx].connection.lcl_port;
1032 sctp_conn->sub_conn[idx].connection.rmt_port;
1040 sctp_conn->sub_conn[idx].connection.c_index;
1068 sctp_conn->sub_conn[idx].connection.is_ip4);
1089 sctp_conn->sub_conn[idx].connection.lcl_port;
1091 sctp_conn->sub_conn[idx].connection.rmt_port;
1098 sctp_conn->sub_conn[idx].connection.c_index;
1150 sctp_conn->ack_state = 0;
1153 sctp_conn->sub_conn[idx].connection.c_index;
1192 sctp_conn->sub_conn[idx].connection.c_index;
1227 sctp_conn->sub_conn[idx].connection.c_index;
1257 sctp_conn->sub_conn[i].
1260 sctp_conn->sub_conn[
i].unacknowledged_hb += 1;
1283 sctp_conn->sub_conn[idx].connection.lcl_port;
1285 sctp_conn->sub_conn[idx].connection.rmt_port;
1292 sctp_conn->sub_conn[idx].connection.c_index;
1323 clib_warning (
"Reached MAX_INIT_RETRANS times. Aborting connection.");
1346 sctp_conn->sub_conn[idx].c_fib_index);
1350 sctp_conn->sub_conn[idx].RTO);
1353 sctp_conn->state = SCTP_STATE_COOKIE_WAIT;
1369 || (b->
flags & VLIB_BUFFER_NEXT_PRESENT));
1372 "b->current_data = %p " 1386 (
"SCTP_CONN = %p, IDX = %u, S_INDEX = %u, C_INDEX = %u, sctp_conn->[...].LCL_PORT = %u, sctp_conn->[...].RMT_PORT = %u",
1387 sctp_conn, idx, sctp_conn->sub_conn[idx].connection.s_index,
1388 sctp_conn->sub_conn[idx].connection.c_index,
1389 sctp_conn->sub_conn[idx].connection.lcl_port,
1390 sctp_conn->sub_conn[idx].connection.rmt_port);
1393 sctp_conn->sub_conn[idx].connection.lcl_port;
1395 sctp_conn->sub_conn[idx].connection.rmt_port;
1398 data_chunk->
tsn = clib_host_to_net_u32 (sctp_conn->next_tsn);
1399 data_chunk->
stream_id = clib_host_to_net_u16 (0);
1400 data_chunk->
stream_seq = clib_host_to_net_u16 (0);
1414 sctp_conn->last_unacked_tsn = sctp_conn->next_tsn;
1417 sctp_conn->next_tsn += data_len;
1419 u32 inflight = sctp_conn->next_tsn - sctp_conn->last_unacked_tsn;
1421 if (sctp_conn->sub_conn[idx].partially_acked_bytes >=
1422 sctp_conn->sub_conn[idx].cwnd
1423 && inflight >= sctp_conn->sub_conn[idx].cwnd)
1425 sctp_conn->sub_conn[idx].cwnd += sctp_conn->sub_conn[idx].PMTU;
1426 sctp_conn->sub_conn[idx].partially_acked_bytes -=
1427 sctp_conn->sub_conn[idx].cwnd;
1433 sctp_conn->sub_conn[idx].connection.c_index;
1445 "S_INDEX = %u, C_INDEX = %u," 1446 "trans_conn->LCL_PORT = %u, trans_conn->RMT_PORT = %u",
1449 trans_conn->s_index,
1450 trans_conn->c_index,
1451 trans_conn->lcl_port, trans_conn->rmt_port);
1469 u32 bi, available_bytes, seg_size;
1472 ASSERT (sctp_conn->state >= SCTP_STATE_ESTABLISHED);
1473 ASSERT (max_deq_bytes != 0);
1480 ASSERT (available_bytes >= offset);
1481 available_bytes -=
offset;
1482 if (!available_bytes)
1484 max_deq_bytes =
clib_min (sctp_conn->sub_conn[idx].cwnd, max_deq_bytes);
1485 max_deq_bytes =
clib_min (available_bytes, max_deq_bytes);
1487 seg_size = max_deq_bytes;
1503 offset, max_deq_bytes);
1504 ASSERT (n_bytes == max_deq_bytes);
1517 u32 bi, n_bytes = 0;
1520 (
"SCTP_CONN = %p, IDX = %u, S_INDEX = %u, C_INDEX = %u, sctp_conn->[...].LCL_PORT = %u, sctp_conn->[...].RMT_PORT = %u",
1521 sctp_conn, idx, sctp_conn->sub_conn[idx].connection.s_index,
1522 sctp_conn->sub_conn[idx].connection.c_index,
1523 sctp_conn->sub_conn[idx].connection.lcl_port,
1524 sctp_conn->sub_conn[idx].connection.rmt_port);
1526 if (sctp_conn->state >= SCTP_STATE_ESTABLISHED)
1535 sctp_conn->sub_conn[idx].cwnd, &b);
1542 sctp_conn->sub_conn[idx].connection.is_ip4);
1547 #if SCTP_DEBUG_STATE_MACHINE 1553 switch (sctp_conn->state)
1555 case SCTP_STATE_CLOSED:
1559 case SCTP_STATE_ESTABLISHED:
1565 case SCTP_STATE_COOKIE_WAIT:
1569 case SCTP_STATE_SHUTDOWN_SENT:
1573 case SCTP_STATE_SHUTDOWN_RECEIVED:
1585 return sctp_conn->sub_conn[idx].is_retransmitting;
1593 u32 n_left_from, next_index, *from, *to_next;
1601 while (n_left_from > 0)
1607 while (n_left_from > 0 && n_left_to_next > 0)
1615 u32 error0 = SCTP_ERROR_PKTS_SENT, next0 =
1618 #if SCTP_DEBUG_STATE_MACHINE 1619 u16 packet_length = 0;
1627 n_left_to_next -= 1;
1637 error0 = SCTP_ERROR_INVALID_CONNECTION;
1650 &sctp_conn->sub_conn
1667 packet_length = clib_net_to_host_u16 (iph4->
length);
1674 &sctp_conn->sub_conn
1678 &sctp_conn->sub_conn
1704 (
"Trying to send an unrecognized chunk... something is really bad.");
1705 error0 = SCTP_ERROR_UNKOWN_CHUNK;
1710 #if SCTP_DEBUG_STATE_MACHINE 1712 (sctp_conn->sub_conn[idx].connection.lcl_port ==
1714 || sctp_conn->sub_conn[idx].connection.lcl_port ==
1716 && (sctp_conn->sub_conn[idx].connection.rmt_port ==
1718 || sctp_conn->sub_conn[idx].connection.rmt_port ==
1724 "packet_length = %u, " 1725 "chunk_type = %u [%s], " 1726 "connection.lcl_port = %u, sctp_hdr->src_port = %u, " 1727 "connection.rmt_port = %u, sctp_hdr->dst_port = %u",
1728 sctp_conn->sub_conn[idx].
1729 connection.c_index, packet_length,
1732 sctp_conn->sub_conn[idx].
1733 connection.lcl_port, sctp_hdr->
src_port,
1734 sctp_conn->sub_conn[idx].
1735 connection.rmt_port,
1738 error0 = SCTP_ERROR_UNKOWN_CHUNK;
1744 (
"SESSION_INDEX = %u, CONN_INDEX = %u, CURR_CONN_STATE = %u (%s), " 1745 "CHUNK_TYPE = %s, " "SRC_PORT = %u, DST_PORT = %u",
1746 sctp_conn->sub_conn[idx].connection.s_index,
1747 sctp_conn->sub_conn[idx].connection.c_index,
1753 #if SCTP_DEBUG_STATE_MACHINE 1754 if (sctp_validate_output_state_machine (sctp_conn, chunk_type) != 0)
1757 (
"Sending the wrong chunk (%s) based on state-machine status (%s)",
1761 error0 = SCTP_ERROR_UNKOWN_CHUNK;
1774 if (chunk_type ==
DATA 1775 && sctp_conn->sub_conn[idx].RTO_pending == 0)
1777 sctp_conn->sub_conn[idx].RTO_pending = 1;
1789 sctp_conn->state = SCTP_STATE_COOKIE_ECHOED;
1797 sctp_conn->sub_conn[idx].RTO);
1804 sctp_conn->sub_conn[idx].RTO);
1805 sctp_conn->state = SCTP_STATE_SHUTDOWN_SENT;
1812 sctp_conn->sub_conn[idx].RTO);
1813 sctp_conn->state = SCTP_STATE_SHUTDOWN_ACK_SENT;
1818 sctp_conn->state = SCTP_STATE_CLOSED;
1825 sctp_conn->sub_conn[idx].c_fib_index;
1827 b0->
flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
1830 (
"SESSION_INDEX = %u, CONNECTION_INDEX = %u, " "NEW_STATE = %s, " 1831 "CHUNK_SENT = %s", sctp_conn->sub_conn[idx].connection.s_index,
1832 sctp_conn->sub_conn[idx].connection.c_index,
1857 n_left_to_next, bi0, next0);
1885 .vector_size =
sizeof (
u32),
1890 #define _(s,n) [SCTP_OUTPUT_NEXT_##s] = n, 1905 .name =
"sctp6-output",
1907 .vector_size =
sizeof (
u32),
1912 #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)
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
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 u32 sctp_set_time_now(u32 thread_index)
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.
ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
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 u32 sctp_time_now(void)
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 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)
u32 stream_session_tx_fifo_max_dequeue(transport_connection_t *tc)
sctp_chunks_common_hdr_t chunk_hdr
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
#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)
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.
#define clib_mem_unaligned(pointer, type)
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)
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