FD.io VPP  v19.01.3-6-g70449b9b9
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 <vnet/sctp/sctp.h>
16 #include <vnet/sctp/sctp_debug.h>
17 #include <vppinfra/random.h>
18 #include <openssl/hmac.h>
19 
22 
23 typedef enum _sctp_output_next
24 {
29 
30 #define foreach_sctp4_output_next \
31  _ (DROP, "error-drop") \
32  _ (IP_LOOKUP, "ip4-lookup")
33 
34 #define foreach_sctp6_output_next \
35  _ (DROP, "error-drop") \
36  _ (IP_LOOKUP, "ip6-lookup")
37 
38 static char *sctp_error_strings[] = {
39 #define sctp_error(n,s) s,
40 #include <vnet/sctp/sctp_error.def>
41 #undef sctp_error
42 };
43 
44 typedef struct
45 {
49 
50 /**
51  * Flush tx frame populated by retransmits and timer pops
52  */
53 void
54 sctp_flush_frame_to_output (vlib_main_t * vm, u8 thread_index, u8 is_ip4)
55 {
56  if (sctp_main.tx_frames[!is_ip4][thread_index])
57  {
58  u32 next_index;
59  next_index = is_ip4 ? sctp4_output_node.index : sctp6_output_node.index;
60  vlib_put_frame_to_node (vm, next_index,
61  sctp_main.tx_frames[!is_ip4][thread_index]);
62  sctp_main.tx_frames[!is_ip4][thread_index] = 0;
63  }
64 }
65 
66 /**
67  * Flush ip lookup tx frames populated by timer pops
68  */
69 always_inline void
71 {
72  if (sctp_main.ip_lookup_tx_frames[!is_ip4][thread_index])
73  {
74  u32 next_index;
75  next_index = is_ip4 ? ip4_lookup_node.index : ip6_lookup_node.index;
76  vlib_put_frame_to_node (vm, next_index,
77  sctp_main.ip_lookup_tx_frames[!is_ip4]
78  [thread_index]);
79  sctp_main.ip_lookup_tx_frames[!is_ip4][thread_index] = 0;
80  }
81 }
82 
83 /**
84  * Flush v4 and v6 sctp and ip-lookup tx frames for thread index
85  */
86 void
88 {
90  sctp_flush_frame_to_output (vm, thread_index, 1);
91  sctp_flush_frame_to_output (vm, thread_index, 0);
92  sctp_flush_frame_to_ip_lookup (vm, thread_index, 1);
93  sctp_flush_frame_to_ip_lookup (vm, thread_index, 0);
94 }
95 
96 u32
98  ip4_header_t * ip0)
99 {
100  ip_csum_t checksum;
101  u32 ip_header_length, payload_length_host_byte_order;
102  u32 n_this_buffer, n_bytes_left, n_ip_bytes_this_buffer;
103  void *data_this_buffer;
104 
105  /* Initialize checksum with ip header. */
106  ip_header_length = ip4_header_bytes (ip0);
107  payload_length_host_byte_order =
108  clib_net_to_host_u16 (ip0->length) - ip_header_length;
109  checksum =
110  clib_host_to_net_u32 (payload_length_host_byte_order +
111  (ip0->protocol << 16));
112 
113  if (BITS (uword) == 32)
114  {
115  checksum =
116  ip_csum_with_carry (checksum,
118  checksum =
119  ip_csum_with_carry (checksum,
121  }
122  else
123  checksum =
124  ip_csum_with_carry (checksum,
126 
127  n_bytes_left = n_this_buffer = payload_length_host_byte_order;
128  data_this_buffer = (void *) ip0 + ip_header_length;
129  n_ip_bytes_this_buffer =
130  p0->current_length - (((u8 *) ip0 - p0->data) - p0->current_data);
131  if (n_this_buffer + ip_header_length > n_ip_bytes_this_buffer)
132  {
133  n_this_buffer = n_ip_bytes_this_buffer > ip_header_length ?
134  n_ip_bytes_this_buffer - ip_header_length : 0;
135  }
136  while (1)
137  {
138  checksum =
139  ip_incremental_checksum (checksum, data_this_buffer, n_this_buffer);
140  n_bytes_left -= n_this_buffer;
141  if (n_bytes_left == 0)
142  break;
143 
144  ASSERT (p0->flags & VLIB_BUFFER_NEXT_PRESENT);
145  p0 = vlib_get_buffer (vm, p0->next_buffer);
146  data_this_buffer = vlib_buffer_get_current (p0);
147  n_this_buffer = p0->current_length;
148  }
149 
150  return checksum;
151 }
152 
153 u32
155  ip6_header_t * ip0, int *bogus_lengthp)
156 {
157  ip_csum_t checksum;
158  u16 payload_length_host_byte_order;
159  u32 i, n_this_buffer, n_bytes_left;
160  u32 headers_size = sizeof (ip0[0]);
161  void *data_this_buffer;
162 
163  ASSERT (bogus_lengthp);
164  *bogus_lengthp = 0;
165 
166  /* Initialize checksum with ip header. */
167  checksum = ip0->payload_length + clib_host_to_net_u16 (ip0->protocol);
168  payload_length_host_byte_order = clib_net_to_host_u16 (ip0->payload_length);
169  data_this_buffer = (void *) (ip0 + 1);
170 
171  for (i = 0; i < ARRAY_LEN (ip0->src_address.as_uword); i++)
172  {
173  checksum = ip_csum_with_carry (checksum,
174  clib_mem_unaligned (&ip0->
175  src_address.as_uword
176  [i], uword));
177  checksum =
178  ip_csum_with_carry (checksum,
180  uword));
181  }
182 
183  /* some icmp packets may come with a "router alert" hop-by-hop extension header (e.g., mldv2 packets)
184  * or UDP-Ping packets */
185  if (PREDICT_FALSE (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS))
186  {
187  u32 skip_bytes;
188  ip6_hop_by_hop_ext_t *ext_hdr =
189  (ip6_hop_by_hop_ext_t *) data_this_buffer;
190 
191  /* validate really icmp6 next */
192  ASSERT ((ext_hdr->next_hdr == IP_PROTOCOL_SCTP));
193 
194  skip_bytes = 8 * (1 + ext_hdr->n_data_u64s);
195  data_this_buffer = (void *) ((u8 *) data_this_buffer + skip_bytes);
196 
197  payload_length_host_byte_order -= skip_bytes;
198  headers_size += skip_bytes;
199  }
200 
201  n_bytes_left = n_this_buffer = payload_length_host_byte_order;
202  if (p0 && n_this_buffer + headers_size > p0->current_length)
203  n_this_buffer =
204  p0->current_length >
205  headers_size ? p0->current_length - headers_size : 0;
206  while (1)
207  {
208  checksum =
209  ip_incremental_checksum (checksum, data_this_buffer, n_this_buffer);
210  n_bytes_left -= n_this_buffer;
211  if (n_bytes_left == 0)
212  break;
213 
214  if (!(p0->flags & VLIB_BUFFER_NEXT_PRESENT))
215  {
216  *bogus_lengthp = 1;
217  return 0xfefe;
218  }
219  p0 = vlib_get_buffer (vm, p0->next_buffer);
220  data_this_buffer = vlib_buffer_get_current (p0);
221  n_this_buffer = p0->current_length;
222  }
223 
224  return checksum;
225 }
226 
227 void
229  vlib_buffer_t * b)
230 {
233  if (sctp_sub_conn->c_is_ip4)
234  {
235  ip4_header_t *ih;
236  ih = vlib_buffer_push_ip4 (vm, b, &sctp_sub_conn->c_lcl_ip4,
237  &sctp_sub_conn->c_rmt_ip4, IP_PROTOCOL_SCTP,
238  1);
239  th->checksum = ip4_sctp_compute_checksum (vm, b, ih);
240  }
241  else
242  {
243  ip6_header_t *ih;
244  int bogus = ~0;
245 
246  ih = vlib_buffer_push_ip6 (vm, b, &sctp_sub_conn->c_lcl_ip6,
247  &sctp_sub_conn->c_rmt_ip6, IP_PROTOCOL_SCTP);
248  th->checksum = ip6_sctp_compute_checksum (vm, b, ih, &bogus);
249  ASSERT (!bogus);
250  }
251 }
252 
253 always_inline void *
255 {
256  if (b->flags & VLIB_BUFFER_NEXT_PRESENT)
258  /* Zero all flags but free list index and trace flag */
259  b->flags &= VLIB_BUFFER_NEXT_PRESENT - 1;
260  b->current_data = 0;
261  b->current_length = 0;
263  vnet_buffer (b)->sctp.flags = 0;
264  vnet_buffer (b)->sctp.subconn_idx = MAX_SCTP_CONNECTIONS;
265 
266  /* Leave enough space for headers */
268 }
269 
270 always_inline void *
272 {
273  ASSERT ((b->flags & VLIB_BUFFER_NEXT_PRESENT) == 0);
274  b->flags &= VLIB_BUFFER_NON_DEFAULT_FREELIST;
275  b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
277  vnet_buffer (b)->sctp.flags = 0;
278  vnet_buffer (b)->sctp.subconn_idx = MAX_SCTP_CONNECTIONS;
280  /* Leave enough space for headers */
282 }
283 
284 always_inline int
285 sctp_alloc_tx_buffers (sctp_main_t * tm, u8 thread_index, u32 n_free_buffers)
286 {
288  u32 current_length = vec_len (tm->tx_buffers[thread_index]);
289  u32 n_allocated;
290 
291  vec_validate (tm->tx_buffers[thread_index],
292  current_length + n_free_buffers - 1);
293  n_allocated =
294  vlib_buffer_alloc (vm, &tm->tx_buffers[thread_index][current_length],
295  n_free_buffers);
296  _vec_len (tm->tx_buffers[thread_index]) = current_length + n_allocated;
297  /* buffer shortage, report failure */
298  if (vec_len (tm->tx_buffers[thread_index]) == 0)
299  {
300  clib_warning ("out of buffers");
301  return -1;
302  }
303  return 0;
304 }
305 
306 always_inline int
308 {
309  u32 *my_tx_buffers;
310  u32 thread_index = vlib_get_thread_index ();
311  if (PREDICT_FALSE (vec_len (tm->tx_buffers[thread_index]) == 0))
312  {
313  if (sctp_alloc_tx_buffers (tm, thread_index, VLIB_FRAME_SIZE))
314  return -1;
315  }
316  my_tx_buffers = tm->tx_buffers[thread_index];
317  *bidx = my_tx_buffers[vec_len (my_tx_buffers) - 1];
318  _vec_len (my_tx_buffers) -= 1;
319  return 0;
320 }
321 
322 always_inline void
324  u8 is_ip4, u8 flush)
325 {
327  u32 thread_index = vlib_get_thread_index ();
328  u32 *to_next, next_index;
329  vlib_frame_t *f;
330 
331  b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
332  b->error = 0;
333 
334  /* Decide where to send the packet */
335  next_index = is_ip4 ? sctp4_output_node.index : sctp6_output_node.index;
337 
338  /* Get frame to v4/6 output node */
339  f = tm->tx_frames[!is_ip4][thread_index];
340  if (!f)
341  {
342  f = vlib_get_frame_to_node (vm, next_index);
343  ASSERT (f);
344  tm->tx_frames[!is_ip4][thread_index] = f;
345  }
346  to_next = vlib_frame_vector_args (f);
347  to_next[f->n_vectors] = bi;
348  f->n_vectors += 1;
349  if (flush || f->n_vectors == VLIB_FRAME_SIZE)
350  {
351  vlib_put_frame_to_node (vm, next_index, f);
352  tm->tx_frames[!is_ip4][thread_index] = 0;
353  }
354 }
355 
356 always_inline void
358  u8 is_ip4)
359 {
360  sctp_enqueue_to_output_i (vm, b, bi, is_ip4, 1);
361 }
362 
363 always_inline void
365  u8 is_ip4, u32 fib_index, u8 flush)
366 {
368  u32 thread_index = vlib_get_thread_index ();
369  u32 *to_next, next_index;
370  vlib_frame_t *f;
371 
372  b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
373  b->error = 0;
374 
375  vnet_buffer (b)->sw_if_index[VLIB_TX] = fib_index;
376  vnet_buffer (b)->sw_if_index[VLIB_RX] = 0;
377 
378  /* Send to IP lookup */
379  next_index = is_ip4 ? ip4_lookup_node.index : ip6_lookup_node.index;
381  {
382  b->pre_data[0] = 2;
383  b->pre_data[1] = next_index;
384  }
385 
386  f = tm->ip_lookup_tx_frames[!is_ip4][thread_index];
387  if (!f)
388  {
389  f = vlib_get_frame_to_node (vm, next_index);
390  ASSERT (f);
391  tm->ip_lookup_tx_frames[!is_ip4][thread_index] = f;
392  }
393 
394  to_next = vlib_frame_vector_args (f);
395  to_next[f->n_vectors] = bi;
396  f->n_vectors += 1;
397  if (flush || f->n_vectors == VLIB_FRAME_SIZE)
398  {
399  vlib_put_frame_to_node (vm, next_index, f);
400  tm->ip_lookup_tx_frames[!is_ip4][thread_index] = 0;
401  }
402 }
403 
404 always_inline void
406  u8 is_ip4, u32 fib_index)
407 {
408  sctp_enqueue_to_ip_lookup_i (vm, b, bi, is_ip4, fib_index, 0);
409  if (vm->thread_index == 0 && vlib_num_workers ())
411 }
412 
413 /**
414  * Convert buffer to INIT
415  */
416 void
418  vlib_buffer_t * b)
419 {
420  u32 random_seed = random_default_seed ();
421  u16 alloc_bytes = sizeof (sctp_init_chunk_t);
422  sctp_sub_connection_t *sub_conn = &sctp_conn->sub_conn[idx];
423 
424  sctp_ipv4_addr_param_t *ip4_param = 0;
425  sctp_ipv6_addr_param_t *ip6_param = 0;
426 
427  if (sub_conn->c_is_ip4)
428  alloc_bytes += sizeof (sctp_ipv4_addr_param_t);
429  else
430  alloc_bytes += sizeof (sctp_ipv6_addr_param_t);
431 
432  /* As per RFC 4960 the chunk_length value does NOT contemplate
433  * the size of the first header (see sctp_header_t) and any padding
434  */
435  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
436 
437  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
438 
439  sctp_init_chunk_t *init_chunk = vlib_buffer_push_uninit (b, alloc_bytes);
440 
441  u16 pointer_offset = sizeof (init_chunk);
442  if (sub_conn->c_is_ip4)
443  {
444  ip4_param = (sctp_ipv4_addr_param_t *) init_chunk + pointer_offset;
445  ip4_param->address.as_u32 = sub_conn->c_lcl_ip.ip4.as_u32;
446 
447  pointer_offset += sizeof (sctp_ipv4_addr_param_t);
448  }
449  else
450  {
451  ip6_param = (sctp_ipv6_addr_param_t *) init_chunk + pointer_offset;
452  ip6_param->address.as_u64[0] = sub_conn->c_lcl_ip.ip6.as_u64[0];
453  ip6_param->address.as_u64[1] = sub_conn->c_lcl_ip.ip6.as_u64[1];
454 
455  pointer_offset += sizeof (sctp_ipv6_addr_param_t);
456  }
457 
458  init_chunk->sctp_hdr.src_port = sub_conn->c_lcl_port; /* No need of host_to_net conversion, already in net-byte order */
459  init_chunk->sctp_hdr.dst_port = sub_conn->c_rmt_port; /* No need of host_to_net conversion, already in net-byte order */
460  init_chunk->sctp_hdr.checksum = 0;
461  /* The sender of an INIT must set the VERIFICATION_TAG to 0 as per RFC 4960 Section 8.5.1 */
462  init_chunk->sctp_hdr.verification_tag = 0x0;
463 
464  vnet_sctp_set_chunk_type (&init_chunk->chunk_hdr, INIT);
465  vnet_sctp_set_chunk_length (&init_chunk->chunk_hdr, chunk_len);
467 
468  sctp_init_cwnd (sctp_conn);
469 
470  init_chunk->a_rwnd = clib_host_to_net_u32 (sctp_conn->sub_conn[idx].cwnd);
471  init_chunk->initiate_tag = clib_host_to_net_u32 (random_u32 (&random_seed));
472  init_chunk->inboud_streams_count =
473  clib_host_to_net_u16 (INBOUND_STREAMS_COUNT);
474  init_chunk->outbound_streams_count =
475  clib_host_to_net_u16 (OUTBOUND_STREAMS_COUNT);
476 
477  init_chunk->initial_tsn =
478  clib_host_to_net_u32 (sctp_conn->local_initial_tsn);
479  SCTP_CONN_TRACKING_DBG ("sctp_conn->local_initial_tsn = %u",
480  sctp_conn->local_initial_tsn);
481 
482  sctp_conn->local_tag = init_chunk->initiate_tag;
483 
484  vnet_buffer (b)->sctp.connection_index = sub_conn->c_c_index;
485  vnet_buffer (b)->sctp.subconn_idx = idx;
486 
487  SCTP_DBG_STATE_MACHINE ("CONN_INDEX = %u, CURR_CONN_STATE = %u (%s), "
488  "CHUNK_TYPE = %s, "
489  "SRC_PORT = %u, DST_PORT = %u",
490  sub_conn->connection.c_index,
491  sctp_conn->state,
492  sctp_state_to_string (sctp_conn->state),
494  init_chunk->sctp_hdr.src_port,
495  init_chunk->sctp_hdr.dst_port);
496 }
497 
498 void
500  sctp_state_cookie_param_t * state_cookie)
501 {
502 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
503  HMAC_CTX *ctx;
504 #else
505  HMAC_CTX ctx;
506 #endif
507  unsigned int len = 0;
508  const EVP_MD *md = EVP_sha1 ();
509 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
510  ctx = HMAC_CTX_new ();
511  HMAC_Init_ex (ctx, &state_cookie->creation_time,
512  sizeof (state_cookie->creation_time), md, NULL);
513  HMAC_Update (ctx, (const unsigned char *) &sctp_conn, sizeof (sctp_conn));
514  HMAC_Final (ctx, state_cookie->mac, &len);
515 #else
516  HMAC_CTX_init (&ctx);
517  HMAC_Init_ex (&ctx, &state_cookie->creation_time,
518  sizeof (state_cookie->creation_time), md, NULL);
519  HMAC_Update (&ctx, (const unsigned char *) &sctp_conn, sizeof (sctp_conn));
520  HMAC_Final (&ctx, state_cookie->mac, &len);
521  HMAC_CTX_cleanup (&ctx);
522 #endif
523 
524  ENDIANESS_SWAP (state_cookie->mac);
525 }
526 
527 void
529  vlib_buffer_t * b)
530 {
532 
533  sctp_reuse_buffer (vm, b);
534 
535  u16 alloc_bytes = sizeof (sctp_cookie_ack_chunk_t);
536 
537  /* As per RFC 4960 the chunk_length value does NOT contemplate
538  * the size of the first header (see sctp_header_t) and any padding
539  */
540  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
541 
542  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
543 
544  sctp_cookie_ack_chunk_t *cookie_ack_chunk =
545  vlib_buffer_push_uninit (b, alloc_bytes);
546 
547  cookie_ack_chunk->sctp_hdr.checksum = 0;
548  cookie_ack_chunk->sctp_hdr.src_port =
549  sctp_conn->sub_conn[idx].connection.lcl_port;
550  cookie_ack_chunk->sctp_hdr.dst_port =
551  sctp_conn->sub_conn[idx].connection.rmt_port;
552  cookie_ack_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
553  vnet_sctp_set_chunk_type (&cookie_ack_chunk->chunk_hdr, COOKIE_ACK);
554  vnet_sctp_set_chunk_length (&cookie_ack_chunk->chunk_hdr, chunk_len);
555 
556  vnet_buffer (b)->sctp.connection_index =
557  sctp_conn->sub_conn[idx].connection.c_index;
558  vnet_buffer (b)->sctp.subconn_idx = idx;
559 }
560 
561 void
563  vlib_buffer_t * b, u8 reuse_buffer)
564 {
566 
567  if (reuse_buffer)
568  sctp_reuse_buffer (vm, b);
569 
570  /* The minimum size of the message is given by the sctp_init_ack_chunk_t */
571  u16 alloc_bytes = sizeof (sctp_cookie_echo_chunk_t);
572  /* As per RFC 4960 the chunk_length value does NOT contemplate
573  * the size of the first header (see sctp_header_t) and any padding
574  */
575  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
576  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
577  sctp_cookie_echo_chunk_t *cookie_echo_chunk =
578  vlib_buffer_push_uninit (b, alloc_bytes);
579  cookie_echo_chunk->sctp_hdr.checksum = 0;
580  cookie_echo_chunk->sctp_hdr.src_port =
581  sctp_conn->sub_conn[idx].connection.lcl_port;
582  cookie_echo_chunk->sctp_hdr.dst_port =
583  sctp_conn->sub_conn[idx].connection.rmt_port;
584  cookie_echo_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
585  vnet_sctp_set_chunk_type (&cookie_echo_chunk->chunk_hdr, COOKIE_ECHO);
586  vnet_sctp_set_chunk_length (&cookie_echo_chunk->chunk_hdr, chunk_len);
587  clib_memcpy_fast (&(cookie_echo_chunk->cookie), &sctp_conn->cookie_param,
588  sizeof (sctp_state_cookie_param_t));
589 
590  vnet_buffer (b)->sctp.connection_index =
591  sctp_conn->sub_conn[idx].connection.c_index;
592  vnet_buffer (b)->sctp.subconn_idx = idx;
593 }
594 
595 
596 /*
597  * Send COOKIE_ECHO
598  */
599 void
601 {
602  vlib_buffer_t *b;
603  u32 bi;
606 
607  if (PREDICT_FALSE (sctp_conn->init_retransmit_err > SCTP_MAX_INIT_RETRANS))
608  {
609  clib_warning ("Reached MAX_INIT_RETRANS times. Aborting connection.");
610 
611  session_stream_connect_notify (&sctp_conn->sub_conn
612  [SCTP_PRIMARY_PATH_IDX].connection, 1);
613 
614  sctp_connection_timers_reset (sctp_conn);
615 
616  sctp_connection_cleanup (sctp_conn);
617  }
618 
620  return;
621 
622  b = vlib_get_buffer (vm, bi);
624 
625  sctp_init_buffer (vm, b);
626  sctp_prepare_cookie_echo_chunk (sctp_conn, idx, b, 0);
627  sctp_enqueue_to_output_now (vm, b, bi, sctp_conn->sub_conn[idx].c_is_ip4);
628 
629  /* Start the T1_INIT timer */
630  sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T1_INIT,
631  sctp_conn->sub_conn[idx].RTO);
632 
633  /* Change state to COOKIE_WAIT */
634  sctp_conn->state = SCTP_STATE_COOKIE_WAIT;
635 
636  /* Measure RTT with this */
637  sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now ();
638 }
639 
640 
641 /**
642  * Convert buffer to ERROR
643  */
644 void
646  vlib_buffer_t * b, u8 err_cause)
647 {
649 
650  sctp_reuse_buffer (vm, b);
651 
652  /* The minimum size of the message is given by the sctp_operation_error_t */
653  u16 alloc_bytes =
655 
656  /* As per RFC 4960 the chunk_length value does NOT contemplate
657  * the size of the first header (see sctp_header_t) and any padding
658  */
659  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
660 
661  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
662 
663  sctp_operation_error_t *err_chunk =
664  vlib_buffer_push_uninit (b, alloc_bytes);
665 
666  /* src_port & dst_port are already in network byte-order */
667  err_chunk->sctp_hdr.checksum = 0;
668  err_chunk->sctp_hdr.src_port = sctp_conn->sub_conn[idx].connection.lcl_port;
669  err_chunk->sctp_hdr.dst_port = sctp_conn->sub_conn[idx].connection.rmt_port;
670  /* As per RFC4960 Section 5.2.2: copy the INITIATE_TAG into the VERIFICATION_TAG of the ABORT chunk */
671  err_chunk->sctp_hdr.verification_tag = sctp_conn->local_tag;
672 
673  err_chunk->err_causes[0].param_hdr.length =
674  clib_host_to_net_u16 (sizeof (err_chunk->err_causes[0].param_hdr.type) +
675  sizeof (err_chunk->err_causes[0].param_hdr.length));
676  err_chunk->err_causes[0].param_hdr.type = clib_host_to_net_u16 (err_cause);
677 
679  vnet_sctp_set_chunk_length (&err_chunk->chunk_hdr, chunk_len);
680 
681  vnet_buffer (b)->sctp.connection_index =
682  sctp_conn->sub_conn[idx].connection.c_index;
683  vnet_buffer (b)->sctp.subconn_idx = idx;
684 }
685 
686 /**
687  * Convert buffer to ABORT
688  */
689 void
691  vlib_buffer_t * b, ip4_address_t * ip4_addr,
692  ip6_address_t * ip6_addr)
693 {
695 
696  sctp_reuse_buffer (vm, b);
697 
698  /* The minimum size of the message is given by the sctp_abort_chunk_t */
699  u16 alloc_bytes = sizeof (sctp_abort_chunk_t);
700 
701  /* As per RFC 4960 the chunk_length value does NOT contemplate
702  * the size of the first header (see sctp_header_t) and any padding
703  */
704  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
705 
706  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
707 
708  sctp_abort_chunk_t *abort_chunk = vlib_buffer_push_uninit (b, alloc_bytes);
709 
710  /* src_port & dst_port are already in network byte-order */
711  abort_chunk->sctp_hdr.checksum = 0;
712  abort_chunk->sctp_hdr.src_port =
713  sctp_conn->sub_conn[idx].connection.lcl_port;
714  abort_chunk->sctp_hdr.dst_port =
715  sctp_conn->sub_conn[idx].connection.rmt_port;
716  /* As per RFC4960 Section 5.2.2: copy the INITIATE_TAG into the VERIFICATION_TAG of the ABORT chunk */
717  abort_chunk->sctp_hdr.verification_tag = sctp_conn->local_tag;
718 
719  vnet_sctp_set_chunk_type (&abort_chunk->chunk_hdr, ABORT);
720  vnet_sctp_set_chunk_length (&abort_chunk->chunk_hdr, chunk_len);
721 
722  vnet_buffer (b)->sctp.connection_index =
723  sctp_conn->sub_conn[idx].connection.c_index;
724  vnet_buffer (b)->sctp.subconn_idx = idx;
725 }
726 
727 /**
728  * Convert buffer to INIT-ACK
729  */
730 void
732  u8 idx, vlib_buffer_t * b,
733  ip4_address_t * ip4_addr,
734  ip6_address_t * ip6_addr)
735 {
737  sctp_ipv4_addr_param_t *ip4_param = 0;
738  sctp_ipv6_addr_param_t *ip6_param = 0;
739 
740  sctp_reuse_buffer (vm, b);
741 
742  /* The minimum size of the message is given by the sctp_init_ack_chunk_t */
743  u16 alloc_bytes =
745 
746  if (PREDICT_TRUE (ip4_addr != NULL))
747  {
748  /* Create room for variable-length fields in the INIT_ACK chunk */
749  alloc_bytes += SCTP_IPV4_ADDRESS_TYPE_LENGTH;
750  }
751  if (PREDICT_TRUE (ip6_addr != NULL))
752  {
753  /* Create room for variable-length fields in the INIT_ACK chunk */
754  alloc_bytes += SCTP_IPV6_ADDRESS_TYPE_LENGTH;
755  }
756 
757  if (sctp_conn->sub_conn[idx].connection.is_ip4)
758  alloc_bytes += sizeof (sctp_ipv4_addr_param_t);
759  else
760  alloc_bytes += sizeof (sctp_ipv6_addr_param_t);
761 
762  /* As per RFC 4960 the chunk_length value does NOT contemplate
763  * the size of the first header (see sctp_header_t) and any padding
764  */
765  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
766 
767  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
768 
769  sctp_init_ack_chunk_t *init_ack_chunk =
770  vlib_buffer_push_uninit (b, alloc_bytes);
771 
772  u16 pointer_offset = sizeof (sctp_init_ack_chunk_t);
773 
774  /* Create State Cookie parameter */
775  sctp_state_cookie_param_t *state_cookie_param =
776  (sctp_state_cookie_param_t *) ((char *) init_ack_chunk + pointer_offset);
777 
778  state_cookie_param->param_hdr.type =
779  clib_host_to_net_u16 (SCTP_STATE_COOKIE_TYPE);
780  state_cookie_param->param_hdr.length =
781  clib_host_to_net_u16 (sizeof (sctp_state_cookie_param_t));
782  state_cookie_param->creation_time = clib_host_to_net_u64 (sctp_time_now ());
783  state_cookie_param->cookie_lifespan =
784  clib_host_to_net_u32 (SCTP_VALID_COOKIE_LIFE);
785 
786  sctp_compute_mac (sctp_conn, state_cookie_param);
787 
788  pointer_offset += sizeof (sctp_state_cookie_param_t);
789 
790  if (PREDICT_TRUE (ip4_addr != NULL))
791  {
792  sctp_ipv4_addr_param_t *ipv4_addr =
793  (sctp_ipv4_addr_param_t *) init_ack_chunk + pointer_offset;
794 
795  ipv4_addr->param_hdr.type =
796  clib_host_to_net_u16 (SCTP_IPV4_ADDRESS_TYPE);
797  ipv4_addr->param_hdr.length =
798  clib_host_to_net_u16 (SCTP_IPV4_ADDRESS_TYPE_LENGTH);
799  ipv4_addr->address.as_u32 = ip4_addr->as_u32;
800 
801  pointer_offset += SCTP_IPV4_ADDRESS_TYPE_LENGTH;
802  }
803  if (PREDICT_TRUE (ip6_addr != NULL))
804  {
805  sctp_ipv6_addr_param_t *ipv6_addr =
806  (sctp_ipv6_addr_param_t *) init_ack_chunk + pointer_offset;
807 
808  ipv6_addr->param_hdr.type =
809  clib_host_to_net_u16 (SCTP_IPV6_ADDRESS_TYPE);
810  ipv6_addr->param_hdr.length =
811  clib_host_to_net_u16 (SCTP_IPV6_ADDRESS_TYPE_LENGTH);
812  ipv6_addr->address.as_u64[0] = ip6_addr->as_u64[0];
813  ipv6_addr->address.as_u64[1] = ip6_addr->as_u64[1];
814 
815  pointer_offset += SCTP_IPV6_ADDRESS_TYPE_LENGTH;
816  }
817 
818  if (sctp_conn->sub_conn[idx].connection.is_ip4)
819  {
820  ip4_param = (sctp_ipv4_addr_param_t *) init_ack_chunk + pointer_offset;
821  ip4_param->address.as_u32 =
822  sctp_conn->sub_conn[idx].connection.lcl_ip.ip4.as_u32;
823 
824  pointer_offset += sizeof (sctp_ipv4_addr_param_t);
825  }
826  else
827  {
828  ip6_param = (sctp_ipv6_addr_param_t *) init_ack_chunk + pointer_offset;
829  ip6_param->address.as_u64[0] =
830  sctp_conn->sub_conn[idx].connection.lcl_ip.ip6.as_u64[0];
831  ip6_param->address.as_u64[1] =
832  sctp_conn->sub_conn[idx].connection.lcl_ip.ip6.as_u64[1];
833 
834  pointer_offset += sizeof (sctp_ipv6_addr_param_t);
835  }
836 
837  /* src_port & dst_port are already in network byte-order */
838  init_ack_chunk->sctp_hdr.checksum = 0;
839  init_ack_chunk->sctp_hdr.src_port =
840  sctp_conn->sub_conn[idx].connection.lcl_port;
841  init_ack_chunk->sctp_hdr.dst_port =
842  sctp_conn->sub_conn[idx].connection.rmt_port;
843  /* the sctp_conn->verification_tag is already in network byte-order (being a copy of the init_tag coming with the INIT chunk) */
844  init_ack_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
845  init_ack_chunk->initial_tsn =
846  clib_host_to_net_u32 (sctp_conn->local_initial_tsn);
847  SCTP_CONN_TRACKING_DBG ("init_ack_chunk->initial_tsn = %u",
848  init_ack_chunk->initial_tsn);
849 
850  vnet_sctp_set_chunk_type (&init_ack_chunk->chunk_hdr, INIT_ACK);
851  vnet_sctp_set_chunk_length (&init_ack_chunk->chunk_hdr, chunk_len);
852 
853  init_ack_chunk->initiate_tag = sctp_conn->local_tag;
854 
855  init_ack_chunk->a_rwnd =
856  clib_host_to_net_u32 (sctp_conn->sub_conn[idx].cwnd);
857  init_ack_chunk->inboud_streams_count =
858  clib_host_to_net_u16 (INBOUND_STREAMS_COUNT);
859  init_ack_chunk->outbound_streams_count =
860  clib_host_to_net_u16 (OUTBOUND_STREAMS_COUNT);
861 
862  vnet_buffer (b)->sctp.connection_index =
863  sctp_conn->sub_conn[idx].connection.c_index;
864  vnet_buffer (b)->sctp.subconn_idx = idx;
865 }
866 
867 /**
868  * Convert buffer to INIT-ACK
869  */
870 void
872  vlib_buffer_t * b, ip4_address_t * ip4_addr,
873  u8 add_ip4, ip6_address_t * ip6_addr, u8 add_ip6)
874 {
876  sctp_ipv4_addr_param_t *ip4_param = 0;
877  sctp_ipv6_addr_param_t *ip6_param = 0;
878  u32 random_seed = random_default_seed ();
879 
880  sctp_reuse_buffer (vm, b);
881 
882  /* The minimum size of the message is given by the sctp_init_ack_chunk_t */
883  u16 alloc_bytes =
885 
886  if (PREDICT_FALSE (add_ip4 == 1))
887  {
888  /* Create room for variable-length fields in the INIT_ACK chunk */
889  alloc_bytes += SCTP_IPV4_ADDRESS_TYPE_LENGTH;
890  }
891  if (PREDICT_FALSE (add_ip6 == 1))
892  {
893  /* Create room for variable-length fields in the INIT_ACK chunk */
894  alloc_bytes += SCTP_IPV6_ADDRESS_TYPE_LENGTH;
895  }
896 
897  if (sctp_conn->sub_conn[idx].connection.is_ip4)
898  alloc_bytes += sizeof (sctp_ipv4_addr_param_t);
899  else
900  alloc_bytes += sizeof (sctp_ipv6_addr_param_t);
901 
902  /* As per RFC 4960 the chunk_length value does NOT contemplate
903  * the size of the first header (see sctp_header_t) and any padding
904  */
905  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
906 
907  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
908 
909  sctp_init_ack_chunk_t *init_ack_chunk =
910  vlib_buffer_push_uninit (b, alloc_bytes);
911 
912  u16 pointer_offset = sizeof (sctp_init_ack_chunk_t);
913 
914  /* Create State Cookie parameter */
915  sctp_state_cookie_param_t *state_cookie_param =
916  (sctp_state_cookie_param_t *) ((char *) init_ack_chunk + pointer_offset);
917 
918  state_cookie_param->param_hdr.type =
919  clib_host_to_net_u16 (SCTP_STATE_COOKIE_TYPE);
920  state_cookie_param->param_hdr.length =
921  clib_host_to_net_u16 (sizeof (sctp_state_cookie_param_t));
922  state_cookie_param->creation_time = clib_host_to_net_u64 (sctp_time_now ());
923  state_cookie_param->cookie_lifespan =
924  clib_host_to_net_u32 (SCTP_VALID_COOKIE_LIFE);
925 
926  sctp_compute_mac (sctp_conn, state_cookie_param);
927 
928  pointer_offset += sizeof (sctp_state_cookie_param_t);
929 
930  if (PREDICT_TRUE (ip4_addr != NULL))
931  {
932  sctp_ipv4_addr_param_t *ipv4_addr =
933  (sctp_ipv4_addr_param_t *) init_ack_chunk + pointer_offset;
934 
935  ipv4_addr->param_hdr.type =
936  clib_host_to_net_u16 (SCTP_IPV4_ADDRESS_TYPE);
937  ipv4_addr->param_hdr.length =
938  clib_host_to_net_u16 (SCTP_IPV4_ADDRESS_TYPE_LENGTH);
939  ipv4_addr->address.as_u32 = ip4_addr->as_u32;
940 
941  pointer_offset += SCTP_IPV4_ADDRESS_TYPE_LENGTH;
942  }
943  if (PREDICT_TRUE (ip6_addr != NULL))
944  {
945  sctp_ipv6_addr_param_t *ipv6_addr =
946  (sctp_ipv6_addr_param_t *) init_ack_chunk + pointer_offset;
947 
948  ipv6_addr->param_hdr.type =
949  clib_host_to_net_u16 (SCTP_IPV6_ADDRESS_TYPE);
950  ipv6_addr->param_hdr.length =
951  clib_host_to_net_u16 (SCTP_IPV6_ADDRESS_TYPE_LENGTH);
952  ipv6_addr->address.as_u64[0] = ip6_addr->as_u64[0];
953  ipv6_addr->address.as_u64[1] = ip6_addr->as_u64[1];
954 
955  pointer_offset += SCTP_IPV6_ADDRESS_TYPE_LENGTH;
956  }
957 
958  if (sctp_conn->sub_conn[idx].connection.is_ip4)
959  {
960  ip4_param = (sctp_ipv4_addr_param_t *) init_ack_chunk + pointer_offset;
961  ip4_param->address.as_u32 =
962  sctp_conn->sub_conn[idx].connection.lcl_ip.ip4.as_u32;
963 
964  pointer_offset += sizeof (sctp_ipv4_addr_param_t);
965  }
966  else
967  {
968  ip6_param = (sctp_ipv6_addr_param_t *) init_ack_chunk + pointer_offset;
969  ip6_param->address.as_u64[0] =
970  sctp_conn->sub_conn[idx].connection.lcl_ip.ip6.as_u64[0];
971  ip6_param->address.as_u64[1] =
972  sctp_conn->sub_conn[idx].connection.lcl_ip.ip6.as_u64[1];
973 
974  pointer_offset += sizeof (sctp_ipv6_addr_param_t);
975  }
976 
977  /* src_port & dst_port are already in network byte-order */
978  init_ack_chunk->sctp_hdr.checksum = 0;
979  init_ack_chunk->sctp_hdr.src_port =
980  sctp_conn->sub_conn[idx].connection.lcl_port;
981  init_ack_chunk->sctp_hdr.dst_port =
982  sctp_conn->sub_conn[idx].connection.rmt_port;
983  /* the sctp_conn->verification_tag is already in network byte-order (being a copy of the init_tag coming with the INIT chunk) */
984  init_ack_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
985  init_ack_chunk->initial_tsn =
986  clib_host_to_net_u32 (sctp_conn->local_initial_tsn);
987  SCTP_CONN_TRACKING_DBG ("init_ack_chunk->initial_tsn = %u",
988  init_ack_chunk->initial_tsn);
989 
990  vnet_sctp_set_chunk_type (&init_ack_chunk->chunk_hdr, INIT_ACK);
991  vnet_sctp_set_chunk_length (&init_ack_chunk->chunk_hdr, chunk_len);
992 
993  init_ack_chunk->initiate_tag =
994  clib_host_to_net_u32 (random_u32 (&random_seed));
995 
996  init_ack_chunk->a_rwnd =
997  clib_host_to_net_u32 (sctp_conn->sub_conn[idx].cwnd);
998  init_ack_chunk->inboud_streams_count =
999  clib_host_to_net_u16 (INBOUND_STREAMS_COUNT);
1000  init_ack_chunk->outbound_streams_count =
1001  clib_host_to_net_u16 (OUTBOUND_STREAMS_COUNT);
1002 
1003  sctp_conn->local_tag = init_ack_chunk->initiate_tag;
1004 
1005  vnet_buffer (b)->sctp.connection_index =
1006  sctp_conn->sub_conn[idx].connection.c_index;
1007  vnet_buffer (b)->sctp.subconn_idx = idx;
1008 }
1009 
1010 /**
1011  * Convert buffer to SHUTDOWN
1012  */
1013 void
1015  vlib_buffer_t * b)
1016 {
1017  u16 alloc_bytes = sizeof (sctp_shutdown_association_chunk_t);
1018 
1019  /* As per RFC 4960 the chunk_length value does NOT contemplate
1020  * the size of the first header (see sctp_header_t) and any padding
1021  */
1022  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1023 
1024  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1025 
1026  sctp_shutdown_association_chunk_t *shutdown_chunk =
1027  vlib_buffer_push_uninit (b, alloc_bytes);
1028 
1029  shutdown_chunk->sctp_hdr.checksum = 0;
1030  /* No need of host_to_net conversion, already in net-byte order */
1031  shutdown_chunk->sctp_hdr.src_port =
1032  sctp_conn->sub_conn[idx].connection.lcl_port;
1033  shutdown_chunk->sctp_hdr.dst_port =
1034  sctp_conn->sub_conn[idx].connection.rmt_port;
1035  shutdown_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1036  vnet_sctp_set_chunk_type (&shutdown_chunk->chunk_hdr, SHUTDOWN);
1037  vnet_sctp_set_chunk_length (&shutdown_chunk->chunk_hdr, chunk_len);
1038 
1039  shutdown_chunk->cumulative_tsn_ack = sctp_conn->last_rcvd_tsn;
1040 
1041  vnet_buffer (b)->sctp.connection_index =
1042  sctp_conn->sub_conn[idx].connection.c_index;
1043  vnet_buffer (b)->sctp.subconn_idx = idx;
1044 }
1045 
1046 /*
1047  * Send SHUTDOWN
1048  */
1049 void
1051 {
1052  vlib_buffer_t *b;
1053  u32 bi;
1056 
1057  if (sctp_check_outstanding_data_chunks (sctp_conn) > 0)
1058  return;
1059 
1060  if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
1061  return;
1062 
1063  u8 idx = SCTP_PRIMARY_PATH_IDX;
1064 
1065  b = vlib_get_buffer (vm, bi);
1066  sctp_init_buffer (vm, b);
1067  sctp_prepare_shutdown_chunk (sctp_conn, idx, b);
1068 
1069  sctp_enqueue_to_output_now (vm, b, bi,
1070  sctp_conn->sub_conn[idx].connection.is_ip4);
1071 }
1072 
1073 /**
1074  * Convert buffer to SHUTDOWN_ACK
1075  */
1076 void
1078  vlib_buffer_t * b)
1079 {
1080  u16 alloc_bytes = sizeof (sctp_shutdown_association_chunk_t);
1081  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1082 
1083  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1084 
1085  sctp_shutdown_ack_chunk_t *shutdown_ack_chunk =
1086  vlib_buffer_push_uninit (b, alloc_bytes);
1087 
1088  shutdown_ack_chunk->sctp_hdr.checksum = 0;
1089  /* No need of host_to_net conversion, already in net-byte order */
1090  shutdown_ack_chunk->sctp_hdr.src_port =
1091  sctp_conn->sub_conn[idx].connection.lcl_port;
1092  shutdown_ack_chunk->sctp_hdr.dst_port =
1093  sctp_conn->sub_conn[idx].connection.rmt_port;
1094  shutdown_ack_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1095 
1096  vnet_sctp_set_chunk_type (&shutdown_ack_chunk->chunk_hdr, SHUTDOWN_ACK);
1097  vnet_sctp_set_chunk_length (&shutdown_ack_chunk->chunk_hdr, chunk_len);
1098 
1099  vnet_buffer (b)->sctp.connection_index =
1100  sctp_conn->sub_conn[idx].connection.c_index;
1101  vnet_buffer (b)->sctp.subconn_idx = idx;
1102 }
1103 
1104 /*
1105  * Send SHUTDOWN_ACK
1106  */
1107 void
1109  vlib_buffer_t * b)
1110 {
1112 
1113  if (sctp_check_outstanding_data_chunks (sctp_conn) > 0)
1114  return;
1115 
1116  sctp_reuse_buffer (vm, b);
1117 
1118  sctp_prepare_shutdown_ack_chunk (sctp_conn, idx, b);
1119 }
1120 
1121 /**
1122  * Convert buffer to SACK
1123  */
1124 void
1126  vlib_buffer_t * b)
1127 {
1129 
1130  sctp_reuse_buffer (vm, b);
1131 
1132  u16 alloc_bytes = sizeof (sctp_selective_ack_chunk_t);
1133 
1134  /* As per RFC 4960 the chunk_length value does NOT contemplate
1135  * the size of the first header (see sctp_header_t) and any padding
1136  */
1137  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1138 
1139  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1140 
1141  sctp_selective_ack_chunk_t *sack = vlib_buffer_push_uninit (b, alloc_bytes);
1142 
1143  sack->sctp_hdr.checksum = 0;
1144  sack->sctp_hdr.src_port = sctp_conn->sub_conn[idx].connection.lcl_port;
1145  sack->sctp_hdr.dst_port = sctp_conn->sub_conn[idx].connection.rmt_port;
1146  sack->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1148  vnet_sctp_set_chunk_length (&sack->chunk_hdr, chunk_len);
1149 
1150  sack->cumulative_tsn_ack = sctp_conn->next_tsn_expected;
1151 
1152  sctp_conn->ack_state = 0;
1153 
1154  vnet_buffer (b)->sctp.connection_index =
1155  sctp_conn->sub_conn[idx].connection.c_index;
1156  vnet_buffer (b)->sctp.subconn_idx = idx;
1157 }
1158 
1159 /**
1160  * Convert buffer to HEARTBEAT_ACK
1161  */
1162 void
1164  vlib_buffer_t * b)
1165 {
1167 
1168  u16 alloc_bytes = sizeof (sctp_hb_ack_chunk_t);
1169 
1170  sctp_reuse_buffer (vm, b);
1171 
1172  /* As per RFC 4960 the chunk_length value does NOT contemplate
1173  * the size of the first header (see sctp_header_t) and any padding
1174  */
1175  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1176 
1177  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1178 
1179  sctp_hb_ack_chunk_t *hb_ack = vlib_buffer_push_uninit (b, alloc_bytes);
1180 
1181  hb_ack->sctp_hdr.checksum = 0;
1182  /* No need of host_to_net conversion, already in net-byte order */
1183  hb_ack->sctp_hdr.src_port = sctp_conn->sub_conn[idx].connection.lcl_port;
1184  hb_ack->sctp_hdr.dst_port = sctp_conn->sub_conn[idx].connection.rmt_port;
1185  hb_ack->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1186  hb_ack->hb_info.param_hdr.type = clib_host_to_net_u16 (1);
1187  hb_ack->hb_info.param_hdr.length =
1188  clib_host_to_net_u16 (sizeof (hb_ack->hb_info.hb_info));
1189 
1191  vnet_sctp_set_chunk_length (&hb_ack->chunk_hdr, chunk_len);
1192 
1193  vnet_buffer (b)->sctp.connection_index =
1194  sctp_conn->sub_conn[idx].connection.c_index;
1195  vnet_buffer (b)->sctp.subconn_idx = idx;
1196 }
1197 
1198 /**
1199  * Convert buffer to HEARTBEAT
1200  */
1201 void
1203  vlib_buffer_t * b)
1204 {
1205  u16 alloc_bytes = sizeof (sctp_hb_req_chunk_t);
1206 
1207  /* As per RFC 4960 the chunk_length value does NOT contemplate
1208  * the size of the first header (see sctp_header_t) and any padding
1209  */
1210  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1211 
1212  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1213 
1214  sctp_hb_req_chunk_t *hb_req = vlib_buffer_push_uninit (b, alloc_bytes);
1215 
1216  hb_req->sctp_hdr.checksum = 0;
1217  /* No need of host_to_net conversion, already in net-byte order */
1218  hb_req->sctp_hdr.src_port = sctp_conn->sub_conn[idx].connection.lcl_port;
1219  hb_req->sctp_hdr.dst_port = sctp_conn->sub_conn[idx].connection.rmt_port;
1220  hb_req->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1221  hb_req->hb_info.param_hdr.type = clib_host_to_net_u16 (1);
1222  hb_req->hb_info.param_hdr.length =
1223  clib_host_to_net_u16 (sizeof (hb_req->hb_info.hb_info));
1224 
1226  vnet_sctp_set_chunk_length (&hb_req->chunk_hdr, chunk_len);
1227 
1228  vnet_buffer (b)->sctp.connection_index =
1229  sctp_conn->sub_conn[idx].connection.c_index;
1230  vnet_buffer (b)->sctp.subconn_idx = idx;
1231 }
1232 
1233 void
1235 {
1236  vlib_buffer_t *b;
1237  u32 bi;
1240 
1241  u8 i;
1242  u64 now = sctp_time_now ();
1243 
1244  for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
1245  {
1246  if (sctp_conn->sub_conn[i].state == SCTP_SUBCONN_STATE_DOWN)
1247  continue;
1248 
1249  if (now > (sctp_conn->sub_conn[i].last_seen + SCTP_HB_INTERVAL))
1250  {
1251  if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
1252  return;
1253 
1254  b = vlib_get_buffer (vm, bi);
1255  sctp_init_buffer (vm, b);
1256  sctp_prepare_heartbeat_chunk (sctp_conn, i, b);
1257 
1258  sctp_enqueue_to_output_now (vm, b, bi,
1259  sctp_conn->sub_conn[i].
1260  connection.is_ip4);
1261 
1262  sctp_conn->sub_conn[i].unacknowledged_hb += 1;
1263  }
1264  }
1265 }
1266 
1267 /**
1268  * Convert buffer to SHUTDOWN_COMPLETE
1269  */
1270 void
1272  vlib_buffer_t * b)
1273 {
1274  u16 alloc_bytes = sizeof (sctp_shutdown_association_chunk_t);
1275  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1276 
1277  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1278 
1279  sctp_shutdown_complete_chunk_t *shutdown_complete =
1280  vlib_buffer_push_uninit (b, alloc_bytes);
1281 
1282  shutdown_complete->sctp_hdr.checksum = 0;
1283  /* No need of host_to_net conversion, already in net-byte order */
1284  shutdown_complete->sctp_hdr.src_port =
1285  sctp_conn->sub_conn[idx].connection.lcl_port;
1286  shutdown_complete->sctp_hdr.dst_port =
1287  sctp_conn->sub_conn[idx].connection.rmt_port;
1288  shutdown_complete->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1289 
1290  vnet_sctp_set_chunk_type (&shutdown_complete->chunk_hdr, SHUTDOWN_COMPLETE);
1291  vnet_sctp_set_chunk_length (&shutdown_complete->chunk_hdr, chunk_len);
1292 
1293  vnet_buffer (b)->sctp.connection_index =
1294  sctp_conn->sub_conn[idx].connection.c_index;
1295  vnet_buffer (b)->sctp.subconn_idx = idx;
1296 }
1297 
1298 void
1300  vlib_buffer_t * b0)
1301 {
1303 
1304  if (sctp_check_outstanding_data_chunks (sctp_conn) > 0)
1305  return;
1306 
1307  sctp_reuse_buffer (vm, b0);
1308 
1309  sctp_prepare_shutdown_complete_chunk (sctp_conn, idx, b0);
1310 }
1311 
1312 /*
1313  * Send INIT
1314  */
1315 void
1317 {
1318  vlib_buffer_t *b;
1319  u32 bi;
1322 
1323  if (PREDICT_FALSE (sctp_conn->init_retransmit_err > SCTP_MAX_INIT_RETRANS))
1324  {
1325  clib_warning ("Reached MAX_INIT_RETRANS times. Aborting connection.");
1326 
1327  session_stream_connect_notify (&sctp_conn->sub_conn
1328  [SCTP_PRIMARY_PATH_IDX].connection, 1);
1329 
1330  sctp_connection_timers_reset (sctp_conn);
1331 
1332  sctp_connection_cleanup (sctp_conn);
1333 
1334  return;
1335  }
1336 
1337  if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
1338  return;
1339 
1340  b = vlib_get_buffer (vm, bi);
1341  u8 idx = SCTP_PRIMARY_PATH_IDX;
1342 
1343  sctp_init_buffer (vm, b);
1344  sctp_prepare_init_chunk (sctp_conn, idx, b);
1345 
1346  sctp_push_ip_hdr (tm, &sctp_conn->sub_conn[idx], b);
1347  sctp_enqueue_to_ip_lookup (vm, b, bi, sctp_conn->sub_conn[idx].c_is_ip4,
1348  sctp_conn->sub_conn[idx].c_fib_index);
1349 
1350  /* Start the T1_INIT timer */
1351  sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T1_INIT,
1352  sctp_conn->sub_conn[idx].RTO);
1353 
1354  /* Change state to COOKIE_WAIT */
1355  sctp_conn->state = SCTP_STATE_COOKIE_WAIT;
1356 
1357  /* Measure RTT with this */
1358  sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now ();
1359 }
1360 
1361 /**
1362  * Push SCTP header and update connection variables
1363  */
1364 static void
1366  sctp_state_t next_state)
1367 {
1368  u16 data_len =
1370 
1372  || (b->flags & VLIB_BUFFER_NEXT_PRESENT));
1373 
1374  SCTP_ADV_DBG_OUTPUT ("b->current_length = %u, "
1375  "b->current_data = %p "
1376  "data_len = %u",
1377  b->current_length, b->current_data, data_len);
1378 
1379  u16 data_padding = vnet_sctp_calculate_padding (b->current_length);
1380  if (data_padding > 0)
1381  {
1382  u8 *p_tail = vlib_buffer_put_uninit (b, data_padding);
1383  clib_memset_u8 (p_tail, 0, data_padding);
1384  }
1385 
1386  u16 bytes_to_add = sizeof (sctp_payload_data_chunk_t);
1387  u16 chunk_length = data_len + bytes_to_add - sizeof (sctp_header_t);
1388 
1389  sctp_payload_data_chunk_t *data_chunk =
1390  vlib_buffer_push_uninit (b, bytes_to_add);
1391 
1392  u8 idx = sctp_data_subconn_select (sctp_conn);
1394  ("SCTP_CONN = %p, IDX = %u, S_INDEX = %u, C_INDEX = %u, sctp_conn->[...].LCL_PORT = %u, sctp_conn->[...].RMT_PORT = %u",
1395  sctp_conn, idx, sctp_conn->sub_conn[idx].connection.s_index,
1396  sctp_conn->sub_conn[idx].connection.c_index,
1397  sctp_conn->sub_conn[idx].connection.lcl_port,
1398  sctp_conn->sub_conn[idx].connection.rmt_port);
1399  data_chunk->sctp_hdr.checksum = 0;
1400  data_chunk->sctp_hdr.src_port =
1401  sctp_conn->sub_conn[idx].connection.lcl_port;
1402  data_chunk->sctp_hdr.dst_port =
1403  sctp_conn->sub_conn[idx].connection.rmt_port;
1404  data_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1405 
1406  data_chunk->tsn = clib_host_to_net_u32 (sctp_conn->next_tsn);
1407  data_chunk->stream_id = clib_host_to_net_u16 (0);
1408  data_chunk->stream_seq = clib_host_to_net_u16 (0);
1409 
1410  vnet_sctp_set_chunk_type (&data_chunk->chunk_hdr, DATA);
1411  vnet_sctp_set_chunk_length (&data_chunk->chunk_hdr, chunk_length);
1412 
1413  vnet_sctp_set_bbit (&data_chunk->chunk_hdr);
1414  vnet_sctp_set_ebit (&data_chunk->chunk_hdr);
1415 
1416  SCTP_ADV_DBG_OUTPUT ("POINTER_WITH_DATA = %p, DATA_OFFSET = %u",
1417  b->data, b->current_data);
1418 
1419  if (sctp_conn->sub_conn[idx].state != SCTP_SUBCONN_AWAITING_SACK)
1420  {
1421  sctp_conn->sub_conn[idx].state = SCTP_SUBCONN_AWAITING_SACK;
1422  sctp_conn->last_unacked_tsn = sctp_conn->next_tsn;
1423  }
1424 
1425  sctp_conn->next_tsn += data_len;
1426 
1427  u32 inflight = sctp_conn->next_tsn - sctp_conn->last_unacked_tsn;
1428  /* Section 7.2.2; point (3) */
1429  if (sctp_conn->sub_conn[idx].partially_acked_bytes >=
1430  sctp_conn->sub_conn[idx].cwnd
1431  && inflight >= sctp_conn->sub_conn[idx].cwnd)
1432  {
1433  sctp_conn->sub_conn[idx].cwnd += sctp_conn->sub_conn[idx].PMTU;
1434  sctp_conn->sub_conn[idx].partially_acked_bytes -=
1435  sctp_conn->sub_conn[idx].cwnd;
1436  }
1437 
1438  sctp_conn->sub_conn[idx].last_data_ts = sctp_time_now ();
1439 
1440  vnet_buffer (b)->sctp.connection_index =
1441  sctp_conn->sub_conn[idx].connection.c_index;
1442 
1443  vnet_buffer (b)->sctp.subconn_idx = idx;
1444 }
1445 
1446 u32
1448 {
1449  sctp_connection_t *sctp_conn =
1451 
1452  SCTP_DBG_OUTPUT ("TRANS_CONN = %p, SCTP_CONN = %p, "
1453  "S_INDEX = %u, C_INDEX = %u,"
1454  "trans_conn->LCL_PORT = %u, trans_conn->RMT_PORT = %u",
1455  trans_conn,
1456  sctp_conn,
1457  trans_conn->s_index,
1458  trans_conn->c_index,
1459  trans_conn->lcl_port, trans_conn->rmt_port);
1460 
1461  sctp_push_hdr_i (sctp_conn, b, SCTP_STATE_ESTABLISHED);
1462 
1464 
1465  return 0;
1466 }
1467 
1468 u32
1470  u8 idx,
1471  u32 offset,
1472  u32 max_deq_bytes, vlib_buffer_t ** b)
1473 {
1476  int n_bytes = 0;
1477  u32 bi, available_bytes, seg_size;
1478  u8 *data;
1479 
1480  ASSERT (sctp_conn->state >= SCTP_STATE_ESTABLISHED);
1481  ASSERT (max_deq_bytes != 0);
1482 
1483  /*
1484  * Make sure we can retransmit something
1485  */
1486  available_bytes =
1487  session_tx_fifo_max_dequeue (&sctp_conn->sub_conn[idx].connection);
1488  ASSERT (available_bytes >= offset);
1489  available_bytes -= offset;
1490  if (!available_bytes)
1491  return 0;
1492  max_deq_bytes = clib_min (sctp_conn->sub_conn[idx].cwnd, max_deq_bytes);
1493  max_deq_bytes = clib_min (available_bytes, max_deq_bytes);
1494 
1495  seg_size = max_deq_bytes;
1496 
1497  /*
1498  * Allocate and fill in buffer(s)
1499  */
1500 
1501  if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
1502  return 0;
1503  *b = vlib_get_buffer (vm, bi);
1504  data = sctp_init_buffer (vm, *b);
1505 
1506  /* Easy case, buffer size greater than mss */
1507  if (PREDICT_TRUE (seg_size <= tm->bytes_per_buffer))
1508  {
1509  n_bytes =
1510  stream_session_peek_bytes (&sctp_conn->sub_conn[idx].connection, data,
1511  offset, max_deq_bytes);
1512  ASSERT (n_bytes == max_deq_bytes);
1513  b[0]->current_length = n_bytes;
1514  sctp_push_hdr_i (sctp_conn, *b, sctp_conn->state);
1515  }
1516 
1517  return n_bytes;
1518 }
1519 
1520 void
1522 {
1524  vlib_buffer_t *b = 0;
1525  u32 bi, n_bytes = 0;
1526 
1527  u8 idx = sctp_data_subconn_select (sctp_conn);
1528 
1530  ("SCTP_CONN = %p, IDX = %u, S_INDEX = %u, C_INDEX = %u, sctp_conn->[...].LCL_PORT = %u, sctp_conn->[...].RMT_PORT = %u",
1531  sctp_conn, idx, sctp_conn->sub_conn[idx].connection.s_index,
1532  sctp_conn->sub_conn[idx].connection.c_index,
1533  sctp_conn->sub_conn[idx].connection.lcl_port,
1534  sctp_conn->sub_conn[idx].connection.rmt_port);
1535 
1536  if (sctp_conn->state >= SCTP_STATE_ESTABLISHED)
1537  {
1538  return;
1539  }
1540 
1541  n_bytes =
1542  sctp_prepare_data_retransmit (sctp_conn, idx, 0,
1543  sctp_conn->sub_conn[idx].cwnd, &b);
1544  if (n_bytes > 0)
1545  SCTP_DBG_OUTPUT ("We have data (%u bytes) to retransmit", n_bytes);
1546 
1547  bi = vlib_get_buffer_index (vm, b);
1548 
1549  sctp_enqueue_to_output_now (vm, b, bi,
1550  sctp_conn->sub_conn[idx].connection.is_ip4);
1551 
1552  return;
1553 }
1554 
1555 #if SCTP_DEBUG_STATE_MACHINE
1557 sctp_validate_output_state_machine (sctp_connection_t * sctp_conn,
1558  u8 chunk_type)
1559 {
1560  u8 result = 0;
1561  switch (sctp_conn->state)
1562  {
1563  case SCTP_STATE_CLOSED:
1564  if (chunk_type != INIT && chunk_type != INIT_ACK)
1565  result = 1;
1566  break;
1567  case SCTP_STATE_ESTABLISHED:
1568  if (chunk_type != DATA && chunk_type != HEARTBEAT &&
1569  chunk_type != HEARTBEAT_ACK && chunk_type != SACK &&
1570  chunk_type != COOKIE_ACK && chunk_type != SHUTDOWN)
1571  result = 1;
1572  break;
1573  case SCTP_STATE_COOKIE_WAIT:
1574  if (chunk_type != COOKIE_ECHO)
1575  result = 1;
1576  break;
1577  case SCTP_STATE_SHUTDOWN_SENT:
1578  if (chunk_type != SHUTDOWN_COMPLETE)
1579  result = 1;
1580  break;
1581  case SCTP_STATE_SHUTDOWN_RECEIVED:
1582  if (chunk_type != SHUTDOWN_ACK)
1583  result = 1;
1584  break;
1585  }
1586  return result;
1587 }
1588 #endif
1589 
1592 {
1593  return sctp_conn->sub_conn[idx].is_retransmitting;
1594 }
1595 
1598  vlib_node_runtime_t * node,
1599  vlib_frame_t * from_frame, int is_ip4)
1600 {
1601  u32 n_left_from, next_index, *from, *to_next;
1602  u32 my_thread_index = vm->thread_index;
1603 
1604  from = vlib_frame_vector_args (from_frame);
1605  n_left_from = from_frame->n_vectors;
1606  next_index = node->cached_next_index;
1607  sctp_set_time_now (my_thread_index);
1608 
1609  while (n_left_from > 0)
1610  {
1611  u32 n_left_to_next;
1612 
1613  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1614 
1615  while (n_left_from > 0 && n_left_to_next > 0)
1616  {
1617  u32 bi0;
1618  vlib_buffer_t *b0;
1619  sctp_header_t *sctp_hdr = 0;
1620  sctp_connection_t *sctp_conn;
1621  sctp_tx_trace_t *t0;
1622  sctp_header_t *th0 = 0;
1623  u32 error0 = SCTP_ERROR_PKTS_SENT, next0 =
1625 
1626 #if SCTP_DEBUG_STATE_MACHINE
1627  u16 packet_length = 0;
1628 #endif
1629 
1630  bi0 = from[0];
1631  to_next[0] = bi0;
1632  from += 1;
1633  to_next += 1;
1634  n_left_from -= 1;
1635  n_left_to_next -= 1;
1636 
1637  b0 = vlib_get_buffer (vm, bi0);
1638 
1639  sctp_conn =
1640  sctp_connection_get (vnet_buffer (b0)->sctp.connection_index,
1641  my_thread_index);
1642 
1643  if (PREDICT_FALSE (sctp_conn == 0))
1644  {
1645  error0 = SCTP_ERROR_INVALID_CONNECTION;
1646  next0 = SCTP_OUTPUT_NEXT_DROP;
1647  goto done;
1648  }
1649 
1650  u8 idx = vnet_buffer (b0)->sctp.subconn_idx;
1651 
1652  th0 = vlib_buffer_get_current (b0);
1653 
1654  if (is_ip4)
1655  {
1656  ip4_header_t *iph4 = vlib_buffer_push_ip4 (vm,
1657  b0,
1658  &sctp_conn->sub_conn
1659  [idx].connection.
1660  lcl_ip.ip4,
1661  &sctp_conn->
1662  sub_conn
1663  [idx].connection.
1664  rmt_ip.ip4,
1665  IP_PROTOCOL_SCTP, 1);
1666 
1667  u32 checksum = ip4_sctp_compute_checksum (vm, b0, iph4);
1668 
1669  sctp_hdr = ip4_next_header (iph4);
1670  sctp_hdr->checksum = checksum;
1671 
1672  vnet_buffer (b0)->l4_hdr_offset = (u8 *) th0 - b0->data;
1673 
1675  packet_length = clib_net_to_host_u16 (iph4->length);
1676 #endif
1677  }
1678  else
1679  {
1680  ip6_header_t *iph6 = vlib_buffer_push_ip6 (vm,
1681  b0,
1682  &sctp_conn->sub_conn
1683  [idx].
1684  connection.lcl_ip.
1685  ip6,
1686  &sctp_conn->sub_conn
1687  [idx].
1688  connection.rmt_ip.
1689  ip6,
1691 
1692  int bogus = ~0;
1693  u32 checksum = ip6_sctp_compute_checksum (vm, b0, iph6, &bogus);
1694  ASSERT (!bogus);
1695 
1696  sctp_hdr = ip6_next_header (iph6);
1697  sctp_hdr->checksum = checksum;
1698 
1699  vnet_buffer (b0)->l3_hdr_offset = (u8 *) iph6 - b0->data;
1700  vnet_buffer (b0)->l4_hdr_offset = (u8 *) th0 - b0->data;
1701 
1703  packet_length = clib_net_to_host_u16 (iph6->payload_length);
1704 #endif
1705  }
1706 
1707  sctp_full_hdr_t *full_hdr = (sctp_full_hdr_t *) sctp_hdr;
1708  u8 chunk_type = vnet_sctp_get_chunk_type (&full_hdr->common_hdr);
1709  if (chunk_type >= UNKNOWN)
1710  {
1711  clib_warning
1712  ("Trying to send an unrecognized chunk... something is really bad.");
1713  error0 = SCTP_ERROR_UNKNOWN_CHUNK;
1714  next0 = SCTP_OUTPUT_NEXT_DROP;
1715  goto done;
1716  }
1717 
1718 #if SCTP_DEBUG_STATE_MACHINE
1719  u8 is_valid =
1720  (sctp_conn->sub_conn[idx].connection.lcl_port ==
1721  sctp_hdr->src_port
1722  || sctp_conn->sub_conn[idx].connection.lcl_port ==
1723  sctp_hdr->dst_port)
1724  && (sctp_conn->sub_conn[idx].connection.rmt_port ==
1725  sctp_hdr->dst_port
1726  || sctp_conn->sub_conn[idx].connection.rmt_port ==
1727  sctp_hdr->src_port);
1728 
1729  if (!is_valid)
1730  {
1731  SCTP_DBG_STATE_MACHINE ("BUFFER IS INCORRECT: conn_index = %u, "
1732  "packet_length = %u, "
1733  "chunk_type = %u [%s], "
1734  "connection.lcl_port = %u, sctp_hdr->src_port = %u, "
1735  "connection.rmt_port = %u, sctp_hdr->dst_port = %u",
1736  sctp_conn->sub_conn[idx].
1737  connection.c_index, packet_length,
1738  chunk_type,
1739  sctp_chunk_to_string (chunk_type),
1740  sctp_conn->sub_conn[idx].
1741  connection.lcl_port, sctp_hdr->src_port,
1742  sctp_conn->sub_conn[idx].
1743  connection.rmt_port,
1744  sctp_hdr->dst_port);
1745 
1746  error0 = SCTP_ERROR_UNKNOWN_CHUNK;
1747  next0 = SCTP_OUTPUT_NEXT_DROP;
1748  goto done;
1749  }
1750 #endif
1752  ("SESSION_INDEX = %u, CONN_INDEX = %u, CURR_CONN_STATE = %u (%s), "
1753  "CHUNK_TYPE = %s, " "SRC_PORT = %u, DST_PORT = %u",
1754  sctp_conn->sub_conn[idx].connection.s_index,
1755  sctp_conn->sub_conn[idx].connection.c_index,
1756  sctp_conn->state, sctp_state_to_string (sctp_conn->state),
1757  sctp_chunk_to_string (chunk_type), full_hdr->hdr.src_port,
1758  full_hdr->hdr.dst_port);
1759 
1760  /* Let's make sure the state-machine does not send anything crazy */
1761 #if SCTP_DEBUG_STATE_MACHINE
1762  if (sctp_validate_output_state_machine (sctp_conn, chunk_type) != 0)
1763  {
1765  ("Sending the wrong chunk (%s) based on state-machine status (%s)",
1766  sctp_chunk_to_string (chunk_type),
1767  sctp_state_to_string (sctp_conn->state));
1768 
1769  error0 = SCTP_ERROR_UNKNOWN_CHUNK;
1770  next0 = SCTP_OUTPUT_NEXT_DROP;
1771  goto done;
1772 
1773  }
1774 #endif
1775 
1776  /* Karn's algorithm: RTT measurements MUST NOT be made using
1777  * packets that were retransmitted
1778  */
1779  if (!sctp_is_retransmitting (sctp_conn, idx))
1780  {
1781  /* Measure RTT with this */
1782  if (chunk_type == DATA
1783  && sctp_conn->sub_conn[idx].RTO_pending == 0)
1784  {
1785  sctp_conn->sub_conn[idx].RTO_pending = 1;
1786  sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now ();
1787  }
1788  else
1789  sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now ();
1790  }
1791 
1792  /* Let's take care of TIMERS */
1793  switch (chunk_type)
1794  {
1795  case COOKIE_ECHO:
1796  {
1797  sctp_conn->state = SCTP_STATE_COOKIE_ECHOED;
1798  break;
1799  }
1800  case DATA:
1801  {
1802  SCTP_ADV_DBG_OUTPUT ("PACKET_LENGTH = %u", packet_length);
1803 
1804  sctp_timer_update (sctp_conn, idx, SCTP_TIMER_T3_RXTX,
1805  sctp_conn->sub_conn[idx].RTO);
1806  break;
1807  }
1808  case SHUTDOWN:
1809  {
1810  /* Start the SCTP_TIMER_T2_SHUTDOWN timer */
1811  sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T2_SHUTDOWN,
1812  sctp_conn->sub_conn[idx].RTO);
1813  sctp_conn->state = SCTP_STATE_SHUTDOWN_SENT;
1814  break;
1815  }
1816  case SHUTDOWN_ACK:
1817  {
1818  /* Start the SCTP_TIMER_T2_SHUTDOWN timer */
1819  sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T2_SHUTDOWN,
1820  sctp_conn->sub_conn[idx].RTO);
1821  sctp_conn->state = SCTP_STATE_SHUTDOWN_ACK_SENT;
1822  break;
1823  }
1824  case SHUTDOWN_COMPLETE:
1825  {
1826  sctp_conn->state = SCTP_STATE_CLOSED;
1827  break;
1828  }
1829  }
1830 
1831  vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
1832  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1833  sctp_conn->sub_conn[idx].c_fib_index;
1834 
1835  b0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
1836 
1838  ("SESSION_INDEX = %u, CONNECTION_INDEX = %u, " "NEW_STATE = %s, "
1839  "CHUNK_SENT = %s", sctp_conn->sub_conn[idx].connection.s_index,
1840  sctp_conn->sub_conn[idx].connection.c_index,
1841  sctp_state_to_string (sctp_conn->state),
1842  sctp_chunk_to_string (chunk_type));
1843 
1845 
1846  done:
1847  b0->error = node->errors[error0];
1848  if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1849  {
1850  t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
1851  if (th0)
1852  {
1853  clib_memcpy_fast (&t0->sctp_header, th0,
1854  sizeof (t0->sctp_header));
1855  }
1856  else
1857  {
1858  clib_memset (&t0->sctp_header, 0, sizeof (t0->sctp_header));
1859  }
1860  clib_memcpy_fast (&t0->sctp_connection, sctp_conn,
1861  sizeof (t0->sctp_connection));
1862  }
1863 
1864  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1865  n_left_to_next, bi0, next0);
1866  }
1867 
1868  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1869  }
1870 
1871  return from_frame->n_vectors;
1872 }
1873 
1874 static uword
1876  vlib_frame_t * from_frame)
1877 {
1878  return sctp46_output_inline (vm, node, from_frame, 1 /* is_ip4 */ );
1879 }
1880 
1881 static uword
1883  vlib_frame_t * from_frame)
1884 {
1885  return sctp46_output_inline (vm, node, from_frame, 0 /* is_ip4 */ );
1886 }
1887 
1888 /* *INDENT-OFF* */
1890 {
1891  .function = sctp4_output,.name = "sctp4-output",
1892  /* Takes a vector of packets. */
1893  .vector_size = sizeof (u32),
1894  .n_errors = SCTP_N_ERROR,
1895  .error_strings = sctp_error_strings,
1896  .n_next_nodes = SCTP_OUTPUT_N_NEXT,
1897  .next_nodes = {
1898 #define _(s,n) [SCTP_OUTPUT_NEXT_##s] = n,
1900 #undef _
1901  },
1902  .format_buffer = format_sctp_header,
1903  .format_trace = format_sctp_tx_trace,
1904 };
1905 /* *INDENT-ON* */
1906 
1908 
1909 /* *INDENT-OFF* */
1911 {
1912  .function = sctp6_output,
1913  .name = "sctp6-output",
1914  /* Takes a vector of packets. */
1915  .vector_size = sizeof (u32),
1916  .n_errors = SCTP_N_ERROR,
1917  .error_strings = sctp_error_strings,
1918  .n_next_nodes = SCTP_OUTPUT_N_NEXT,
1919  .next_nodes = {
1920 #define _(s,n) [SCTP_OUTPUT_NEXT_##s] = n,
1922 #undef _
1923  },
1924  .format_buffer = format_sctp_header,
1925  .format_trace = format_sctp_tx_trace,
1926 };
1927 /* *INDENT-ON* */
1928 
1930 
1931 /*
1932  * fd.io coding-style-patch-verification: ON
1933  *
1934  * Local Variables:
1935  * eval: (c-set-style "gnu")
1936  * End:
1937  */
#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:1163
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:405
void sctp_connection_timers_reset(sctp_connection_t *sctp_conn)
Stop all connection timers.
Definition: sctp.c:160
u16 sctp_check_outstanding_data_chunks(sctp_connection_t *sctp_conn)
Definition: sctp.c:558
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:594
void session_flush_frames_main_thread(vlib_main_t *vm)
Definition: session.c:1398
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:295
static char * sctp_error_strings[]
Definition: sctp_output.c:38
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:87
ip4_address_t src_address
Definition: ip4_packet.h:170
struct _transport_connection transport_connection_t
void sctp_prepare_cookie_ack_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Definition: sctp_output.c:528
#define SCTP_ADV_DBG_OUTPUT(_fmt, _args...)
Definition: sctp_debug.h:59
static uword sctp46_output_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame, int is_ip4)
Definition: sctp_output.c:1597
#define PREDICT_TRUE(x)
Definition: clib.h:112
#define SCTP_IPV4_ADDRESS_TYPE_LENGTH
Definition: sctp_packet.h:777
u64 as_u64[2]
Definition: ip6_packet.h:51
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 NULL
Definition: clib.h:58
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
#define foreach_sctp4_output_next
Definition: sctp_output.c:30
#define INBOUND_STREAMS_COUNT
Definition: sctp_packet.h:516
vlib_node_registration_t sctp6_output_node
(constructor) VLIB_REGISTER_NODE (sctp6_output_node)
Definition: sctp_output.c:21
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:591
static u64 sctp_time_now(void)
Definition: sctp.h:669
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:731
u32 thread_index
Definition: main.h:179
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:412
int i
uword ip_csum_t
Definition: ip_packet.h:181
static ip_csum_t ip_csum_with_carry(ip_csum_t sum, ip_csum_t x)
Definition: ip_packet.h:184
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:1254
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:493
void sctp_compute_mac(sctp_connection_t *sctp_conn, sctp_state_cookie_param_t *state_cookie)
Definition: sctp_output.c:499
static uword sctp6_output(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: sctp_output.c:1882
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:1339
ip6_address_t src_address
Definition: ip6_packet.h:378
VLIB_NODE_FUNCTION_MULTIARCH(sctp4_output_node, sctp4_output)
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:542
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:103
void sctp_send_shutdown_ack(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Definition: sctp_output.c:1108
void sctp_prepare_sack_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to SACK.
Definition: sctp_output.c:1125
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:1411
sctp_main_t sctp_main
Definition: sctp.c:18
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
static void sctp_init_cwnd(sctp_connection_t *sctp_conn)
Definition: sctp.h:901
#define always_inline
Definition: clib.h:98
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:364
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:181
u8 pre_data[VLIB_BUFFER_PRE_DATA_SIZE]
Space for inserting data before buffer start.
Definition: buffer.h:168
sctp_header_t sctp_hdr
Definition: sctp_packet.h:1338
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:241
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:357
#define SCTP_STATE_COOKIE_TYPE
Definition: sctp_packet.h:780
#define VLIB_FRAME_SIZE
Definition: node.h:401
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
Definition: buffer_funcs.h:158
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:1365
ip6_address_t address
Definition: sctp_packet.h:842
#define SCTP_DBG_OUTPUT(_fmt, _args...)
Definition: sctp_debug.h:52
void sctp_data_retransmit(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:1521
void sctp_prepare_init_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to INIT.
Definition: sctp_output.c:417
static sctp_connection_t * sctp_get_connection_from_transport(transport_connection_t *tconn)
Definition: sctp.h:650
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:690
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:114
static void * vlib_buffer_make_headroom(vlib_buffer_t *b, u8 size)
Make head room, typically for packet headers.
Definition: buffer.h:335
#define MAX_HDRS_LEN
Definition: session.h:31
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
u8 * format_sctp_tx_trace(u8 *s, va_list *args)
Definition: sctp_format.c:26
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:190
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:214
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:323
#define PREDICT_FALSE(x)
Definition: clib.h:111
#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:44
static u64 sctp_set_time_now(u32 thread_index)
Definition: sctp.h:586
static void * sctp_reuse_buffer(vlib_main_t *vm, vlib_buffer_t *b)
Definition: sctp_output.c:254
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:218
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:338
#define MAX_SCTP_CONNECTIONS
Definition: sctp.h:80
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:70
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:139
static char * sctp_state_to_string(u8 state)
Definition: sctp.h:365
u8 len
Definition: ip_types.api:49
static u8 vnet_sctp_get_chunk_type(sctp_chunks_common_hdr_t *h)
Definition: sctp_packet.h:342
sctp_hb_req_chunk_t sctp_hb_ack_chunk_t
Definition: sctp_packet.h:1287
sctp_chunks_common_hdr_t common_hdr
Definition: sctp_packet.h:261
ip4_address_t address
Definition: sctp_packet.h:804
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
enum _sctp_state sctp_state_t
u16 n_vectors
Definition: node.h:420
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:212
vlib_main_t * vm
Definition: buffer.c:301
void sctp_push_ip_hdr(sctp_main_t *tm, sctp_sub_connection_t *sctp_sub_conn, vlib_buffer_t *b)
Definition: sctp_output.c:228
static ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
Definition: ip_packet.h:254
#define IP_PROTOCOL_SCTP
Definition: sctp.h:343
void sctp_send_init(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:1316
#define clib_warning(format, args...)
Definition: error.h:59
#define VLIB_BUFFER_TRACE_TRAJECTORY
Compile time buffer trajectory tracing option Turn this on if you run into "bad monkey" contexts...
Definition: buffer.h:486
void sctp_send_cookie_echo(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:600
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:1077
static int sctp_alloc_tx_buffers(sctp_main_t *tm, u8 thread_index, u32 n_free_buffers)
Definition: sctp_output.c:285
#define sctp_trajectory_add_start(b, start)
Definition: sctp.h:89
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:1271
#define ARRAY_LEN(x)
Definition: clib.h:62
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:452
sctp_opt_params_hdr_t param_hdr
Definition: sctp_packet.h:836
static void * ip6_next_header(ip6_header_t *i)
Definition: ip6_packet.h:405
u32 ip4_sctp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip4_header_t *ip0)
Definition: sctp_output.c:97
enum _sctp_output_next sctp_output_next_t
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:546
void sctp_prepare_shutdown_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to SHUTDOWN.
Definition: sctp_output.c:1014
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:537
#define ASSERT(truth)
sctp_opt_params_hdr_t param_hdr
Definition: sctp_packet.h:1313
u32 session_tx_fifo_max_dequeue(transport_connection_t *tc)
Definition: session.c:498
#define SCTP_PRIMARY_PATH_IDX
Definition: sctp.h:81
static u8 sctp_is_retransmitting(sctp_connection_t *sctp_conn, u8 idx)
Definition: sctp_output.c:1591
sctp_connection_t sctp_connection
Definition: sctp_output.c:47
static u16 vnet_sctp_calculate_padding(u16 base_length)
Definition: sctp_packet.h:508
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:130
#define SCTP_CONN_TRACKING_DBG(_fmt, _args...)
Definition: sctp_debug.h:66
format_function_t format_sctp_header
Definition: format.h:101
static void * sctp_init_buffer(vlib_main_t *vm, vlib_buffer_t *b)
Definition: sctp_output.c:271
#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:528
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:414
sctp_header_t sctp_header
Definition: sctp_output.c:46
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static void sctp_timer_update(sctp_connection_t *tc, u8 conn_idx, u8 timer_id, u32 interval)
Definition: sctp.h:730
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:57
sctp_hb_info_param_t hb_info
Definition: sctp_packet.h:1255
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
Definition: buffer.h:156
struct _vlib_node_registration vlib_node_registration_t
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:1202
Definition: defs.h:47
void sctp_send_shutdown_complete(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b0)
Definition: sctp_output.c:1299
static void * vlib_buffer_push_uninit(vlib_buffer_t *b, u8 size)
Prepend uninitialized data to buffer.
Definition: buffer.h:320
static sctp_connection_t * sctp_connection_get(u32 conn_index, u32 thread_index)
Definition: sctp.h:755
u16 payload_length
Definition: ip6_packet.h:369
#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:154
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:1469
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:632
void sctp_send_heartbeat(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:1234
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:54
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:645
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
sctp_err_cause_param_t err_causes[]
Definition: sctp_packet.h:1340
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
Definition: buffer.h:495
u64 uword
Definition: types.h:112
#define SCTP_VALID_COOKIE_LIFE
Definition: sctp.h:462
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
#define SCTP_DEBUG_STATE_MACHINE
Definition: sctp_debug.h:27
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:1447
void sctp_prepare_cookie_echo_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b, u8 reuse_buffer)
Definition: sctp_output.c:562
#define vnet_buffer(b)
Definition: buffer.h:368
static char * sctp_chunk_to_string(u8 type)
Definition: sctp.h:390
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:630
static uword sctp4_output(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: sctp_output.c:1875
#define ENDIANESS_SWAP(x)
Definition: sctp.h:175
static u32 vlib_num_workers()
Definition: threads.h:366
#define SCTP_HB_INTERVAL
Definition: sctp.h:466
u8 data[0]
Packet data.
Definition: buffer.h:176
static void * vlib_buffer_put_uninit(vlib_buffer_t *b, u16 size)
Append uninitialized data to buffer.
Definition: buffer.h:306
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:570
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:307
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:766
sctp_header_t hdr
Definition: sctp_packet.h:260
#define SCTP_IPV6_ADDRESS_TYPE_LENGTH
Definition: sctp_packet.h:779
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:117
static u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:485
#define BITS(x)
Definition: clib.h:61
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:1075
int stream_session_peek_bytes(transport_connection_t *tc, u8 *buffer, u32 offset, u32 max_bytes)
Definition: session.c:507
sctp_opt_params_hdr_t param_hdr
Definition: sctp_packet.h:798
#define foreach_sctp6_output_next
Definition: sctp_output.c:34
static void vnet_sctp_set_chunk_length(sctp_chunks_common_hdr_t *h, u16 length)
Definition: sctp_packet.h:348
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:370
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:62
vlib_node_registration_t sctp4_output_node
(constructor) VLIB_REGISTER_NODE (sctp4_output_node)
Definition: sctp_output.c:20
#define SCTP_DBG_STATE_MACHINE(_fmt, _args...)
Definition: sctp_debug.h:31
#define SCTP_MAX_INIT_RETRANS
Definition: sctp.h:465
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:871
void sctp_send_shutdown(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:1050
Definition: defs.h:46
ip6_address_t dst_address
Definition: ip6_packet.h:378
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:1374