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>
18 #include <openssl/hmac.h>
21 * Flush tx frame populated by retransmits and timer pops
24 sctp_flush_frame_to_output (vlib_main_t * vm, u8 thread_index, u8 is_ip4)
26 if (sctp_main.tx_frames[!is_ip4][thread_index])
29 next_index = is_ip4 ? sctp4_output_node.index : sctp6_output_node.index;
30 vlib_put_frame_to_node (vm, next_index,
31 sctp_main.tx_frames[!is_ip4][thread_index]);
32 sctp_main.tx_frames[!is_ip4][thread_index] = 0;
37 * Flush ip lookup tx frames populated by timer pops
40 sctp_flush_frame_to_ip_lookup (vlib_main_t * vm, u8 thread_index, u8 is_ip4)
42 if (sctp_main.ip_lookup_tx_frames[!is_ip4][thread_index])
45 next_index = is_ip4 ? ip4_lookup_node.index : ip6_lookup_node.index;
46 vlib_put_frame_to_node (vm, next_index,
47 sctp_main.ip_lookup_tx_frames[!is_ip4]
49 sctp_main.ip_lookup_tx_frames[!is_ip4][thread_index] = 0;
54 * Flush v4 and v6 sctp and ip-lookup tx frames for thread index
57 sctp_flush_frames_to_output (u8 thread_index)
59 vlib_main_t *vm = vlib_get_main ();
60 sctp_flush_frame_to_output (vm, thread_index, 1);
61 sctp_flush_frame_to_output (vm, thread_index, 0);
62 sctp_flush_frame_to_ip_lookup (vm, thread_index, 1);
63 sctp_flush_frame_to_ip_lookup (vm, thread_index, 0);
67 ip4_sctp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0,
71 u32 ip_header_length, payload_length_host_byte_order;
72 u32 n_this_buffer, n_bytes_left, n_ip_bytes_this_buffer;
73 void *data_this_buffer;
75 /* Initialize checksum with ip header. */
76 ip_header_length = ip4_header_bytes (ip0);
77 payload_length_host_byte_order =
78 clib_net_to_host_u16 (ip0->length) - ip_header_length;
80 clib_host_to_net_u32 (payload_length_host_byte_order +
81 (ip0->protocol << 16));
83 if (BITS (uword) == 32)
86 ip_csum_with_carry (checksum,
87 clib_mem_unaligned (&ip0->src_address, u32));
89 ip_csum_with_carry (checksum,
90 clib_mem_unaligned (&ip0->dst_address, u32));
94 ip_csum_with_carry (checksum,
95 clib_mem_unaligned (&ip0->src_address, u64));
97 n_bytes_left = n_this_buffer = payload_length_host_byte_order;
98 data_this_buffer = (void *) ip0 + ip_header_length;
99 n_ip_bytes_this_buffer =
100 p0->current_length - (((u8 *) ip0 - p0->data) - p0->current_data);
101 if (n_this_buffer + ip_header_length > n_ip_bytes_this_buffer)
103 n_this_buffer = n_ip_bytes_this_buffer > ip_header_length ?
104 n_ip_bytes_this_buffer - ip_header_length : 0;
109 ip_incremental_checksum (checksum, data_this_buffer, n_this_buffer);
110 n_bytes_left -= n_this_buffer;
111 if (n_bytes_left == 0)
114 ASSERT (p0->flags & VLIB_BUFFER_NEXT_PRESENT);
115 p0 = vlib_get_buffer (vm, p0->next_buffer);
116 data_this_buffer = vlib_buffer_get_current (p0);
117 n_this_buffer = p0->current_length;
124 ip6_sctp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0,
125 ip6_header_t * ip0, int *bogus_lengthp)
128 u16 payload_length_host_byte_order;
129 u32 i, n_this_buffer, n_bytes_left;
130 u32 headers_size = sizeof (ip0[0]);
131 void *data_this_buffer;
133 ASSERT (bogus_lengthp);
136 /* Initialize checksum with ip header. */
137 checksum = ip0->payload_length + clib_host_to_net_u16 (ip0->protocol);
138 payload_length_host_byte_order = clib_net_to_host_u16 (ip0->payload_length);
139 data_this_buffer = (void *) (ip0 + 1);
141 for (i = 0; i < ARRAY_LEN (ip0->src_address.as_uword); i++)
143 checksum = ip_csum_with_carry (checksum,
144 clib_mem_unaligned (&ip0->
148 ip_csum_with_carry (checksum,
149 clib_mem_unaligned (&ip0->dst_address.as_uword[i],
153 /* some icmp packets may come with a "router alert" hop-by-hop extension header (e.g., mldv2 packets)
154 * or UDP-Ping packets */
155 if (PREDICT_FALSE (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS))
158 ip6_hop_by_hop_ext_t *ext_hdr =
159 (ip6_hop_by_hop_ext_t *) data_this_buffer;
161 /* validate really icmp6 next */
162 ASSERT ((ext_hdr->next_hdr == IP_PROTOCOL_SCTP));
164 skip_bytes = 8 * (1 + ext_hdr->n_data_u64s);
165 data_this_buffer = (void *) ((u8 *) data_this_buffer + skip_bytes);
167 payload_length_host_byte_order -= skip_bytes;
168 headers_size += skip_bytes;
171 n_bytes_left = n_this_buffer = payload_length_host_byte_order;
172 if (p0 && n_this_buffer + headers_size > p0->current_length)
175 headers_size ? p0->current_length - headers_size : 0;
179 ip_incremental_checksum (checksum, data_this_buffer, n_this_buffer);
180 n_bytes_left -= n_this_buffer;
181 if (n_bytes_left == 0)
184 if (!(p0->flags & VLIB_BUFFER_NEXT_PRESENT))
189 p0 = vlib_get_buffer (vm, p0->next_buffer);
190 data_this_buffer = vlib_buffer_get_current (p0);
191 n_this_buffer = p0->current_length;
198 sctp_push_ip_hdr (sctp_main_t * tm, sctp_sub_connection_t * sctp_sub_conn,
201 sctp_header_t *th = vlib_buffer_get_current (b);
202 vlib_main_t *vm = vlib_get_main ();
203 if (sctp_sub_conn->c_is_ip4)
206 ih = vlib_buffer_push_ip4 (vm, b, &sctp_sub_conn->c_lcl_ip4,
207 &sctp_sub_conn->c_rmt_ip4, IP_PROTOCOL_SCTP,
209 th->checksum = ip4_sctp_compute_checksum (vm, b, ih);
216 ih = vlib_buffer_push_ip6 (vm, b, &sctp_sub_conn->c_lcl_ip6,
217 &sctp_sub_conn->c_rmt_ip6, IP_PROTOCOL_SCTP);
218 th->checksum = ip6_sctp_compute_checksum (vm, b, ih, &bogus);
224 sctp_reuse_buffer (vlib_main_t * vm, vlib_buffer_t * b)
226 if (b->flags & VLIB_BUFFER_NEXT_PRESENT)
227 vlib_buffer_free_one (vm, b->next_buffer);
228 /* Zero all flags but free list index and trace flag */
229 b->flags &= VLIB_BUFFER_NEXT_PRESENT - 1;
231 b->current_length = 0;
232 b->total_length_not_including_first_buffer = 0;
233 vnet_buffer (b)->sctp.flags = 0;
234 vnet_buffer (b)->sctp.subconn_idx = MAX_SCTP_CONNECTIONS;
236 /* Leave enough space for headers */
237 return vlib_buffer_make_headroom (b, TRANSPORT_MAX_HDRS_LEN);
241 sctp_init_buffer (vlib_main_t * vm, vlib_buffer_t * b)
243 ASSERT ((b->flags & VLIB_BUFFER_NEXT_PRESENT) == 0);
244 b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
245 b->total_length_not_including_first_buffer = 0;
246 vnet_buffer (b)->sctp.flags = 0;
247 vnet_buffer (b)->sctp.subconn_idx = MAX_SCTP_CONNECTIONS;
248 VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b);
249 /* Leave enough space for headers */
250 return vlib_buffer_make_headroom (b, TRANSPORT_MAX_HDRS_LEN);
254 sctp_alloc_tx_buffers (sctp_main_t * tm, u8 thread_index, u32 n_free_buffers)
256 vlib_main_t *vm = vlib_get_main ();
257 u32 current_length = vec_len (tm->tx_buffers[thread_index]);
260 vec_validate (tm->tx_buffers[thread_index],
261 current_length + n_free_buffers - 1);
263 vlib_buffer_alloc (vm, &tm->tx_buffers[thread_index][current_length],
265 _vec_len (tm->tx_buffers[thread_index]) = current_length + n_allocated;
266 /* buffer shortage, report failure */
267 if (vec_len (tm->tx_buffers[thread_index]) == 0)
269 clib_warning ("out of buffers");
276 sctp_get_free_buffer_index (sctp_main_t * tm, u32 * bidx)
279 u32 thread_index = vlib_get_thread_index ();
280 if (PREDICT_FALSE (vec_len (tm->tx_buffers[thread_index]) == 0))
282 if (sctp_alloc_tx_buffers (tm, thread_index, VLIB_FRAME_SIZE))
285 my_tx_buffers = tm->tx_buffers[thread_index];
286 *bidx = my_tx_buffers[vec_len (my_tx_buffers) - 1];
287 _vec_len (my_tx_buffers) -= 1;
292 sctp_enqueue_to_output_i (vlib_main_t * vm, vlib_buffer_t * b, u32 bi,
295 sctp_main_t *tm = vnet_get_sctp_main ();
296 u32 thread_index = vlib_get_thread_index ();
297 u32 *to_next, next_index;
300 b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
303 /* Decide where to send the packet */
304 next_index = is_ip4 ? sctp4_output_node.index : sctp6_output_node.index;
305 sctp_trajectory_add_start (b, 2);
307 /* Get frame to v4/6 output node */
308 f = tm->tx_frames[!is_ip4][thread_index];
311 f = vlib_get_frame_to_node (vm, next_index);
313 tm->tx_frames[!is_ip4][thread_index] = f;
315 to_next = vlib_frame_vector_args (f);
316 to_next[f->n_vectors] = bi;
318 if (flush || f->n_vectors == VLIB_FRAME_SIZE)
320 vlib_put_frame_to_node (vm, next_index, f);
321 tm->tx_frames[!is_ip4][thread_index] = 0;
326 sctp_enqueue_to_output_now (vlib_main_t * vm, vlib_buffer_t * b, u32 bi,
329 sctp_enqueue_to_output_i (vm, b, bi, is_ip4, 1);
333 sctp_enqueue_to_ip_lookup_i (vlib_main_t * vm, vlib_buffer_t * b, u32 bi,
334 u8 is_ip4, u32 fib_index, u8 flush)
336 sctp_main_t *tm = vnet_get_sctp_main ();
337 u32 thread_index = vlib_get_thread_index ();
338 u32 *to_next, next_index;
341 b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
344 vnet_buffer (b)->sw_if_index[VLIB_TX] = fib_index;
345 vnet_buffer (b)->sw_if_index[VLIB_RX] = 0;
347 /* Send to IP lookup */
348 next_index = is_ip4 ? ip4_lookup_node.index : ip6_lookup_node.index;
349 if (VLIB_BUFFER_TRACE_TRAJECTORY > 0)
352 b->pre_data[1] = next_index;
355 f = tm->ip_lookup_tx_frames[!is_ip4][thread_index];
358 f = vlib_get_frame_to_node (vm, next_index);
360 tm->ip_lookup_tx_frames[!is_ip4][thread_index] = f;
363 to_next = vlib_frame_vector_args (f);
364 to_next[f->n_vectors] = bi;
366 if (flush || f->n_vectors == VLIB_FRAME_SIZE)
368 vlib_put_frame_to_node (vm, next_index, f);
369 tm->ip_lookup_tx_frames[!is_ip4][thread_index] = 0;
374 sctp_enqueue_to_ip_lookup (vlib_main_t * vm, vlib_buffer_t * b, u32 bi,
375 u8 is_ip4, u32 fib_index)
377 sctp_enqueue_to_ip_lookup_i (vm, b, bi, is_ip4, fib_index, 0);
378 if (vm->thread_index == 0 && vlib_num_workers ())
379 session_flush_frames_main_thread (vm);
383 * Convert buffer to INIT
386 sctp_prepare_init_chunk (sctp_connection_t * sctp_conn, u8 idx,
389 u32 random_seed = random_default_seed ();
390 u16 alloc_bytes = sizeof (sctp_init_chunk_t);
391 sctp_sub_connection_t *sub_conn = &sctp_conn->sub_conn[idx];
393 sctp_ipv4_addr_param_t *ip4_param = 0;
394 sctp_ipv6_addr_param_t *ip6_param = 0;
396 if (sub_conn->c_is_ip4)
397 alloc_bytes += sizeof (sctp_ipv4_addr_param_t);
399 alloc_bytes += sizeof (sctp_ipv6_addr_param_t);
401 /* As per RFC 4960 the chunk_length value does NOT contemplate
402 * the size of the first header (see sctp_header_t) and any padding
404 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
406 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
408 sctp_init_chunk_t *init_chunk = vlib_buffer_push_uninit (b, alloc_bytes);
410 u16 pointer_offset = sizeof (init_chunk);
411 if (sub_conn->c_is_ip4)
413 ip4_param = (sctp_ipv4_addr_param_t *) init_chunk + pointer_offset;
414 ip4_param->address.as_u32 = sub_conn->c_lcl_ip.ip4.as_u32;
416 pointer_offset += sizeof (sctp_ipv4_addr_param_t);
420 ip6_param = (sctp_ipv6_addr_param_t *) init_chunk + pointer_offset;
421 ip6_param->address.as_u64[0] = sub_conn->c_lcl_ip.ip6.as_u64[0];
422 ip6_param->address.as_u64[1] = sub_conn->c_lcl_ip.ip6.as_u64[1];
424 pointer_offset += sizeof (sctp_ipv6_addr_param_t);
427 init_chunk->sctp_hdr.src_port = sub_conn->c_lcl_port; /* No need of host_to_net conversion, already in net-byte order */
428 init_chunk->sctp_hdr.dst_port = sub_conn->c_rmt_port; /* No need of host_to_net conversion, already in net-byte order */
429 init_chunk->sctp_hdr.checksum = 0;
430 /* The sender of an INIT must set the VERIFICATION_TAG to 0 as per RFC 4960 Section 8.5.1 */
431 init_chunk->sctp_hdr.verification_tag = 0x0;
433 vnet_sctp_set_chunk_type (&init_chunk->chunk_hdr, INIT);
434 vnet_sctp_set_chunk_length (&init_chunk->chunk_hdr, chunk_len);
435 vnet_sctp_common_hdr_params_host_to_net (&init_chunk->chunk_hdr);
437 sctp_init_cwnd (sctp_conn);
439 init_chunk->a_rwnd = clib_host_to_net_u32 (sctp_conn->sub_conn[idx].cwnd);
440 init_chunk->initiate_tag = clib_host_to_net_u32 (random_u32 (&random_seed));
441 init_chunk->inboud_streams_count =
442 clib_host_to_net_u16 (INBOUND_STREAMS_COUNT);
443 init_chunk->outbound_streams_count =
444 clib_host_to_net_u16 (OUTBOUND_STREAMS_COUNT);
446 init_chunk->initial_tsn =
447 clib_host_to_net_u32 (sctp_conn->local_initial_tsn);
448 SCTP_CONN_TRACKING_DBG ("sctp_conn->local_initial_tsn = %u",
449 sctp_conn->local_initial_tsn);
451 sctp_conn->local_tag = init_chunk->initiate_tag;
453 vnet_buffer (b)->sctp.connection_index = sub_conn->c_c_index;
454 vnet_buffer (b)->sctp.subconn_idx = idx;
456 SCTP_DBG_STATE_MACHINE ("CONN_INDEX = %u, CURR_CONN_STATE = %u (%s), "
458 "SRC_PORT = %u, DST_PORT = %u",
459 sub_conn->connection.c_index,
461 sctp_state_to_string (sctp_conn->state),
462 sctp_chunk_to_string (INIT),
463 init_chunk->sctp_hdr.src_port,
464 init_chunk->sctp_hdr.dst_port);
468 sctp_compute_mac (sctp_connection_t * sctp_conn,
469 sctp_state_cookie_param_t * state_cookie)
471 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
476 unsigned int len = 0;
477 const EVP_MD *md = EVP_sha1 ();
478 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
479 ctx = HMAC_CTX_new ();
480 HMAC_Init_ex (ctx, &state_cookie->creation_time,
481 sizeof (state_cookie->creation_time), md, NULL);
482 HMAC_Update (ctx, (const unsigned char *) &sctp_conn, sizeof (sctp_conn));
483 HMAC_Final (ctx, state_cookie->mac, &len);
485 HMAC_CTX_init (&ctx);
486 HMAC_Init_ex (&ctx, &state_cookie->creation_time,
487 sizeof (state_cookie->creation_time), md, NULL);
488 HMAC_Update (&ctx, (const unsigned char *) &sctp_conn, sizeof (sctp_conn));
489 HMAC_Final (&ctx, state_cookie->mac, &len);
490 HMAC_CTX_cleanup (&ctx);
493 ENDIANESS_SWAP (state_cookie->mac);
497 sctp_prepare_cookie_ack_chunk (sctp_connection_t * sctp_conn, u8 idx,
500 vlib_main_t *vm = vlib_get_main ();
502 sctp_reuse_buffer (vm, b);
504 u16 alloc_bytes = sizeof (sctp_cookie_ack_chunk_t);
506 /* As per RFC 4960 the chunk_length value does NOT contemplate
507 * the size of the first header (see sctp_header_t) and any padding
509 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
511 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
513 sctp_cookie_ack_chunk_t *cookie_ack_chunk =
514 vlib_buffer_push_uninit (b, alloc_bytes);
516 cookie_ack_chunk->sctp_hdr.checksum = 0;
517 cookie_ack_chunk->sctp_hdr.src_port =
518 sctp_conn->sub_conn[idx].connection.lcl_port;
519 cookie_ack_chunk->sctp_hdr.dst_port =
520 sctp_conn->sub_conn[idx].connection.rmt_port;
521 cookie_ack_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
522 vnet_sctp_set_chunk_type (&cookie_ack_chunk->chunk_hdr, COOKIE_ACK);
523 vnet_sctp_set_chunk_length (&cookie_ack_chunk->chunk_hdr, chunk_len);
525 vnet_buffer (b)->sctp.connection_index =
526 sctp_conn->sub_conn[idx].connection.c_index;
527 vnet_buffer (b)->sctp.subconn_idx = idx;
531 sctp_prepare_cookie_echo_chunk (sctp_connection_t * sctp_conn, u8 idx,
532 vlib_buffer_t * b, u8 reuse_buffer)
534 vlib_main_t *vm = vlib_get_main ();
537 sctp_reuse_buffer (vm, b);
539 /* The minimum size of the message is given by the sctp_init_ack_chunk_t */
540 u16 alloc_bytes = sizeof (sctp_cookie_echo_chunk_t);
541 /* As per RFC 4960 the chunk_length value does NOT contemplate
542 * the size of the first header (see sctp_header_t) and any padding
544 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
545 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
546 sctp_cookie_echo_chunk_t *cookie_echo_chunk =
547 vlib_buffer_push_uninit (b, alloc_bytes);
548 cookie_echo_chunk->sctp_hdr.checksum = 0;
549 cookie_echo_chunk->sctp_hdr.src_port =
550 sctp_conn->sub_conn[idx].connection.lcl_port;
551 cookie_echo_chunk->sctp_hdr.dst_port =
552 sctp_conn->sub_conn[idx].connection.rmt_port;
553 cookie_echo_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
554 vnet_sctp_set_chunk_type (&cookie_echo_chunk->chunk_hdr, COOKIE_ECHO);
555 vnet_sctp_set_chunk_length (&cookie_echo_chunk->chunk_hdr, chunk_len);
556 clib_memcpy_fast (&(cookie_echo_chunk->cookie), &sctp_conn->cookie_param,
557 sizeof (sctp_state_cookie_param_t));
559 vnet_buffer (b)->sctp.connection_index =
560 sctp_conn->sub_conn[idx].connection.c_index;
561 vnet_buffer (b)->sctp.subconn_idx = idx;
569 sctp_send_cookie_echo (sctp_connection_t * sctp_conn)
573 sctp_main_t *tm = vnet_get_sctp_main ();
574 vlib_main_t *vm = vlib_get_main ();
576 if (PREDICT_FALSE (sctp_conn->init_retransmit_err > SCTP_MAX_INIT_RETRANS))
578 clib_warning ("Reached MAX_INIT_RETRANS times. Aborting connection.");
580 session_stream_connect_notify (&sctp_conn->sub_conn
581 [SCTP_PRIMARY_PATH_IDX].connection, 1);
583 sctp_connection_timers_reset (sctp_conn);
585 sctp_connection_cleanup (sctp_conn);
588 if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
591 b = vlib_get_buffer (vm, bi);
592 u8 idx = SCTP_PRIMARY_PATH_IDX;
594 sctp_init_buffer (vm, b);
595 sctp_prepare_cookie_echo_chunk (sctp_conn, idx, b, 0);
596 sctp_enqueue_to_output_now (vm, b, bi, sctp_conn->sub_conn[idx].c_is_ip4);
598 /* Start the T1_INIT timer */
599 sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T1_INIT,
600 sctp_conn->sub_conn[idx].RTO);
602 /* Change state to COOKIE_WAIT */
603 sctp_conn->state = SCTP_STATE_COOKIE_WAIT;
605 /* Measure RTT with this */
606 sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now ();
611 * Convert buffer to ERROR
614 sctp_prepare_operation_error (sctp_connection_t * sctp_conn, u8 idx,
615 vlib_buffer_t * b, u8 err_cause)
617 vlib_main_t *vm = vlib_get_main ();
619 sctp_reuse_buffer (vm, b);
621 /* The minimum size of the message is given by the sctp_operation_error_t */
623 sizeof (sctp_operation_error_t) + sizeof (sctp_err_cause_param_t);
625 /* As per RFC 4960 the chunk_length value does NOT contemplate
626 * the size of the first header (see sctp_header_t) and any padding
628 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
630 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
632 sctp_operation_error_t *err_chunk =
633 vlib_buffer_push_uninit (b, alloc_bytes);
635 /* src_port & dst_port are already in network byte-order */
636 err_chunk->sctp_hdr.checksum = 0;
637 err_chunk->sctp_hdr.src_port = sctp_conn->sub_conn[idx].connection.lcl_port;
638 err_chunk->sctp_hdr.dst_port = sctp_conn->sub_conn[idx].connection.rmt_port;
639 /* As per RFC4960 Section 5.2.2: copy the INITIATE_TAG into the VERIFICATION_TAG of the ABORT chunk */
640 err_chunk->sctp_hdr.verification_tag = sctp_conn->local_tag;
642 err_chunk->err_causes[0].param_hdr.length =
643 clib_host_to_net_u16 (sizeof (err_chunk->err_causes[0].param_hdr.type) +
644 sizeof (err_chunk->err_causes[0].param_hdr.length));
645 err_chunk->err_causes[0].param_hdr.type = clib_host_to_net_u16 (err_cause);
647 vnet_sctp_set_chunk_type (&err_chunk->chunk_hdr, OPERATION_ERROR);
648 vnet_sctp_set_chunk_length (&err_chunk->chunk_hdr, chunk_len);
650 vnet_buffer (b)->sctp.connection_index =
651 sctp_conn->sub_conn[idx].connection.c_index;
652 vnet_buffer (b)->sctp.subconn_idx = idx;
656 * Convert buffer to ABORT
659 sctp_prepare_abort_for_collision (sctp_connection_t * sctp_conn, u8 idx,
660 vlib_buffer_t * b, ip4_address_t * ip4_addr,
661 ip6_address_t * ip6_addr)
663 vlib_main_t *vm = vlib_get_main ();
665 sctp_reuse_buffer (vm, b);
667 /* The minimum size of the message is given by the sctp_abort_chunk_t */
668 u16 alloc_bytes = sizeof (sctp_abort_chunk_t);
670 /* As per RFC 4960 the chunk_length value does NOT contemplate
671 * the size of the first header (see sctp_header_t) and any padding
673 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
675 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
677 sctp_abort_chunk_t *abort_chunk = vlib_buffer_push_uninit (b, alloc_bytes);
679 /* src_port & dst_port are already in network byte-order */
680 abort_chunk->sctp_hdr.checksum = 0;
681 abort_chunk->sctp_hdr.src_port =
682 sctp_conn->sub_conn[idx].connection.lcl_port;
683 abort_chunk->sctp_hdr.dst_port =
684 sctp_conn->sub_conn[idx].connection.rmt_port;
685 /* As per RFC4960 Section 5.2.2: copy the INITIATE_TAG into the VERIFICATION_TAG of the ABORT chunk */
686 abort_chunk->sctp_hdr.verification_tag = sctp_conn->local_tag;
688 vnet_sctp_set_chunk_type (&abort_chunk->chunk_hdr, ABORT);
689 vnet_sctp_set_chunk_length (&abort_chunk->chunk_hdr, chunk_len);
691 vnet_buffer (b)->sctp.connection_index =
692 sctp_conn->sub_conn[idx].connection.c_index;
693 vnet_buffer (b)->sctp.subconn_idx = idx;
697 * Convert buffer to INIT-ACK
700 sctp_prepare_initack_chunk_for_collision (sctp_connection_t * sctp_conn,
701 u8 idx, vlib_buffer_t * b,
702 ip4_address_t * ip4_addr,
703 ip6_address_t * ip6_addr)
705 vlib_main_t *vm = vlib_get_main ();
706 sctp_ipv4_addr_param_t *ip4_param = 0;
707 sctp_ipv6_addr_param_t *ip6_param = 0;
709 sctp_reuse_buffer (vm, b);
711 /* The minimum size of the message is given by the sctp_init_ack_chunk_t */
713 sizeof (sctp_init_ack_chunk_t) + sizeof (sctp_state_cookie_param_t);
715 if (PREDICT_TRUE (ip4_addr != NULL))
717 /* Create room for variable-length fields in the INIT_ACK chunk */
718 alloc_bytes += SCTP_IPV4_ADDRESS_TYPE_LENGTH;
720 if (PREDICT_TRUE (ip6_addr != NULL))
722 /* Create room for variable-length fields in the INIT_ACK chunk */
723 alloc_bytes += SCTP_IPV6_ADDRESS_TYPE_LENGTH;
726 if (sctp_conn->sub_conn[idx].connection.is_ip4)
727 alloc_bytes += sizeof (sctp_ipv4_addr_param_t);
729 alloc_bytes += sizeof (sctp_ipv6_addr_param_t);
731 /* As per RFC 4960 the chunk_length value does NOT contemplate
732 * the size of the first header (see sctp_header_t) and any padding
734 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
736 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
738 sctp_init_ack_chunk_t *init_ack_chunk =
739 vlib_buffer_push_uninit (b, alloc_bytes);
741 u16 pointer_offset = sizeof (sctp_init_ack_chunk_t);
743 /* Create State Cookie parameter */
744 sctp_state_cookie_param_t *state_cookie_param =
745 (sctp_state_cookie_param_t *) ((char *) init_ack_chunk + pointer_offset);
747 state_cookie_param->param_hdr.type =
748 clib_host_to_net_u16 (SCTP_STATE_COOKIE_TYPE);
749 state_cookie_param->param_hdr.length =
750 clib_host_to_net_u16 (sizeof (sctp_state_cookie_param_t));
751 state_cookie_param->creation_time = clib_host_to_net_u64 (sctp_time_now ());
752 state_cookie_param->cookie_lifespan =
753 clib_host_to_net_u32 (SCTP_VALID_COOKIE_LIFE);
755 sctp_compute_mac (sctp_conn, state_cookie_param);
757 pointer_offset += sizeof (sctp_state_cookie_param_t);
759 if (PREDICT_TRUE (ip4_addr != NULL))
761 sctp_ipv4_addr_param_t *ipv4_addr =
762 (sctp_ipv4_addr_param_t *) init_ack_chunk + pointer_offset;
764 ipv4_addr->param_hdr.type =
765 clib_host_to_net_u16 (SCTP_IPV4_ADDRESS_TYPE);
766 ipv4_addr->param_hdr.length =
767 clib_host_to_net_u16 (SCTP_IPV4_ADDRESS_TYPE_LENGTH);
768 ipv4_addr->address.as_u32 = ip4_addr->as_u32;
770 pointer_offset += SCTP_IPV4_ADDRESS_TYPE_LENGTH;
772 if (PREDICT_TRUE (ip6_addr != NULL))
774 sctp_ipv6_addr_param_t *ipv6_addr =
775 (sctp_ipv6_addr_param_t *) init_ack_chunk + pointer_offset;
777 ipv6_addr->param_hdr.type =
778 clib_host_to_net_u16 (SCTP_IPV6_ADDRESS_TYPE);
779 ipv6_addr->param_hdr.length =
780 clib_host_to_net_u16 (SCTP_IPV6_ADDRESS_TYPE_LENGTH);
781 ipv6_addr->address.as_u64[0] = ip6_addr->as_u64[0];
782 ipv6_addr->address.as_u64[1] = ip6_addr->as_u64[1];
784 pointer_offset += SCTP_IPV6_ADDRESS_TYPE_LENGTH;
787 if (sctp_conn->sub_conn[idx].connection.is_ip4)
789 ip4_param = (sctp_ipv4_addr_param_t *) init_ack_chunk + pointer_offset;
790 ip4_param->address.as_u32 =
791 sctp_conn->sub_conn[idx].connection.lcl_ip.ip4.as_u32;
793 pointer_offset += sizeof (sctp_ipv4_addr_param_t);
797 ip6_param = (sctp_ipv6_addr_param_t *) init_ack_chunk + pointer_offset;
798 ip6_param->address.as_u64[0] =
799 sctp_conn->sub_conn[idx].connection.lcl_ip.ip6.as_u64[0];
800 ip6_param->address.as_u64[1] =
801 sctp_conn->sub_conn[idx].connection.lcl_ip.ip6.as_u64[1];
803 pointer_offset += sizeof (sctp_ipv6_addr_param_t);
806 /* src_port & dst_port are already in network byte-order */
807 init_ack_chunk->sctp_hdr.checksum = 0;
808 init_ack_chunk->sctp_hdr.src_port =
809 sctp_conn->sub_conn[idx].connection.lcl_port;
810 init_ack_chunk->sctp_hdr.dst_port =
811 sctp_conn->sub_conn[idx].connection.rmt_port;
812 /* the sctp_conn->verification_tag is already in network byte-order (being a copy of the init_tag coming with the INIT chunk) */
813 init_ack_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
814 init_ack_chunk->initial_tsn =
815 clib_host_to_net_u32 (sctp_conn->local_initial_tsn);
816 SCTP_CONN_TRACKING_DBG ("init_ack_chunk->initial_tsn = %u",
817 init_ack_chunk->initial_tsn);
819 vnet_sctp_set_chunk_type (&init_ack_chunk->chunk_hdr, INIT_ACK);
820 vnet_sctp_set_chunk_length (&init_ack_chunk->chunk_hdr, chunk_len);
822 init_ack_chunk->initiate_tag = sctp_conn->local_tag;
824 init_ack_chunk->a_rwnd =
825 clib_host_to_net_u32 (sctp_conn->sub_conn[idx].cwnd);
826 init_ack_chunk->inboud_streams_count =
827 clib_host_to_net_u16 (INBOUND_STREAMS_COUNT);
828 init_ack_chunk->outbound_streams_count =
829 clib_host_to_net_u16 (OUTBOUND_STREAMS_COUNT);
831 vnet_buffer (b)->sctp.connection_index =
832 sctp_conn->sub_conn[idx].connection.c_index;
833 vnet_buffer (b)->sctp.subconn_idx = idx;
837 * Convert buffer to INIT-ACK
840 sctp_prepare_initack_chunk (sctp_connection_t * sctp_conn, u8 idx,
841 vlib_buffer_t * b, ip4_address_t * ip4_addr,
842 u8 add_ip4, ip6_address_t * ip6_addr, u8 add_ip6)
844 vlib_main_t *vm = vlib_get_main ();
845 sctp_ipv4_addr_param_t *ip4_param = 0;
846 sctp_ipv6_addr_param_t *ip6_param = 0;
847 u32 random_seed = random_default_seed ();
849 sctp_reuse_buffer (vm, b);
851 /* The minimum size of the message is given by the sctp_init_ack_chunk_t */
853 sizeof (sctp_init_ack_chunk_t) + sizeof (sctp_state_cookie_param_t);
855 if (PREDICT_FALSE (add_ip4 == 1))
857 /* Create room for variable-length fields in the INIT_ACK chunk */
858 alloc_bytes += SCTP_IPV4_ADDRESS_TYPE_LENGTH;
860 if (PREDICT_FALSE (add_ip6 == 1))
862 /* Create room for variable-length fields in the INIT_ACK chunk */
863 alloc_bytes += SCTP_IPV6_ADDRESS_TYPE_LENGTH;
866 if (sctp_conn->sub_conn[idx].connection.is_ip4)
867 alloc_bytes += sizeof (sctp_ipv4_addr_param_t);
869 alloc_bytes += sizeof (sctp_ipv6_addr_param_t);
871 /* As per RFC 4960 the chunk_length value does NOT contemplate
872 * the size of the first header (see sctp_header_t) and any padding
874 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
876 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
878 sctp_init_ack_chunk_t *init_ack_chunk =
879 vlib_buffer_push_uninit (b, alloc_bytes);
881 u16 pointer_offset = sizeof (sctp_init_ack_chunk_t);
883 /* Create State Cookie parameter */
884 sctp_state_cookie_param_t *state_cookie_param =
885 (sctp_state_cookie_param_t *) ((char *) init_ack_chunk + pointer_offset);
887 state_cookie_param->param_hdr.type =
888 clib_host_to_net_u16 (SCTP_STATE_COOKIE_TYPE);
889 state_cookie_param->param_hdr.length =
890 clib_host_to_net_u16 (sizeof (sctp_state_cookie_param_t));
891 state_cookie_param->creation_time = clib_host_to_net_u64 (sctp_time_now ());
892 state_cookie_param->cookie_lifespan =
893 clib_host_to_net_u32 (SCTP_VALID_COOKIE_LIFE);
895 sctp_compute_mac (sctp_conn, state_cookie_param);
897 pointer_offset += sizeof (sctp_state_cookie_param_t);
899 if (PREDICT_TRUE (ip4_addr != NULL))
901 sctp_ipv4_addr_param_t *ipv4_addr =
902 (sctp_ipv4_addr_param_t *) init_ack_chunk + pointer_offset;
904 ipv4_addr->param_hdr.type =
905 clib_host_to_net_u16 (SCTP_IPV4_ADDRESS_TYPE);
906 ipv4_addr->param_hdr.length =
907 clib_host_to_net_u16 (SCTP_IPV4_ADDRESS_TYPE_LENGTH);
908 ipv4_addr->address.as_u32 = ip4_addr->as_u32;
910 pointer_offset += SCTP_IPV4_ADDRESS_TYPE_LENGTH;
912 if (PREDICT_TRUE (ip6_addr != NULL))
914 sctp_ipv6_addr_param_t *ipv6_addr =
915 (sctp_ipv6_addr_param_t *) init_ack_chunk + pointer_offset;
917 ipv6_addr->param_hdr.type =
918 clib_host_to_net_u16 (SCTP_IPV6_ADDRESS_TYPE);
919 ipv6_addr->param_hdr.length =
920 clib_host_to_net_u16 (SCTP_IPV6_ADDRESS_TYPE_LENGTH);
921 ipv6_addr->address.as_u64[0] = ip6_addr->as_u64[0];
922 ipv6_addr->address.as_u64[1] = ip6_addr->as_u64[1];
924 pointer_offset += SCTP_IPV6_ADDRESS_TYPE_LENGTH;
927 if (sctp_conn->sub_conn[idx].connection.is_ip4)
929 ip4_param = (sctp_ipv4_addr_param_t *) init_ack_chunk + pointer_offset;
930 ip4_param->address.as_u32 =
931 sctp_conn->sub_conn[idx].connection.lcl_ip.ip4.as_u32;
933 pointer_offset += sizeof (sctp_ipv4_addr_param_t);
937 ip6_param = (sctp_ipv6_addr_param_t *) init_ack_chunk + pointer_offset;
938 ip6_param->address.as_u64[0] =
939 sctp_conn->sub_conn[idx].connection.lcl_ip.ip6.as_u64[0];
940 ip6_param->address.as_u64[1] =
941 sctp_conn->sub_conn[idx].connection.lcl_ip.ip6.as_u64[1];
943 pointer_offset += sizeof (sctp_ipv6_addr_param_t);
946 /* src_port & dst_port are already in network byte-order */
947 init_ack_chunk->sctp_hdr.checksum = 0;
948 init_ack_chunk->sctp_hdr.src_port =
949 sctp_conn->sub_conn[idx].connection.lcl_port;
950 init_ack_chunk->sctp_hdr.dst_port =
951 sctp_conn->sub_conn[idx].connection.rmt_port;
952 /* the sctp_conn->verification_tag is already in network byte-order (being a copy of the init_tag coming with the INIT chunk) */
953 init_ack_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
954 init_ack_chunk->initial_tsn =
955 clib_host_to_net_u32 (sctp_conn->local_initial_tsn);
956 SCTP_CONN_TRACKING_DBG ("init_ack_chunk->initial_tsn = %u",
957 init_ack_chunk->initial_tsn);
959 vnet_sctp_set_chunk_type (&init_ack_chunk->chunk_hdr, INIT_ACK);
960 vnet_sctp_set_chunk_length (&init_ack_chunk->chunk_hdr, chunk_len);
962 init_ack_chunk->initiate_tag =
963 clib_host_to_net_u32 (random_u32 (&random_seed));
965 init_ack_chunk->a_rwnd =
966 clib_host_to_net_u32 (sctp_conn->sub_conn[idx].cwnd);
967 init_ack_chunk->inboud_streams_count =
968 clib_host_to_net_u16 (INBOUND_STREAMS_COUNT);
969 init_ack_chunk->outbound_streams_count =
970 clib_host_to_net_u16 (OUTBOUND_STREAMS_COUNT);
972 sctp_conn->local_tag = init_ack_chunk->initiate_tag;
974 vnet_buffer (b)->sctp.connection_index =
975 sctp_conn->sub_conn[idx].connection.c_index;
976 vnet_buffer (b)->sctp.subconn_idx = idx;
980 * Convert buffer to SHUTDOWN
983 sctp_prepare_shutdown_chunk (sctp_connection_t * sctp_conn, u8 idx,
986 u16 alloc_bytes = sizeof (sctp_shutdown_association_chunk_t);
988 /* As per RFC 4960 the chunk_length value does NOT contemplate
989 * the size of the first header (see sctp_header_t) and any padding
991 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
993 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
995 sctp_shutdown_association_chunk_t *shutdown_chunk =
996 vlib_buffer_push_uninit (b, alloc_bytes);
998 shutdown_chunk->sctp_hdr.checksum = 0;
999 /* No need of host_to_net conversion, already in net-byte order */
1000 shutdown_chunk->sctp_hdr.src_port =
1001 sctp_conn->sub_conn[idx].connection.lcl_port;
1002 shutdown_chunk->sctp_hdr.dst_port =
1003 sctp_conn->sub_conn[idx].connection.rmt_port;
1004 shutdown_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1005 vnet_sctp_set_chunk_type (&shutdown_chunk->chunk_hdr, SHUTDOWN);
1006 vnet_sctp_set_chunk_length (&shutdown_chunk->chunk_hdr, chunk_len);
1008 shutdown_chunk->cumulative_tsn_ack = sctp_conn->last_rcvd_tsn;
1010 vnet_buffer (b)->sctp.connection_index =
1011 sctp_conn->sub_conn[idx].connection.c_index;
1012 vnet_buffer (b)->sctp.subconn_idx = idx;
1019 sctp_send_shutdown (sctp_connection_t * sctp_conn)
1023 sctp_main_t *tm = vnet_get_sctp_main ();
1024 vlib_main_t *vm = vlib_get_main ();
1026 if (sctp_check_outstanding_data_chunks (sctp_conn) > 0)
1029 if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
1032 u8 idx = SCTP_PRIMARY_PATH_IDX;
1034 b = vlib_get_buffer (vm, bi);
1035 sctp_init_buffer (vm, b);
1036 sctp_prepare_shutdown_chunk (sctp_conn, idx, b);
1038 sctp_enqueue_to_output_now (vm, b, bi,
1039 sctp_conn->sub_conn[idx].connection.is_ip4);
1043 * Convert buffer to SHUTDOWN_ACK
1046 sctp_prepare_shutdown_ack_chunk (sctp_connection_t * sctp_conn, u8 idx,
1049 u16 alloc_bytes = sizeof (sctp_shutdown_association_chunk_t);
1050 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1052 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1054 sctp_shutdown_ack_chunk_t *shutdown_ack_chunk =
1055 vlib_buffer_push_uninit (b, alloc_bytes);
1057 shutdown_ack_chunk->sctp_hdr.checksum = 0;
1058 /* No need of host_to_net conversion, already in net-byte order */
1059 shutdown_ack_chunk->sctp_hdr.src_port =
1060 sctp_conn->sub_conn[idx].connection.lcl_port;
1061 shutdown_ack_chunk->sctp_hdr.dst_port =
1062 sctp_conn->sub_conn[idx].connection.rmt_port;
1063 shutdown_ack_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1065 vnet_sctp_set_chunk_type (&shutdown_ack_chunk->chunk_hdr, SHUTDOWN_ACK);
1066 vnet_sctp_set_chunk_length (&shutdown_ack_chunk->chunk_hdr, chunk_len);
1068 vnet_buffer (b)->sctp.connection_index =
1069 sctp_conn->sub_conn[idx].connection.c_index;
1070 vnet_buffer (b)->sctp.subconn_idx = idx;
1077 sctp_send_shutdown_ack (sctp_connection_t * sctp_conn, u8 idx,
1080 vlib_main_t *vm = vlib_get_main ();
1082 if (sctp_check_outstanding_data_chunks (sctp_conn) > 0)
1085 sctp_reuse_buffer (vm, b);
1087 sctp_prepare_shutdown_ack_chunk (sctp_conn, idx, b);
1091 * Convert buffer to SACK
1094 sctp_prepare_sack_chunk (sctp_connection_t * sctp_conn, u8 idx,
1097 vlib_main_t *vm = vlib_get_main ();
1099 sctp_reuse_buffer (vm, b);
1101 u16 alloc_bytes = sizeof (sctp_selective_ack_chunk_t);
1103 /* As per RFC 4960 the chunk_length value does NOT contemplate
1104 * the size of the first header (see sctp_header_t) and any padding
1106 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1108 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1110 sctp_selective_ack_chunk_t *sack = vlib_buffer_push_uninit (b, alloc_bytes);
1112 sack->sctp_hdr.checksum = 0;
1113 sack->sctp_hdr.src_port = sctp_conn->sub_conn[idx].connection.lcl_port;
1114 sack->sctp_hdr.dst_port = sctp_conn->sub_conn[idx].connection.rmt_port;
1115 sack->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1116 vnet_sctp_set_chunk_type (&sack->chunk_hdr, SACK);
1117 vnet_sctp_set_chunk_length (&sack->chunk_hdr, chunk_len);
1119 sack->cumulative_tsn_ack = sctp_conn->next_tsn_expected;
1121 sctp_conn->ack_state = 0;
1123 vnet_buffer (b)->sctp.connection_index =
1124 sctp_conn->sub_conn[idx].connection.c_index;
1125 vnet_buffer (b)->sctp.subconn_idx = idx;
1129 * Convert buffer to HEARTBEAT_ACK
1132 sctp_prepare_heartbeat_ack_chunk (sctp_connection_t * sctp_conn, u8 idx,
1135 vlib_main_t *vm = vlib_get_main ();
1137 u16 alloc_bytes = sizeof (sctp_hb_ack_chunk_t);
1139 sctp_reuse_buffer (vm, b);
1141 /* As per RFC 4960 the chunk_length value does NOT contemplate
1142 * the size of the first header (see sctp_header_t) and any padding
1144 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1146 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1148 sctp_hb_ack_chunk_t *hb_ack = vlib_buffer_push_uninit (b, alloc_bytes);
1150 hb_ack->sctp_hdr.checksum = 0;
1151 /* No need of host_to_net conversion, already in net-byte order */
1152 hb_ack->sctp_hdr.src_port = sctp_conn->sub_conn[idx].connection.lcl_port;
1153 hb_ack->sctp_hdr.dst_port = sctp_conn->sub_conn[idx].connection.rmt_port;
1154 hb_ack->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1155 hb_ack->hb_info.param_hdr.type = clib_host_to_net_u16 (1);
1156 hb_ack->hb_info.param_hdr.length =
1157 clib_host_to_net_u16 (sizeof (hb_ack->hb_info.hb_info));
1159 vnet_sctp_set_chunk_type (&hb_ack->chunk_hdr, HEARTBEAT_ACK);
1160 vnet_sctp_set_chunk_length (&hb_ack->chunk_hdr, chunk_len);
1162 vnet_buffer (b)->sctp.connection_index =
1163 sctp_conn->sub_conn[idx].connection.c_index;
1164 vnet_buffer (b)->sctp.subconn_idx = idx;
1168 * Convert buffer to HEARTBEAT
1171 sctp_prepare_heartbeat_chunk (sctp_connection_t * sctp_conn, u8 idx,
1174 u16 alloc_bytes = sizeof (sctp_hb_req_chunk_t);
1176 /* As per RFC 4960 the chunk_length value does NOT contemplate
1177 * the size of the first header (see sctp_header_t) and any padding
1179 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1181 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1183 sctp_hb_req_chunk_t *hb_req = vlib_buffer_push_uninit (b, alloc_bytes);
1185 hb_req->sctp_hdr.checksum = 0;
1186 /* No need of host_to_net conversion, already in net-byte order */
1187 hb_req->sctp_hdr.src_port = sctp_conn->sub_conn[idx].connection.lcl_port;
1188 hb_req->sctp_hdr.dst_port = sctp_conn->sub_conn[idx].connection.rmt_port;
1189 hb_req->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1190 hb_req->hb_info.param_hdr.type = clib_host_to_net_u16 (1);
1191 hb_req->hb_info.param_hdr.length =
1192 clib_host_to_net_u16 (sizeof (hb_req->hb_info.hb_info));
1194 vnet_sctp_set_chunk_type (&hb_req->chunk_hdr, HEARTBEAT);
1195 vnet_sctp_set_chunk_length (&hb_req->chunk_hdr, chunk_len);
1197 vnet_buffer (b)->sctp.connection_index =
1198 sctp_conn->sub_conn[idx].connection.c_index;
1199 vnet_buffer (b)->sctp.subconn_idx = idx;
1203 sctp_send_heartbeat (sctp_connection_t * sctp_conn)
1207 sctp_main_t *tm = vnet_get_sctp_main ();
1208 vlib_main_t *vm = vlib_get_main ();
1211 u64 now = sctp_time_now ();
1213 for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
1215 if (sctp_conn->sub_conn[i].state == SCTP_SUBCONN_STATE_DOWN)
1218 if (now > (sctp_conn->sub_conn[i].last_seen + SCTP_HB_INTERVAL))
1220 if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
1223 b = vlib_get_buffer (vm, bi);
1224 sctp_init_buffer (vm, b);
1225 sctp_prepare_heartbeat_chunk (sctp_conn, i, b);
1227 sctp_enqueue_to_output_now (vm, b, bi,
1228 sctp_conn->sub_conn[i].
1231 sctp_conn->sub_conn[i].unacknowledged_hb += 1;
1237 * Convert buffer to SHUTDOWN_COMPLETE
1240 sctp_prepare_shutdown_complete_chunk (sctp_connection_t * sctp_conn, u8 idx,
1243 u16 alloc_bytes = sizeof (sctp_shutdown_association_chunk_t);
1244 alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1246 u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1248 sctp_shutdown_complete_chunk_t *shutdown_complete =
1249 vlib_buffer_push_uninit (b, alloc_bytes);
1251 shutdown_complete->sctp_hdr.checksum = 0;
1252 /* No need of host_to_net conversion, already in net-byte order */
1253 shutdown_complete->sctp_hdr.src_port =
1254 sctp_conn->sub_conn[idx].connection.lcl_port;
1255 shutdown_complete->sctp_hdr.dst_port =
1256 sctp_conn->sub_conn[idx].connection.rmt_port;
1257 shutdown_complete->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1259 vnet_sctp_set_chunk_type (&shutdown_complete->chunk_hdr, SHUTDOWN_COMPLETE);
1260 vnet_sctp_set_chunk_length (&shutdown_complete->chunk_hdr, chunk_len);
1262 vnet_buffer (b)->sctp.connection_index =
1263 sctp_conn->sub_conn[idx].connection.c_index;
1264 vnet_buffer (b)->sctp.subconn_idx = idx;
1268 sctp_send_shutdown_complete (sctp_connection_t * sctp_conn, u8 idx,
1271 vlib_main_t *vm = vlib_get_main ();
1273 if (sctp_check_outstanding_data_chunks (sctp_conn) > 0)
1276 sctp_reuse_buffer (vm, b0);
1278 sctp_prepare_shutdown_complete_chunk (sctp_conn, idx, b0);
1285 sctp_send_init (sctp_connection_t * sctp_conn)
1289 sctp_main_t *tm = vnet_get_sctp_main ();
1290 vlib_main_t *vm = vlib_get_main ();
1292 if (PREDICT_FALSE (sctp_conn->init_retransmit_err > SCTP_MAX_INIT_RETRANS))
1294 clib_warning ("Reached MAX_INIT_RETRANS times. Aborting connection.");
1296 session_stream_connect_notify (&sctp_conn->sub_conn
1297 [SCTP_PRIMARY_PATH_IDX].connection, 1);
1299 sctp_connection_timers_reset (sctp_conn);
1301 sctp_connection_cleanup (sctp_conn);
1306 if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
1309 b = vlib_get_buffer (vm, bi);
1310 u8 idx = SCTP_PRIMARY_PATH_IDX;
1312 sctp_init_buffer (vm, b);
1313 sctp_prepare_init_chunk (sctp_conn, idx, b);
1315 sctp_push_ip_hdr (tm, &sctp_conn->sub_conn[idx], b);
1316 sctp_enqueue_to_ip_lookup (vm, b, bi, sctp_conn->sub_conn[idx].c_is_ip4,
1317 sctp_conn->sub_conn[idx].c_fib_index);
1319 /* Start the T1_INIT timer */
1320 sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T1_INIT,
1321 sctp_conn->sub_conn[idx].RTO);
1323 /* Change state to COOKIE_WAIT */
1324 sctp_conn->state = SCTP_STATE_COOKIE_WAIT;
1326 /* Measure RTT with this */
1327 sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now ();
1331 * Push SCTP header and update connection variables
1334 sctp_push_hdr_i (sctp_connection_t * sctp_conn, vlib_buffer_t * b,
1335 sctp_state_t next_state)
1337 u16 data_len = b->current_length;
1339 if (b->flags & VLIB_BUFFER_TOTAL_LENGTH_VALID)
1340 data_len += b->total_length_not_including_first_buffer;
1342 ASSERT (!b->total_length_not_including_first_buffer
1343 || (b->flags & VLIB_BUFFER_NEXT_PRESENT));
1345 SCTP_ADV_DBG_OUTPUT ("b->current_length = %u, "
1346 "b->current_data = %p "
1348 b->current_length, b->current_data, data_len);
1350 u16 data_padding = vnet_sctp_calculate_padding (b->current_length);
1351 if (data_padding > 0)
1353 u8 *p_tail = vlib_buffer_put_uninit (b, data_padding);
1354 clib_memset_u8 (p_tail, 0, data_padding);
1357 u16 bytes_to_add = sizeof (sctp_payload_data_chunk_t);
1358 u16 chunk_length = data_len + bytes_to_add - sizeof (sctp_header_t);
1360 sctp_payload_data_chunk_t *data_chunk =
1361 vlib_buffer_push_uninit (b, bytes_to_add);
1363 u8 idx = sctp_data_subconn_select (sctp_conn);
1365 ("SCTP_CONN = %p, IDX = %u, S_INDEX = %u, C_INDEX = %u, sctp_conn->[...].LCL_PORT = %u, sctp_conn->[...].RMT_PORT = %u",
1366 sctp_conn, idx, sctp_conn->sub_conn[idx].connection.s_index,
1367 sctp_conn->sub_conn[idx].connection.c_index,
1368 sctp_conn->sub_conn[idx].connection.lcl_port,
1369 sctp_conn->sub_conn[idx].connection.rmt_port);
1370 data_chunk->sctp_hdr.checksum = 0;
1371 data_chunk->sctp_hdr.src_port =
1372 sctp_conn->sub_conn[idx].connection.lcl_port;
1373 data_chunk->sctp_hdr.dst_port =
1374 sctp_conn->sub_conn[idx].connection.rmt_port;
1375 data_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1377 data_chunk->tsn = clib_host_to_net_u32 (sctp_conn->next_tsn);
1378 data_chunk->stream_id = clib_host_to_net_u16 (0);
1379 data_chunk->stream_seq = clib_host_to_net_u16 (0);
1381 vnet_sctp_set_chunk_type (&data_chunk->chunk_hdr, DATA);
1382 vnet_sctp_set_chunk_length (&data_chunk->chunk_hdr, chunk_length);
1384 vnet_sctp_set_bbit (&data_chunk->chunk_hdr);
1385 vnet_sctp_set_ebit (&data_chunk->chunk_hdr);
1387 SCTP_ADV_DBG_OUTPUT ("POINTER_WITH_DATA = %p, DATA_OFFSET = %u",
1388 b->data, b->current_data);
1390 if (sctp_conn->sub_conn[idx].state != SCTP_SUBCONN_AWAITING_SACK)
1392 sctp_conn->sub_conn[idx].state = SCTP_SUBCONN_AWAITING_SACK;
1393 sctp_conn->last_unacked_tsn = sctp_conn->next_tsn;
1396 sctp_conn->next_tsn += data_len;
1398 u32 inflight = sctp_conn->next_tsn - sctp_conn->last_unacked_tsn;
1399 /* Section 7.2.2; point (3) */
1400 if (sctp_conn->sub_conn[idx].partially_acked_bytes >=
1401 sctp_conn->sub_conn[idx].cwnd
1402 && inflight >= sctp_conn->sub_conn[idx].cwnd)
1404 sctp_conn->sub_conn[idx].cwnd += sctp_conn->sub_conn[idx].PMTU;
1405 sctp_conn->sub_conn[idx].partially_acked_bytes -=
1406 sctp_conn->sub_conn[idx].cwnd;
1409 sctp_conn->sub_conn[idx].last_data_ts = sctp_time_now ();
1411 vnet_buffer (b)->sctp.connection_index =
1412 sctp_conn->sub_conn[idx].connection.c_index;
1414 vnet_buffer (b)->sctp.subconn_idx = idx;
1418 sctp_push_header (transport_connection_t * trans_conn, vlib_buffer_t * b)
1420 sctp_connection_t *sctp_conn =
1421 sctp_get_connection_from_transport (trans_conn);
1423 SCTP_DBG_OUTPUT ("TRANS_CONN = %p, SCTP_CONN = %p, "
1424 "S_INDEX = %u, C_INDEX = %u,"
1425 "trans_conn->LCL_PORT = %u, trans_conn->RMT_PORT = %u",
1428 trans_conn->s_index,
1429 trans_conn->c_index,
1430 trans_conn->lcl_port, trans_conn->rmt_port);
1432 sctp_push_hdr_i (sctp_conn, b, SCTP_STATE_ESTABLISHED);
1434 sctp_trajectory_add_start (b, 3);
1440 sctp_prepare_data_retransmit (sctp_connection_t * sctp_conn,
1443 u32 max_deq_bytes, vlib_buffer_t ** b)
1445 sctp_main_t *tm = vnet_get_sctp_main ();
1446 vlib_main_t *vm = vlib_get_main ();
1448 u32 bi, available_bytes, seg_size;
1451 ASSERT (sctp_conn->state >= SCTP_STATE_ESTABLISHED);
1452 ASSERT (max_deq_bytes != 0);
1455 * Make sure we can retransmit something
1458 transport_max_tx_dequeue (&sctp_conn->sub_conn[idx].connection);
1459 ASSERT (available_bytes >= offset);
1460 available_bytes -= offset;
1461 if (!available_bytes)
1463 max_deq_bytes = clib_min (sctp_conn->sub_conn[idx].cwnd, max_deq_bytes);
1464 max_deq_bytes = clib_min (available_bytes, max_deq_bytes);
1466 seg_size = max_deq_bytes;
1469 * Allocate and fill in buffer(s)
1472 if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
1474 *b = vlib_get_buffer (vm, bi);
1475 data = sctp_init_buffer (vm, *b);
1477 /* Easy case, buffer size greater than mss */
1478 if (PREDICT_TRUE (seg_size <= tm->bytes_per_buffer))
1481 session_tx_fifo_peek_bytes (&sctp_conn->sub_conn[idx].connection,
1482 data, offset, max_deq_bytes);
1483 ASSERT (n_bytes == max_deq_bytes);
1484 b[0]->current_length = n_bytes;
1485 sctp_push_hdr_i (sctp_conn, *b, sctp_conn->state);
1492 sctp_data_retransmit (sctp_connection_t * sctp_conn)
1494 vlib_main_t *vm = vlib_get_main ();
1495 vlib_buffer_t *b = 0;
1496 u32 bi, n_bytes = 0;
1498 u8 idx = sctp_data_subconn_select (sctp_conn);
1501 ("SCTP_CONN = %p, IDX = %u, S_INDEX = %u, C_INDEX = %u, sctp_conn->[...].LCL_PORT = %u, sctp_conn->[...].RMT_PORT = %u",
1502 sctp_conn, idx, sctp_conn->sub_conn[idx].connection.s_index,
1503 sctp_conn->sub_conn[idx].connection.c_index,
1504 sctp_conn->sub_conn[idx].connection.lcl_port,
1505 sctp_conn->sub_conn[idx].connection.rmt_port);
1507 if (sctp_conn->state >= SCTP_STATE_ESTABLISHED)
1513 sctp_prepare_data_retransmit (sctp_conn, idx, 0,
1514 sctp_conn->sub_conn[idx].cwnd, &b);
1516 SCTP_DBG_OUTPUT ("We have data (%u bytes) to retransmit", n_bytes);
1518 bi = vlib_get_buffer_index (vm, b);
1520 sctp_enqueue_to_output_now (vm, b, bi,
1521 sctp_conn->sub_conn[idx].connection.is_ip4);
1526 #if SCTP_DEBUG_STATE_MACHINE
1528 sctp_validate_output_state_machine (sctp_connection_t * sctp_conn,
1532 switch (sctp_conn->state)
1534 case SCTP_STATE_CLOSED:
1535 if (chunk_type != INIT && chunk_type != INIT_ACK)
1538 case SCTP_STATE_ESTABLISHED:
1539 if (chunk_type != DATA && chunk_type != HEARTBEAT &&
1540 chunk_type != HEARTBEAT_ACK && chunk_type != SACK &&
1541 chunk_type != COOKIE_ACK && chunk_type != SHUTDOWN)
1544 case SCTP_STATE_COOKIE_WAIT:
1545 if (chunk_type != COOKIE_ECHO)
1548 case SCTP_STATE_SHUTDOWN_SENT:
1549 if (chunk_type != SHUTDOWN_COMPLETE)
1552 case SCTP_STATE_SHUTDOWN_RECEIVED:
1553 if (chunk_type != SHUTDOWN_ACK)
1562 * fd.io coding-style-patch-verification: ON
1565 * eval: (c-set-style "gnu")