FD.io VPP  v19.08.3-2-gbabecb413
Vector Packet Processing
sctp_output.c
Go to the documentation of this file.
1 /*
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:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
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.
14  */
15 #include <sctp/sctp.h>
16 #include <sctp/sctp_debug.h>
17 #include <vppinfra/random.h>
18 #include <openssl/hmac.h>
19 
20 /**
21  * Flush tx frame populated by retransmits and timer pops
22  */
23 void
24 sctp_flush_frame_to_output (vlib_main_t * vm, u8 thread_index, u8 is_ip4)
25 {
26  if (sctp_main.tx_frames[!is_ip4][thread_index])
27  {
28  u32 next_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;
33  }
34 }
35 
36 /**
37  * Flush ip lookup tx frames populated by timer pops
38  */
39 always_inline void
41 {
42  if (sctp_main.ip_lookup_tx_frames[!is_ip4][thread_index])
43  {
44  u32 next_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]
48  [thread_index]);
49  sctp_main.ip_lookup_tx_frames[!is_ip4][thread_index] = 0;
50  }
51 }
52 
53 /**
54  * Flush v4 and v6 sctp and ip-lookup tx frames for thread index
55  */
56 void
58 {
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);
64 }
65 
66 u32
68  ip4_header_t * ip0)
69 {
70  ip_csum_t checksum;
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;
74 
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;
79  checksum =
80  clib_host_to_net_u32 (payload_length_host_byte_order +
81  (ip0->protocol << 16));
82 
83  if (BITS (uword) == 32)
84  {
85  checksum =
86  ip_csum_with_carry (checksum,
88  checksum =
89  ip_csum_with_carry (checksum,
91  }
92  else
93  checksum =
94  ip_csum_with_carry (checksum,
96 
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)
102  {
103  n_this_buffer = n_ip_bytes_this_buffer > ip_header_length ?
104  n_ip_bytes_this_buffer - ip_header_length : 0;
105  }
106  while (1)
107  {
108  checksum =
109  ip_incremental_checksum (checksum, data_this_buffer, n_this_buffer);
110  n_bytes_left -= n_this_buffer;
111  if (n_bytes_left == 0)
112  break;
113 
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;
118  }
119 
120  return checksum;
121 }
122 
123 u32
125  ip6_header_t * ip0, int *bogus_lengthp)
126 {
127  ip_csum_t checksum;
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;
132 
133  ASSERT (bogus_lengthp);
134  *bogus_lengthp = 0;
135 
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);
140 
141  for (i = 0; i < ARRAY_LEN (ip0->src_address.as_uword); i++)
142  {
143  checksum = ip_csum_with_carry (checksum,
144  clib_mem_unaligned (&ip0->
145  src_address.as_uword
146  [i], uword));
147  checksum =
148  ip_csum_with_carry (checksum,
150  uword));
151  }
152 
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))
156  {
157  u32 skip_bytes;
158  ip6_hop_by_hop_ext_t *ext_hdr =
159  (ip6_hop_by_hop_ext_t *) data_this_buffer;
160 
161  /* validate really icmp6 next */
162  ASSERT ((ext_hdr->next_hdr == IP_PROTOCOL_SCTP));
163 
164  skip_bytes = 8 * (1 + ext_hdr->n_data_u64s);
165  data_this_buffer = (void *) ((u8 *) data_this_buffer + skip_bytes);
166 
167  payload_length_host_byte_order -= skip_bytes;
168  headers_size += skip_bytes;
169  }
170 
171  n_bytes_left = n_this_buffer = payload_length_host_byte_order;
172  if (p0 && n_this_buffer + headers_size > p0->current_length)
173  n_this_buffer =
174  p0->current_length >
175  headers_size ? p0->current_length - headers_size : 0;
176  while (1)
177  {
178  checksum =
179  ip_incremental_checksum (checksum, data_this_buffer, n_this_buffer);
180  n_bytes_left -= n_this_buffer;
181  if (n_bytes_left == 0)
182  break;
183 
184  if (!(p0->flags & VLIB_BUFFER_NEXT_PRESENT))
185  {
186  *bogus_lengthp = 1;
187  return 0xfefe;
188  }
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;
192  }
193 
194  return checksum;
195 }
196 
197 void
199  vlib_buffer_t * b)
200 {
203  if (sctp_sub_conn->c_is_ip4)
204  {
205  ip4_header_t *ih;
206  ih = vlib_buffer_push_ip4 (vm, b, &sctp_sub_conn->c_lcl_ip4,
207  &sctp_sub_conn->c_rmt_ip4, IP_PROTOCOL_SCTP,
208  1);
209  th->checksum = ip4_sctp_compute_checksum (vm, b, ih);
210  }
211  else
212  {
213  ip6_header_t *ih;
214  int bogus = ~0;
215 
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);
219  ASSERT (!bogus);
220  }
221 }
222 
223 always_inline void *
225 {
226  if (b->flags & VLIB_BUFFER_NEXT_PRESENT)
228  /* Zero all flags but free list index and trace flag */
229  b->flags &= VLIB_BUFFER_NEXT_PRESENT - 1;
230  b->current_data = 0;
231  b->current_length = 0;
233  sctp_buffer_opaque (b)->sctp.flags = 0;
234  sctp_buffer_opaque (b)->sctp.subconn_idx = MAX_SCTP_CONNECTIONS;
235 
236  /* Leave enough space for headers */
238 }
239 
240 always_inline void *
242 {
243  ASSERT ((b->flags & VLIB_BUFFER_NEXT_PRESENT) == 0);
244  b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
246  sctp_buffer_opaque (b)->sctp.flags = 0;
247  sctp_buffer_opaque (b)->sctp.subconn_idx = MAX_SCTP_CONNECTIONS;
249  /* Leave enough space for headers */
251 }
252 
253 always_inline int
254 sctp_alloc_tx_buffers (sctp_main_t * tm, u8 thread_index, u32 n_free_buffers)
255 {
257  u32 current_length = vec_len (tm->tx_buffers[thread_index]);
258  u32 n_allocated;
259 
260  vec_validate (tm->tx_buffers[thread_index],
261  current_length + n_free_buffers - 1);
262  n_allocated =
263  vlib_buffer_alloc (vm, &tm->tx_buffers[thread_index][current_length],
264  n_free_buffers);
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)
268  {
269  clib_warning ("out of buffers");
270  return -1;
271  }
272  return 0;
273 }
274 
275 always_inline int
277 {
278  u32 *my_tx_buffers;
279  u32 thread_index = vlib_get_thread_index ();
280  if (PREDICT_FALSE (vec_len (tm->tx_buffers[thread_index]) == 0))
281  {
282  if (sctp_alloc_tx_buffers (tm, thread_index, VLIB_FRAME_SIZE))
283  return -1;
284  }
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;
288  return 0;
289 }
290 
291 always_inline void
293  u8 is_ip4, u8 flush)
294 {
296  u32 thread_index = vlib_get_thread_index ();
297  u32 *to_next, next_index;
298  vlib_frame_t *f;
299 
300  b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
301  b->error = 0;
302 
303  /* Decide where to send the packet */
304  next_index = is_ip4 ? sctp4_output_node.index : sctp6_output_node.index;
306 
307  /* Get frame to v4/6 output node */
308  f = tm->tx_frames[!is_ip4][thread_index];
309  if (!f)
310  {
311  f = vlib_get_frame_to_node (vm, next_index);
312  ASSERT (f);
313  tm->tx_frames[!is_ip4][thread_index] = f;
314  }
315  to_next = vlib_frame_vector_args (f);
316  to_next[f->n_vectors] = bi;
317  f->n_vectors += 1;
318  if (flush || f->n_vectors == VLIB_FRAME_SIZE)
319  {
320  vlib_put_frame_to_node (vm, next_index, f);
321  tm->tx_frames[!is_ip4][thread_index] = 0;
322  }
323 }
324 
325 always_inline void
327  u8 is_ip4)
328 {
329  sctp_enqueue_to_output_i (vm, b, bi, is_ip4, 1);
330 }
331 
332 always_inline void
334  u8 is_ip4, u32 fib_index, u8 flush)
335 {
337  u32 thread_index = vlib_get_thread_index ();
338  u32 *to_next, next_index;
339  vlib_frame_t *f;
340 
341  b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
342  b->error = 0;
343 
344  vnet_buffer (b)->sw_if_index[VLIB_TX] = fib_index;
345  vnet_buffer (b)->sw_if_index[VLIB_RX] = 0;
346 
347  /* Send to IP lookup */
348  next_index = is_ip4 ? ip4_lookup_node.index : ip6_lookup_node.index;
350  {
351  b->pre_data[0] = 2;
352  b->pre_data[1] = next_index;
353  }
354 
355  f = tm->ip_lookup_tx_frames[!is_ip4][thread_index];
356  if (!f)
357  {
358  f = vlib_get_frame_to_node (vm, next_index);
359  ASSERT (f);
360  tm->ip_lookup_tx_frames[!is_ip4][thread_index] = f;
361  }
362 
363  to_next = vlib_frame_vector_args (f);
364  to_next[f->n_vectors] = bi;
365  f->n_vectors += 1;
366  if (flush || f->n_vectors == VLIB_FRAME_SIZE)
367  {
368  vlib_put_frame_to_node (vm, next_index, f);
369  tm->ip_lookup_tx_frames[!is_ip4][thread_index] = 0;
370  }
371 }
372 
373 always_inline void
375  u8 is_ip4, u32 fib_index)
376 {
377  sctp_enqueue_to_ip_lookup_i (vm, b, bi, is_ip4, fib_index, 0);
378  if (vm->thread_index == 0 && vlib_num_workers ())
380 }
381 
382 /**
383  * Convert buffer to INIT
384  */
385 void
387  vlib_buffer_t * b)
388 {
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];
392 
393  sctp_ipv4_addr_param_t *ip4_param = 0;
394  sctp_ipv6_addr_param_t *ip6_param = 0;
395 
396  if (sub_conn->c_is_ip4)
397  alloc_bytes += sizeof (sctp_ipv4_addr_param_t);
398  else
399  alloc_bytes += sizeof (sctp_ipv6_addr_param_t);
400 
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
403  */
404  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
405 
406  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
407 
408  sctp_init_chunk_t *init_chunk = vlib_buffer_push_uninit (b, alloc_bytes);
409 
410  u16 pointer_offset = sizeof (init_chunk);
411  if (sub_conn->c_is_ip4)
412  {
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;
415 
416  pointer_offset += sizeof (sctp_ipv4_addr_param_t);
417  }
418  else
419  {
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];
423 
424  pointer_offset += sizeof (sctp_ipv6_addr_param_t);
425  }
426 
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;
432 
433  vnet_sctp_set_chunk_type (&init_chunk->chunk_hdr, INIT);
434  vnet_sctp_set_chunk_length (&init_chunk->chunk_hdr, chunk_len);
436 
437  sctp_init_cwnd (sctp_conn);
438 
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);
445 
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);
450 
451  sctp_conn->local_tag = init_chunk->initiate_tag;
452 
453  sctp_buffer_opaque (b)->sctp.connection_index = sub_conn->c_c_index;
454  sctp_buffer_opaque (b)->sctp.subconn_idx = idx;
455 
456  SCTP_DBG_STATE_MACHINE ("CONN_INDEX = %u, CURR_CONN_STATE = %u (%s), "
457  "CHUNK_TYPE = %s, "
458  "SRC_PORT = %u, DST_PORT = %u",
459  sub_conn->connection.c_index,
460  sctp_conn->state,
461  sctp_state_to_string (sctp_conn->state),
463  init_chunk->sctp_hdr.src_port,
464  init_chunk->sctp_hdr.dst_port);
465 }
466 
467 void
469  sctp_state_cookie_param_t * state_cookie)
470 {
471 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
472  HMAC_CTX *ctx;
473 #else
474  HMAC_CTX ctx;
475 #endif
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);
484 #else
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);
491 #endif
492 
493  ENDIANESS_SWAP (state_cookie->mac);
494 }
495 
496 void
498  vlib_buffer_t * b)
499 {
501 
502  sctp_reuse_buffer (vm, b);
503 
504  u16 alloc_bytes = sizeof (sctp_cookie_ack_chunk_t);
505 
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
508  */
509  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
510 
511  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
512 
513  sctp_cookie_ack_chunk_t *cookie_ack_chunk =
514  vlib_buffer_push_uninit (b, alloc_bytes);
515 
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);
524 
525  sctp_buffer_opaque (b)->sctp.connection_index =
526  sctp_conn->sub_conn[idx].connection.c_index;
527  sctp_buffer_opaque (b)->sctp.subconn_idx = idx;
528 }
529 
530 void
532  vlib_buffer_t * b, u8 reuse_buffer)
533 {
535 
536  if (reuse_buffer)
537  sctp_reuse_buffer (vm, b);
538 
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
543  */
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));
558 
559  sctp_buffer_opaque (b)->sctp.connection_index =
560  sctp_conn->sub_conn[idx].connection.c_index;
561  sctp_buffer_opaque (b)->sctp.subconn_idx = idx;
562 }
563 
564 
565 /*
566  * Send COOKIE_ECHO
567  */
568 void
570 {
571  vlib_buffer_t *b;
572  u32 bi;
575 
576  if (PREDICT_FALSE (sctp_conn->init_retransmit_err > SCTP_MAX_INIT_RETRANS))
577  {
578  clib_warning ("Reached MAX_INIT_RETRANS times. Aborting connection.");
579 
580  session_stream_connect_notify (&sctp_conn->sub_conn
581  [SCTP_PRIMARY_PATH_IDX].connection, 1);
582 
583  sctp_connection_timers_reset (sctp_conn);
584 
585  sctp_connection_cleanup (sctp_conn);
586  }
587 
589  return;
590 
591  b = vlib_get_buffer (vm, bi);
593 
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);
597 
598  /* Start the T1_INIT timer */
599  sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T1_INIT,
600  sctp_conn->sub_conn[idx].RTO);
601 
602  /* Change state to COOKIE_WAIT */
603  sctp_conn->state = SCTP_STATE_COOKIE_WAIT;
604 
605  /* Measure RTT with this */
606  sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now ();
607 }
608 
609 
610 /**
611  * Convert buffer to ERROR
612  */
613 void
615  vlib_buffer_t * b, u8 err_cause)
616 {
618 
619  sctp_reuse_buffer (vm, b);
620 
621  /* The minimum size of the message is given by the sctp_operation_error_t */
622  u16 alloc_bytes =
624 
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
627  */
628  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
629 
630  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
631 
632  sctp_operation_error_t *err_chunk =
633  vlib_buffer_push_uninit (b, alloc_bytes);
634 
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;
641 
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);
646 
648  vnet_sctp_set_chunk_length (&err_chunk->chunk_hdr, chunk_len);
649 
650  sctp_buffer_opaque (b)->sctp.connection_index =
651  sctp_conn->sub_conn[idx].connection.c_index;
652  sctp_buffer_opaque (b)->sctp.subconn_idx = idx;
653 }
654 
655 /**
656  * Convert buffer to ABORT
657  */
658 void
660  vlib_buffer_t * b, ip4_address_t * ip4_addr,
661  ip6_address_t * ip6_addr)
662 {
664 
665  sctp_reuse_buffer (vm, b);
666 
667  /* The minimum size of the message is given by the sctp_abort_chunk_t */
668  u16 alloc_bytes = sizeof (sctp_abort_chunk_t);
669 
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
672  */
673  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
674 
675  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
676 
677  sctp_abort_chunk_t *abort_chunk = vlib_buffer_push_uninit (b, alloc_bytes);
678 
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;
687 
688  vnet_sctp_set_chunk_type (&abort_chunk->chunk_hdr, ABORT);
689  vnet_sctp_set_chunk_length (&abort_chunk->chunk_hdr, chunk_len);
690 
691  sctp_buffer_opaque (b)->sctp.connection_index =
692  sctp_conn->sub_conn[idx].connection.c_index;
693  sctp_buffer_opaque (b)->sctp.subconn_idx = idx;
694 }
695 
696 /**
697  * Convert buffer to INIT-ACK
698  */
699 void
701  u8 idx, vlib_buffer_t * b,
702  ip4_address_t * ip4_addr,
703  ip6_address_t * ip6_addr)
704 {
706  sctp_ipv4_addr_param_t *ip4_param = 0;
707  sctp_ipv6_addr_param_t *ip6_param = 0;
708 
709  sctp_reuse_buffer (vm, b);
710 
711  /* The minimum size of the message is given by the sctp_init_ack_chunk_t */
712  u16 alloc_bytes =
714 
715  if (PREDICT_TRUE (ip4_addr != NULL))
716  {
717  /* Create room for variable-length fields in the INIT_ACK chunk */
718  alloc_bytes += SCTP_IPV4_ADDRESS_TYPE_LENGTH;
719  }
720  if (PREDICT_TRUE (ip6_addr != NULL))
721  {
722  /* Create room for variable-length fields in the INIT_ACK chunk */
723  alloc_bytes += SCTP_IPV6_ADDRESS_TYPE_LENGTH;
724  }
725 
726  if (sctp_conn->sub_conn[idx].connection.is_ip4)
727  alloc_bytes += sizeof (sctp_ipv4_addr_param_t);
728  else
729  alloc_bytes += sizeof (sctp_ipv6_addr_param_t);
730 
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
733  */
734  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
735 
736  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
737 
738  sctp_init_ack_chunk_t *init_ack_chunk =
739  vlib_buffer_push_uninit (b, alloc_bytes);
740 
741  u16 pointer_offset = sizeof (sctp_init_ack_chunk_t);
742 
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);
746 
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);
754 
755  sctp_compute_mac (sctp_conn, state_cookie_param);
756 
757  pointer_offset += sizeof (sctp_state_cookie_param_t);
758 
759  if (PREDICT_TRUE (ip4_addr != NULL))
760  {
761  sctp_ipv4_addr_param_t *ipv4_addr =
762  (sctp_ipv4_addr_param_t *) init_ack_chunk + pointer_offset;
763 
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;
769 
770  pointer_offset += SCTP_IPV4_ADDRESS_TYPE_LENGTH;
771  }
772  if (PREDICT_TRUE (ip6_addr != NULL))
773  {
774  sctp_ipv6_addr_param_t *ipv6_addr =
775  (sctp_ipv6_addr_param_t *) init_ack_chunk + pointer_offset;
776 
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];
783 
784  pointer_offset += SCTP_IPV6_ADDRESS_TYPE_LENGTH;
785  }
786 
787  if (sctp_conn->sub_conn[idx].connection.is_ip4)
788  {
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;
792 
793  pointer_offset += sizeof (sctp_ipv4_addr_param_t);
794  }
795  else
796  {
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];
802 
803  pointer_offset += sizeof (sctp_ipv6_addr_param_t);
804  }
805 
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);
818 
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);
821 
822  init_ack_chunk->initiate_tag = sctp_conn->local_tag;
823 
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);
830 
831  sctp_buffer_opaque (b)->sctp.connection_index =
832  sctp_conn->sub_conn[idx].connection.c_index;
833  sctp_buffer_opaque (b)->sctp.subconn_idx = idx;
834 }
835 
836 /**
837  * Convert buffer to INIT-ACK
838  */
839 void
841  vlib_buffer_t * b, ip4_address_t * ip4_addr,
842  u8 add_ip4, ip6_address_t * ip6_addr, u8 add_ip6)
843 {
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 ();
848 
849  sctp_reuse_buffer (vm, b);
850 
851  /* The minimum size of the message is given by the sctp_init_ack_chunk_t */
852  u16 alloc_bytes =
854 
855  if (PREDICT_FALSE (add_ip4 == 1))
856  {
857  /* Create room for variable-length fields in the INIT_ACK chunk */
858  alloc_bytes += SCTP_IPV4_ADDRESS_TYPE_LENGTH;
859  }
860  if (PREDICT_FALSE (add_ip6 == 1))
861  {
862  /* Create room for variable-length fields in the INIT_ACK chunk */
863  alloc_bytes += SCTP_IPV6_ADDRESS_TYPE_LENGTH;
864  }
865 
866  if (sctp_conn->sub_conn[idx].connection.is_ip4)
867  alloc_bytes += sizeof (sctp_ipv4_addr_param_t);
868  else
869  alloc_bytes += sizeof (sctp_ipv6_addr_param_t);
870 
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
873  */
874  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
875 
876  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
877 
878  sctp_init_ack_chunk_t *init_ack_chunk =
879  vlib_buffer_push_uninit (b, alloc_bytes);
880 
881  u16 pointer_offset = sizeof (sctp_init_ack_chunk_t);
882 
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);
886 
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);
894 
895  sctp_compute_mac (sctp_conn, state_cookie_param);
896 
897  pointer_offset += sizeof (sctp_state_cookie_param_t);
898 
899  if (PREDICT_TRUE (ip4_addr != NULL))
900  {
901  sctp_ipv4_addr_param_t *ipv4_addr =
902  (sctp_ipv4_addr_param_t *) init_ack_chunk + pointer_offset;
903 
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;
909 
910  pointer_offset += SCTP_IPV4_ADDRESS_TYPE_LENGTH;
911  }
912  if (PREDICT_TRUE (ip6_addr != NULL))
913  {
914  sctp_ipv6_addr_param_t *ipv6_addr =
915  (sctp_ipv6_addr_param_t *) init_ack_chunk + pointer_offset;
916 
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];
923 
924  pointer_offset += SCTP_IPV6_ADDRESS_TYPE_LENGTH;
925  }
926 
927  if (sctp_conn->sub_conn[idx].connection.is_ip4)
928  {
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;
932 
933  pointer_offset += sizeof (sctp_ipv4_addr_param_t);
934  }
935  else
936  {
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];
942 
943  pointer_offset += sizeof (sctp_ipv6_addr_param_t);
944  }
945 
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);
958 
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);
961 
962  init_ack_chunk->initiate_tag =
963  clib_host_to_net_u32 (random_u32 (&random_seed));
964 
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);
971 
972  sctp_conn->local_tag = init_ack_chunk->initiate_tag;
973 
974  sctp_buffer_opaque (b)->sctp.connection_index =
975  sctp_conn->sub_conn[idx].connection.c_index;
976  sctp_buffer_opaque (b)->sctp.subconn_idx = idx;
977 }
978 
979 /**
980  * Convert buffer to SHUTDOWN
981  */
982 void
984  vlib_buffer_t * b)
985 {
986  u16 alloc_bytes = sizeof (sctp_shutdown_association_chunk_t);
987 
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
990  */
991  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
992 
993  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
994 
995  sctp_shutdown_association_chunk_t *shutdown_chunk =
996  vlib_buffer_push_uninit (b, alloc_bytes);
997 
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);
1007 
1008  shutdown_chunk->cumulative_tsn_ack = sctp_conn->last_rcvd_tsn;
1009 
1010  sctp_buffer_opaque (b)->sctp.connection_index =
1011  sctp_conn->sub_conn[idx].connection.c_index;
1012  sctp_buffer_opaque (b)->sctp.subconn_idx = idx;
1013 }
1014 
1015 /*
1016  * Send SHUTDOWN
1017  */
1018 void
1020 {
1021  vlib_buffer_t *b;
1022  u32 bi;
1025 
1026  if (sctp_check_outstanding_data_chunks (sctp_conn) > 0)
1027  return;
1028 
1029  if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
1030  return;
1031 
1032  u8 idx = SCTP_PRIMARY_PATH_IDX;
1033 
1034  b = vlib_get_buffer (vm, bi);
1035  sctp_init_buffer (vm, b);
1036  sctp_prepare_shutdown_chunk (sctp_conn, idx, b);
1037 
1038  sctp_enqueue_to_output_now (vm, b, bi,
1039  sctp_conn->sub_conn[idx].connection.is_ip4);
1040 }
1041 
1042 /**
1043  * Convert buffer to SHUTDOWN_ACK
1044  */
1045 void
1047  vlib_buffer_t * b)
1048 {
1049  u16 alloc_bytes = sizeof (sctp_shutdown_association_chunk_t);
1050  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1051 
1052  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1053 
1054  sctp_shutdown_ack_chunk_t *shutdown_ack_chunk =
1055  vlib_buffer_push_uninit (b, alloc_bytes);
1056 
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;
1064 
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);
1067 
1068  sctp_buffer_opaque (b)->sctp.connection_index =
1069  sctp_conn->sub_conn[idx].connection.c_index;
1070  sctp_buffer_opaque (b)->sctp.subconn_idx = idx;
1071 }
1072 
1073 /*
1074  * Send SHUTDOWN_ACK
1075  */
1076 void
1078  vlib_buffer_t * b)
1079 {
1081 
1082  if (sctp_check_outstanding_data_chunks (sctp_conn) > 0)
1083  return;
1084 
1085  sctp_reuse_buffer (vm, b);
1086 
1087  sctp_prepare_shutdown_ack_chunk (sctp_conn, idx, b);
1088 }
1089 
1090 /**
1091  * Convert buffer to SACK
1092  */
1093 void
1095  vlib_buffer_t * b)
1096 {
1098 
1099  sctp_reuse_buffer (vm, b);
1100 
1101  u16 alloc_bytes = sizeof (sctp_selective_ack_chunk_t);
1102 
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
1105  */
1106  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1107 
1108  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1109 
1110  sctp_selective_ack_chunk_t *sack = vlib_buffer_push_uninit (b, alloc_bytes);
1111 
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;
1117  vnet_sctp_set_chunk_length (&sack->chunk_hdr, chunk_len);
1118 
1119  sack->cumulative_tsn_ack = sctp_conn->next_tsn_expected;
1120 
1121  sctp_conn->ack_state = 0;
1122 
1123  sctp_buffer_opaque (b)->sctp.connection_index =
1124  sctp_conn->sub_conn[idx].connection.c_index;
1125  sctp_buffer_opaque (b)->sctp.subconn_idx = idx;
1126 }
1127 
1128 /**
1129  * Convert buffer to HEARTBEAT_ACK
1130  */
1131 void
1133  vlib_buffer_t * b)
1134 {
1136 
1137  u16 alloc_bytes = sizeof (sctp_hb_ack_chunk_t);
1138 
1139  sctp_reuse_buffer (vm, b);
1140 
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
1143  */
1144  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1145 
1146  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1147 
1148  sctp_hb_ack_chunk_t *hb_ack = vlib_buffer_push_uninit (b, alloc_bytes);
1149 
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));
1158 
1160  vnet_sctp_set_chunk_length (&hb_ack->chunk_hdr, chunk_len);
1161 
1162  sctp_buffer_opaque (b)->sctp.connection_index =
1163  sctp_conn->sub_conn[idx].connection.c_index;
1164  sctp_buffer_opaque (b)->sctp.subconn_idx = idx;
1165 }
1166 
1167 /**
1168  * Convert buffer to HEARTBEAT
1169  */
1170 void
1172  vlib_buffer_t * b)
1173 {
1174  u16 alloc_bytes = sizeof (sctp_hb_req_chunk_t);
1175 
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
1178  */
1179  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1180 
1181  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1182 
1183  sctp_hb_req_chunk_t *hb_req = vlib_buffer_push_uninit (b, alloc_bytes);
1184 
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));
1193 
1195  vnet_sctp_set_chunk_length (&hb_req->chunk_hdr, chunk_len);
1196 
1197  sctp_buffer_opaque (b)->sctp.connection_index =
1198  sctp_conn->sub_conn[idx].connection.c_index;
1199  sctp_buffer_opaque (b)->sctp.subconn_idx = idx;
1200 }
1201 
1202 void
1204 {
1205  vlib_buffer_t *b;
1206  u32 bi;
1209 
1210  u8 i;
1211  u64 now = sctp_time_now ();
1212 
1213  for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
1214  {
1215  if (sctp_conn->sub_conn[i].state == SCTP_SUBCONN_STATE_DOWN)
1216  continue;
1217 
1218  if (now > (sctp_conn->sub_conn[i].last_seen + SCTP_HB_INTERVAL))
1219  {
1220  if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
1221  return;
1222 
1223  b = vlib_get_buffer (vm, bi);
1224  sctp_init_buffer (vm, b);
1225  sctp_prepare_heartbeat_chunk (sctp_conn, i, b);
1226 
1227  sctp_enqueue_to_output_now (vm, b, bi,
1228  sctp_conn->sub_conn[i].
1229  connection.is_ip4);
1230 
1231  sctp_conn->sub_conn[i].unacknowledged_hb += 1;
1232  }
1233  }
1234 }
1235 
1236 /**
1237  * Convert buffer to SHUTDOWN_COMPLETE
1238  */
1239 void
1241  vlib_buffer_t * b)
1242 {
1243  u16 alloc_bytes = sizeof (sctp_shutdown_association_chunk_t);
1244  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1245 
1246  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1247 
1248  sctp_shutdown_complete_chunk_t *shutdown_complete =
1249  vlib_buffer_push_uninit (b, alloc_bytes);
1250 
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;
1258 
1259  vnet_sctp_set_chunk_type (&shutdown_complete->chunk_hdr, SHUTDOWN_COMPLETE);
1260  vnet_sctp_set_chunk_length (&shutdown_complete->chunk_hdr, chunk_len);
1261 
1262  sctp_buffer_opaque (b)->sctp.connection_index =
1263  sctp_conn->sub_conn[idx].connection.c_index;
1264  sctp_buffer_opaque (b)->sctp.subconn_idx = idx;
1265 }
1266 
1267 void
1269  vlib_buffer_t * b0)
1270 {
1272 
1273  if (sctp_check_outstanding_data_chunks (sctp_conn) > 0)
1274  return;
1275 
1276  sctp_reuse_buffer (vm, b0);
1277 
1278  sctp_prepare_shutdown_complete_chunk (sctp_conn, idx, b0);
1279 }
1280 
1281 /*
1282  * Send INIT
1283  */
1284 void
1286 {
1287  vlib_buffer_t *b;
1288  u32 bi;
1291 
1292  if (PREDICT_FALSE (sctp_conn->init_retransmit_err > SCTP_MAX_INIT_RETRANS))
1293  {
1294  clib_warning ("Reached MAX_INIT_RETRANS times. Aborting connection.");
1295 
1296  session_stream_connect_notify (&sctp_conn->sub_conn
1297  [SCTP_PRIMARY_PATH_IDX].connection, 1);
1298 
1299  sctp_connection_timers_reset (sctp_conn);
1300 
1301  sctp_connection_cleanup (sctp_conn);
1302 
1303  return;
1304  }
1305 
1306  if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
1307  return;
1308 
1309  b = vlib_get_buffer (vm, bi);
1310  u8 idx = SCTP_PRIMARY_PATH_IDX;
1311 
1312  sctp_init_buffer (vm, b);
1313  sctp_prepare_init_chunk (sctp_conn, idx, b);
1314 
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);
1318 
1319  /* Start the T1_INIT timer */
1320  sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T1_INIT,
1321  sctp_conn->sub_conn[idx].RTO);
1322 
1323  /* Change state to COOKIE_WAIT */
1324  sctp_conn->state = SCTP_STATE_COOKIE_WAIT;
1325 
1326  /* Measure RTT with this */
1327  sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now ();
1328 }
1329 
1330 /**
1331  * Push SCTP header and update connection variables
1332  */
1333 static void
1335  sctp_state_t next_state)
1336 {
1337  u16 data_len = b->current_length;
1338 
1339  if (b->flags & VLIB_BUFFER_TOTAL_LENGTH_VALID)
1341 
1343  || (b->flags & VLIB_BUFFER_NEXT_PRESENT)
1344  || !(b->flags & VLIB_BUFFER_TOTAL_LENGTH_VALID));
1345 
1346  SCTP_ADV_DBG_OUTPUT ("b->current_length = %u, "
1347  "b->current_data = %p "
1348  "data_len = %u",
1349  b->current_length, b->current_data, data_len);
1350 
1351  u16 data_padding = vnet_sctp_calculate_padding (b->current_length);
1352  if (data_padding > 0)
1353  {
1354  u8 *p_tail = vlib_buffer_put_uninit (b, data_padding);
1355  clib_memset_u8 (p_tail, 0, data_padding);
1356  }
1357 
1358  u16 bytes_to_add = sizeof (sctp_payload_data_chunk_t);
1359  u16 chunk_length = data_len + bytes_to_add - sizeof (sctp_header_t);
1360 
1361  sctp_payload_data_chunk_t *data_chunk =
1362  vlib_buffer_push_uninit (b, bytes_to_add);
1363 
1364  u8 idx = sctp_data_subconn_select (sctp_conn);
1366  ("SCTP_CONN = %p, IDX = %u, S_INDEX = %u, C_INDEX = %u, sctp_conn->[...].LCL_PORT = %u, sctp_conn->[...].RMT_PORT = %u",
1367  sctp_conn, idx, sctp_conn->sub_conn[idx].connection.s_index,
1368  sctp_conn->sub_conn[idx].connection.c_index,
1369  sctp_conn->sub_conn[idx].connection.lcl_port,
1370  sctp_conn->sub_conn[idx].connection.rmt_port);
1371  data_chunk->sctp_hdr.checksum = 0;
1372  data_chunk->sctp_hdr.src_port =
1373  sctp_conn->sub_conn[idx].connection.lcl_port;
1374  data_chunk->sctp_hdr.dst_port =
1375  sctp_conn->sub_conn[idx].connection.rmt_port;
1376  data_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1377 
1378  data_chunk->tsn = clib_host_to_net_u32 (sctp_conn->next_tsn);
1379  data_chunk->stream_id = clib_host_to_net_u16 (0);
1380  data_chunk->stream_seq = clib_host_to_net_u16 (0);
1381 
1382  vnet_sctp_set_chunk_type (&data_chunk->chunk_hdr, DATA);
1383  vnet_sctp_set_chunk_length (&data_chunk->chunk_hdr, chunk_length);
1384 
1385  vnet_sctp_set_bbit (&data_chunk->chunk_hdr);
1386  vnet_sctp_set_ebit (&data_chunk->chunk_hdr);
1387 
1388  SCTP_ADV_DBG_OUTPUT ("POINTER_WITH_DATA = %p, DATA_OFFSET = %u",
1389  b->data, b->current_data);
1390 
1391  if (sctp_conn->sub_conn[idx].state != SCTP_SUBCONN_AWAITING_SACK)
1392  {
1393  sctp_conn->sub_conn[idx].state = SCTP_SUBCONN_AWAITING_SACK;
1394  sctp_conn->last_unacked_tsn = sctp_conn->next_tsn;
1395  }
1396 
1397  sctp_conn->next_tsn += data_len;
1398 
1399  u32 inflight = sctp_conn->next_tsn - sctp_conn->last_unacked_tsn;
1400  /* Section 7.2.2; point (3) */
1401  if (sctp_conn->sub_conn[idx].partially_acked_bytes >=
1402  sctp_conn->sub_conn[idx].cwnd
1403  && inflight >= sctp_conn->sub_conn[idx].cwnd)
1404  {
1405  sctp_conn->sub_conn[idx].cwnd += sctp_conn->sub_conn[idx].PMTU;
1406  sctp_conn->sub_conn[idx].partially_acked_bytes -=
1407  sctp_conn->sub_conn[idx].cwnd;
1408  }
1409 
1410  sctp_conn->sub_conn[idx].last_data_ts = sctp_time_now ();
1411 
1412  sctp_buffer_opaque (b)->sctp.connection_index =
1413  sctp_conn->sub_conn[idx].connection.c_index;
1414 
1415  sctp_buffer_opaque (b)->sctp.subconn_idx = idx;
1416 }
1417 
1418 u32
1420 {
1421  sctp_connection_t *sctp_conn =
1423 
1424  SCTP_DBG_OUTPUT ("TRANS_CONN = %p, SCTP_CONN = %p, "
1425  "S_INDEX = %u, C_INDEX = %u,"
1426  "trans_conn->LCL_PORT = %u, trans_conn->RMT_PORT = %u",
1427  trans_conn,
1428  sctp_conn,
1429  trans_conn->s_index,
1430  trans_conn->c_index,
1431  trans_conn->lcl_port, trans_conn->rmt_port);
1432 
1433  sctp_push_hdr_i (sctp_conn, b, SCTP_STATE_ESTABLISHED);
1434 
1436 
1437  return 0;
1438 }
1439 
1440 u32
1442  u8 idx,
1443  u32 offset,
1444  u32 max_deq_bytes, vlib_buffer_t ** b)
1445 {
1448  int n_bytes = 0;
1449  u32 bi, available_bytes, seg_size;
1450  u8 *data;
1451 
1452  ASSERT (sctp_conn->state >= SCTP_STATE_ESTABLISHED);
1453  ASSERT (max_deq_bytes != 0);
1454 
1455  /*
1456  * Make sure we can retransmit something
1457  */
1458  available_bytes =
1459  transport_max_tx_dequeue (&sctp_conn->sub_conn[idx].connection);
1460  ASSERT (available_bytes >= offset);
1461  available_bytes -= offset;
1462  if (!available_bytes)
1463  return 0;
1464  max_deq_bytes = clib_min (sctp_conn->sub_conn[idx].cwnd, max_deq_bytes);
1465  max_deq_bytes = clib_min (available_bytes, max_deq_bytes);
1466 
1467  seg_size = max_deq_bytes;
1468 
1469  /*
1470  * Allocate and fill in buffer(s)
1471  */
1472 
1473  if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
1474  return 0;
1475  *b = vlib_get_buffer (vm, bi);
1476  data = sctp_init_buffer (vm, *b);
1477 
1478  /* Easy case, buffer size greater than mss */
1479  if (PREDICT_TRUE (seg_size <= tm->bytes_per_buffer))
1480  {
1481  n_bytes =
1482  session_tx_fifo_peek_bytes (&sctp_conn->sub_conn[idx].connection,
1483  data, offset, max_deq_bytes);
1484  ASSERT (n_bytes == max_deq_bytes);
1485  b[0]->current_length = n_bytes;
1486  sctp_push_hdr_i (sctp_conn, *b, sctp_conn->state);
1487  }
1488 
1489  return n_bytes;
1490 }
1491 
1492 void
1494 {
1496  vlib_buffer_t *b = 0;
1497  u32 bi, n_bytes = 0;
1498 
1499  u8 idx = sctp_data_subconn_select (sctp_conn);
1500 
1502  ("SCTP_CONN = %p, IDX = %u, S_INDEX = %u, C_INDEX = %u, sctp_conn->[...].LCL_PORT = %u, sctp_conn->[...].RMT_PORT = %u",
1503  sctp_conn, idx, sctp_conn->sub_conn[idx].connection.s_index,
1504  sctp_conn->sub_conn[idx].connection.c_index,
1505  sctp_conn->sub_conn[idx].connection.lcl_port,
1506  sctp_conn->sub_conn[idx].connection.rmt_port);
1507 
1508  if (sctp_conn->state >= SCTP_STATE_ESTABLISHED)
1509  {
1510  return;
1511  }
1512 
1513  n_bytes =
1514  sctp_prepare_data_retransmit (sctp_conn, idx, 0,
1515  sctp_conn->sub_conn[idx].cwnd, &b);
1516  if (n_bytes > 0)
1517  SCTP_DBG_OUTPUT ("We have data (%u bytes) to retransmit", n_bytes);
1518 
1519  bi = vlib_get_buffer_index (vm, b);
1520 
1521  sctp_enqueue_to_output_now (vm, b, bi,
1522  sctp_conn->sub_conn[idx].connection.is_ip4);
1523 
1524  return;
1525 }
1526 
1527 #if SCTP_DEBUG_STATE_MACHINE
1529 sctp_validate_output_state_machine (sctp_connection_t * sctp_conn,
1530  u8 chunk_type)
1531 {
1532  u8 result = 0;
1533  switch (sctp_conn->state)
1534  {
1535  case SCTP_STATE_CLOSED:
1536  if (chunk_type != INIT && chunk_type != INIT_ACK)
1537  result = 1;
1538  break;
1539  case SCTP_STATE_ESTABLISHED:
1540  if (chunk_type != DATA && chunk_type != HEARTBEAT &&
1541  chunk_type != HEARTBEAT_ACK && chunk_type != SACK &&
1542  chunk_type != COOKIE_ACK && chunk_type != SHUTDOWN)
1543  result = 1;
1544  break;
1545  case SCTP_STATE_COOKIE_WAIT:
1546  if (chunk_type != COOKIE_ECHO)
1547  result = 1;
1548  break;
1549  case SCTP_STATE_SHUTDOWN_SENT:
1550  if (chunk_type != SHUTDOWN_COMPLETE)
1551  result = 1;
1552  break;
1553  case SCTP_STATE_SHUTDOWN_RECEIVED:
1554  if (chunk_type != SHUTDOWN_ACK)
1555  result = 1;
1556  break;
1557  }
1558  return result;
1559 }
1560 #endif
1561 
1562 /*
1563  * fd.io coding-style-patch-verification: ON
1564  *
1565  * Local Variables:
1566  * eval: (c-set-style "gnu")
1567  * End:
1568  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:439
void sctp_prepare_heartbeat_ack_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to HEARTBEAT_ACK.
Definition: sctp_output.c:1132
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
static void sctp_enqueue_to_ip_lookup(vlib_main_t *vm, vlib_buffer_t *b, u32 bi, u8 is_ip4, u32 fib_index)
Definition: sctp_output.c:374
void sctp_connection_timers_reset(sctp_connection_t *sctp_conn)
Stop all connection timers.
Definition: sctp.c:164
u16 sctp_check_outstanding_data_chunks(sctp_connection_t *sctp_conn)
Definition: sctp.c:562
struct _sctp_main sctp_main_t
static void sctp_timer_set(sctp_connection_t *tc, u8 conn_idx, u8 timer_id, u32 interval)
Definition: sctp.h:627
void session_flush_frames_main_thread(vlib_main_t *vm)
Definition: session.c:1498
static void vnet_sctp_set_ebit(sctp_chunks_common_hdr_t *h)
Definition: sctp_packet.h:322
#define clib_min(x, y)
Definition: clib.h:302
static uword random_default_seed(void)
Default random seed (unix/linux user-mode)
Definition: random.h:91
void sctp_flush_frames_to_output(u8 thread_index)
Flush v4 and v6 sctp and ip-lookup tx frames for thread index.
Definition: sctp_output.c:57
ip4_address_t src_address
Definition: ip4_packet.h:170
int session_tx_fifo_peek_bytes(transport_connection_t *tc, u8 *buffer, u32 offset, u32 max_bytes)
Definition: session.c:503
void sctp_prepare_cookie_ack_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Definition: sctp_output.c:497
#define SCTP_ADV_DBG_OUTPUT(_fmt, _args...)
Definition: sctp_debug.h:59
#define PREDICT_TRUE(x)
Definition: clib.h:113
#define SCTP_IPV4_ADDRESS_TYPE_LENGTH
Definition: sctp_packet.h:777
u64 as_u64[2]
Definition: ip6_packet.h:51
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
unsigned long u64
Definition: types.h:89
struct _sctp_sub_connection sctp_sub_connection_t
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
#define INBOUND_STREAMS_COUNT
Definition: sctp_packet.h:516
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:591
static u64 sctp_time_now(void)
Definition: sctp.h:702
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.
Definition: sctp_output.c:700
u32 thread_index
Definition: main.h:218
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
vlib_node_registration_t sctp6_output_node
(constructor) VLIB_REGISTER_NODE (sctp6_output_node)
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:412
int i
uword ip_csum_t
Definition: ip_packet.h:219
static ip_csum_t ip_csum_with_carry(ip_csum_t sum, ip_csum_t x)
Definition: ip_packet.h:222
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:1254
u8 data[128]
Definition: ipsec.api:251
void sctp_compute_mac(sctp_connection_t *sctp_conn, sctp_state_cookie_param_t *state_cookie)
Definition: sctp_output.c:468
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:1339
ip6_address_t src_address
Definition: ip6_packet.h:383
unsigned char u8
Definition: types.h:56
uword as_uword[16/sizeof(uword)]
Definition: ip6_packet.h:52
static sctp_main_t * vnet_get_sctp_main()
Definition: sctp.h:574
static void vnet_sctp_common_hdr_params_host_to_net(sctp_chunks_common_hdr_t *h)
Definition: sctp_packet.h:284
vlib_node_registration_t ip4_lookup_node
(constructor) VLIB_REGISTER_NODE (ip4_lookup_node)
Definition: ip4_forward.c:101
void sctp_send_shutdown_ack(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Definition: sctp_output.c:1077
void sctp_prepare_sack_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to SACK.
Definition: sctp_output.c:1094
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:1411
sctp_main_t sctp_main
Definition: sctp.c:22
static void sctp_init_cwnd(sctp_connection_t *sctp_conn)
Definition: sctp.h:934
#define always_inline
Definition: clib.h:99
static void vnet_sctp_set_chunk_type(sctp_chunks_common_hdr_t *h, sctp_chunk_type t)
Definition: sctp_packet.h:335
ip4_address_t dst_address
Definition: ip4_packet.h:170
static void sctp_enqueue_to_ip_lookup_i(vlib_main_t *vm, vlib_buffer_t *b, u32 bi, u8 is_ip4, u32 fib_index, u8 flush)
Definition: sctp_output.c:333
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:185
sctp_header_t sctp_hdr
Definition: sctp_packet.h:1338
unsigned int u32
Definition: types.h:88
static void sctp_enqueue_to_output_now(vlib_main_t *vm, vlib_buffer_t *b, u32 bi, u8 is_ip4)
Definition: sctp_output.c:326
#define SCTP_STATE_COOKIE_TYPE
Definition: sctp_packet.h:780
#define VLIB_FRAME_SIZE
Definition: node.h:378
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
Definition: buffer_funcs.h:257
static void sctp_push_hdr_i(sctp_connection_t *sctp_conn, vlib_buffer_t *b, sctp_state_t next_state)
Push SCTP header and update connection variables.
Definition: sctp_output.c:1334
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
ip6_address_t address
Definition: sctp_packet.h:842
#define TRANSPORT_MAX_HDRS_LEN
#define SCTP_DBG_OUTPUT(_fmt, _args...)
Definition: sctp_debug.h:52
void sctp_data_retransmit(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:1493
void sctp_prepare_init_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to INIT.
Definition: sctp_output.c:386
static sctp_connection_t * sctp_get_connection_from_transport(transport_connection_t *tconn)
Definition: sctp.h:683
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.
Definition: sctp_output.c:659
static void * vlib_buffer_make_headroom(vlib_buffer_t *b, u8 size)
Make head room, typically for packet headers.
Definition: buffer.h:350
sctp_init_chunk_t sctp_init_ack_chunk_t
Definition: sctp_packet.h:690
long ctx[MAX_CONNS]
Definition: main.c:144
unsigned short u16
Definition: types.h:57
sctp_opt_params_hdr_t param_hdr
Definition: sctp_packet.h:1203
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:194
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
sctp_header_t sctp_hdr
Definition: sctp_packet.h:1253
static void sctp_enqueue_to_output_i(vlib_main_t *vm, vlib_buffer_t *b, u32 bi, u8 is_ip4, u8 flush)
Definition: sctp_output.c:292
#define PREDICT_FALSE(x)
Definition: clib.h:112
#define OUTBOUND_STREAMS_COUNT
Definition: sctp_packet.h:517
struct _sctp_connection sctp_connection_t
#define SCTP_IPV6_ADDRESS_TYPE
Definition: sctp_packet.h:778
vl_api_address_union_t src_address
Definition: ip_types.api:97
static void * sctp_reuse_buffer(vlib_main_t *vm, vlib_buffer_t *b)
Definition: sctp_output.c:224
#define MAX_SCTP_CONNECTIONS
Definition: sctp.h:106
u32 verification_tag
Definition: sctp_packet.h:73
static void sctp_flush_frame_to_ip_lookup(vlib_main_t *vm, u8 thread_index, u8 is_ip4)
Flush ip lookup tx frames populated by timer pops.
Definition: sctp_output.c:40
static char * sctp_state_to_string(u8 state)
Definition: sctp.h:392
vlib_node_registration_t sctp4_output_node
(constructor) VLIB_REGISTER_NODE (sctp4_output_node)
u8 len
Definition: ip_types.api:90
sctp_hb_req_chunk_t sctp_hb_ack_chunk_t
Definition: sctp_packet.h:1287
ip4_address_t address
Definition: sctp_packet.h:804
enum _sctp_state sctp_state_t
u16 n_vectors
Definition: node.h:397
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:218
#define sctp_buffer_opaque(b)
Definition: sctp.h:46
vlib_main_t * vm
Definition: buffer.c:323
void sctp_push_ip_hdr(sctp_main_t *tm, sctp_sub_connection_t *sctp_sub_conn, vlib_buffer_t *b)
Definition: sctp_output.c:198
#define IP_PROTOCOL_SCTP
Definition: sctp.h:370
void sctp_send_init(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:1285
#define clib_warning(format, args...)
Definition: error.h:59
u8 data[]
Packet data.
Definition: buffer.h:181
#define VLIB_BUFFER_TRACE_TRAJECTORY
Compile time buffer trajectory tracing option Turn this on if you run into "bad monkey" contexts...
Definition: buffer.h:480
void sctp_send_cookie_echo(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:569
void sctp_prepare_shutdown_ack_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to SHUTDOWN_ACK.
Definition: sctp_output.c:1046
static int sctp_alloc_tx_buffers(sctp_main_t *tm, u8 thread_index, u32 n_free_buffers)
Definition: sctp_output.c:254
struct _transport_connection transport_connection_t
#define sctp_trajectory_add_start(b, start)
Definition: sctp.h:115
void sctp_prepare_shutdown_complete_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to SHUTDOWN_COMPLETE.
Definition: sctp_output.c:1240
#define ARRAY_LEN(x)
Definition: clib.h:63
sctp_opt_params_hdr_t param_hdr
Definition: sctp_packet.h:836
u32 ip4_sctp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip4_header_t *ip0)
Definition: sctp_output.c:67
static u32 transport_max_tx_dequeue(transport_connection_t *tc)
Definition: session.h:478
sctp_header_t sctp_hdr
Definition: sctp_packet.h:590
vlib_node_registration_t ip6_lookup_node
(constructor) VLIB_REGISTER_NODE (ip6_lookup_node)
Definition: ip6_forward.c:656
void sctp_prepare_shutdown_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to SHUTDOWN.
Definition: sctp_output.c:983
#define ASSERT(truth)
sctp_opt_params_hdr_t param_hdr
Definition: sctp_packet.h:1313
u8 pre_data[VLIB_BUFFER_PRE_DATA_SIZE]
Space for inserting data before buffer start.
Definition: buffer.h:178
#define SCTP_PRIMARY_PATH_IDX
Definition: sctp.h:107
static u16 vnet_sctp_calculate_padding(u16 base_length)
Definition: sctp_packet.h:508
#define SCTP_CONN_TRACKING_DBG(_fmt, _args...)
Definition: sctp_debug.h:66
static void * sctp_init_buffer(vlib_main_t *vm, vlib_buffer_t *b)
Definition: sctp_output.c:241
#define clib_mem_unaligned(pointer, type)
Definition: types.h:155
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:1452
void sctp_connection_cleanup(sctp_connection_t *sctp_conn)
Cleans up connection state.
Definition: sctp.c:532
sctp_header_t sctp_hdr
Definition: sctp_packet.h:1373
static_always_inline void clib_memset_u8(void *p, u8 val, uword count)
Definition: string.h:424
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
sctp_hb_info_param_t hb_info
Definition: sctp_packet.h:1255
template key/value backing page structure
Definition: bihash_doc.h:44
void sctp_prepare_heartbeat_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to HEARTBEAT.
Definition: sctp_output.c:1171
Definition: defs.h:47
void sctp_send_shutdown_complete(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b0)
Definition: sctp_output.c:1268
static void * vlib_buffer_push_uninit(vlib_buffer_t *b, u8 size)
Prepend uninitialized data to buffer.
Definition: buffer.h:335
u16 payload_length
Definition: ip6_packet.h:374
#define SCTP_IPV4_ADDRESS_TYPE
Definition: sctp_packet.h:776
u32 ip6_sctp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip6_header_t *ip0, int *bogus_lengthp)
Definition: sctp_output.c:124
u32 sctp_prepare_data_retransmit(sctp_connection_t *sctp_conn, u8 idx, u32 offset, u32 max_deq_bytes, vlib_buffer_t **b)
Definition: sctp_output.c:1441
static void * vlib_buffer_push_ip6(vlib_main_t *vm, vlib_buffer_t *b, ip6_address_t *src, ip6_address_t *dst, int proto)
Push IPv6 header to buffer.
Definition: ip6.h:663
void sctp_send_heartbeat(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:1203
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.
Definition: sctp_output.c:24
void sctp_prepare_operation_error(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b, u8 err_cause)
Convert buffer to ERROR.
Definition: sctp_output.c:614
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:140
sctp_err_cause_param_t err_causes[]
Definition: sctp_packet.h:1340
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
Definition: buffer.h:489
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
#define SCTP_VALID_COOKIE_LIFE
Definition: sctp.h:489
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
Linear Congruential Random Number Generator.
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:771
struct clib_bihash_value offset
template key/value backing page structure
u32 sctp_push_header(transport_connection_t *trans_conn, vlib_buffer_t *b)
Definition: sctp_output.c:1419
void sctp_prepare_cookie_echo_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b, u8 reuse_buffer)
Definition: sctp_output.c:531
#define vnet_buffer(b)
Definition: buffer.h:365
static char * sctp_chunk_to_string(u8 type)
Definition: sctp.h:417
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
int session_stream_connect_notify(transport_connection_t *tc, u8 is_fail)
Definition: session.c:765
#define ENDIANESS_SWAP(x)
Definition: sctp.h:201
static u32 vlib_num_workers()
Definition: threads.h:372
#define SCTP_HB_INTERVAL
Definition: sctp.h:493
static void * vlib_buffer_put_uninit(vlib_buffer_t *b, u16 size)
Append uninitialized data to buffer.
Definition: buffer.h:321
static void vlib_buffer_free_one(vlib_main_t *vm, u32 buffer_index)
Free one buffer Shorthand to free a single buffer chain.
Definition: buffer_funcs.h:898
static int ip4_header_bytes(const ip4_header_t *i)
Definition: ip4_packet.h:235
static int sctp_get_free_buffer_index(sctp_main_t *tm, u32 *bidx)
Definition: sctp_output.c:276
static void vnet_sctp_set_bbit(sctp_chunks_common_hdr_t *h)
Definition: sctp_packet.h:309
static u8 sctp_data_subconn_select(sctp_connection_t *sctp_conn)
Definition: sctp.h:799
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
Definition: buffer.h:167
#define SCTP_IPV6_ADDRESS_TYPE_LENGTH
Definition: sctp_packet.h:779
static u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:612
#define BITS(x)
Definition: clib.h:62
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:1075
sctp_opt_params_hdr_t param_hdr
Definition: sctp_packet.h:798
static void vnet_sctp_set_chunk_length(sctp_chunks_common_hdr_t *h, u16 length)
Definition: sctp_packet.h:348
static ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
Definition: ip_packet.h:293
static void * vlib_buffer_push_ip4(vlib_main_t *vm, vlib_buffer_t *b, ip4_address_t *src, ip4_address_t *dst, int proto, u8 csum_offload)
Push IPv4 header to buffer.
Definition: ip4.h:386
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
#define SCTP_DBG_STATE_MACHINE(_fmt, _args...)
Definition: sctp_debug.h:31
#define SCTP_MAX_INIT_RETRANS
Definition: sctp.h:492
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.
Definition: sctp_output.c:840
void sctp_send_shutdown(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:1019
Definition: defs.h:46
ip6_address_t dst_address
Definition: ip6_packet.h:383
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:1374