2 * Copyright (c) 2017 SUSE LLC.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
15 #include <vnet/sctp/sctp.h>
16 #include <vnet/sctp/sctp_debug.h>
17 #include <vppinfra/random.h>
19 vlib_node_registration_t sctp4_output_node;
20 vlib_node_registration_t sctp6_output_node;
22 typedef enum _sctp_output_next
24 SCTP_OUTPUT_NEXT_DROP,
25 SCTP_OUTPUT_NEXT_IP_LOOKUP,
29 #define foreach_sctp4_output_next \
30 _ (DROP, "error-drop") \
31 _ (IP_LOOKUP, "ip4-lookup")
33 #define foreach_sctp6_output_next \
34 _ (DROP, "error-drop") \
35 _ (IP_LOOKUP, "ip6-lookup")
37 static char *sctp_error_strings[] = {
38 #define sctp_error(n,s) s,
39 #include <vnet/sctp/sctp_error.def>
45 sctp_header_t sctp_header;
46 sctp_connection_t sctp_connection;
50 * Flush tx frame populated by retransmits and timer pops
53 sctp_flush_frame_to_output (vlib_main_t * vm, u8 thread_index, u8 is_ip4)
55 if (sctp_main.tx_frames[!is_ip4][thread_index])
58 next_index = is_ip4 ? sctp4_output_node.index : sctp6_output_node.index;
59 vlib_put_frame_to_node (vm, next_index,
60 sctp_main.tx_frames[!is_ip4][thread_index]);
61 sctp_main.tx_frames[!is_ip4][thread_index] = 0;
66 * Flush ip lookup tx frames populated by timer pops
69 sctp_flush_frame_to_ip_lookup (vlib_main_t * vm, u8 thread_index, u8 is_ip4)
71 if (sctp_main.ip_lookup_tx_frames[!is_ip4][thread_index])
74 next_index = is_ip4 ? ip4_lookup_node.index : ip6_lookup_node.index;
75 vlib_put_frame_to_node (vm, next_index,
76 sctp_main.ip_lookup_tx_frames[!is_ip4]
78 sctp_main.ip_lookup_tx_frames[!is_ip4][thread_index] = 0;
83 * Flush v4 and v6 sctp and ip-lookup tx frames for thread index
86 sctp_flush_frames_to_output (u8 thread_index)
88 vlib_main_t *vm = vlib_get_main ();
89 sctp_flush_frame_to_output (vm, thread_index, 1);
90 sctp_flush_frame_to_output (vm, thread_index, 0);
91 sctp_flush_frame_to_ip_lookup (vm, thread_index, 1);
92 sctp_flush_frame_to_ip_lookup (vm, thread_index, 0);
96 ip4_sctp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0,
100 u32 ip_header_length, payload_length_host_byte_order;
101 u32 n_this_buffer, n_bytes_left, n_ip_bytes_this_buffer;
102 void *data_this_buffer;
104 /* Initialize checksum with ip header. */
105 ip_header_length = ip4_header_bytes (ip0);
106 payload_length_host_byte_order =
107 clib_net_to_host_u16 (ip0->length) - ip_header_length;
109 clib_host_to_net_u32 (payload_length_host_byte_order +
110 (ip0->protocol << 16));
112 if (BITS (uword) == 32)
115 ip_csum_with_carry (checksum,
116 clib_mem_unaligned (&ip0->src_address, u32));
118 ip_csum_with_carry (checksum,
119 clib_mem_unaligned (&ip0->dst_address, u32));
123 ip_csum_with_carry (checksum,
124 clib_mem_unaligned (&ip0->src_address, u64));
126 n_bytes_left = n_this_buffer = payload_length_host_byte_order;
127 data_this_buffer = (void *) ip0 + ip_header_length;
128 n_ip_bytes_this_buffer =
129 p0->current_length - (((u8 *) ip0 - p0->data) - p0->current_data);
130 if (n_this_buffer + ip_header_length > n_ip_bytes_this_buffer)
132 n_this_buffer = n_ip_bytes_this_buffer > ip_header_length ?
133 n_ip_bytes_this_buffer - ip_header_length : 0;
138 ip_incremental_checksum (checksum, data_this_buffer, n_this_buffer);
139 n_bytes_left -= n_this_buffer;
140 if (n_bytes_left == 0)
143 ASSERT (p0->flags & VLIB_BUFFER_NEXT_PRESENT);
144 p0 = vlib_get_buffer (vm, p0->next_buffer);
145 data_this_buffer = vlib_buffer_get_current (p0);
146 n_this_buffer = p0->current_length;
153 ip6_sctp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0,
154 ip6_header_t * ip0, int *bogus_lengthp)
157 u16 payload_length_host_byte_order;
158 u32 i, n_this_buffer, n_bytes_left;
159 u32 headers_size = sizeof (ip0[0]);
160 void *data_this_buffer;
162 ASSERT (bogus_lengthp);
165 /* Initialize checksum with ip header. */
166 checksum = ip0->payload_length + clib_host_to_net_u16 (ip0->protocol);
167 payload_length_host_byte_order = clib_net_to_host_u16 (ip0->payload_length);
168 data_this_buffer = (void *) (ip0 + 1);
170 for (i = 0; i < ARRAY_LEN (ip0->src_address.as_uword); i++)
172 checksum = ip_csum_with_carry (checksum,
173 clib_mem_unaligned (&ip0->
177 ip_csum_with_carry (checksum,
178 clib_mem_unaligned (&ip0->dst_address.as_uword[i],
182 /* some icmp packets may come with a "router alert" hop-by-hop extension header (e.g., mldv2 packets)
183 * or UDP-Ping packets */
184 if (PREDICT_FALSE (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS))
187 ip6_hop_by_hop_ext_t *ext_hdr =
188 (ip6_hop_by_hop_ext_t *) data_this_buffer;
190 /* validate really icmp6 next */
191 ASSERT ((ext_hdr->next_hdr == IP_PROTOCOL_SCTP));
193 skip_bytes = 8 * (1 + ext_hdr->n_data_u64s);
194 data_this_buffer = (void *) ((u8 *) data_this_buffer + skip_bytes);
196 payload_length_host_byte_order -= skip_bytes;
197 headers_size += skip_bytes;
200 n_bytes_left = n_this_buffer = payload_length_host_byte_order;
201 if (p0 && n_this_buffer + headers_size > p0->current_length)
204 headers_size ? p0->current_length - headers_size : 0;
208 ip_incremental_checksum (checksum, data_this_buffer, n_this_buffer);
209 n_bytes_left -= n_this_buffer;
210 if (n_bytes_left == 0)
213 if (!(p0->flags & VLIB_BUFFER_NEXT_PRESENT))
218 p0 = vlib_get_buffer (vm, p0->next_buffer);
219 data_this_buffer = vlib_buffer_get_current (p0);
220 n_this_buffer = p0->current_length;
227 sctp_push_ip_hdr (sctp_main_t * tm, sctp_sub_connection_t * tc,
230 sctp_header_t *th = vlib_buffer_get_current (b);
231 vlib_main_t *vm = vlib_get_main ();
235 ih = vlib_buffer_push_ip4 (vm, b, &tc->c_lcl_ip4,
236 &tc->c_rmt_ip4, IP_PROTOCOL_SCTP, 1);
237 th->checksum = ip4_sctp_compute_checksum (vm, b, ih);
244 ih = vlib_buffer_push_ip6 (vm, b, &tc->c_lcl_ip6,
245 &tc->c_rmt_ip6, IP_PROTOCOL_SCTP);
246 th->checksum = ip6_sctp_compute_checksum (vm, b, ih, &bogus);
252 sctp_reuse_buffer (vlib_main_t * vm, vlib_buffer_t * b)
254 if (b->flags & VLIB_BUFFER_NEXT_PRESENT)
255 vlib_buffer_free_one (vm, b->next_buffer);
256 /* Zero all flags but free list index and trace flag */
257 b->flags &= VLIB_BUFFER_NEXT_PRESENT - 1;
259 b->current_length = 0;
260 b->total_length_not_including_first_buffer = 0;
261 vnet_buffer (b)->sctp.flags = 0;
263 /* Leave enough space for headers */
264 return vlib_buffer_make_headroom (b, MAX_HDRS_LEN);
268 sctp_init_buffer (vlib_main_t * vm, vlib_buffer_t * b)
270 ASSERT ((b->flags & VLIB_BUFFER_NEXT_PRESENT) == 0);
271 b->flags &= VLIB_BUFFER_FREE_LIST_INDEX_MASK;
272 b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
273 b->total_length_not_including_first_buffer = 0;
274 vnet_buffer (b)->sctp.flags = 0;
275 VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b);
276 /* Leave enough space for headers */
277 return vlib_buffer_make_headroom (b, MAX_HDRS_LEN);
281 sctp_alloc_tx_buffers (sctp_main_t * tm, u8 thread_index, u32 n_free_buffers)
283 vlib_main_t *vm = vlib_get_main ();
284 u32 current_length = vec_len (tm->tx_buffers[thread_index]);
287 vec_validate (tm->tx_buffers[thread_index],
288 current_length + n_free_buffers - 1);
290 vlib_buffer_alloc (vm, &tm->tx_buffers[thread_index][current_length],
292 _vec_len (tm->tx_buffers[thread_index]) = current_length + n_allocated;
293 /* buffer shortage, report failure */
294 if (vec_len (tm->tx_buffers[thread_index]) == 0)
296 clib_warning ("out of buffers");
303 sctp_get_free_buffer_index (sctp_main_t * tm, u32 * bidx)
306 u32 thread_index = vlib_get_thread_index ();
307 if (PREDICT_FALSE (vec_len (tm->tx_buffers[thread_index]) == 0))
309 if (sctp_alloc_tx_buffers (tm, thread_index, VLIB_FRAME_SIZE))
312 my_tx_buffers = tm->tx_buffers[thread_index];
313 *bidx = my_tx_buffers[vec_len (my_tx_buffers) - 1];
314 _vec_len (my_tx_buffers) -= 1;
319 sctp_enqueue_to_output_i (vlib_main_t * vm, vlib_buffer_t * b, u32 bi,
322 sctp_main_t *tm = vnet_get_sctp_main ();
323 u32 thread_index = vlib_get_thread_index ();
324 u32 *to_next, next_index;
327 b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
330 /* Decide where to send the packet */
331 next_index = is_ip4 ? sctp4_output_node.index : sctp6_output_node.index;
332 sctp_trajectory_add_start (b, 2);
334 /* Get frame to v4/6 output node */
335 f = tm->tx_frames[!is_ip4][thread_index];
338 f = vlib_get_frame_to_node (vm, next_index);
340 tm->tx_frames[!is_ip4][thread_index] = f;
342 to_next = vlib_frame_vector_args (f);
343 to_next[f->n_vectors] = bi;
345 if (flush || f->n_vectors == VLIB_FRAME_SIZE)
347 vlib_put_frame_to_node (vm, next_index, f);
348 tm->tx_frames[!is_ip4][thread_index] = 0;
353 sctp_enqueue_to_output_now (vlib_main_t * vm, vlib_buffer_t * b, u32 bi,
356 sctp_enqueue_to_output_i (vm, b, bi, is_ip4, 1);
360 sctp_enqueue_to_ip_lookup_i (vlib_main_t * vm, vlib_buffer_t * b, u32 bi,
363 sctp_main_t *tm = vnet_get_sctp_main ();
364 u32 thread_index = vlib_get_thread_index ();
365 u32 *to_next, next_index;
368 b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
371 /* Default FIB for now */
372 vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
374 /* Send to IP lookup */
375 next_index = is_ip4 ? ip4_lookup_node.index : ip6_lookup_node.index;
376 if (VLIB_BUFFER_TRACE_TRAJECTORY > 0)
379 b->pre_data[1] = next_index;
382 f = tm->ip_lookup_tx_frames[!is_ip4][thread_index];
385 f = vlib_get_frame_to_node (vm, next_index);
387 tm->ip_lookup_tx_frames[!is_ip4][thread_index] = f;
390 to_next = vlib_frame_vector_args (f);
391 to_next[f->n_vectors] = bi;
393 if (flush || f->n_vectors == VLIB_FRAME_SIZE)
395 vlib_put_frame_to_node (vm, next_index, f);
396 tm->ip_lookup_tx_frames[!is_ip4][thread_index] = 0;
401 sctp_enqueue_to_ip_lookup (vlib_main_t * vm, vlib_buffer_t * b, u32 bi,
404 sctp_enqueue_to_ip_lookup_i (vm, b, bi, is_ip4, 0);
408 sctp_enqueue_to_ip_lookup_now (vlib_main_t * vm, vlib_buffer_t * b, u32 bi,
411 sctp_enqueue_to_ip_lookup_i (vm, b, bi, is_ip4, 1);
415 * Convert buffer to INIT
418 sctp_prepare_init_chunk (sctp_connection_t * sctp_conn, vlib_buffer_t * b)
420 u32 random_seed = random_default_seed ();
421 u16 alloc_bytes = sizeof (sctp_init_chunk_t);
422 sctp_sub_connection_t *sub_conn =
423 &sctp_conn->sub_conn[sctp_pick_conn_idx_on_chunk (INIT)];
425 sctp_ipv4_addr_param_t *ip4_param = 0;
426 sctp_ipv6_addr_param_t *ip6_param = 0;
428 if (sub_conn->c_is_ip4)
429 alloc_bytes += sizeof (sctp_ipv4_addr_param_t);
431 alloc_bytes += sizeof (sctp_ipv6_addr_param_t);
433 /* As per RFC 4960 the chunk_length value does NOT contemplate
434 * the size of the first header (see sctp_header_t) and any padding
436 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
438 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
440 sctp_init_chunk_t *init_chunk = vlib_buffer_push_uninit (b, alloc_bytes);
442 u16 pointer_offset = sizeof (init_chunk);
443 if (sub_conn->c_is_ip4)
445 ip4_param = (sctp_ipv4_addr_param_t *) init_chunk + pointer_offset;
446 ip4_param->address.as_u32 = sub_conn->c_lcl_ip.ip4.as_u32;
448 pointer_offset += sizeof (sctp_ipv4_addr_param_t);
452 ip6_param = (sctp_ipv6_addr_param_t *) init_chunk + pointer_offset;
453 ip6_param->address.as_u64[0] = sub_conn->c_lcl_ip.ip6.as_u64[0];
454 ip6_param->address.as_u64[1] = sub_conn->c_lcl_ip.ip6.as_u64[1];
456 pointer_offset += sizeof (sctp_ipv6_addr_param_t);
459 init_chunk->sctp_hdr.src_port = sub_conn->c_lcl_port; /* No need of host_to_net conversion, already in net-byte order */
460 init_chunk->sctp_hdr.dst_port = sub_conn->c_rmt_port; /* No need of host_to_net conversion, already in net-byte order */
461 init_chunk->sctp_hdr.checksum = 0;
462 /* The sender of an INIT must set the VERIFICATION_TAG to 0 as per RFC 4960 Section 8.5.1 */
463 init_chunk->sctp_hdr.verification_tag = 0x0;
465 vnet_sctp_set_chunk_type (&init_chunk->chunk_hdr, INIT);
466 vnet_sctp_set_chunk_length (&init_chunk->chunk_hdr, chunk_len);
467 vnet_sctp_common_hdr_params_host_to_net (&init_chunk->chunk_hdr);
469 init_chunk->a_rwnd = clib_host_to_net_u32 (DEFAULT_A_RWND);
470 init_chunk->initiate_tag = clib_host_to_net_u32 (random_u32 (&random_seed));
471 init_chunk->inboud_streams_count =
472 clib_host_to_net_u16 (INBOUND_STREAMS_COUNT);
473 init_chunk->outbound_streams_count =
474 clib_host_to_net_u16 (OUTBOUND_STREAMS_COUNT);
476 sctp_conn->local_tag = init_chunk->initiate_tag;
478 vnet_buffer (b)->sctp.connection_index = sub_conn->c_c_index;
480 SCTP_DBG_STATE_MACHINE ("CONN_INDEX = %u, CURR_CONN_STATE = %u (%s), "
482 "SRC_PORT = %u, DST_PORT = %u",
483 sub_conn->connection.c_index,
485 sctp_state_to_string (sctp_conn->state),
486 sctp_chunk_to_string (INIT),
487 init_chunk->sctp_hdr.src_port,
488 init_chunk->sctp_hdr.dst_port);
498 sctp_prepare_cookie_ack_chunk (sctp_connection_t * tc, vlib_buffer_t * b)
500 vlib_main_t *vm = vlib_get_main ();
501 u8 idx = sctp_pick_conn_idx_on_chunk (COOKIE_ACK);
503 sctp_reuse_buffer (vm, b);
505 u16 alloc_bytes = sizeof (sctp_cookie_ack_chunk_t);
507 /* As per RFC 4960 the chunk_length value does NOT contemplate
508 * the size of the first header (see sctp_header_t) and any padding
510 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
512 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
514 sctp_cookie_ack_chunk_t *cookie_ack_chunk =
515 vlib_buffer_push_uninit (b, alloc_bytes);
517 cookie_ack_chunk->sctp_hdr.checksum = 0;
518 cookie_ack_chunk->sctp_hdr.src_port = tc->sub_conn[idx].connection.lcl_port;
519 cookie_ack_chunk->sctp_hdr.dst_port = tc->sub_conn[idx].connection.rmt_port;
520 cookie_ack_chunk->sctp_hdr.verification_tag = tc->remote_tag;
521 vnet_sctp_set_chunk_type (&cookie_ack_chunk->chunk_hdr, COOKIE_ACK);
522 vnet_sctp_set_chunk_length (&cookie_ack_chunk->chunk_hdr, chunk_len);
524 vnet_buffer (b)->sctp.connection_index =
525 tc->sub_conn[idx].connection.c_index;
529 sctp_prepare_cookie_echo_chunk (sctp_connection_t * tc, vlib_buffer_t * b,
530 sctp_state_cookie_param_t * sc)
532 vlib_main_t *vm = vlib_get_main ();
533 u8 idx = sctp_pick_conn_idx_on_chunk (COOKIE_ECHO);
535 sctp_reuse_buffer (vm, b);
537 /* The minimum size of the message is given by the sctp_init_ack_chunk_t */
538 u16 alloc_bytes = sizeof (sctp_cookie_echo_chunk_t);
539 /* As per RFC 4960 the chunk_length value does NOT contemplate
540 * the size of the first header (see sctp_header_t) and any padding
542 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
543 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
544 sctp_cookie_echo_chunk_t *cookie_echo_chunk =
545 vlib_buffer_push_uninit (b, alloc_bytes);
546 cookie_echo_chunk->sctp_hdr.checksum = 0;
547 cookie_echo_chunk->sctp_hdr.src_port =
548 tc->sub_conn[idx].connection.lcl_port;
549 cookie_echo_chunk->sctp_hdr.dst_port =
550 tc->sub_conn[idx].connection.rmt_port;
551 cookie_echo_chunk->sctp_hdr.verification_tag = tc->remote_tag;
552 vnet_sctp_set_chunk_type (&cookie_echo_chunk->chunk_hdr, COOKIE_ECHO);
553 vnet_sctp_set_chunk_length (&cookie_echo_chunk->chunk_hdr, chunk_len);
554 clib_memcpy (&(cookie_echo_chunk->cookie), sc,
555 sizeof (sctp_state_cookie_param_t));
556 vnet_buffer (b)->sctp.connection_index =
557 tc->sub_conn[idx].connection.c_index;
561 * Convert buffer to INIT-ACK
564 sctp_prepare_initack_chunk (sctp_connection_t * tc, vlib_buffer_t * b,
565 ip4_address_t * ip4_addr,
566 ip6_address_t * ip6_addr)
568 vlib_main_t *vm = vlib_get_main ();
569 sctp_ipv4_addr_param_t *ip4_param = 0;
570 sctp_ipv6_addr_param_t *ip6_param = 0;
571 u8 idx = sctp_pick_conn_idx_on_chunk (INIT_ACK);
572 u32 random_seed = random_default_seed ();
574 sctp_reuse_buffer (vm, b);
576 /* The minimum size of the message is given by the sctp_init_ack_chunk_t */
578 sizeof (sctp_init_ack_chunk_t) + sizeof (sctp_state_cookie_param_t);
580 if (PREDICT_TRUE (ip4_addr != NULL))
582 /* Create room for variable-length fields in the INIT_ACK chunk */
583 alloc_bytes += SCTP_IPV4_ADDRESS_TYPE_LENGTH;
585 if (PREDICT_TRUE (ip6_addr != NULL))
587 /* Create room for variable-length fields in the INIT_ACK chunk */
588 alloc_bytes += SCTP_IPV6_ADDRESS_TYPE_LENGTH;
591 if (tc->sub_conn[idx].connection.is_ip4)
592 alloc_bytes += sizeof (sctp_ipv4_addr_param_t);
594 alloc_bytes += sizeof (sctp_ipv6_addr_param_t);
596 /* As per RFC 4960 the chunk_length value does NOT contemplate
597 * the size of the first header (see sctp_header_t) and any padding
599 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
601 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
603 sctp_init_ack_chunk_t *init_ack_chunk =
604 vlib_buffer_push_uninit (b, alloc_bytes);
606 u16 pointer_offset = sizeof (sctp_init_ack_chunk_t);
608 /* Create State Cookie parameter */
609 sctp_state_cookie_param_t *state_cookie_param =
610 (sctp_state_cookie_param_t *) ((char *) init_ack_chunk + pointer_offset);
612 state_cookie_param->param_hdr.type =
613 clib_host_to_net_u16 (SCTP_STATE_COOKIE_TYPE);
614 state_cookie_param->param_hdr.length =
615 clib_host_to_net_u16 (sizeof (sctp_state_cookie_param_t));
616 state_cookie_param->creation_time = clib_host_to_net_u32 (sctp_time_now ());
617 state_cookie_param->cookie_lifespan =
618 clib_host_to_net_u32 (SCTP_VALID_COOKIE_LIFE);
619 state_cookie_param->mac = clib_host_to_net_u64 (sctp_compute_mac ());
621 pointer_offset += sizeof (sctp_state_cookie_param_t);
623 if (PREDICT_TRUE (ip4_addr != NULL))
625 sctp_ipv4_addr_param_t *ipv4_addr =
626 (sctp_ipv4_addr_param_t *) init_ack_chunk + pointer_offset;
628 ipv4_addr->param_hdr.type =
629 clib_host_to_net_u16 (SCTP_IPV4_ADDRESS_TYPE);
630 ipv4_addr->param_hdr.length =
631 clib_host_to_net_u16 (SCTP_IPV4_ADDRESS_TYPE_LENGTH);
632 ipv4_addr->address.as_u32 = ip4_addr->as_u32;
634 pointer_offset += SCTP_IPV4_ADDRESS_TYPE_LENGTH;
636 if (PREDICT_TRUE (ip6_addr != NULL))
638 sctp_ipv6_addr_param_t *ipv6_addr =
639 (sctp_ipv6_addr_param_t *) init_ack_chunk +
640 sizeof (sctp_init_chunk_t) + pointer_offset;
642 ipv6_addr->param_hdr.type =
643 clib_host_to_net_u16 (SCTP_IPV6_ADDRESS_TYPE);
644 ipv6_addr->param_hdr.length =
645 clib_host_to_net_u16 (SCTP_IPV6_ADDRESS_TYPE_LENGTH);
646 ipv6_addr->address.as_u64[0] = ip6_addr->as_u64[0];
647 ipv6_addr->address.as_u64[1] = ip6_addr->as_u64[1];
649 pointer_offset += SCTP_IPV6_ADDRESS_TYPE_LENGTH;
652 if (tc->sub_conn[idx].connection.is_ip4)
654 ip4_param = (sctp_ipv4_addr_param_t *) init_ack_chunk + pointer_offset;
655 ip4_param->address.as_u32 =
656 tc->sub_conn[idx].connection.lcl_ip.ip4.as_u32;
658 pointer_offset += sizeof (sctp_ipv4_addr_param_t);
662 ip6_param = (sctp_ipv6_addr_param_t *) init_ack_chunk + pointer_offset;
663 ip6_param->address.as_u64[0] =
664 tc->sub_conn[idx].connection.lcl_ip.ip6.as_u64[0];
665 ip6_param->address.as_u64[1] =
666 tc->sub_conn[idx].connection.lcl_ip.ip6.as_u64[1];
668 pointer_offset += sizeof (sctp_ipv6_addr_param_t);
671 /* src_port & dst_port are already in network byte-order */
672 init_ack_chunk->sctp_hdr.checksum = 0;
673 init_ack_chunk->sctp_hdr.src_port = tc->sub_conn[idx].connection.lcl_port;
674 init_ack_chunk->sctp_hdr.dst_port = tc->sub_conn[idx].connection.rmt_port;
675 /* the tc->verification_tag is already in network byte-order (being a copy of the init_tag coming with the INIT chunk) */
676 init_ack_chunk->sctp_hdr.verification_tag = tc->remote_tag;
678 vnet_sctp_set_chunk_type (&init_ack_chunk->chunk_hdr, INIT_ACK);
679 vnet_sctp_set_chunk_length (&init_ack_chunk->chunk_hdr, chunk_len);
681 init_ack_chunk->initiate_tag =
682 clib_host_to_net_u32 (random_u32 (&random_seed));
683 /* As per RFC 4960, the initial_tsn may be the same value as the initiate_tag */
684 init_ack_chunk->initial_tsn = init_ack_chunk->initiate_tag;
685 init_ack_chunk->a_rwnd = clib_host_to_net_u32 (DEFAULT_A_RWND);
686 init_ack_chunk->inboud_streams_count =
687 clib_host_to_net_u16 (INBOUND_STREAMS_COUNT);
688 init_ack_chunk->outbound_streams_count =
689 clib_host_to_net_u16 (OUTBOUND_STREAMS_COUNT);
691 tc->local_tag = init_ack_chunk->initiate_tag;
693 vnet_buffer (b)->sctp.connection_index =
694 tc->sub_conn[idx].connection.c_index;
698 * Convert buffer to SHUTDOWN
701 sctp_prepare_shutdown_chunk (sctp_connection_t * tc, vlib_buffer_t * b)
703 vlib_main_t *vm = vlib_get_main ();
704 u8 idx = sctp_pick_conn_idx_on_chunk (SHUTDOWN);
705 u16 alloc_bytes = sizeof (sctp_shutdown_association_chunk_t);
707 b = sctp_reuse_buffer (vm, b);
709 /* As per RFC 4960 the chunk_length value does NOT contemplate
710 * the size of the first header (see sctp_header_t) and any padding
712 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
714 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
716 sctp_shutdown_association_chunk_t *shutdown_chunk =
717 vlib_buffer_push_uninit (b, alloc_bytes);
719 shutdown_chunk->sctp_hdr.checksum = 0;
720 /* No need of host_to_net conversion, already in net-byte order */
721 shutdown_chunk->sctp_hdr.src_port = tc->sub_conn[idx].connection.lcl_port;
722 shutdown_chunk->sctp_hdr.dst_port = tc->sub_conn[idx].connection.rmt_port;
723 shutdown_chunk->sctp_hdr.verification_tag = tc->remote_tag;
724 vnet_sctp_set_chunk_type (&shutdown_chunk->chunk_hdr, SHUTDOWN);
725 vnet_sctp_set_chunk_length (&shutdown_chunk->chunk_hdr, chunk_len);
727 shutdown_chunk->cumulative_tsn_ack = tc->rcv_las;
729 vnet_buffer (b)->sctp.connection_index =
730 tc->sub_conn[idx].connection.c_index;
737 sctp_send_shutdown (sctp_connection_t * tc)
741 sctp_main_t *tm = vnet_get_sctp_main ();
742 vlib_main_t *vm = vlib_get_main ();
744 if (sctp_check_outstanding_data_chunks (tc) > 0)
747 if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
750 b = vlib_get_buffer (vm, bi);
751 sctp_init_buffer (vm, b);
752 sctp_prepare_shutdown_chunk (tc, b);
754 u8 idx = sctp_pick_conn_idx_on_chunk (SHUTDOWN);
755 sctp_push_ip_hdr (tm, &tc->sub_conn[idx], b);
756 sctp_enqueue_to_output_now (vm, b, bi, tc->sub_conn[idx].connection.is_ip4);
760 * Convert buffer to SHUTDOWN_ACK
763 sctp_prepare_shutdown_ack_chunk (sctp_connection_t * tc, vlib_buffer_t * b)
765 u8 idx = sctp_pick_conn_idx_on_chunk (SHUTDOWN_ACK);
766 u16 alloc_bytes = sizeof (sctp_shutdown_association_chunk_t);
767 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
769 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
771 sctp_shutdown_ack_chunk_t *shutdown_ack_chunk =
772 vlib_buffer_push_uninit (b, alloc_bytes);
774 shutdown_ack_chunk->sctp_hdr.checksum = 0;
775 /* No need of host_to_net conversion, already in net-byte order */
776 shutdown_ack_chunk->sctp_hdr.src_port =
777 tc->sub_conn[idx].connection.lcl_port;
778 shutdown_ack_chunk->sctp_hdr.dst_port =
779 tc->sub_conn[idx].connection.rmt_port;
780 shutdown_ack_chunk->sctp_hdr.verification_tag = tc->remote_tag;
782 vnet_sctp_set_chunk_type (&shutdown_ack_chunk->chunk_hdr, SHUTDOWN_ACK);
783 vnet_sctp_set_chunk_length (&shutdown_ack_chunk->chunk_hdr, chunk_len);
785 vnet_buffer (b)->sctp.connection_index =
786 tc->sub_conn[idx].connection.c_index;
793 sctp_send_shutdown_ack (sctp_connection_t * tc)
797 sctp_main_t *tm = vnet_get_sctp_main ();
798 vlib_main_t *vm = vlib_get_main ();
800 if (sctp_check_outstanding_data_chunks (tc) > 0)
803 if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
806 b = vlib_get_buffer (vm, bi);
807 sctp_init_buffer (vm, b);
808 sctp_prepare_shutdown_ack_chunk (tc, b);
810 u8 idx = sctp_pick_conn_idx_on_chunk (SHUTDOWN_ACK);
811 sctp_push_ip_hdr (tm, &tc->sub_conn[idx], b);
812 sctp_enqueue_to_ip_lookup (vm, b, bi, tc->sub_conn[idx].connection.is_ip4);
814 /* Start the SCTP_TIMER_T2_SHUTDOWN timer */
815 sctp_timer_set (tc, idx, SCTP_TIMER_T2_SHUTDOWN, SCTP_RTO_INIT);
816 tc->state = SCTP_STATE_SHUTDOWN_ACK_SENT;
820 * Convert buffer to SACK
823 sctp_prepare_sack_chunk (sctp_connection_t * tc, vlib_buffer_t * b)
825 vlib_main_t *vm = vlib_get_main ();
826 u8 idx = sctp_pick_conn_idx_on_chunk (SACK);
828 sctp_reuse_buffer (vm, b);
830 u16 alloc_bytes = sizeof (sctp_selective_ack_chunk_t);
832 /* As per RFC 4960 the chunk_length value does NOT contemplate
833 * the size of the first header (see sctp_header_t) and any padding
835 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
837 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
839 sctp_selective_ack_chunk_t *sack = vlib_buffer_push_uninit (b, alloc_bytes);
841 sack->sctp_hdr.checksum = 0;
842 sack->sctp_hdr.src_port = tc->sub_conn[idx].connection.lcl_port;
843 sack->sctp_hdr.dst_port = tc->sub_conn[idx].connection.rmt_port;
844 sack->sctp_hdr.verification_tag = tc->remote_tag;
845 vnet_sctp_set_chunk_type (&sack->chunk_hdr, SACK);
846 vnet_sctp_set_chunk_length (&sack->chunk_hdr, chunk_len);
848 vnet_buffer (b)->sctp.connection_index =
849 tc->sub_conn[idx].connection.c_index;
853 * Convert buffer to SHUTDOWN_COMPLETE
856 sctp_prepare_shutdown_complete_chunk (sctp_connection_t * tc,
859 u8 idx = sctp_pick_conn_idx_on_chunk (SHUTDOWN_COMPLETE);
860 u16 alloc_bytes = sizeof (sctp_shutdown_association_chunk_t);
861 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
863 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
865 sctp_shutdown_complete_chunk_t *shutdown_complete =
866 vlib_buffer_push_uninit (b, alloc_bytes);
868 shutdown_complete->sctp_hdr.checksum = 0;
869 /* No need of host_to_net conversion, already in net-byte order */
870 shutdown_complete->sctp_hdr.src_port =
871 tc->sub_conn[idx].connection.lcl_port;
872 shutdown_complete->sctp_hdr.dst_port =
873 tc->sub_conn[idx].connection.rmt_port;
874 shutdown_complete->sctp_hdr.verification_tag = tc->remote_tag;
876 vnet_sctp_set_chunk_type (&shutdown_complete->chunk_hdr, SHUTDOWN_COMPLETE);
877 vnet_sctp_set_chunk_length (&shutdown_complete->chunk_hdr, chunk_len);
879 vnet_buffer (b)->sctp.connection_index =
880 tc->sub_conn[idx].connection.c_index;
884 sctp_send_shutdown_complete (sctp_connection_t * tc)
888 sctp_main_t *tm = vnet_get_sctp_main ();
889 vlib_main_t *vm = vlib_get_main ();
891 if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
894 b = vlib_get_buffer (vm, bi);
895 sctp_init_buffer (vm, b);
896 sctp_prepare_shutdown_complete_chunk (tc, b);
898 u8 idx = sctp_pick_conn_idx_on_chunk (SHUTDOWN_COMPLETE);
899 sctp_push_ip_hdr (tm, &tc->sub_conn[idx], b);
900 sctp_enqueue_to_ip_lookup (vm, b, bi, tc->sub_conn[idx].connection.is_ip4);
902 tc->state = SCTP_STATE_CLOSED;
910 sctp_send_init (sctp_connection_t * tc)
914 sctp_main_t *tm = vnet_get_sctp_main ();
915 vlib_main_t *vm = vlib_get_main ();
917 if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
920 b = vlib_get_buffer (vm, bi);
921 u8 idx = sctp_pick_conn_idx_on_chunk (INIT);
923 sctp_init_buffer (vm, b);
924 sctp_prepare_init_chunk (tc, b);
926 /* Measure RTT with this */
927 tc->rtt_ts = sctp_time_now ();
928 tc->rtt_seq = tc->snd_nxt;
931 sctp_push_ip_hdr (tm, &tc->sub_conn[idx], b);
932 sctp_enqueue_to_ip_lookup_now (vm, b, bi, tc->sub_conn[idx].c_is_ip4);
934 /* Start the T1_INIT timer */
935 sctp_timer_set (tc, idx, SCTP_TIMER_T1_INIT, SCTP_RTO_INIT);
936 /* Change state to COOKIE_WAIT */
937 tc->state = SCTP_STATE_COOKIE_WAIT;
941 sctp_in_cong_recovery (sctp_connection_t * sctp_conn)
947 * Push SCTP header and update connection variables
950 sctp_push_hdr_i (sctp_connection_t * tc, vlib_buffer_t * b,
951 sctp_state_t next_state)
953 u8 idx = sctp_pick_conn_idx_on_chunk (DATA);
956 b->current_length + b->total_length_not_including_first_buffer;
957 ASSERT (!b->total_length_not_including_first_buffer
958 || (b->flags & VLIB_BUFFER_NEXT_PRESENT));
960 SCTP_ADV_DBG_OUTPUT ("b->current_length = %u, "
961 "b->current_data = %p "
963 b->current_length, b->current_data, data_len);
965 u16 bytes_to_add = sizeof (sctp_payload_data_chunk_t);
966 u16 chunk_length = data_len + bytes_to_add - sizeof (sctp_header_t);
968 bytes_to_add += vnet_sctp_calculate_padding (bytes_to_add + data_len);
970 sctp_payload_data_chunk_t *data_chunk =
971 vlib_buffer_push_uninit (b, bytes_to_add);
973 data_chunk->sctp_hdr.checksum = 0;
974 data_chunk->sctp_hdr.src_port = tc->sub_conn[idx].connection.lcl_port;
975 data_chunk->sctp_hdr.dst_port = tc->sub_conn[idx].connection.rmt_port;
976 data_chunk->sctp_hdr.verification_tag = tc->remote_tag;
978 data_chunk->tsn = clib_host_to_net_u32 (0);
979 data_chunk->stream_id = clib_host_to_net_u16 (0);
980 data_chunk->stream_seq = clib_host_to_net_u16 (0);
982 vnet_sctp_set_chunk_type (&data_chunk->chunk_hdr, DATA);
983 vnet_sctp_set_chunk_length (&data_chunk->chunk_hdr, chunk_length);
985 SCTP_ADV_DBG_OUTPUT ("POINTER_WITH_DATA = %p, DATA_OFFSET = %u",
986 b->data, b->current_data);
988 vnet_buffer (b)->sctp.connection_index =
989 tc->sub_conn[idx].connection.c_index;
993 sctp_push_header (transport_connection_t * tconn, vlib_buffer_t * b)
995 sctp_connection_t *tc = sctp_get_connection_from_transport (tconn);
996 sctp_push_hdr_i (tc, b, SCTP_STATE_ESTABLISHED);
998 if (tc->rtt_ts == 0 && !sctp_in_cong_recovery (tc))
1000 tc->rtt_ts = sctp_time_now ();
1001 tc->rtt_seq = tc->snd_nxt;
1003 sctp_trajectory_add_start (b0, 3);
1010 sctp46_output_inline (vlib_main_t * vm,
1011 vlib_node_runtime_t * node,
1012 vlib_frame_t * from_frame, int is_ip4)
1014 u32 n_left_from, next_index, *from, *to_next;
1015 u32 my_thread_index = vm->thread_index;
1017 from = vlib_frame_vector_args (from_frame);
1018 n_left_from = from_frame->n_vectors;
1019 next_index = node->cached_next_index;
1020 sctp_set_time_now (my_thread_index);
1022 while (n_left_from > 0)
1026 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1028 while (n_left_from > 0 && n_left_to_next > 0)
1032 sctp_header_t *sctp_hdr = 0;
1033 sctp_connection_t *tc0;
1034 sctp_tx_trace_t *t0;
1035 sctp_header_t *th0 = 0;
1036 u32 error0 = SCTP_ERROR_PKTS_SENT, next0 =
1037 SCTP_OUTPUT_NEXT_IP_LOOKUP;
1039 #if SCTP_DEBUG_STATE_MACHINE
1040 u16 packet_length = 0;
1048 n_left_to_next -= 1;
1050 b0 = vlib_get_buffer (vm, bi0);
1051 tc0 = sctp_connection_get (vnet_buffer (b0)->sctp.connection_index,
1054 if (PREDICT_FALSE (tc0 == 0))
1056 error0 = SCTP_ERROR_INVALID_CONNECTION;
1057 next0 = SCTP_OUTPUT_NEXT_DROP;
1061 u8 idx = sctp_pick_conn_idx_on_state (tc0->state);
1063 th0 = vlib_buffer_get_current (b0);
1067 ip4_header_t *th0 = vlib_buffer_push_ip4 (vm,
1076 IP_PROTOCOL_SCTP, 1);
1078 u32 checksum = ip4_sctp_compute_checksum (vm, b0, th0);
1080 sctp_hdr = ip4_next_header (th0);
1081 sctp_hdr->checksum = checksum;
1083 vnet_buffer (b0)->l4_hdr_offset = (u8 *) th0 - b0->data;
1086 #if SCTP_DEBUG_STATE_MACHINE
1087 packet_length = clib_net_to_host_u16 (th0->length);
1093 ih0 = vlib_buffer_push_ip6 (vm,
1095 &tc0->sub_conn[idx].
1096 connection.lcl_ip.ip6,
1097 &tc0->sub_conn[idx].
1098 connection.rmt_ip.ip6,
1102 u32 checksum = ip6_sctp_compute_checksum (vm, b0, ih0, &bogus);
1105 sctp_hdr = ip6_next_header (ih0);
1106 sctp_hdr->checksum = checksum;
1108 vnet_buffer (b0)->l3_hdr_offset = (u8 *) ih0 - b0->data;
1109 vnet_buffer (b0)->l4_hdr_offset = (u8 *) th0 - b0->data;
1112 #if SCTP_DEBUG_STATE_MACHINE
1113 packet_length = clib_net_to_host_u16 (ih0->payload_length);
1118 (tc0->sub_conn[idx].connection.lcl_port ==
1120 || tc0->sub_conn[idx].connection.lcl_port ==
1122 && (tc0->sub_conn[idx].connection.rmt_port ==
1124 || tc0->sub_conn[idx].connection.rmt_port ==
1125 sctp_hdr->src_port);
1127 sctp_full_hdr_t *full_hdr = (sctp_full_hdr_t *) sctp_hdr;
1128 u8 chunk_type = vnet_sctp_get_chunk_type (&full_hdr->common_hdr);
1132 SCTP_DBG_STATE_MACHINE ("BUFFER IS INCORRECT: conn_index = %u, "
1133 "packet_length = %u, "
1134 "chunk_type = %u [%s], "
1135 "connection.lcl_port = %u, sctp_hdr->src_port = %u, "
1136 "connection.rmt_port = %u, sctp_hdr->dst_port = %u",
1138 [idx].connection.c_index, packet_length,
1140 sctp_chunk_to_string (chunk_type),
1141 tc0->sub_conn[idx].connection.lcl_port,
1143 tc0->sub_conn[idx].connection.rmt_port,
1144 sctp_hdr->dst_port);
1146 error0 = SCTP_ERROR_UNKOWN_CHUNK;
1147 next0 = SCTP_OUTPUT_NEXT_DROP;
1151 SCTP_DBG_STATE_MACHINE
1152 ("CONN_INDEX = %u, CURR_CONN_STATE = %u (%s), "
1153 "CHUNK_TYPE = %s, " "SRC_PORT = %u, DST_PORT = %u",
1154 tc0->sub_conn[idx].connection.c_index,
1155 tc0->state, sctp_state_to_string (tc0->state),
1156 sctp_chunk_to_string (chunk_type), full_hdr->hdr.src_port,
1157 full_hdr->hdr.dst_port);
1159 if (chunk_type == DATA)
1160 SCTP_ADV_DBG_OUTPUT ("PACKET_LENGTH = %u", packet_length);
1162 /* Let's make sure the state-machine does not send anything crazy */
1165 case SCTP_STATE_CLOSED:
1167 if (chunk_type != INIT && chunk_type != INIT_ACK)
1169 SCTP_DBG_STATE_MACHINE
1170 ("Sending the wrong chunk (%s) based on state-machine status (%s)",
1171 sctp_chunk_to_string (chunk_type),
1172 sctp_state_to_string (tc0->state));
1174 error0 = SCTP_ERROR_UNKOWN_CHUNK;
1175 next0 = SCTP_OUTPUT_NEXT_DROP;
1180 case SCTP_STATE_ESTABLISHED:
1181 if (chunk_type != DATA && chunk_type != HEARTBEAT &&
1182 chunk_type != HEARTBEAT_ACK && chunk_type != SACK &&
1183 chunk_type != COOKIE_ACK && chunk_type != SHUTDOWN)
1185 SCTP_DBG_STATE_MACHINE
1186 ("Sending the wrong chunk (%s) based on state-machine status (%s)",
1187 sctp_chunk_to_string (chunk_type),
1188 sctp_state_to_string (tc0->state));
1190 error0 = SCTP_ERROR_UNKOWN_CHUNK;
1191 next0 = SCTP_OUTPUT_NEXT_DROP;
1195 case SCTP_STATE_COOKIE_WAIT:
1196 if (chunk_type != COOKIE_ECHO)
1198 SCTP_DBG_STATE_MACHINE
1199 ("Sending the wrong chunk (%s) based on state-machine status (%s)",
1200 sctp_chunk_to_string (chunk_type),
1201 sctp_state_to_string (tc0->state));
1203 error0 = SCTP_ERROR_UNKOWN_CHUNK;
1204 next0 = SCTP_OUTPUT_NEXT_DROP;
1208 tc0->state = SCTP_STATE_COOKIE_ECHOED;
1211 SCTP_DBG_STATE_MACHINE
1212 ("Sending chunk (%s) based on state-machine status (%s)",
1213 sctp_chunk_to_string (chunk_type),
1214 sctp_state_to_string (tc0->state));
1218 if (chunk_type == SHUTDOWN)
1220 /* Start the SCTP_TIMER_T2_SHUTDOWN timer */
1221 sctp_timer_set (tc0, idx, SCTP_TIMER_T2_SHUTDOWN,
1223 tc0->state = SCTP_STATE_SHUTDOWN_SENT;
1226 vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
1227 vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
1229 b0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
1231 SCTP_DBG_STATE_MACHINE ("CONNECTION_INDEX = %u, "
1234 tc0->sub_conn[idx].connection.c_index,
1235 sctp_state_to_string (tc0->state),
1236 sctp_chunk_to_string (chunk_type));
1238 vnet_sctp_common_hdr_params_host_to_net (&full_hdr->common_hdr);
1241 b0->error = node->errors[error0];
1242 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1244 t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
1247 clib_memcpy (&t0->sctp_header, th0,
1248 sizeof (t0->sctp_header));
1252 memset (&t0->sctp_header, 0, sizeof (t0->sctp_header));
1254 clib_memcpy (&t0->sctp_connection, tc0,
1255 sizeof (t0->sctp_connection));
1258 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1259 n_left_to_next, bi0, next0);
1262 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1265 return from_frame->n_vectors;
1269 sctp4_output (vlib_main_t * vm, vlib_node_runtime_t * node,
1270 vlib_frame_t * from_frame)
1272 return sctp46_output_inline (vm, node, from_frame, 1 /* is_ip4 */ );
1276 sctp6_output (vlib_main_t * vm, vlib_node_runtime_t * node,
1277 vlib_frame_t * from_frame)
1279 return sctp46_output_inline (vm, node, from_frame, 0 /* is_ip4 */ );
1283 VLIB_REGISTER_NODE (sctp4_output_node) =
1285 .function = sctp4_output,.name = "sctp4-output",
1286 /* Takes a vector of packets. */
1287 .vector_size = sizeof (u32),
1288 .n_errors = SCTP_N_ERROR,
1289 .error_strings = sctp_error_strings,
1290 .n_next_nodes = SCTP_OUTPUT_N_NEXT,
1292 #define _(s,n) [SCTP_OUTPUT_NEXT_##s] = n,
1293 foreach_sctp4_output_next
1296 .format_buffer = format_sctp_header,
1297 .format_trace = format_sctp_tx_trace,
1301 VLIB_NODE_FUNCTION_MULTIARCH (sctp4_output_node, sctp4_output);
1304 VLIB_REGISTER_NODE (sctp6_output_node) =
1306 .function = sctp6_output,
1307 .name = "sctp6-output",
1308 /* Takes a vector of packets. */
1309 .vector_size = sizeof (u32),
1310 .n_errors = SCTP_N_ERROR,
1311 .error_strings = sctp_error_strings,
1312 .n_next_nodes = SCTP_OUTPUT_N_NEXT,
1314 #define _(s,n) [SCTP_OUTPUT_NEXT_##s] = n,
1315 foreach_sctp6_output_next
1318 .format_buffer = format_sctp_header,
1319 .format_trace = format_sctp_tx_trace,
1323 VLIB_NODE_FUNCTION_MULTIARCH (sctp6_output_node, sctp6_output);
1326 * fd.io coding-style-patch-verification: ON
1329 * eval: (c-set-style "gnu")