23 #define sctp_error(n,s) s, 29 #define foreach_sctp_state_next \ 30 _ (DROP4, "ip4-drop") \ 31 _ (DROP6, "ip6-drop") \ 32 _ (SCTP4_OUTPUT, "sctp4-output") \ 33 _ (SCTP6_OUTPUT, "sctp6-output") 35 typedef enum _sctp_established_phase_next
37 #define _(s,n) SCTP_ESTABLISHED_PHASE_NEXT_##s, 43 typedef enum _sctp_rcv_phase_next
45 #define _(s,n) SCTP_RCV_PHASE_NEXT_##s, 51 typedef enum _sctp_listen_phase_next
53 #define _(s,n) SCTP_LISTEN_PHASE_NEXT_##s, 59 typedef enum _sctp_shutdown_phase_next
61 #define _(s,n) SCTP_SHUTDOWN_PHASE_NEXT_##s, 68 typedef enum _sctp_state_next
70 #define _(s,n) SCTP_NEXT_##s, 76 typedef enum _sctp_input_next
93 return "SCTP_INPUT_NEXT_DROP";
95 return "SCTP_INPUT_NEXT_LISTEN_PHASE";
97 return "SCTP_INPUT_NEXT_RCV_PHASE";
99 return "SCTP_INPUT_NEXT_ESTABLISHED_PHASE";
101 return "SCTP_INPUT_NEXT_SHUTDOWN_PHASE";
103 return "SCTP_INPUT_NEXT_PUNT_PHASE";
108 #define foreach_sctp4_input_next \ 109 _ (DROP, "error-drop") \ 110 _ (RCV_PHASE, "sctp4-rcv") \ 111 _ (LISTEN_PHASE, "sctp4-listen") \ 112 _ (ESTABLISHED_PHASE, "sctp4-established") \ 113 _ (SHUTDOWN_PHASE, "sctp4-shutdown") \ 114 _ (PUNT_PHASE, "ip4-punt") 117 #define foreach_sctp6_input_next \ 118 _ (DROP, "error-drop") \ 119 _ (RCV_PHASE, "sctp6-rcv") \ 120 _ (LISTEN_PHASE, "sctp6-listen") \ 121 _ (ESTABLISHED_PHASE, "sctp6-established") \ 122 _ (SHUTDOWN_PHASE, "sctp6-shutdown") \ 123 _ (PUNT_PHASE, "ip6-punt") 135 u8 is_valid = (trans_conn->lcl_port == sctp_hdr->
dst_port 136 && (sctp_conn->state == SCTP_STATE_CLOSED
137 || trans_conn->rmt_port == sctp_hdr->
src_port));
165 thread_index, &is_filtered);
170 if ((tm->connections[thread_index]->sub_conn[i].
171 connection.lcl_ip.ip4.as_u32 ==
173 && (tm->connections[thread_index]->sub_conn[i].
174 connection.rmt_ip.ip4.as_u32 ==
178 &tm->connections[thread_index]->sub_conn[
i].connection;
197 thread_index, &is_filtered);
202 if ((tm->connections[thread_index]->sub_conn[i].
203 connection.lcl_ip.ip6.as_u64[0] ==
205 && tm->connections[thread_index]->sub_conn[i].
206 connection.lcl_ip.ip6.as_u64[1] ==
208 && (tm->connections[thread_index]->sub_conn[i].
209 connection.rmt_ip.ip6.as_u64[0] ==
211 && tm->connections[thread_index]->
212 sub_conn[i].connection.rmt_ip.ip6.as_u64[1] ==
216 &tm->connections[thread_index]->sub_conn[
i].connection;
234 #define sctp_next_output(is_ip4) (is_ip4 ? SCTP_NEXT_SCTP4_OUTPUT \ 235 : SCTP_NEXT_SCTP6_OUTPUT) 237 #define sctp_next_drop(is_ip4) (is_ip4 ? SCTP_NEXT_DROP4 \ 263 u16 sctp_implied_packet_length = 0;
266 sctp_implied_packet_length =
269 sctp_implied_packet_length =
270 clib_net_to_host_u16 (ip6_hdr->
payload_length) -
sizeof (ip6_hdr);
272 return sctp_implied_packet_length;
279 if (sctp_implied_length !=
295 return SCTP_ERROR_INVALID_TAG;
301 if (sctp_conn->state != SCTP_STATE_COOKIE_ECHOED)
308 sub_conn[idx].connection);
312 return SCTP_ERROR_NONE;
319 u16 sctp_implied_length)
335 if (sctp_conn->state != SCTP_STATE_CLOSED)
337 switch (sctp_conn->state)
339 case SCTP_STATE_COOKIE_WAIT:
340 SCTP_ADV_DBG (
"Received INIT chunk while in COOKIE_WAIT state");
343 b0, &ip4_addr, &ip6_addr);
344 return SCTP_ERROR_NONE;
345 case SCTP_STATE_COOKIE_ECHOED:
346 case SCTP_STATE_SHUTDOWN_ACK_SENT:
347 SCTP_ADV_DBG (
"Received INIT chunk while in COOKIE_ECHOED state");
348 if (sctp_conn->forming_association_changed == 0)
356 &ip4_addr, &ip6_addr);
357 return SCTP_ERROR_NONE;
362 return SCTP_ERROR_INVALID_TAG_FOR_INIT;
368 return SCTP_ERROR_BUNDLING_VIOLATION;
373 sctp_conn->remote_initial_tsn =
375 sctp_conn->last_rcvd_tsn = sctp_conn->remote_initial_tsn;
376 sctp_conn->next_tsn_expected = sctp_conn->remote_initial_tsn + 1;
378 sctp_conn->remote_initial_tsn);
380 sctp_conn->peer_rwnd = clib_net_to_host_u32 (init_chunk->
a_rwnd);
390 while (pointer_offset < length)
395 switch (clib_net_to_host_u16 (opt_params_hdr->
type))
435 sctp_conn->peer_cookie_life_span_increment =
453 pointer_offset += clib_net_to_host_u16 (opt_params_hdr->
length);
459 add_ip4, &ip6_addr, add_ip6);
460 return SCTP_ERROR_NONE;
467 u16 sctp_implied_length)
475 return SCTP_ERROR_INVALID_TAG;
482 return SCTP_ERROR_BUNDLING_VIOLATION;
484 return SCTP_ERROR_NONE;
501 return SCTP_ERROR_INVALID_TAG;
508 return SCTP_ERROR_BUNDLING_VIOLATION;
517 sctp_conn->remote_initial_tsn =
518 clib_net_to_host_u32 (init_ack_chunk->
initial_tsn);
519 sctp_conn->last_rcvd_tsn = sctp_conn->remote_initial_tsn;
520 sctp_conn->next_tsn_expected = sctp_conn->remote_initial_tsn + 1;
522 sctp_conn->remote_initial_tsn);
523 sctp_conn->peer_rwnd = clib_net_to_host_u32 (init_ack_chunk->
a_rwnd);
534 while (pointer_offset < length)
540 switch (clib_net_to_host_u16 (opt_params_hdr->
type))
571 clib_memcpy (&(sctp_conn->cookie_param), state_cookie_param,
589 u16 increment = clib_net_to_host_u16 (opt_params_hdr->
length);
593 return SCTP_ERROR_INVALID_TAG;
595 pointer_offset += increment;
603 SCTP_TIMER_T1_COOKIE, sctp_conn->sub_conn[idx].RTO);
605 return SCTP_ERROR_NONE;
613 int written, error = SCTP_ERROR_ENQUEUED;
617 sub_conn[conn_idx].connection, b, 0,
624 sctp_conn->next_tsn_expected += written;
626 SCTP_ADV_DBG (
"CONN = %u, WRITTEN [%u] == DATA_LEN [%d]",
627 sctp_conn->sub_conn[conn_idx].connection.c_index,
631 else if (written > data_len)
633 sctp_conn->next_tsn_expected += written;
635 SCTP_ADV_DBG (
"CONN = %u, WRITTEN [%u] > DATA_LEN [%d]",
636 sctp_conn->sub_conn[conn_idx].connection.c_index,
639 else if (written > 0)
642 sctp_conn->next_tsn_expected += written;
644 error = SCTP_ERROR_PARTIALLY_ENQUEUED;
647 (
"CONN = %u, WRITTEN [%u] > 0 (SCTP_ERROR_PARTIALLY_ENQUEUED)",
648 sctp_conn->sub_conn[conn_idx].connection.c_index, written);
652 SCTP_ADV_DBG (
"CONN = %u, WRITTEN == 0 (SCTP_ERROR_FIFO_FULL)",
653 sctp_conn->sub_conn[conn_idx].connection.c_index);
655 return SCTP_ERROR_FIFO_FULL;
666 u16 data_len,
u8 conn_idx)
668 int written, error = SCTP_ERROR_ENQUEUED;
672 sub_conn[conn_idx].connection, b, 0,
679 sctp_conn->next_tsn_expected += written;
681 SCTP_ADV_DBG (
"CONN = %u, WRITTEN [%u] == DATA_LEN [%d]",
682 sctp_conn->sub_conn[conn_idx].connection.c_index,
686 else if (written > data_len)
688 sctp_conn->next_tsn_expected += written;
690 SCTP_ADV_DBG (
"CONN = %u, WRITTEN [%u] > DATA_LEN [%d]",
691 sctp_conn->sub_conn[conn_idx].connection.c_index,
694 else if (written > 0)
697 sctp_conn->next_tsn_expected += written;
699 error = SCTP_ERROR_PARTIALLY_ENQUEUED;
702 (
"CONN = %u, WRITTEN [%u] > 0 (SCTP_ERROR_PARTIALLY_ENQUEUED)",
703 sctp_conn->sub_conn[conn_idx].connection.c_index, written);
707 SCTP_ADV_DBG (
"CONN = %u, WRITTEN == 0 (SCTP_ERROR_FIFO_FULL)",
708 sctp_conn->sub_conn[conn_idx].connection.c_index);
710 return SCTP_ERROR_FIFO_FULL;
719 if (sctp_conn->conn_config.never_delay_sack)
726 if (sctp_conn->state == SCTP_STATE_SHUTDOWN_SENT)
736 (
"gapping != 0: CONN_INDEX = %u, sctp_conn->ack_state = %u",
737 sctp_conn->sub_conn[idx].connection.c_index, sctp_conn->ack_state);
741 sctp_conn->ack_state += 1;
745 (
"sctp_conn->ack_state >= MAX_ENQUEABLE_SACKS: CONN_INDEX = %u, sctp_conn->ack_state = %u",
746 sctp_conn->sub_conn[idx].connection.c_index, sctp_conn->ack_state);
757 if (sctp_conn->next_tsn_expected != tsn)
760 (
"GAPPING: CONN_INDEX = %u, sctp_conn->next_tsn_expected = %u, tsn = %u, diff = %u",
762 sctp_conn->next_tsn_expected, tsn,
763 sctp_conn->next_tsn_expected - tsn);
774 u32 error = 0, n_data_bytes;
780 return SCTP_ERROR_INVALID_TAG;
786 u32 tsn = clib_net_to_host_u32 (sctp_data_chunk->
tsn);
794 sctp_conn->last_rcvd_tsn = tsn;
801 if (bbit == 1 && ebit == 1)
811 else if (bbit == 1 && ebit == 0)
815 else if (bbit == 0 && ebit == 1)
831 sctp_conn->last_rcvd_tsn = tsn;
843 sctp_conn->sub_conn[idx].enqueue_state = error;
862 return SCTP_ERROR_INVALID_TAG;
869 u64 cookie_lifespan =
872 if (now > creation_time + cookie_lifespan)
874 SCTP_DBG (
"now (%u) > creation_time (%u) + cookie_lifespan (%u)",
875 now, creation_time, cookie_lifespan);
876 return SCTP_ERROR_COOKIE_ECHO_VIOLATION;
882 sctp_conn->state = SCTP_STATE_ESTABLISHED;
887 sctp_conn->sub_conn[idx].RTO);
891 return SCTP_ERROR_NONE;
904 return SCTP_ERROR_INVALID_TAG;
911 sctp_conn->state = SCTP_STATE_ESTABLISHED;
917 sctp_conn->sub_conn[idx].RTO);
921 return SCTP_ERROR_NONE;
931 u32 n_left_from, next_index, *from, *to_next;
939 while (n_left_from > 0)
945 while (n_left_from > 0 && n_left_to_next > 0)
954 u16 sctp_implied_length = 0;
972 sctp.connection_index);
977 (
"sctp_conn == NULL; return SCTP_ERROR_INVALID_CONNECTION");
978 error0 = SCTP_ERROR_INVALID_CONNECTION;
994 sctp_conn->sub_conn[idx].subconn_idx = idx;
1000 sctp_implied_length =
1010 b0, sctp_implied_length);
1012 if (error0 == SCTP_ERROR_NONE)
1014 pool_get (tm->connections[my_thread_index], new_sctp_conn);
1016 sizeof (*new_sctp_conn));
1017 new_sctp_conn->sub_conn[idx].c_c_index =
1018 new_sctp_conn - tm->connections[my_thread_index];
1019 new_sctp_conn->sub_conn[idx].c_thread_index =
1021 new_sctp_conn->sub_conn[idx].PMTU =
1022 sctp_conn->sub_conn[idx].PMTU;
1023 new_sctp_conn->sub_conn[idx].subconn_idx = idx;
1028 (
"Cannot cleanup half-open connection; not the owning thread");
1037 new_sctp_conn, idx, b0,
1038 sctp_implied_length);
1041 (&new_sctp_conn->sub_conn[idx].connection, 0))
1044 (
"conn_index = %u: session_stream_connect_notify error; cleaning up connection",
1045 new_sctp_conn->sub_conn[idx].connection.c_index);
1064 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
1069 if (error0 != SCTP_ERROR_NONE)
1087 n_left_to_next, bi0, next0);
1116 s =
format (s,
"%d -> %d (%U)",
1128 .name =
"sctp4-rcv",
1130 .vector_size =
sizeof (
u32),
1136 #define _(s,n) [SCTP_RCV_PHASE_NEXT_##s] = n, 1150 .name =
"sctp6-rcv",
1152 .vector_size =
sizeof (
u32),
1158 #define _(s,n) [SCTP_RCV_PHASE_NEXT_##s] = n, 1184 return SCTP_ERROR_INVALID_TAG;
1191 return SCTP_ERROR_BUNDLING_VIOLATION;
1193 switch (sctp_conn->state)
1195 case SCTP_STATE_ESTABLISHED:
1197 sctp_conn->state = SCTP_STATE_SHUTDOWN_RECEIVED;
1201 case SCTP_STATE_SHUTDOWN_SENT:
1208 return SCTP_ERROR_NONE;
1224 return SCTP_ERROR_INVALID_TAG;
1231 return SCTP_ERROR_BUNDLING_VIOLATION;
1244 return SCTP_ERROR_NONE;
1260 return SCTP_ERROR_INVALID_TAG;
1267 return SCTP_ERROR_BUNDLING_VIOLATION;
1273 sctp_conn->state = SCTP_STATE_CLOSED;
1277 return SCTP_ERROR_NONE;
1285 u32 n_left_from, next_index, *from, *to_next;
1293 while (n_left_from > 0)
1299 while (n_left_from > 0 && n_left_to_next > 0)
1309 u16 sctp_implied_length = 0;
1318 n_left_to_next -= 1;
1328 (
"sctp_conn == NULL; return SCTP_ERROR_INVALID_CONNECTION");
1329 error0 = SCTP_ERROR_INVALID_CONNECTION;
1349 sctp_implied_length =
1358 idx, b0, sctp_implied_length, &next0);
1364 idx, b0, sctp_implied_length,
1372 sctp_implied_length, &next0);
1384 sctp_conn, idx, b0, &next0);
1396 error0 = SCTP_ERROR_NONE;
1404 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
1409 if (error0 != SCTP_ERROR_NONE)
1423 if (sctp_hdr !=
NULL)
1427 if (sctp_conn !=
NULL)
1435 n_left_to_next, bi0, next0);
1463 .name =
"sctp4-shutdown",
1465 .vector_size =
sizeof (
u32),
1471 #define _(s,n) [SCTP_SHUTDOWN_PHASE_NEXT_##s] = n, 1486 .name =
"sctp6-shutdown",
1488 .vector_size =
sizeof (
u32),
1494 #define _(s,n) [SCTP_SHUTDOWN_PHASE_NEXT_##s] = n, 1521 (
"sctp_conn->local_tag != sack_chunk->sctp_hdr.verification_tag");
1525 return SCTP_ERROR_INVALID_TAG;
1533 if (sctp_conn->sub_conn[idx].cwnd > sctp_conn->sub_conn[idx].ssthresh)
1534 sctp_conn->sub_conn[idx].partially_acked_bytes =
1539 sctp_conn->sub_conn[idx].partially_acked_bytes = 0;
1546 sctp_conn->sub_conn[idx].RTO);
1548 sctp_conn->sub_conn[idx].RTO_pending = 0;
1552 return SCTP_ERROR_NONE;
1563 return SCTP_ERROR_INVALID_TAG;
1570 return SCTP_ERROR_NONE;
1580 sctp_conn->sub_conn[idx].unacknowledged_hb -= 1;
1583 sctp_conn->sub_conn[idx].RTO);
1587 return SCTP_ERROR_NONE;
1592 u8 is_ip4,
u8 evt,
u8 val)
1608 u32 n_left_from, next_index, *from, *to_next;
1616 while (n_left_from > 0)
1622 while (n_left_from > 0 && n_left_to_next > 0)
1638 n_left_to_next -= 1;
1658 my_thread_index, is_ip4);
1663 (
"conn_index = %u: child_conn->state != SCTP_STATE_CLOSED.... STATE=%s",
1667 error0 = SCTP_ERROR_CREATE_EXISTS;
1684 child_conn->state = SCTP_STATE_CLOSED;
1687 connection.fib_index;
1702 sub_conn[SCTP_PRIMARY_PATH_IDX].c_rmt_ip6,
1710 if (chunk_type !=
INIT && chunk_type !=
DATA 1714 (
"conn_index = %u: chunk_type != INIT... chunk_type=%s",
1718 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
1723 u16 sctp_implied_length =
1737 sctp_implied_length);
1739 if (error0 == SCTP_ERROR_NONE)
1745 sub_conn[SCTP_PRIMARY_PATH_IDX].c_s_index, 0))
1749 error0 = SCTP_ERROR_CREATE_SESSION_FAIL;
1784 n_left_to_next, bi0, next0);
1810 u32 n_left_from, next_index, *from, *to_next;
1818 while (n_left_from > 0)
1824 while (n_left_from > 0 && n_left_to_next > 0)
1833 u16 error0 = SCTP_ERROR_ENQUEUED, next0 =
1842 n_left_to_next -= 1;
1852 (
"sctp_conn == NULL; return SCTP_ERROR_INVALID_CONNECTION");
1853 error0 = SCTP_ERROR_INVALID_CONNECTION;
1869 sctp_conn->sub_conn[idx].subconn_idx = idx;
1894 sctp_conn, idx, b0, &next0);
1900 sctp_conn, idx, b0, &next0);
1906 sctp_conn, idx, b0, &next0);
1912 sctp_conn, idx, b0, &next0);
1926 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
1941 n_left_to_next, bi0, next0);
1952 SCTP_ERROR_EVENT_FIFO_FULL, errors);
1982 s =
format (s,
"%U\n%U%U",
1994 .name =
"sctp4-listen",
1996 .vector_size =
sizeof (
u32),
2002 #define _(s,n) [SCTP_LISTEN_PHASE_NEXT_##s] = n, 2016 .name =
"sctp6-listen",
2018 .vector_size =
sizeof (
u32),
2024 #define _(s,n) [SCTP_LISTEN_PHASE_NEXT_##s] = n, 2038 .name =
"sctp4-established",
2040 .vector_size =
sizeof (
u32),
2046 #define _(s,n) [SCTP_ESTABLISHED_PHASE_NEXT_##s] = n, 2061 .name =
"sctp6-established",
2063 .vector_size =
sizeof (
u32),
2069 #define _(s,n) [SCTP_LISTEN_PHASE_NEXT_##s] = n, 2089 u32 n_left_from, next_index, *from, *to_next;
2099 while (n_left_from > 0)
2105 while (n_left_from > 0 && n_left_to_next > 0)
2107 int n_advance_bytes0, n_data_bytes0;
2108 u32 bi0, fib_index0;
2123 n_left_to_next -= 1;
2143 clib_net_to_host_u16 (ip4_hdr->
length) - n_advance_bytes0;
2166 n_advance_bytes0 +=
sizeof (ip6_hdr[0]);
2181 error0 = SCTP_ERROR_LENGTH;
2192 (
"Received an unrecognized chunk; sending back OPERATION_ERROR chunk");
2197 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
2209 vnet_buffer (b0)->sctp.connection_index = trans_conn->c_index;
2210 vnet_buffer (b0)->sctp.data_offset = n_advance_bytes0;
2213 next0 = tm->dispatch_table[sctp_conn->state][chunk_type].next;
2214 error0 = tm->dispatch_table[sctp_conn->state][chunk_type].error;
2217 (
"S_INDEX = %u, C_INDEX = %u, TRANS_CONN = %p, SCTP_CONN = %p, CURRENT_CONNECTION_STATE = %s," 2218 "CHUNK_TYPE_RECEIVED = %s " "NEXT_PHASE = %s",
2222 connection.c_index, trans_conn, sctp_conn,
2226 if (chunk_type ==
DATA)
2227 SCTP_ADV_DBG (
"n_advance_bytes0 = %u, n_data_bytes0 = %u",
2228 n_advance_bytes0, n_data_bytes0);
2236 error0 = SCTP_ERROR_FILTERED;
2238 else if ((is_ip4 && tm->punt_unknown4) ||
2239 (!is_ip4 && tm->punt_unknown6))
2242 error0 = SCTP_ERROR_PUNT;
2247 error0 = SCTP_ERROR_NO_LISTENER;
2264 n_left_to_next, bi0, next0);
2290 .name =
"sctp4-input",
2292 .vector_size =
sizeof (
u32),
2298 #define _(s,n) [SCTP_INPUT_NEXT_##s] = n, 2313 .name =
"sctp6-input",
2315 .vector_size =
sizeof (
u32),
2321 #define _(s,n) [SCTP_INPUT_NEXT_##s] = n, 2339 for (i = 0; i <
ARRAY_LEN (tm->dispatch_table); i++)
2340 for (j = 0; j <
ARRAY_LEN (tm->dispatch_table[i]); j++)
2343 tm->dispatch_table[
i][j].error = SCTP_ERROR_DISPATCH;
2346 #define _(t,f,n,e) \ 2348 tm->dispatch_table[SCTP_STATE_##t][f].next = (n); \ 2349 tm->dispatch_table[SCTP_STATE_##t][f].error = (e); \ 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.
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 sctp_connection_timers_init(sctp_connection_t *sctp_conn)
Initialize all connection timers as invalid.
static u8 sctp_sub_conn_id_via_ip4h(sctp_connection_t *sctp_conn, ip4_header_t *ip4h)
#define SCTP_DBG(_fmt, _args...)
void sctp_init_snd_vars(sctp_connection_t *sctp_conn)
Initialize connection send variables.
sctp_state_cookie_param_t cookie
struct _transport_connection transport_connection_t
#define COOKIE_RECEIVED_WHILE_SHUTTING_DOWN
static int ip4_header_bytes(ip4_header_t *i)
sctp_header_t sctp_header
sctp_chunks_common_hdr_t chunk_hdr
static u8 vnet_sctp_get_ebit(sctp_chunks_common_hdr_t *h)
static u64 sctp_time_now(void)
#define SCTP_ADV_DBG(_fmt, _args...)
sctp_chunks_common_hdr_t chunk_hdr
#define SCTP_HOSTNAME_ADDRESS_TYPE
void sctp_prepare_cookie_ack_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
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.
static void sctp_calculate_rto(sctp_connection_t *sctp_conn, u8 conn_idx)
int session_enqueue_stream_connection(transport_connection_t *tc, vlib_buffer_t *b, u32 offset, u8 queue_event, u8 is_in_order)
vlib_error_t * errors
Vector of errors for this node.
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
static sctp_main_t * vnet_get_sctp_main()
sctp_chunks_common_hdr_t chunk_hdr
#define VLIB_INIT_FUNCTION(x)
static void sctp_init_cwnd(sctp_connection_t *sctp_conn)
void stream_session_accept_notify(transport_connection_t *tc)
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.
#define STALE_COOKIE_ERROR
#define UNRECOGNIZED_CHUNK_TYPE
static void vnet_sctp_common_hdr_params_net_to_host(sctp_chunks_common_hdr_t *h)
static void * ip4_next_header(ip4_header_t *i)
void sctp_prepare_sack_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to SACK.
static int sctp_half_open_connection_cleanup(sctp_connection_t *tc)
Try to cleanup half-open connection.
sctp_connection_t * sctp_connection_new(u8 thread_index)
#define vlib_call_init_function(vm, x)
#define SCTP_STATE_COOKIE_TYPE
#define SCTP_UNRECOGNIZED_TYPE
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_timer_reset(sctp_connection_t *tc, u8 conn_idx, u8 timer_id)
static sctp_connection_t * sctp_get_connection_from_transport(transport_connection_t *tconn)
sctp_init_chunk_t sctp_init_ack_chunk_t
static u8 vnet_sctp_get_bbit(sctp_chunks_common_hdr_t *h)
u8 sctp_sub_connection_add_ip4(vlib_main_t *vm, ip4_address_t *lcl_addr, ip4_address_t *rmt_addr)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
struct _sctp_connection sctp_connection_t
#define SCTP_IPV6_ADDRESS_TYPE
static u64 sctp_set_time_now(u32 thread_index)
#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.
int stream_session_accept(transport_connection_t *tc, u32 listener_index, u8 notify)
Accept a stream session.
#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
vlib_error_t error
Error code for buffers to be enqueued to error handler.
static char * sctp_state_to_string(u8 state)
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
static u8 vnet_sctp_get_chunk_type(sctp_chunks_common_hdr_t *h)
#define MAX_ENQUEABLE_SACKS
sctp_chunks_common_hdr_t common_hdr
#define VLIB_REGISTER_NODE(x,...)
u8 * format_sctp_connection(u8 *s, va_list *args)
#define clib_warning(format, args...)
#define clib_memcpy(a, b, c)
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.
static u32 sctp_header_bytes()
static void * ip6_next_header(ip6_header_t *i)
char hostname[FQDN_MAX_LENGTH]
void stream_session_disconnect_notify(transport_connection_t *tc)
Notification from transport that connection is being closed.
void sctp_send_shutdown_complete(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b0)
transport_connection_t * session_lookup_connection_wt4(u32 fib_index, ip4_address_t *lcl, ip4_address_t *rmt, u16 lcl_port, u16 rmt_port, u8 proto, u32 thread_index, u8 *is_filtered)
Lookup connection with ip4 and transport layer information.
void sctp_prepare_operation_error(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b, u8 err_cause)
Convert buffer to ERROR.
static sctp_connection_t * sctp_half_open_connection_get(u32 conn_index)
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
#define SCTP_CONN_TRACKING_DBG(_fmt, _args...)
sctp_connection_t sctp_connection
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
sctp_chunks_common_hdr_t chunk_hdr
void sctp_connection_cleanup(sctp_connection_t *sctp_conn)
Cleans up connection state.
transport_connection_t * session_lookup_connection_wt6(u32 fib_index, ip6_address_t *lcl, ip6_address_t *rmt, u16 lcl_port, u16 rmt_port, u8 proto, u32 thread_index, u8 *is_filtered)
Lookup connection with ip6 and transport layer information.
static vlib_main_t * vlib_get_main(void)
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_prepare_cookie_echo_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b, u8 reuse_buffer)
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)
struct _vlib_node_registration vlib_node_registration_t
static sctp_connection_t * sctp_connection_get(u32 conn_index, u32 thread_index)
#define SCTP_IPV4_ADDRESS_TYPE
sctp_err_cause_param_t err_causes[]
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
clib_error_t * sctp_init(vlib_main_t *vm)
sctp_chunks_common_hdr_t chunk_hdr
int session_manager_flush_enqueue_events(u8 transport_proto, u32 thread_index)
Flushes queue of sessions that are to be notified of new data enqueued events.
static u16 vnet_sctp_get_chunk_length(sctp_chunks_common_hdr_t *h)
static char * sctp_chunk_to_string(u8 type)
int session_stream_connect_notify(transport_connection_t *tc, u8 is_fail)
static u8 sctp_sub_conn_id_via_ip6h(sctp_connection_t *sctp_conn, ip6_header_t *ip6h)
#define SCTP_COOKIE_PRESERVATIVE_TYPE
static sctp_connection_t * sctp_listener_get(u32 tli)
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 sctp_header_t * sctp_buffer_hdr(vlib_buffer_t *b)
u8 sctp_sub_connection_add_ip6(vlib_main_t *vm, ip6_address_t *lcl_addr, ip6_address_t *rmt_addr)
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
#define SCTP_DBG_STATE_MACHINE(_fmt, _args...)
void sctp_send_shutdown_ack(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
format_function_t format_sctp_state
#define SCTP_SUPPORTED_ADDRESS_TYPES