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))
590 u16 increment = clib_net_to_host_u16 (opt_params_hdr->
length);
594 return SCTP_ERROR_INVALID_TAG;
596 pointer_offset += increment;
604 SCTP_TIMER_T1_COOKIE, sctp_conn->sub_conn[idx].RTO);
606 return SCTP_ERROR_NONE;
614 int written, error = SCTP_ERROR_ENQUEUED;
618 sub_conn[conn_idx].connection, b, 0,
625 sctp_conn->next_tsn_expected += written;
627 SCTP_ADV_DBG (
"CONN = %u, WRITTEN [%u] == DATA_LEN [%d]",
628 sctp_conn->sub_conn[conn_idx].connection.c_index,
632 else if (written > data_len)
634 sctp_conn->next_tsn_expected += written;
636 SCTP_ADV_DBG (
"CONN = %u, WRITTEN [%u] > DATA_LEN [%d]",
637 sctp_conn->sub_conn[conn_idx].connection.c_index,
640 else if (written > 0)
643 sctp_conn->next_tsn_expected += written;
645 error = SCTP_ERROR_PARTIALLY_ENQUEUED;
648 (
"CONN = %u, WRITTEN [%u] > 0 (SCTP_ERROR_PARTIALLY_ENQUEUED)",
649 sctp_conn->sub_conn[conn_idx].connection.c_index, written);
653 SCTP_ADV_DBG (
"CONN = %u, WRITTEN == 0 (SCTP_ERROR_FIFO_FULL)",
654 sctp_conn->sub_conn[conn_idx].connection.c_index);
656 return SCTP_ERROR_FIFO_FULL;
667 u16 data_len,
u8 conn_idx)
669 int written, error = SCTP_ERROR_ENQUEUED;
673 sub_conn[conn_idx].connection, b, 0,
680 sctp_conn->next_tsn_expected += written;
682 SCTP_ADV_DBG (
"CONN = %u, WRITTEN [%u] == DATA_LEN [%d]",
683 sctp_conn->sub_conn[conn_idx].connection.c_index,
687 else if (written > data_len)
689 sctp_conn->next_tsn_expected += written;
691 SCTP_ADV_DBG (
"CONN = %u, WRITTEN [%u] > DATA_LEN [%d]",
692 sctp_conn->sub_conn[conn_idx].connection.c_index,
695 else if (written > 0)
698 sctp_conn->next_tsn_expected += written;
700 error = SCTP_ERROR_PARTIALLY_ENQUEUED;
703 (
"CONN = %u, WRITTEN [%u] > 0 (SCTP_ERROR_PARTIALLY_ENQUEUED)",
704 sctp_conn->sub_conn[conn_idx].connection.c_index, written);
708 SCTP_ADV_DBG (
"CONN = %u, WRITTEN == 0 (SCTP_ERROR_FIFO_FULL)",
709 sctp_conn->sub_conn[conn_idx].connection.c_index);
711 return SCTP_ERROR_FIFO_FULL;
720 if (sctp_conn->conn_config.never_delay_sack)
727 if (sctp_conn->state == SCTP_STATE_SHUTDOWN_SENT)
737 (
"gapping != 0: CONN_INDEX = %u, sctp_conn->ack_state = %u",
738 sctp_conn->sub_conn[idx].connection.c_index, sctp_conn->ack_state);
742 sctp_conn->ack_state += 1;
746 (
"sctp_conn->ack_state >= MAX_ENQUEABLE_SACKS: CONN_INDEX = %u, sctp_conn->ack_state = %u",
747 sctp_conn->sub_conn[idx].connection.c_index, sctp_conn->ack_state);
758 if (sctp_conn->next_tsn_expected != tsn)
761 (
"GAPPING: CONN_INDEX = %u, sctp_conn->next_tsn_expected = %u, tsn = %u, diff = %u",
763 sctp_conn->next_tsn_expected, tsn,
764 sctp_conn->next_tsn_expected - tsn);
775 u32 error = 0, n_data_bytes;
782 sctp_conn->sub_conn[idx].enqueue_state = SCTP_ERROR_INVALID_TAG;
783 return sctp_conn->sub_conn[idx].enqueue_state;
789 u32 tsn = clib_net_to_host_u32 (sctp_data_chunk->
tsn);
816 sctp_conn->last_rcvd_tsn = tsn;
823 if (bbit == 1 && ebit == 1)
833 else if (bbit == 1 && ebit == 0)
837 else if (bbit == 0 && ebit == 1)
853 sctp_conn->last_rcvd_tsn = tsn;
865 sctp_conn->sub_conn[idx].enqueue_state = error;
885 return SCTP_ERROR_INVALID_TAG;
892 u64 cookie_lifespan =
895 if (now > creation_time + cookie_lifespan)
897 SCTP_DBG (
"now (%u) > creation_time (%u) + cookie_lifespan (%u)",
898 now, creation_time, cookie_lifespan);
899 return SCTP_ERROR_COOKIE_ECHO_VIOLATION;
905 sctp_conn->state = SCTP_STATE_ESTABLISHED;
910 sctp_conn->sub_conn[idx].RTO);
914 return SCTP_ERROR_NONE;
928 return SCTP_ERROR_INVALID_TAG;
935 sctp_conn->state = SCTP_STATE_ESTABLISHED;
941 sctp_conn->sub_conn[idx].RTO);
945 return SCTP_ERROR_NONE;
955 u32 n_left_from, next_index, *from, *to_next;
963 while (n_left_from > 0)
969 while (n_left_from > 0 && n_left_to_next > 0)
978 u16 sctp_implied_length = 0;
996 sctp.connection_index);
1001 (
"sctp_conn == NULL; return SCTP_ERROR_INVALID_CONNECTION");
1002 error0 = SCTP_ERROR_INVALID_CONNECTION;
1018 sctp_conn->sub_conn[idx].subconn_idx = idx;
1024 sctp_implied_length =
1034 b0, sctp_implied_length);
1036 if (error0 == SCTP_ERROR_NONE)
1038 pool_get (tm->connections[my_thread_index], new_sctp_conn);
1040 sizeof (*new_sctp_conn));
1041 new_sctp_conn->sub_conn[idx].c_c_index =
1042 new_sctp_conn - tm->connections[my_thread_index];
1043 new_sctp_conn->sub_conn[idx].c_thread_index =
1045 new_sctp_conn->sub_conn[idx].PMTU =
1046 sctp_conn->sub_conn[idx].PMTU;
1047 new_sctp_conn->sub_conn[idx].subconn_idx = idx;
1052 (
"Cannot cleanup half-open connection; not the owning thread");
1061 new_sctp_conn, idx, b0,
1062 sctp_implied_length);
1065 (&new_sctp_conn->sub_conn[idx].connection, 0))
1068 (
"conn_index = %u: session_stream_connect_notify error; cleaning up connection",
1069 new_sctp_conn->sub_conn[idx].connection.c_index);
1088 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
1093 if (error0 != SCTP_ERROR_NONE)
1111 n_left_to_next, bi0, next0);
1140 s =
format (s,
"%d -> %d (%U)",
1152 .name =
"sctp4-rcv",
1154 .vector_size =
sizeof (
u32),
1160 #define _(s,n) [SCTP_RCV_PHASE_NEXT_##s] = n, 1174 .name =
"sctp6-rcv",
1176 .vector_size =
sizeof (
u32),
1182 #define _(s,n) [SCTP_RCV_PHASE_NEXT_##s] = n, 1209 return SCTP_ERROR_INVALID_TAG;
1216 return SCTP_ERROR_BUNDLING_VIOLATION;
1218 switch (sctp_conn->state)
1220 case SCTP_STATE_ESTABLISHED:
1222 sctp_conn->state = SCTP_STATE_SHUTDOWN_RECEIVED;
1226 case SCTP_STATE_SHUTDOWN_SENT:
1233 return SCTP_ERROR_NONE;
1250 return SCTP_ERROR_INVALID_TAG;
1257 return SCTP_ERROR_BUNDLING_VIOLATION;
1270 return SCTP_ERROR_NONE;
1287 return SCTP_ERROR_INVALID_TAG;
1294 return SCTP_ERROR_BUNDLING_VIOLATION;
1300 sctp_conn->state = SCTP_STATE_CLOSED;
1304 return SCTP_ERROR_NONE;
1312 u32 n_left_from, next_index, *from, *to_next;
1320 while (n_left_from > 0)
1326 while (n_left_from > 0 && n_left_to_next > 0)
1336 u16 sctp_implied_length = 0;
1345 n_left_to_next -= 1;
1355 (
"sctp_conn == NULL; return SCTP_ERROR_INVALID_CONNECTION");
1356 error0 = SCTP_ERROR_INVALID_CONNECTION;
1376 sctp_implied_length =
1385 idx, b0, sctp_implied_length, &next0);
1391 idx, b0, sctp_implied_length,
1399 sctp_implied_length, &next0);
1411 sctp_conn, idx, b0, &next0);
1423 error0 = SCTP_ERROR_NONE;
1431 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
1436 if (error0 != SCTP_ERROR_NONE)
1450 if (sctp_hdr !=
NULL)
1454 if (sctp_conn !=
NULL)
1462 n_left_to_next, bi0, next0);
1490 .name =
"sctp4-shutdown",
1492 .vector_size =
sizeof (
u32),
1498 #define _(s,n) [SCTP_SHUTDOWN_PHASE_NEXT_##s] = n, 1513 .name =
"sctp6-shutdown",
1515 .vector_size =
sizeof (
u32),
1521 #define _(s,n) [SCTP_SHUTDOWN_PHASE_NEXT_##s] = n, 1548 return SCTP_ERROR_INVALID_TAG;
1556 if (sctp_conn->sub_conn[idx].cwnd > sctp_conn->sub_conn[idx].ssthresh)
1557 sctp_conn->sub_conn[idx].partially_acked_bytes =
1562 sctp_conn->sub_conn[idx].partially_acked_bytes = 0;
1569 sctp_conn->sub_conn[idx].RTO);
1571 sctp_conn->sub_conn[idx].RTO_pending = 0;
1575 return SCTP_ERROR_NONE;
1587 return SCTP_ERROR_INVALID_TAG;
1594 return SCTP_ERROR_NONE;
1604 sctp_conn->sub_conn[idx].unacknowledged_hb -= 1;
1607 sctp_conn->sub_conn[idx].RTO);
1611 return SCTP_ERROR_NONE;
1616 u8 is_ip4,
u8 evt,
u8 val)
1632 u32 n_left_from, next_index, *from, *to_next;
1640 while (n_left_from > 0)
1646 while (n_left_from > 0 && n_left_to_next > 0)
1662 n_left_to_next -= 1;
1682 my_thread_index, is_ip4);
1687 (
"conn_index = %u: child_conn->state != SCTP_STATE_CLOSED.... STATE=%s",
1691 error0 = SCTP_ERROR_CREATE_EXISTS;
1708 child_conn->state = SCTP_STATE_CLOSED;
1711 connection.fib_index;
1727 sub_conn[SCTP_PRIMARY_PATH_IDX].c_rmt_ip6,
1736 if (chunk_type !=
INIT && chunk_type !=
DATA 1740 (
"conn_index = %u: chunk_type != INIT... chunk_type=%s",
1744 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
1749 u16 sctp_implied_length =
1763 sctp_implied_length);
1765 if (error0 == SCTP_ERROR_NONE)
1771 sub_conn[SCTP_PRIMARY_PATH_IDX].c_s_index, 0))
1775 error0 = SCTP_ERROR_CREATE_SESSION_FAIL;
1810 n_left_to_next, bi0, next0);
1836 u32 n_left_from, next_index, *from, *to_next;
1844 while (n_left_from > 0)
1850 while (n_left_from > 0 && n_left_to_next > 0)
1859 u16 error0 = SCTP_ERROR_ENQUEUED, next0 =
1868 n_left_to_next -= 1;
1878 (
"sctp_conn == NULL; return SCTP_ERROR_INVALID_CONNECTION");
1879 error0 = SCTP_ERROR_INVALID_CONNECTION;
1895 sctp_conn->sub_conn[idx].subconn_idx = idx;
1920 sctp_conn, idx, b0, &next0);
1926 sctp_conn, idx, b0, &next0);
1932 sctp_conn, idx, b0, &next0);
1938 sctp_conn, idx, b0, &next0);
1952 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
1967 n_left_to_next, bi0, next0);
1978 SCTP_ERROR_EVENT_FIFO_FULL, errors);
2008 s =
format (s,
"%U\n%U%U",
2020 .name =
"sctp4-listen",
2022 .vector_size =
sizeof (
u32),
2028 #define _(s,n) [SCTP_LISTEN_PHASE_NEXT_##s] = n, 2042 .name =
"sctp6-listen",
2044 .vector_size =
sizeof (
u32),
2050 #define _(s,n) [SCTP_LISTEN_PHASE_NEXT_##s] = n, 2064 .name =
"sctp4-established",
2066 .vector_size =
sizeof (
u32),
2072 #define _(s,n) [SCTP_ESTABLISHED_PHASE_NEXT_##s] = n, 2087 .name =
"sctp6-established",
2089 .vector_size =
sizeof (
u32),
2095 #define _(s,n) [SCTP_LISTEN_PHASE_NEXT_##s] = n, 2115 u32 n_left_from, next_index, *from, *to_next;
2125 while (n_left_from > 0)
2131 while (n_left_from > 0 && n_left_to_next > 0)
2133 int n_advance_bytes0, n_data_bytes0;
2134 u32 bi0, fib_index0;
2149 n_left_to_next -= 1;
2169 clib_net_to_host_u16 (ip4_hdr->
length) - n_advance_bytes0;
2192 n_advance_bytes0 +=
sizeof (ip6_hdr[0]);
2207 error0 = SCTP_ERROR_LENGTH;
2218 (
"Received an unrecognized chunk; sending back OPERATION_ERROR chunk");
2223 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
2235 vnet_buffer (b0)->sctp.connection_index = trans_conn->c_index;
2236 vnet_buffer (b0)->sctp.data_offset = n_advance_bytes0;
2239 next0 = tm->dispatch_table[sctp_conn->state][chunk_type].next;
2240 error0 = tm->dispatch_table[sctp_conn->state][chunk_type].error;
2243 (
"S_INDEX = %u, C_INDEX = %u, TRANS_CONN = %p, SCTP_CONN = %p, CURRENT_CONNECTION_STATE = %s," 2244 "CHUNK_TYPE_RECEIVED = %s " "NEXT_PHASE = %s",
2248 connection.c_index, trans_conn, sctp_conn,
2252 if (chunk_type ==
DATA)
2253 SCTP_ADV_DBG (
"n_advance_bytes0 = %u, n_data_bytes0 = %u",
2254 n_advance_bytes0, n_data_bytes0);
2262 error0 = SCTP_ERROR_NONE + result;
2264 else if ((is_ip4 && tm->punt_unknown4) ||
2265 (!is_ip4 && tm->punt_unknown6))
2268 error0 = SCTP_ERROR_PUNT;
2273 error0 = SCTP_ERROR_NO_LISTENER;
2290 n_left_to_next, bi0, next0);
2316 .name =
"sctp4-input",
2318 .vector_size =
sizeof (
u32),
2324 #define _(s,n) [SCTP_INPUT_NEXT_##s] = n, 2339 .name =
"sctp6-input",
2341 .vector_size =
sizeof (
u32),
2347 #define _(s,n) [SCTP_INPUT_NEXT_##s] = n, 2365 for (i = 0; i <
ARRAY_LEN (tm->dispatch_table); i++)
2366 for (j = 0; j <
ARRAY_LEN (tm->dispatch_table[i]); j++)
2369 tm->dispatch_table[
i][j].error = SCTP_ERROR_DISPATCH;
2372 #define _(t,f,n,e) \ 2374 tm->dispatch_table[SCTP_STATE_##t][f].next = (n); \ 2375 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.
int stream_session_accept_notify(transport_connection_t *tc)
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
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 *result)
Lookup connection with ip6 and transport layer information.
struct _transport_connection transport_connection_t
#define COOKIE_RECEIVED_WHILE_SHUTTING_DOWN
#define clib_memcpy_fast(a, b, c)
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
void session_transport_closing_notify(transport_connection_t *tc)
Notification from transport that connection is being closed.
#define VLIB_INIT_FUNCTION(x)
static void sctp_init_cwnd(sctp_connection_t *sctp_conn)
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.
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 *result)
Lookup connection with ip4 and transport layer information.
#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)
u16 current_length
Nbytes between current data and the end of this buffer.
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...)
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 sctp_send_shutdown_complete(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b0)
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.
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)
static int ip4_header_bytes(const ip4_header_t *i)
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