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 u32 cookie_lifespan =
871 if (now > creation_time + cookie_lifespan)
873 SCTP_DBG (
"now (%u) > creation_time (%u) + cookie_lifespan (%u)",
874 now, creation_time, cookie_lifespan);
875 return SCTP_ERROR_COOKIE_ECHO_VIOLATION;
881 sctp_conn->state = SCTP_STATE_ESTABLISHED;
886 sctp_conn->sub_conn[idx].RTO);
890 return SCTP_ERROR_NONE;
903 return SCTP_ERROR_INVALID_TAG;
910 sctp_conn->state = SCTP_STATE_ESTABLISHED;
916 sctp_conn->sub_conn[idx].RTO);
920 return SCTP_ERROR_NONE;
930 u32 n_left_from, next_index, *from, *to_next;
938 while (n_left_from > 0)
944 while (n_left_from > 0 && n_left_to_next > 0)
953 u16 sctp_implied_length = 0;
971 sctp.connection_index);
976 (
"sctp_conn == NULL; return SCTP_ERROR_INVALID_CONNECTION");
977 error0 = SCTP_ERROR_INVALID_CONNECTION;
993 sctp_conn->sub_conn[idx].subconn_idx = idx;
999 sctp_implied_length =
1009 b0, sctp_implied_length);
1011 if (error0 == SCTP_ERROR_NONE)
1013 pool_get (tm->connections[my_thread_index], new_sctp_conn);
1015 sizeof (*new_sctp_conn));
1016 new_sctp_conn->sub_conn[idx].c_c_index =
1017 new_sctp_conn - tm->connections[my_thread_index];
1018 new_sctp_conn->sub_conn[idx].c_thread_index =
1020 new_sctp_conn->sub_conn[idx].PMTU =
1021 sctp_conn->sub_conn[idx].PMTU;
1022 new_sctp_conn->sub_conn[idx].subconn_idx = idx;
1027 (
"Cannot cleanup half-open connection; not the owning thread");
1036 new_sctp_conn, idx, b0,
1037 sctp_implied_length);
1040 (&new_sctp_conn->sub_conn[idx].connection, 0))
1043 (
"conn_index = %u: session_stream_connect_notify error; cleaning up connection",
1044 new_sctp_conn->sub_conn[idx].connection.c_index);
1063 error0 = SCTP_ERROR_UNKOWN_CHUNK;
1068 if (error0 != SCTP_ERROR_NONE)
1086 n_left_to_next, bi0, next0);
1115 s =
format (s,
"%d -> %d (%U)",
1127 .name =
"sctp4-rcv",
1129 .vector_size =
sizeof (
u32),
1135 #define _(s,n) [SCTP_RCV_PHASE_NEXT_##s] = n, 1149 .name =
"sctp6-rcv",
1151 .vector_size =
sizeof (
u32),
1157 #define _(s,n) [SCTP_RCV_PHASE_NEXT_##s] = n, 1183 return SCTP_ERROR_INVALID_TAG;
1190 return SCTP_ERROR_BUNDLING_VIOLATION;
1192 switch (sctp_conn->state)
1194 case SCTP_STATE_ESTABLISHED:
1196 sctp_conn->state = SCTP_STATE_SHUTDOWN_RECEIVED;
1200 case SCTP_STATE_SHUTDOWN_SENT:
1207 return SCTP_ERROR_NONE;
1223 return SCTP_ERROR_INVALID_TAG;
1230 return SCTP_ERROR_BUNDLING_VIOLATION;
1243 return SCTP_ERROR_NONE;
1259 return SCTP_ERROR_INVALID_TAG;
1266 return SCTP_ERROR_BUNDLING_VIOLATION;
1272 sctp_conn->state = SCTP_STATE_CLOSED;
1276 return SCTP_ERROR_NONE;
1284 u32 n_left_from, next_index, *from, *to_next;
1292 while (n_left_from > 0)
1298 while (n_left_from > 0 && n_left_to_next > 0)
1308 u16 sctp_implied_length = 0;
1317 n_left_to_next -= 1;
1327 (
"sctp_conn == NULL; return SCTP_ERROR_INVALID_CONNECTION");
1328 error0 = SCTP_ERROR_INVALID_CONNECTION;
1348 sctp_implied_length =
1357 idx, b0, sctp_implied_length, &next0);
1363 idx, b0, sctp_implied_length,
1371 sctp_implied_length, &next0);
1383 sctp_conn, idx, b0, &next0);
1395 error0 = SCTP_ERROR_NONE;
1403 error0 = SCTP_ERROR_UNKOWN_CHUNK;
1408 if (error0 != SCTP_ERROR_NONE)
1422 if (sctp_hdr !=
NULL)
1426 if (sctp_conn !=
NULL)
1434 n_left_to_next, bi0, next0);
1462 .name =
"sctp4-shutdown",
1464 .vector_size =
sizeof (
u32),
1470 #define _(s,n) [SCTP_SHUTDOWN_PHASE_NEXT_##s] = n, 1485 .name =
"sctp6-shutdown",
1487 .vector_size =
sizeof (
u32),
1493 #define _(s,n) [SCTP_SHUTDOWN_PHASE_NEXT_##s] = n, 1519 return SCTP_ERROR_INVALID_TAG;
1527 if (sctp_conn->sub_conn[idx].cwnd > sctp_conn->sub_conn[idx].ssthresh)
1528 sctp_conn->sub_conn[idx].partially_acked_bytes =
1533 sctp_conn->sub_conn[idx].partially_acked_bytes = 0;
1540 sctp_conn->sub_conn[idx].RTO);
1542 sctp_conn->sub_conn[idx].RTO_pending = 0;
1546 return SCTP_ERROR_NONE;
1557 return SCTP_ERROR_INVALID_TAG;
1564 return SCTP_ERROR_NONE;
1574 sctp_conn->sub_conn[idx].unacknowledged_hb -= 1;
1577 sctp_conn->sub_conn[idx].RTO);
1581 return SCTP_ERROR_NONE;
1586 u8 is_ip4,
u8 evt,
u8 val)
1602 u32 n_left_from, next_index, *from, *to_next;
1610 while (n_left_from > 0)
1616 while (n_left_from > 0 && n_left_to_next > 0)
1632 n_left_to_next -= 1;
1652 my_thread_index, is_ip4);
1657 (
"conn_index = %u: child_conn->state != SCTP_STATE_CLOSED.... STATE=%s",
1661 error0 = SCTP_ERROR_CREATE_EXISTS;
1678 child_conn->state = SCTP_STATE_CLOSED;
1681 connection.fib_index;
1696 sub_conn[SCTP_PRIMARY_PATH_IDX].c_rmt_ip6,
1704 if (chunk_type !=
INIT && chunk_type !=
DATA 1708 (
"conn_index = %u: chunk_type != INIT... chunk_type=%s",
1712 error0 = SCTP_ERROR_UNKOWN_CHUNK;
1717 u16 sctp_implied_length =
1731 sctp_implied_length);
1733 if (error0 == SCTP_ERROR_NONE)
1739 sub_conn[SCTP_PRIMARY_PATH_IDX].c_s_index, 0))
1743 error0 = SCTP_ERROR_CREATE_SESSION_FAIL;
1778 n_left_to_next, bi0, next0);
1804 u32 n_left_from, next_index, *from, *to_next;
1812 while (n_left_from > 0)
1818 while (n_left_from > 0 && n_left_to_next > 0)
1827 u16 error0 = SCTP_ERROR_ENQUEUED, next0 =
1836 n_left_to_next -= 1;
1846 (
"sctp_conn == NULL; return SCTP_ERROR_INVALID_CONNECTION");
1847 error0 = SCTP_ERROR_INVALID_CONNECTION;
1863 sctp_conn->sub_conn[idx].subconn_idx = idx;
1888 sctp_conn, idx, b0, &next0);
1894 sctp_conn, idx, b0, &next0);
1900 sctp_conn, idx, b0, &next0);
1906 sctp_conn, idx, b0, &next0);
1920 error0 = SCTP_ERROR_UNKOWN_CHUNK;
1935 n_left_to_next, bi0, next0);
1946 SCTP_ERROR_EVENT_FIFO_FULL, errors);
1976 s =
format (s,
"%U\n%U%U",
1988 .name =
"sctp4-listen",
1990 .vector_size =
sizeof (
u32),
1996 #define _(s,n) [SCTP_LISTEN_PHASE_NEXT_##s] = n, 2010 .name =
"sctp6-listen",
2012 .vector_size =
sizeof (
u32),
2018 #define _(s,n) [SCTP_LISTEN_PHASE_NEXT_##s] = n, 2032 .name =
"sctp4-established",
2034 .vector_size =
sizeof (
u32),
2040 #define _(s,n) [SCTP_ESTABLISHED_PHASE_NEXT_##s] = n, 2055 .name =
"sctp6-established",
2057 .vector_size =
sizeof (
u32),
2063 #define _(s,n) [SCTP_LISTEN_PHASE_NEXT_##s] = n, 2083 u32 n_left_from, next_index, *from, *to_next;
2093 while (n_left_from > 0)
2099 while (n_left_from > 0 && n_left_to_next > 0)
2101 int n_advance_bytes0, n_data_bytes0;
2102 u32 bi0, fib_index0;
2117 n_left_to_next -= 1;
2137 clib_net_to_host_u16 (ip4_hdr->
length) - n_advance_bytes0;
2160 n_advance_bytes0 +=
sizeof (ip6_hdr[0]);
2175 error0 = SCTP_ERROR_LENGTH;
2186 (
"Received an unrecognized chunk; sending back OPERATION_ERROR chunk");
2191 error0 = SCTP_ERROR_UNKOWN_CHUNK;
2203 vnet_buffer (b0)->sctp.connection_index = trans_conn->c_index;
2204 vnet_buffer (b0)->sctp.data_offset = n_advance_bytes0;
2207 next0 = tm->dispatch_table[sctp_conn->state][chunk_type].next;
2208 error0 = tm->dispatch_table[sctp_conn->state][chunk_type].error;
2211 (
"S_INDEX = %u, C_INDEX = %u, TRANS_CONN = %p, SCTP_CONN = %p, CURRENT_CONNECTION_STATE = %s," 2212 "CHUNK_TYPE_RECEIVED = %s " "NEXT_PHASE = %s",
2216 connection.c_index, trans_conn, sctp_conn,
2220 if (chunk_type ==
DATA)
2221 SCTP_ADV_DBG (
"n_advance_bytes0 = %u, n_data_bytes0 = %u",
2222 n_advance_bytes0, n_data_bytes0);
2230 error0 = SCTP_ERROR_FILTERED;
2232 else if ((is_ip4 && tm->punt_unknown4) ||
2233 (!is_ip4 && tm->punt_unknown6))
2236 error0 = SCTP_ERROR_PUNT;
2241 error0 = SCTP_ERROR_NO_LISTENER;
2258 n_left_to_next, bi0, next0);
2284 .name =
"sctp4-input",
2286 .vector_size =
sizeof (
u32),
2292 #define _(s,n) [SCTP_INPUT_NEXT_##s] = n, 2307 .name =
"sctp6-input",
2309 .vector_size =
sizeof (
u32),
2315 #define _(s,n) [SCTP_INPUT_NEXT_##s] = n, 2333 for (i = 0; i <
ARRAY_LEN (tm->dispatch_table); i++)
2334 for (j = 0; j <
ARRAY_LEN (tm->dispatch_table[i]); j++)
2337 tm->dispatch_table[
i][j].error = SCTP_ERROR_DISPATCH;
2340 #define _(t,f,n,e) \ 2342 tm->dispatch_table[SCTP_STATE_##t][f].next = (n); \ 2343 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)
#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)
static u32 sctp_set_time_now(u32 thread_index)
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)
static u32 sctp_time_now(void)
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
#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