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
87 #ifndef CLIB_MARCH_VARIANT 94 return "SCTP_INPUT_NEXT_DROP";
96 return "SCTP_INPUT_NEXT_LISTEN_PHASE";
98 return "SCTP_INPUT_NEXT_RCV_PHASE";
100 return "SCTP_INPUT_NEXT_ESTABLISHED_PHASE";
102 return "SCTP_INPUT_NEXT_SHUTDOWN_PHASE";
104 return "SCTP_INPUT_NEXT_PUNT_PHASE";
110 #define foreach_sctp4_input_next \ 111 _ (DROP, "error-drop") \ 112 _ (RCV_PHASE, "sctp4-rcv") \ 113 _ (LISTEN_PHASE, "sctp4-listen") \ 114 _ (ESTABLISHED_PHASE, "sctp4-established") \ 115 _ (SHUTDOWN_PHASE, "sctp4-shutdown") \ 116 _ (PUNT_PHASE, "ip4-punt") 119 #define foreach_sctp6_input_next \ 120 _ (DROP, "error-drop") \ 121 _ (RCV_PHASE, "sctp6-rcv") \ 122 _ (LISTEN_PHASE, "sctp6-listen") \ 123 _ (ESTABLISHED_PHASE, "sctp6-established") \ 124 _ (SHUTDOWN_PHASE, "sctp6-shutdown") \ 125 _ (PUNT_PHASE, "ip6-punt") 137 u8 is_valid = (trans_conn->lcl_port == sctp_hdr->
dst_port 138 && (sctp_conn->state == SCTP_STATE_CLOSED
139 || trans_conn->rmt_port == sctp_hdr->
src_port));
166 TRANSPORT_PROTO_SCTP,
167 thread_index, &is_filtered);
172 if ((tm->connections[thread_index]->sub_conn[i].
173 connection.lcl_ip.ip4.as_u32 ==
175 && (tm->connections[thread_index]->sub_conn[i].
176 connection.rmt_ip.ip4.as_u32 ==
180 &tm->connections[thread_index]->sub_conn[
i].connection;
198 TRANSPORT_PROTO_SCTP,
199 thread_index, &is_filtered);
204 if ((tm->connections[thread_index]->sub_conn[i].
205 connection.lcl_ip.ip6.as_u64[0] ==
207 && tm->connections[thread_index]->sub_conn[i].
208 connection.lcl_ip.ip6.as_u64[1] ==
210 && (tm->connections[thread_index]->sub_conn[i].
211 connection.rmt_ip.ip6.as_u64[0] ==
213 && tm->connections[thread_index]->
214 sub_conn[i].connection.rmt_ip.ip6.as_u64[1] ==
218 &tm->connections[thread_index]->sub_conn[
i].connection;
236 #define sctp_next_output(is_ip4) (is_ip4 ? SCTP_NEXT_SCTP4_OUTPUT \ 237 : SCTP_NEXT_SCTP6_OUTPUT) 239 #define sctp_next_drop(is_ip4) (is_ip4 ? SCTP_NEXT_DROP4 \ 265 u16 sctp_implied_packet_length = 0;
268 sctp_implied_packet_length =
271 sctp_implied_packet_length =
272 clib_net_to_host_u16 (ip6_hdr->
payload_length) -
sizeof (ip6_hdr);
274 return sctp_implied_packet_length;
281 if (sctp_implied_length !=
297 return SCTP_ERROR_INVALID_TAG;
303 if (sctp_conn->state != SCTP_STATE_COOKIE_ECHOED)
310 sub_conn[idx].connection);
314 return SCTP_ERROR_NONE;
321 u16 sctp_implied_length)
337 if (sctp_conn->state != SCTP_STATE_CLOSED)
339 switch (sctp_conn->state)
341 case SCTP_STATE_COOKIE_WAIT:
342 SCTP_ADV_DBG (
"Received INIT chunk while in COOKIE_WAIT state");
345 b0, &ip4_addr, &ip6_addr);
346 return SCTP_ERROR_NONE;
347 case SCTP_STATE_COOKIE_ECHOED:
348 case SCTP_STATE_SHUTDOWN_ACK_SENT:
349 SCTP_ADV_DBG (
"Received INIT chunk while in COOKIE_ECHOED state");
350 if (sctp_conn->forming_association_changed == 0)
358 &ip4_addr, &ip6_addr);
359 return SCTP_ERROR_NONE;
364 return SCTP_ERROR_INVALID_TAG_FOR_INIT;
370 return SCTP_ERROR_BUNDLING_VIOLATION;
375 sctp_conn->remote_initial_tsn =
377 sctp_conn->last_rcvd_tsn = sctp_conn->remote_initial_tsn;
378 sctp_conn->next_tsn_expected = sctp_conn->remote_initial_tsn + 1;
380 sctp_conn->remote_initial_tsn);
382 sctp_conn->peer_rwnd = clib_net_to_host_u32 (init_chunk->
a_rwnd);
392 while (pointer_offset < length)
397 switch (clib_net_to_host_u16 (opt_params_hdr->
type))
437 sctp_conn->peer_cookie_life_span_increment =
455 pointer_offset += clib_net_to_host_u16 (opt_params_hdr->
length);
461 add_ip4, &ip6_addr, add_ip6);
462 return SCTP_ERROR_NONE;
469 u16 sctp_implied_length)
477 return SCTP_ERROR_INVALID_TAG;
484 return SCTP_ERROR_BUNDLING_VIOLATION;
486 return SCTP_ERROR_NONE;
503 return SCTP_ERROR_INVALID_TAG;
510 return SCTP_ERROR_BUNDLING_VIOLATION;
519 sctp_conn->remote_initial_tsn =
520 clib_net_to_host_u32 (init_ack_chunk->
initial_tsn);
521 sctp_conn->last_rcvd_tsn = sctp_conn->remote_initial_tsn;
522 sctp_conn->next_tsn_expected = sctp_conn->remote_initial_tsn + 1;
524 sctp_conn->remote_initial_tsn);
525 sctp_conn->peer_rwnd = clib_net_to_host_u32 (init_ack_chunk->
a_rwnd);
536 while (pointer_offset < length)
542 switch (clib_net_to_host_u16 (opt_params_hdr->
type))
592 u16 increment = clib_net_to_host_u16 (opt_params_hdr->
length);
596 return SCTP_ERROR_INVALID_TAG;
598 pointer_offset += increment;
606 SCTP_TIMER_T1_COOKIE, sctp_conn->sub_conn[idx].RTO);
608 return SCTP_ERROR_NONE;
616 int written, error = SCTP_ERROR_ENQUEUED;
620 sub_conn[conn_idx].connection, b, 0,
627 sctp_conn->next_tsn_expected += written;
629 SCTP_ADV_DBG (
"CONN = %u, WRITTEN [%u] == DATA_LEN [%d]",
630 sctp_conn->sub_conn[conn_idx].connection.c_index,
634 else if (written > data_len)
636 sctp_conn->next_tsn_expected += written;
638 SCTP_ADV_DBG (
"CONN = %u, WRITTEN [%u] > DATA_LEN [%d]",
639 sctp_conn->sub_conn[conn_idx].connection.c_index,
642 else if (written > 0)
645 sctp_conn->next_tsn_expected += written;
647 error = SCTP_ERROR_PARTIALLY_ENQUEUED;
650 (
"CONN = %u, WRITTEN [%u] > 0 (SCTP_ERROR_PARTIALLY_ENQUEUED)",
651 sctp_conn->sub_conn[conn_idx].connection.c_index, written);
655 SCTP_ADV_DBG (
"CONN = %u, WRITTEN == 0 (SCTP_ERROR_FIFO_FULL)",
656 sctp_conn->sub_conn[conn_idx].connection.c_index);
658 return SCTP_ERROR_FIFO_FULL;
669 u16 data_len,
u8 conn_idx)
671 int written, error = SCTP_ERROR_ENQUEUED;
675 sub_conn[conn_idx].connection, b, 0,
682 sctp_conn->next_tsn_expected += written;
684 SCTP_ADV_DBG (
"CONN = %u, WRITTEN [%u] == DATA_LEN [%d]",
685 sctp_conn->sub_conn[conn_idx].connection.c_index,
689 else if (written > data_len)
691 sctp_conn->next_tsn_expected += written;
693 SCTP_ADV_DBG (
"CONN = %u, WRITTEN [%u] > DATA_LEN [%d]",
694 sctp_conn->sub_conn[conn_idx].connection.c_index,
697 else if (written > 0)
700 sctp_conn->next_tsn_expected += written;
702 error = SCTP_ERROR_PARTIALLY_ENQUEUED;
705 (
"CONN = %u, WRITTEN [%u] > 0 (SCTP_ERROR_PARTIALLY_ENQUEUED)",
706 sctp_conn->sub_conn[conn_idx].connection.c_index, written);
710 SCTP_ADV_DBG (
"CONN = %u, WRITTEN == 0 (SCTP_ERROR_FIFO_FULL)",
711 sctp_conn->sub_conn[conn_idx].connection.c_index);
713 return SCTP_ERROR_FIFO_FULL;
722 if (sctp_conn->conn_config.never_delay_sack)
729 if (sctp_conn->state == SCTP_STATE_SHUTDOWN_SENT)
739 (
"gapping != 0: CONN_INDEX = %u, sctp_conn->ack_state = %u",
740 sctp_conn->sub_conn[idx].connection.c_index, sctp_conn->ack_state);
744 sctp_conn->ack_state += 1;
748 (
"sctp_conn->ack_state >= MAX_ENQUEABLE_SACKS: CONN_INDEX = %u, sctp_conn->ack_state = %u",
749 sctp_conn->sub_conn[idx].connection.c_index, sctp_conn->ack_state);
760 if (sctp_conn->next_tsn_expected != tsn)
763 (
"GAPPING: CONN_INDEX = %u, sctp_conn->next_tsn_expected = %u, tsn = %u, diff = %u",
765 sctp_conn->next_tsn_expected, tsn,
766 sctp_conn->next_tsn_expected - tsn);
777 u32 error = 0, n_data_bytes;
784 sctp_conn->sub_conn[idx].enqueue_state = SCTP_ERROR_INVALID_TAG;
785 return sctp_conn->sub_conn[idx].enqueue_state;
791 u32 tsn = clib_net_to_host_u32 (sctp_data_chunk->
tsn);
818 sctp_conn->last_rcvd_tsn = tsn;
825 if (bbit == 1 && ebit == 1)
835 else if (bbit == 1 && ebit == 0)
839 else if (bbit == 0 && ebit == 1)
855 sctp_conn->last_rcvd_tsn = tsn;
867 sctp_conn->sub_conn[idx].enqueue_state = error;
887 return SCTP_ERROR_INVALID_TAG;
894 u64 cookie_lifespan =
897 if (now > creation_time + cookie_lifespan)
899 SCTP_DBG (
"now (%u) > creation_time (%u) + cookie_lifespan (%u)",
900 now, creation_time, cookie_lifespan);
901 return SCTP_ERROR_COOKIE_ECHO_VIOLATION;
907 sctp_conn->state = SCTP_STATE_ESTABLISHED;
912 sctp_conn->sub_conn[idx].RTO);
916 return SCTP_ERROR_NONE;
930 return SCTP_ERROR_INVALID_TAG;
937 sctp_conn->state = SCTP_STATE_ESTABLISHED;
943 sctp_conn->sub_conn[idx].RTO);
947 return SCTP_ERROR_NONE;
957 u32 n_left_from, next_index, *from, *to_next;
965 while (n_left_from > 0)
971 while (n_left_from > 0 && n_left_to_next > 0)
980 u16 sctp_implied_length = 0;
998 sctp.connection_index);
1003 (
"sctp_conn == NULL; return SCTP_ERROR_INVALID_CONNECTION");
1004 error0 = SCTP_ERROR_INVALID_CONNECTION;
1020 sctp_conn->sub_conn[idx].subconn_idx = idx;
1026 sctp_implied_length =
1036 b0, sctp_implied_length);
1038 if (error0 == SCTP_ERROR_NONE)
1040 pool_get (tm->connections[my_thread_index], new_sctp_conn);
1042 sizeof (*new_sctp_conn));
1043 new_sctp_conn->sub_conn[idx].c_c_index =
1044 new_sctp_conn - tm->connections[my_thread_index];
1045 new_sctp_conn->sub_conn[idx].c_thread_index =
1047 new_sctp_conn->sub_conn[idx].PMTU =
1048 sctp_conn->sub_conn[idx].PMTU;
1049 new_sctp_conn->sub_conn[idx].subconn_idx = idx;
1054 (
"Cannot cleanup half-open connection; not the owning thread");
1063 new_sctp_conn, idx, b0,
1064 sctp_implied_length);
1067 (&new_sctp_conn->sub_conn[idx].connection, 0))
1070 (
"conn_index = %u: session_stream_connect_notify error; cleaning up connection",
1071 new_sctp_conn->sub_conn[idx].connection.c_index);
1090 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
1095 if (error0 != SCTP_ERROR_NONE)
1113 n_left_to_next, bi0, next0);
1142 s =
format (s,
"%d -> %d (%U)",
1153 .name =
"sctp4-rcv",
1155 .vector_size =
sizeof (
u32),
1161 #define _(s,n) [SCTP_RCV_PHASE_NEXT_##s] = n, 1172 .name =
"sctp6-rcv",
1174 .vector_size =
sizeof (
u32),
1180 #define _(s,n) [SCTP_RCV_PHASE_NEXT_##s] = n, 1202 return SCTP_ERROR_INVALID_TAG;
1209 return SCTP_ERROR_BUNDLING_VIOLATION;
1211 switch (sctp_conn->state)
1213 case SCTP_STATE_ESTABLISHED:
1215 sctp_conn->state = SCTP_STATE_SHUTDOWN_RECEIVED;
1219 case SCTP_STATE_SHUTDOWN_SENT:
1226 return SCTP_ERROR_NONE;
1243 return SCTP_ERROR_INVALID_TAG;
1250 return SCTP_ERROR_BUNDLING_VIOLATION;
1263 return SCTP_ERROR_NONE;
1280 return SCTP_ERROR_INVALID_TAG;
1287 return SCTP_ERROR_BUNDLING_VIOLATION;
1293 sctp_conn->state = SCTP_STATE_CLOSED;
1297 return SCTP_ERROR_NONE;
1305 u32 n_left_from, next_index, *from, *to_next;
1313 while (n_left_from > 0)
1319 while (n_left_from > 0 && n_left_to_next > 0)
1329 u16 sctp_implied_length = 0;
1338 n_left_to_next -= 1;
1343 sctp.connection_index, my_thread_index);
1348 (
"sctp_conn == NULL; return SCTP_ERROR_INVALID_CONNECTION");
1349 error0 = SCTP_ERROR_INVALID_CONNECTION;
1369 sctp_implied_length =
1378 idx, b0, sctp_implied_length, &next0);
1384 idx, b0, sctp_implied_length,
1392 sctp_implied_length, &next0);
1404 sctp_conn, idx, b0, &next0);
1416 error0 = SCTP_ERROR_NONE;
1424 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
1429 if (error0 != SCTP_ERROR_NONE)
1443 if (sctp_hdr !=
NULL)
1447 if (sctp_conn !=
NULL)
1455 n_left_to_next, bi0, next0);
1482 .name =
"sctp4-shutdown",
1484 .vector_size =
sizeof (
u32),
1490 #define _(s,n) [SCTP_SHUTDOWN_PHASE_NEXT_##s] = n, 1501 .name =
"sctp6-shutdown",
1503 .vector_size =
sizeof (
u32),
1509 #define _(s,n) [SCTP_SHUTDOWN_PHASE_NEXT_##s] = n, 1527 return SCTP_ERROR_INVALID_TAG;
1535 if (sctp_conn->sub_conn[idx].cwnd > sctp_conn->sub_conn[idx].ssthresh)
1536 sctp_conn->sub_conn[idx].partially_acked_bytes =
1541 sctp_conn->sub_conn[idx].partially_acked_bytes = 0;
1548 sctp_conn->sub_conn[idx].RTO);
1550 sctp_conn->sub_conn[idx].RTO_pending = 0;
1554 return SCTP_ERROR_NONE;
1566 return SCTP_ERROR_INVALID_TAG;
1573 return SCTP_ERROR_NONE;
1583 sctp_conn->sub_conn[idx].unacknowledged_hb -= 1;
1586 sctp_conn->sub_conn[idx].RTO);
1590 return SCTP_ERROR_NONE;
1611 u32 n_left_from, next_index, *from, *to_next;
1619 while (n_left_from > 0)
1625 while (n_left_from > 0 && n_left_to_next > 0)
1641 n_left_to_next -= 1;
1646 sctp.connection_index);
1662 my_thread_index, is_ip4);
1667 (
"conn_index = %u: child_conn->state != SCTP_STATE_CLOSED.... STATE=%s",
1671 error0 = SCTP_ERROR_CREATE_EXISTS;
1688 child_conn->state = SCTP_STATE_CLOSED;
1691 connection.fib_index;
1707 sub_conn[SCTP_PRIMARY_PATH_IDX].c_rmt_ip6,
1716 if (chunk_type !=
INIT && chunk_type !=
DATA 1720 (
"conn_index = %u: chunk_type != INIT... chunk_type=%s",
1724 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
1729 u16 sctp_implied_length =
1743 sctp_implied_length);
1745 if (error0 == SCTP_ERROR_NONE)
1751 sub_conn[SCTP_PRIMARY_PATH_IDX].c_s_index,
1753 sub_conn[SCTP_PRIMARY_PATH_IDX].c_thread_index, 0))
1757 error0 = SCTP_ERROR_CREATE_SESSION_FAIL;
1792 n_left_to_next, bi0, next0);
1819 u32 n_left_from, next_index, *from, *to_next;
1827 while (n_left_from > 0)
1833 while (n_left_from > 0 && n_left_to_next > 0)
1842 u16 error0 = SCTP_ERROR_ENQUEUED, next0 =
1851 n_left_to_next -= 1;
1856 sctp.connection_index, my_thread_index);
1861 (
"sctp_conn == NULL; return SCTP_ERROR_INVALID_CONNECTION");
1862 error0 = SCTP_ERROR_INVALID_CONNECTION;
1878 sctp_conn->sub_conn[idx].subconn_idx = idx;
1903 sctp_conn, idx, b0, &next0);
1909 sctp_conn, idx, b0, &next0);
1915 sctp_conn, idx, b0, &next0);
1921 sctp_conn, idx, b0, &next0);
1935 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
1950 n_left_to_next, bi0, next0);
1960 sm->sctp6_established_phase_node_index,
1961 SCTP_ERROR_EVENT_FIFO_FULL, errors);
1991 s =
format (s,
"%U\n%U%U",
2002 .name =
"sctp4-listen",
2004 .vector_size =
sizeof (
u32),
2010 #define _(s,n) [SCTP_LISTEN_PHASE_NEXT_##s] = n, 2021 .name =
"sctp6-listen",
2023 .vector_size =
sizeof (
u32),
2029 #define _(s,n) [SCTP_LISTEN_PHASE_NEXT_##s] = n, 2040 .name =
"sctp4-established",
2042 .vector_size =
sizeof (
u32),
2048 #define _(s,n) [SCTP_ESTABLISHED_PHASE_NEXT_##s] = n, 2059 .name =
"sctp6-established",
2061 .vector_size =
sizeof (
u32),
2067 #define _(s,n) [SCTP_LISTEN_PHASE_NEXT_##s] = n, 2084 u32 n_left_from, next_index, *from, *to_next;
2094 while (n_left_from > 0)
2100 while (n_left_from > 0 && n_left_to_next > 0)
2102 int n_advance_bytes0, n_data_bytes0;
2103 u32 bi0, fib_index0;
2118 n_left_to_next -= 1;
2138 clib_net_to_host_u16 (ip4_hdr->
length) - n_advance_bytes0;
2145 TRANSPORT_PROTO_SCTP,
2161 n_advance_bytes0 +=
sizeof (ip6_hdr[0]);
2168 TRANSPORT_PROTO_SCTP,
2176 error0 = SCTP_ERROR_LENGTH;
2187 (
"Received an unrecognized chunk; sending back OPERATION_ERROR chunk");
2192 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
2205 = trans_conn->c_index;
2209 next0 = tm->dispatch_table[sctp_conn->state][chunk_type].next;
2210 error0 = tm->dispatch_table[sctp_conn->state][chunk_type].error;
2213 (
"S_INDEX = %u, C_INDEX = %u, TRANS_CONN = %p, SCTP_CONN = %p, CURRENT_CONNECTION_STATE = %s," 2214 "CHUNK_TYPE_RECEIVED = %s " "NEXT_PHASE = %s",
2218 connection.c_index, trans_conn, sctp_conn,
2222 if (chunk_type ==
DATA)
2223 SCTP_ADV_DBG (
"n_advance_bytes0 = %u, n_data_bytes0 = %u",
2224 n_advance_bytes0, n_data_bytes0);
2232 error0 = SCTP_ERROR_NONE + result;
2234 else if ((is_ip4 && tm->punt_unknown4) ||
2235 (!is_ip4 && tm->punt_unknown6))
2238 error0 = SCTP_ERROR_PUNT;
2243 error0 = SCTP_ERROR_NO_LISTENER;
2260 n_left_to_next, bi0, next0);
2283 .name =
"sctp4-input",
2285 .vector_size =
sizeof (
u32),
2291 #define _(s,n) [SCTP_INPUT_NEXT_##s] = n, 2303 .name =
"sctp6-input",
2305 .vector_size =
sizeof (
u32),
2311 #define _(s,n) [SCTP_INPUT_NEXT_##s] = n, 2320 #ifndef CLIB_MARCH_VARIANT 2325 for (i = 0; i <
ARRAY_LEN (tm->dispatch_table); i++)
2326 for (j = 0; j <
ARRAY_LEN (tm->dispatch_table[i]); j++)
2329 tm->dispatch_table[
i][j].error = SCTP_ERROR_DISPATCH;
2332 #define _(t,f,n,e) \ 2334 tm->dispatch_table[SCTP_STATE_##t][f].next = (n); \ 2335 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.
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
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
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.
#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)
u16 current_length
Nbytes between current data and the end of this buffer.
int session_main_flush_enqueue_events(u8 transport_proto, u32 thread_index)
Flushes queue of sessions that are to be notified of new data enqueued events.
#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.
#define VLIB_NODE_FN(node)
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
vlib_error_t error
Error code for buffers to be enqueued to error handler.
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.
#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 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,...)
#define sctp_buffer_opaque(b)
u8 * format_sctp_connection(u8 *s, va_list *args)
#define clib_warning(format, args...)
struct _transport_connection transport_connection_t
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()
vlib_main_t vlib_node_runtime_t * node
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.
int session_stream_accept_notify(transport_connection_t *tc)
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)
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[]
u8 * format_sctp_header(u8 *s, va_list *args)
VLIB buffer representation.
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
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)
int session_stream_accept(transport_connection_t *tc, u32 listener_index, u32 thread_index, u8 notify)
Accept a stream session.
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