FD.io VPP  v18.04-17-g3a0d853
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 }
410 
411 /**
412  * Convert buffer to INIT
413  */
414 void
416  vlib_buffer_t * b)
417 {
418  u32 random_seed = random_default_seed ();
419  u16 alloc_bytes = sizeof (sctp_init_chunk_t);
420  sctp_sub_connection_t *sub_conn = &sctp_conn->sub_conn[idx];
421 
422  sctp_ipv4_addr_param_t *ip4_param = 0;
423  sctp_ipv6_addr_param_t *ip6_param = 0;
424 
425  if (sub_conn->c_is_ip4)
426  alloc_bytes += sizeof (sctp_ipv4_addr_param_t);
427  else
428  alloc_bytes += sizeof (sctp_ipv6_addr_param_t);
429 
430  /* As per RFC 4960 the chunk_length value does NOT contemplate
431  * the size of the first header (see sctp_header_t) and any padding
432  */
433  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
434 
435  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
436 
437  sctp_init_chunk_t *init_chunk = vlib_buffer_push_uninit (b, alloc_bytes);
438 
439  u16 pointer_offset = sizeof (init_chunk);
440  if (sub_conn->c_is_ip4)
441  {
442  ip4_param = (sctp_ipv4_addr_param_t *) init_chunk + pointer_offset;
443  ip4_param->address.as_u32 = sub_conn->c_lcl_ip.ip4.as_u32;
444 
445  pointer_offset += sizeof (sctp_ipv4_addr_param_t);
446  }
447  else
448  {
449  ip6_param = (sctp_ipv6_addr_param_t *) init_chunk + pointer_offset;
450  ip6_param->address.as_u64[0] = sub_conn->c_lcl_ip.ip6.as_u64[0];
451  ip6_param->address.as_u64[1] = sub_conn->c_lcl_ip.ip6.as_u64[1];
452 
453  pointer_offset += sizeof (sctp_ipv6_addr_param_t);
454  }
455 
456  init_chunk->sctp_hdr.src_port = sub_conn->c_lcl_port; /* No need of host_to_net conversion, already in net-byte order */
457  init_chunk->sctp_hdr.dst_port = sub_conn->c_rmt_port; /* No need of host_to_net conversion, already in net-byte order */
458  init_chunk->sctp_hdr.checksum = 0;
459  /* The sender of an INIT must set the VERIFICATION_TAG to 0 as per RFC 4960 Section 8.5.1 */
460  init_chunk->sctp_hdr.verification_tag = 0x0;
461 
462  vnet_sctp_set_chunk_type (&init_chunk->chunk_hdr, INIT);
463  vnet_sctp_set_chunk_length (&init_chunk->chunk_hdr, chunk_len);
465 
466  sctp_init_cwnd (sctp_conn);
467 
468  init_chunk->a_rwnd = clib_host_to_net_u32 (sctp_conn->sub_conn[idx].cwnd);
469  init_chunk->initiate_tag = clib_host_to_net_u32 (random_u32 (&random_seed));
470  init_chunk->inboud_streams_count =
471  clib_host_to_net_u16 (INBOUND_STREAMS_COUNT);
472  init_chunk->outbound_streams_count =
473  clib_host_to_net_u16 (OUTBOUND_STREAMS_COUNT);
474 
475  init_chunk->initial_tsn =
476  clib_host_to_net_u32 (sctp_conn->local_initial_tsn);
477  SCTP_CONN_TRACKING_DBG ("sctp_conn->local_initial_tsn = %u",
478  sctp_conn->local_initial_tsn);
479 
480  sctp_conn->local_tag = init_chunk->initiate_tag;
481 
482  vnet_buffer (b)->sctp.connection_index = sub_conn->c_c_index;
483  vnet_buffer (b)->sctp.subconn_idx = idx;
484 
485  SCTP_DBG_STATE_MACHINE ("CONN_INDEX = %u, CURR_CONN_STATE = %u (%s), "
486  "CHUNK_TYPE = %s, "
487  "SRC_PORT = %u, DST_PORT = %u",
488  sub_conn->connection.c_index,
489  sctp_conn->state,
490  sctp_state_to_string (sctp_conn->state),
492  init_chunk->sctp_hdr.src_port,
493  init_chunk->sctp_hdr.dst_port);
494 }
495 
496 void
498  sctp_state_cookie_param_t * state_cookie)
499 {
500 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
501  HMAC_CTX *ctx;
502 #else
503  HMAC_CTX ctx;
504 #endif
505  unsigned int len = 0;
506  const EVP_MD *md = EVP_sha1 ();
507 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
508  ctx = HMAC_CTX_new ();
509  HMAC_Init_ex (ctx, &state_cookie->creation_time,
510  sizeof (state_cookie->creation_time), md, NULL);
511  HMAC_Update (ctx, (const unsigned char *) &sctp_conn, sizeof (sctp_conn));
512  HMAC_Final (ctx, state_cookie->mac, &len);
513 #else
514  HMAC_CTX_init (&ctx);
515  HMAC_Init_ex (&ctx, &state_cookie->creation_time,
516  sizeof (state_cookie->creation_time), md, NULL);
517  HMAC_Update (&ctx, (const unsigned char *) &sctp_conn, sizeof (sctp_conn));
518  HMAC_Final (&ctx, state_cookie->mac, &len);
519  HMAC_CTX_cleanup (&ctx);
520 #endif
521 
522  ENDIANESS_SWAP (state_cookie->mac);
523 }
524 
525 void
527  vlib_buffer_t * b)
528 {
530 
531  sctp_reuse_buffer (vm, b);
532 
533  u16 alloc_bytes = sizeof (sctp_cookie_ack_chunk_t);
534 
535  /* As per RFC 4960 the chunk_length value does NOT contemplate
536  * the size of the first header (see sctp_header_t) and any padding
537  */
538  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
539 
540  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
541 
542  sctp_cookie_ack_chunk_t *cookie_ack_chunk =
543  vlib_buffer_push_uninit (b, alloc_bytes);
544 
545  cookie_ack_chunk->sctp_hdr.checksum = 0;
546  cookie_ack_chunk->sctp_hdr.src_port =
547  sctp_conn->sub_conn[idx].connection.lcl_port;
548  cookie_ack_chunk->sctp_hdr.dst_port =
549  sctp_conn->sub_conn[idx].connection.rmt_port;
550  cookie_ack_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
551  vnet_sctp_set_chunk_type (&cookie_ack_chunk->chunk_hdr, COOKIE_ACK);
552  vnet_sctp_set_chunk_length (&cookie_ack_chunk->chunk_hdr, chunk_len);
553 
554  vnet_buffer (b)->sctp.connection_index =
555  sctp_conn->sub_conn[idx].connection.c_index;
556  vnet_buffer (b)->sctp.subconn_idx = idx;
557 }
558 
559 void
561  vlib_buffer_t * b, u8 reuse_buffer)
562 {
564 
565  if (reuse_buffer)
566  sctp_reuse_buffer (vm, b);
567 
568  /* The minimum size of the message is given by the sctp_init_ack_chunk_t */
569  u16 alloc_bytes = sizeof (sctp_cookie_echo_chunk_t);
570  /* As per RFC 4960 the chunk_length value does NOT contemplate
571  * the size of the first header (see sctp_header_t) and any padding
572  */
573  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
574  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
575  sctp_cookie_echo_chunk_t *cookie_echo_chunk =
576  vlib_buffer_push_uninit (b, alloc_bytes);
577  cookie_echo_chunk->sctp_hdr.checksum = 0;
578  cookie_echo_chunk->sctp_hdr.src_port =
579  sctp_conn->sub_conn[idx].connection.lcl_port;
580  cookie_echo_chunk->sctp_hdr.dst_port =
581  sctp_conn->sub_conn[idx].connection.rmt_port;
582  cookie_echo_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
583  vnet_sctp_set_chunk_type (&cookie_echo_chunk->chunk_hdr, COOKIE_ECHO);
584  vnet_sctp_set_chunk_length (&cookie_echo_chunk->chunk_hdr, chunk_len);
585  clib_memcpy (&(cookie_echo_chunk->cookie), &sctp_conn->cookie_param,
586  sizeof (sctp_state_cookie_param_t));
587 
588  vnet_buffer (b)->sctp.connection_index =
589  sctp_conn->sub_conn[idx].connection.c_index;
590  vnet_buffer (b)->sctp.subconn_idx = idx;
591 }
592 
593 
594 /*
595  * Send COOKIE_ECHO
596  */
597 void
599 {
600  vlib_buffer_t *b;
601  u32 bi;
604 
605  if (PREDICT_FALSE (sctp_conn->init_retransmit_err > SCTP_MAX_INIT_RETRANS))
606  {
607  clib_warning ("Reached MAX_INIT_RETRANS times. Aborting connection.");
608 
609  session_stream_connect_notify (&sctp_conn->sub_conn
610  [SCTP_PRIMARY_PATH_IDX].connection, 1);
611 
612  sctp_connection_timers_reset (sctp_conn);
613 
614  sctp_connection_cleanup (sctp_conn);
615  }
616 
618  return;
619 
620  b = vlib_get_buffer (vm, bi);
622 
623  sctp_init_buffer (vm, b);
624  sctp_prepare_cookie_echo_chunk (sctp_conn, idx, b, 0);
625  sctp_enqueue_to_output_now (vm, b, bi, sctp_conn->sub_conn[idx].c_is_ip4);
626 
627  /* Start the T1_INIT timer */
628  sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T1_INIT,
629  sctp_conn->sub_conn[idx].RTO);
630 
631  /* Change state to COOKIE_WAIT */
632  sctp_conn->state = SCTP_STATE_COOKIE_WAIT;
633 
634  /* Measure RTT with this */
635  sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now ();
636 }
637 
638 
639 /**
640  * Convert buffer to ERROR
641  */
642 void
644  vlib_buffer_t * b, u8 err_cause)
645 {
647 
648  sctp_reuse_buffer (vm, b);
649 
650  /* The minimum size of the message is given by the sctp_operation_error_t */
651  u16 alloc_bytes =
653 
654  /* As per RFC 4960 the chunk_length value does NOT contemplate
655  * the size of the first header (see sctp_header_t) and any padding
656  */
657  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
658 
659  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
660 
661  sctp_operation_error_t *err_chunk =
662  vlib_buffer_push_uninit (b, alloc_bytes);
663 
664  /* src_port & dst_port are already in network byte-order */
665  err_chunk->sctp_hdr.checksum = 0;
666  err_chunk->sctp_hdr.src_port = sctp_conn->sub_conn[idx].connection.lcl_port;
667  err_chunk->sctp_hdr.dst_port = sctp_conn->sub_conn[idx].connection.rmt_port;
668  /* As per RFC4960 Section 5.2.2: copy the INITIATE_TAG into the VERIFICATION_TAG of the ABORT chunk */
669  err_chunk->sctp_hdr.verification_tag = sctp_conn->local_tag;
670 
671  err_chunk->err_causes[0].param_hdr.length =
672  clib_host_to_net_u16 (sizeof (err_chunk->err_causes[0].param_hdr.type) +
673  sizeof (err_chunk->err_causes[0].param_hdr.length));
674  err_chunk->err_causes[0].param_hdr.type = clib_host_to_net_u16 (err_cause);
675 
677  vnet_sctp_set_chunk_length (&err_chunk->chunk_hdr, chunk_len);
678 
679  vnet_buffer (b)->sctp.connection_index =
680  sctp_conn->sub_conn[idx].connection.c_index;
681  vnet_buffer (b)->sctp.subconn_idx = idx;
682 }
683 
684 /**
685  * Convert buffer to ABORT
686  */
687 void
689  vlib_buffer_t * b, ip4_address_t * ip4_addr,
690  ip6_address_t * ip6_addr)
691 {
693 
694  sctp_reuse_buffer (vm, b);
695 
696  /* The minimum size of the message is given by the sctp_abort_chunk_t */
697  u16 alloc_bytes = sizeof (sctp_abort_chunk_t);
698 
699  /* As per RFC 4960 the chunk_length value does NOT contemplate
700  * the size of the first header (see sctp_header_t) and any padding
701  */
702  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
703 
704  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
705 
706  sctp_abort_chunk_t *abort_chunk = vlib_buffer_push_uninit (b, alloc_bytes);
707 
708  /* src_port & dst_port are already in network byte-order */
709  abort_chunk->sctp_hdr.checksum = 0;
710  abort_chunk->sctp_hdr.src_port =
711  sctp_conn->sub_conn[idx].connection.lcl_port;
712  abort_chunk->sctp_hdr.dst_port =
713  sctp_conn->sub_conn[idx].connection.rmt_port;
714  /* As per RFC4960 Section 5.2.2: copy the INITIATE_TAG into the VERIFICATION_TAG of the ABORT chunk */
715  abort_chunk->sctp_hdr.verification_tag = sctp_conn->local_tag;
716 
717  vnet_sctp_set_chunk_type (&abort_chunk->chunk_hdr, ABORT);
718  vnet_sctp_set_chunk_length (&abort_chunk->chunk_hdr, chunk_len);
719 
720  vnet_buffer (b)->sctp.connection_index =
721  sctp_conn->sub_conn[idx].connection.c_index;
722  vnet_buffer (b)->sctp.subconn_idx = idx;
723 }
724 
725 /**
726  * Convert buffer to INIT-ACK
727  */
728 void
730  u8 idx, vlib_buffer_t * b,
731  ip4_address_t * ip4_addr,
732  ip6_address_t * ip6_addr)
733 {
735  sctp_ipv4_addr_param_t *ip4_param = 0;
736  sctp_ipv6_addr_param_t *ip6_param = 0;
737 
738  sctp_reuse_buffer (vm, b);
739 
740  /* The minimum size of the message is given by the sctp_init_ack_chunk_t */
741  u16 alloc_bytes =
743 
744  if (PREDICT_TRUE (ip4_addr != NULL))
745  {
746  /* Create room for variable-length fields in the INIT_ACK chunk */
747  alloc_bytes += SCTP_IPV4_ADDRESS_TYPE_LENGTH;
748  }
749  if (PREDICT_TRUE (ip6_addr != NULL))
750  {
751  /* Create room for variable-length fields in the INIT_ACK chunk */
752  alloc_bytes += SCTP_IPV6_ADDRESS_TYPE_LENGTH;
753  }
754 
755  if (sctp_conn->sub_conn[idx].connection.is_ip4)
756  alloc_bytes += sizeof (sctp_ipv4_addr_param_t);
757  else
758  alloc_bytes += sizeof (sctp_ipv6_addr_param_t);
759 
760  /* As per RFC 4960 the chunk_length value does NOT contemplate
761  * the size of the first header (see sctp_header_t) and any padding
762  */
763  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
764 
765  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
766 
767  sctp_init_ack_chunk_t *init_ack_chunk =
768  vlib_buffer_push_uninit (b, alloc_bytes);
769 
770  u16 pointer_offset = sizeof (sctp_init_ack_chunk_t);
771 
772  /* Create State Cookie parameter */
773  sctp_state_cookie_param_t *state_cookie_param =
774  (sctp_state_cookie_param_t *) ((char *) init_ack_chunk + pointer_offset);
775 
776  state_cookie_param->param_hdr.type =
777  clib_host_to_net_u16 (SCTP_STATE_COOKIE_TYPE);
778  state_cookie_param->param_hdr.length =
779  clib_host_to_net_u16 (sizeof (sctp_state_cookie_param_t));
780  state_cookie_param->creation_time = clib_host_to_net_u32 (sctp_time_now ());
781  state_cookie_param->cookie_lifespan =
782  clib_host_to_net_u32 (SCTP_VALID_COOKIE_LIFE);
783 
784  sctp_compute_mac (sctp_conn, state_cookie_param);
785 
786  pointer_offset += sizeof (sctp_state_cookie_param_t);
787 
788  if (PREDICT_TRUE (ip4_addr != NULL))
789  {
790  sctp_ipv4_addr_param_t *ipv4_addr =
791  (sctp_ipv4_addr_param_t *) init_ack_chunk + pointer_offset;
792 
793  ipv4_addr->param_hdr.type =
794  clib_host_to_net_u16 (SCTP_IPV4_ADDRESS_TYPE);
795  ipv4_addr->param_hdr.length =
796  clib_host_to_net_u16 (SCTP_IPV4_ADDRESS_TYPE_LENGTH);
797  ipv4_addr->address.as_u32 = ip4_addr->as_u32;
798 
799  pointer_offset += SCTP_IPV4_ADDRESS_TYPE_LENGTH;
800  }
801  if (PREDICT_TRUE (ip6_addr != NULL))
802  {
803  sctp_ipv6_addr_param_t *ipv6_addr =
804  (sctp_ipv6_addr_param_t *) init_ack_chunk + pointer_offset;
805 
806  ipv6_addr->param_hdr.type =
807  clib_host_to_net_u16 (SCTP_IPV6_ADDRESS_TYPE);
808  ipv6_addr->param_hdr.length =
809  clib_host_to_net_u16 (SCTP_IPV6_ADDRESS_TYPE_LENGTH);
810  ipv6_addr->address.as_u64[0] = ip6_addr->as_u64[0];
811  ipv6_addr->address.as_u64[1] = ip6_addr->as_u64[1];
812 
813  pointer_offset += SCTP_IPV6_ADDRESS_TYPE_LENGTH;
814  }
815 
816  if (sctp_conn->sub_conn[idx].connection.is_ip4)
817  {
818  ip4_param = (sctp_ipv4_addr_param_t *) init_ack_chunk + pointer_offset;
819  ip4_param->address.as_u32 =
820  sctp_conn->sub_conn[idx].connection.lcl_ip.ip4.as_u32;
821 
822  pointer_offset += sizeof (sctp_ipv4_addr_param_t);
823  }
824  else
825  {
826  ip6_param = (sctp_ipv6_addr_param_t *) init_ack_chunk + pointer_offset;
827  ip6_param->address.as_u64[0] =
828  sctp_conn->sub_conn[idx].connection.lcl_ip.ip6.as_u64[0];
829  ip6_param->address.as_u64[1] =
830  sctp_conn->sub_conn[idx].connection.lcl_ip.ip6.as_u64[1];
831 
832  pointer_offset += sizeof (sctp_ipv6_addr_param_t);
833  }
834 
835  /* src_port & dst_port are already in network byte-order */
836  init_ack_chunk->sctp_hdr.checksum = 0;
837  init_ack_chunk->sctp_hdr.src_port =
838  sctp_conn->sub_conn[idx].connection.lcl_port;
839  init_ack_chunk->sctp_hdr.dst_port =
840  sctp_conn->sub_conn[idx].connection.rmt_port;
841  /* the sctp_conn->verification_tag is already in network byte-order (being a copy of the init_tag coming with the INIT chunk) */
842  init_ack_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
843  init_ack_chunk->initial_tsn =
844  clib_host_to_net_u32 (sctp_conn->local_initial_tsn);
845  SCTP_CONN_TRACKING_DBG ("init_ack_chunk->initial_tsn = %u",
846  init_ack_chunk->initial_tsn);
847 
848  vnet_sctp_set_chunk_type (&init_ack_chunk->chunk_hdr, INIT_ACK);
849  vnet_sctp_set_chunk_length (&init_ack_chunk->chunk_hdr, chunk_len);
850 
851  init_ack_chunk->initiate_tag = sctp_conn->local_tag;
852 
853  init_ack_chunk->a_rwnd =
854  clib_host_to_net_u32 (sctp_conn->sub_conn[idx].cwnd);
855  init_ack_chunk->inboud_streams_count =
856  clib_host_to_net_u16 (INBOUND_STREAMS_COUNT);
857  init_ack_chunk->outbound_streams_count =
858  clib_host_to_net_u16 (OUTBOUND_STREAMS_COUNT);
859 
860  vnet_buffer (b)->sctp.connection_index =
861  sctp_conn->sub_conn[idx].connection.c_index;
862  vnet_buffer (b)->sctp.subconn_idx = idx;
863 }
864 
865 /**
866  * Convert buffer to INIT-ACK
867  */
868 void
870  vlib_buffer_t * b, ip4_address_t * ip4_addr,
871  u8 add_ip4, ip6_address_t * ip6_addr, u8 add_ip6)
872 {
874  sctp_ipv4_addr_param_t *ip4_param = 0;
875  sctp_ipv6_addr_param_t *ip6_param = 0;
876  u32 random_seed = random_default_seed ();
877 
878  sctp_reuse_buffer (vm, b);
879 
880  /* The minimum size of the message is given by the sctp_init_ack_chunk_t */
881  u16 alloc_bytes =
883 
884  if (PREDICT_FALSE (add_ip4 == 1))
885  {
886  /* Create room for variable-length fields in the INIT_ACK chunk */
887  alloc_bytes += SCTP_IPV4_ADDRESS_TYPE_LENGTH;
888  }
889  if (PREDICT_FALSE (add_ip6 == 1))
890  {
891  /* Create room for variable-length fields in the INIT_ACK chunk */
892  alloc_bytes += SCTP_IPV6_ADDRESS_TYPE_LENGTH;
893  }
894 
895  if (sctp_conn->sub_conn[idx].connection.is_ip4)
896  alloc_bytes += sizeof (sctp_ipv4_addr_param_t);
897  else
898  alloc_bytes += sizeof (sctp_ipv6_addr_param_t);
899 
900  /* As per RFC 4960 the chunk_length value does NOT contemplate
901  * the size of the first header (see sctp_header_t) and any padding
902  */
903  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
904 
905  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
906 
907  sctp_init_ack_chunk_t *init_ack_chunk =
908  vlib_buffer_push_uninit (b, alloc_bytes);
909 
910  u16 pointer_offset = sizeof (sctp_init_ack_chunk_t);
911 
912  /* Create State Cookie parameter */
913  sctp_state_cookie_param_t *state_cookie_param =
914  (sctp_state_cookie_param_t *) ((char *) init_ack_chunk + pointer_offset);
915 
916  state_cookie_param->param_hdr.type =
917  clib_host_to_net_u16 (SCTP_STATE_COOKIE_TYPE);
918  state_cookie_param->param_hdr.length =
919  clib_host_to_net_u16 (sizeof (sctp_state_cookie_param_t));
920  state_cookie_param->creation_time = clib_host_to_net_u32 (sctp_time_now ());
921  state_cookie_param->cookie_lifespan =
922  clib_host_to_net_u32 (SCTP_VALID_COOKIE_LIFE);
923 
924  sctp_compute_mac (sctp_conn, state_cookie_param);
925 
926  pointer_offset += sizeof (sctp_state_cookie_param_t);
927 
928  if (PREDICT_TRUE (ip4_addr != NULL))
929  {
930  sctp_ipv4_addr_param_t *ipv4_addr =
931  (sctp_ipv4_addr_param_t *) init_ack_chunk + pointer_offset;
932 
933  ipv4_addr->param_hdr.type =
934  clib_host_to_net_u16 (SCTP_IPV4_ADDRESS_TYPE);
935  ipv4_addr->param_hdr.length =
936  clib_host_to_net_u16 (SCTP_IPV4_ADDRESS_TYPE_LENGTH);
937  ipv4_addr->address.as_u32 = ip4_addr->as_u32;
938 
939  pointer_offset += SCTP_IPV4_ADDRESS_TYPE_LENGTH;
940  }
941  if (PREDICT_TRUE (ip6_addr != NULL))
942  {
943  sctp_ipv6_addr_param_t *ipv6_addr =
944  (sctp_ipv6_addr_param_t *) init_ack_chunk + pointer_offset;
945 
946  ipv6_addr->param_hdr.type =
947  clib_host_to_net_u16 (SCTP_IPV6_ADDRESS_TYPE);
948  ipv6_addr->param_hdr.length =
949  clib_host_to_net_u16 (SCTP_IPV6_ADDRESS_TYPE_LENGTH);
950  ipv6_addr->address.as_u64[0] = ip6_addr->as_u64[0];
951  ipv6_addr->address.as_u64[1] = ip6_addr->as_u64[1];
952 
953  pointer_offset += SCTP_IPV6_ADDRESS_TYPE_LENGTH;
954  }
955 
956  if (sctp_conn->sub_conn[idx].connection.is_ip4)
957  {
958  ip4_param = (sctp_ipv4_addr_param_t *) init_ack_chunk + pointer_offset;
959  ip4_param->address.as_u32 =
960  sctp_conn->sub_conn[idx].connection.lcl_ip.ip4.as_u32;
961 
962  pointer_offset += sizeof (sctp_ipv4_addr_param_t);
963  }
964  else
965  {
966  ip6_param = (sctp_ipv6_addr_param_t *) init_ack_chunk + pointer_offset;
967  ip6_param->address.as_u64[0] =
968  sctp_conn->sub_conn[idx].connection.lcl_ip.ip6.as_u64[0];
969  ip6_param->address.as_u64[1] =
970  sctp_conn->sub_conn[idx].connection.lcl_ip.ip6.as_u64[1];
971 
972  pointer_offset += sizeof (sctp_ipv6_addr_param_t);
973  }
974 
975  /* src_port & dst_port are already in network byte-order */
976  init_ack_chunk->sctp_hdr.checksum = 0;
977  init_ack_chunk->sctp_hdr.src_port =
978  sctp_conn->sub_conn[idx].connection.lcl_port;
979  init_ack_chunk->sctp_hdr.dst_port =
980  sctp_conn->sub_conn[idx].connection.rmt_port;
981  /* the sctp_conn->verification_tag is already in network byte-order (being a copy of the init_tag coming with the INIT chunk) */
982  init_ack_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
983  init_ack_chunk->initial_tsn =
984  clib_host_to_net_u32 (sctp_conn->local_initial_tsn);
985  SCTP_CONN_TRACKING_DBG ("init_ack_chunk->initial_tsn = %u",
986  init_ack_chunk->initial_tsn);
987 
988  vnet_sctp_set_chunk_type (&init_ack_chunk->chunk_hdr, INIT_ACK);
989  vnet_sctp_set_chunk_length (&init_ack_chunk->chunk_hdr, chunk_len);
990 
991  init_ack_chunk->initiate_tag =
992  clib_host_to_net_u32 (random_u32 (&random_seed));
993 
994  init_ack_chunk->a_rwnd =
995  clib_host_to_net_u32 (sctp_conn->sub_conn[idx].cwnd);
996  init_ack_chunk->inboud_streams_count =
997  clib_host_to_net_u16 (INBOUND_STREAMS_COUNT);
998  init_ack_chunk->outbound_streams_count =
999  clib_host_to_net_u16 (OUTBOUND_STREAMS_COUNT);
1000 
1001  sctp_conn->local_tag = init_ack_chunk->initiate_tag;
1002 
1003  vnet_buffer (b)->sctp.connection_index =
1004  sctp_conn->sub_conn[idx].connection.c_index;
1005  vnet_buffer (b)->sctp.subconn_idx = idx;
1006 }
1007 
1008 /**
1009  * Convert buffer to SHUTDOWN
1010  */
1011 void
1013  vlib_buffer_t * b)
1014 {
1015  u16 alloc_bytes = sizeof (sctp_shutdown_association_chunk_t);
1016 
1017  /* As per RFC 4960 the chunk_length value does NOT contemplate
1018  * the size of the first header (see sctp_header_t) and any padding
1019  */
1020  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1021 
1022  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1023 
1024  sctp_shutdown_association_chunk_t *shutdown_chunk =
1025  vlib_buffer_push_uninit (b, alloc_bytes);
1026 
1027  shutdown_chunk->sctp_hdr.checksum = 0;
1028  /* No need of host_to_net conversion, already in net-byte order */
1029  shutdown_chunk->sctp_hdr.src_port =
1030  sctp_conn->sub_conn[idx].connection.lcl_port;
1031  shutdown_chunk->sctp_hdr.dst_port =
1032  sctp_conn->sub_conn[idx].connection.rmt_port;
1033  shutdown_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1034  vnet_sctp_set_chunk_type (&shutdown_chunk->chunk_hdr, SHUTDOWN);
1035  vnet_sctp_set_chunk_length (&shutdown_chunk->chunk_hdr, chunk_len);
1036 
1037  shutdown_chunk->cumulative_tsn_ack = sctp_conn->last_rcvd_tsn;
1038 
1039  vnet_buffer (b)->sctp.connection_index =
1040  sctp_conn->sub_conn[idx].connection.c_index;
1041  vnet_buffer (b)->sctp.subconn_idx = idx;
1042 }
1043 
1044 /*
1045  * Send SHUTDOWN
1046  */
1047 void
1049 {
1050  vlib_buffer_t *b;
1051  u32 bi;
1054 
1055  if (sctp_check_outstanding_data_chunks (sctp_conn) > 0)
1056  return;
1057 
1058  if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
1059  return;
1060 
1061  u8 idx = SCTP_PRIMARY_PATH_IDX;
1062 
1063  b = vlib_get_buffer (vm, bi);
1064  sctp_init_buffer (vm, b);
1065  sctp_prepare_shutdown_chunk (sctp_conn, idx, b);
1066 
1067  sctp_enqueue_to_output_now (vm, b, bi,
1068  sctp_conn->sub_conn[idx].connection.is_ip4);
1069 }
1070 
1071 /**
1072  * Convert buffer to SHUTDOWN_ACK
1073  */
1074 void
1076  vlib_buffer_t * b)
1077 {
1078  u16 alloc_bytes = sizeof (sctp_shutdown_association_chunk_t);
1079  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1080 
1081  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1082 
1083  sctp_shutdown_ack_chunk_t *shutdown_ack_chunk =
1084  vlib_buffer_push_uninit (b, alloc_bytes);
1085 
1086  shutdown_ack_chunk->sctp_hdr.checksum = 0;
1087  /* No need of host_to_net conversion, already in net-byte order */
1088  shutdown_ack_chunk->sctp_hdr.src_port =
1089  sctp_conn->sub_conn[idx].connection.lcl_port;
1090  shutdown_ack_chunk->sctp_hdr.dst_port =
1091  sctp_conn->sub_conn[idx].connection.rmt_port;
1092  shutdown_ack_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1093 
1094  vnet_sctp_set_chunk_type (&shutdown_ack_chunk->chunk_hdr, SHUTDOWN_ACK);
1095  vnet_sctp_set_chunk_length (&shutdown_ack_chunk->chunk_hdr, chunk_len);
1096 
1097  vnet_buffer (b)->sctp.connection_index =
1098  sctp_conn->sub_conn[idx].connection.c_index;
1099  vnet_buffer (b)->sctp.subconn_idx = idx;
1100 }
1101 
1102 /*
1103  * Send SHUTDOWN_ACK
1104  */
1105 void
1107  vlib_buffer_t * b)
1108 {
1110 
1111  if (sctp_check_outstanding_data_chunks (sctp_conn) > 0)
1112  return;
1113 
1114  sctp_reuse_buffer (vm, b);
1115 
1116  sctp_prepare_shutdown_ack_chunk (sctp_conn, idx, b);
1117 }
1118 
1119 /**
1120  * Convert buffer to SACK
1121  */
1122 void
1124  vlib_buffer_t * b)
1125 {
1127 
1128  sctp_reuse_buffer (vm, b);
1129 
1130  u16 alloc_bytes = sizeof (sctp_selective_ack_chunk_t);
1131 
1132  /* As per RFC 4960 the chunk_length value does NOT contemplate
1133  * the size of the first header (see sctp_header_t) and any padding
1134  */
1135  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1136 
1137  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1138 
1139  sctp_selective_ack_chunk_t *sack = vlib_buffer_push_uninit (b, alloc_bytes);
1140 
1141  sack->sctp_hdr.checksum = 0;
1142  sack->sctp_hdr.src_port = sctp_conn->sub_conn[idx].connection.lcl_port;
1143  sack->sctp_hdr.dst_port = sctp_conn->sub_conn[idx].connection.rmt_port;
1144  sack->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1146  vnet_sctp_set_chunk_length (&sack->chunk_hdr, chunk_len);
1147 
1148  sack->cumulative_tsn_ack = sctp_conn->next_tsn_expected;
1149 
1150  sctp_conn->ack_state = 0;
1151 
1152  vnet_buffer (b)->sctp.connection_index =
1153  sctp_conn->sub_conn[idx].connection.c_index;
1154  vnet_buffer (b)->sctp.subconn_idx = idx;
1155 }
1156 
1157 /**
1158  * Convert buffer to HEARTBEAT_ACK
1159  */
1160 void
1162  vlib_buffer_t * b)
1163 {
1165 
1166  u16 alloc_bytes = sizeof (sctp_hb_ack_chunk_t);
1167 
1168  sctp_reuse_buffer (vm, b);
1169 
1170  /* As per RFC 4960 the chunk_length value does NOT contemplate
1171  * the size of the first header (see sctp_header_t) and any padding
1172  */
1173  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1174 
1175  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1176 
1177  sctp_hb_ack_chunk_t *hb_ack = vlib_buffer_push_uninit (b, alloc_bytes);
1178 
1179  hb_ack->sctp_hdr.checksum = 0;
1180  /* No need of host_to_net conversion, already in net-byte order */
1181  hb_ack->sctp_hdr.src_port = sctp_conn->sub_conn[idx].connection.lcl_port;
1182  hb_ack->sctp_hdr.dst_port = sctp_conn->sub_conn[idx].connection.rmt_port;
1183  hb_ack->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1184  hb_ack->hb_info.param_hdr.type = clib_host_to_net_u16 (1);
1185  hb_ack->hb_info.param_hdr.length =
1186  clib_host_to_net_u16 (sizeof (hb_ack->hb_info.hb_info));
1187 
1189  vnet_sctp_set_chunk_length (&hb_ack->chunk_hdr, chunk_len);
1190 
1191  vnet_buffer (b)->sctp.connection_index =
1192  sctp_conn->sub_conn[idx].connection.c_index;
1193  vnet_buffer (b)->sctp.subconn_idx = idx;
1194 }
1195 
1196 /**
1197  * Convert buffer to HEARTBEAT
1198  */
1199 void
1201  vlib_buffer_t * b)
1202 {
1203  u16 alloc_bytes = sizeof (sctp_hb_req_chunk_t);
1204 
1205  /* As per RFC 4960 the chunk_length value does NOT contemplate
1206  * the size of the first header (see sctp_header_t) and any padding
1207  */
1208  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1209 
1210  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1211 
1212  sctp_hb_req_chunk_t *hb_req = vlib_buffer_push_uninit (b, alloc_bytes);
1213 
1214  hb_req->sctp_hdr.checksum = 0;
1215  /* No need of host_to_net conversion, already in net-byte order */
1216  hb_req->sctp_hdr.src_port = sctp_conn->sub_conn[idx].connection.lcl_port;
1217  hb_req->sctp_hdr.dst_port = sctp_conn->sub_conn[idx].connection.rmt_port;
1218  hb_req->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1219  hb_req->hb_info.param_hdr.type = clib_host_to_net_u16 (1);
1220  hb_req->hb_info.param_hdr.length =
1221  clib_host_to_net_u16 (sizeof (hb_req->hb_info.hb_info));
1222 
1224  vnet_sctp_set_chunk_length (&hb_req->chunk_hdr, chunk_len);
1225 
1226  vnet_buffer (b)->sctp.connection_index =
1227  sctp_conn->sub_conn[idx].connection.c_index;
1228  vnet_buffer (b)->sctp.subconn_idx = idx;
1229 }
1230 
1231 void
1233 {
1234  vlib_buffer_t *b;
1235  u32 bi;
1238 
1239  u8 i;
1240  u32 now = sctp_time_now ();
1241 
1242  for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
1243  {
1244  if (sctp_conn->sub_conn[i].state == SCTP_SUBCONN_STATE_DOWN)
1245  continue;
1246 
1247  if (now > (sctp_conn->sub_conn[i].last_seen + SCTP_HB_INTERVAL))
1248  {
1249  if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
1250  return;
1251 
1252  b = vlib_get_buffer (vm, bi);
1253  sctp_init_buffer (vm, b);
1254  sctp_prepare_heartbeat_chunk (sctp_conn, i, b);
1255 
1256  sctp_enqueue_to_output_now (vm, b, bi,
1257  sctp_conn->sub_conn[i].
1258  connection.is_ip4);
1259 
1260  sctp_conn->sub_conn[i].unacknowledged_hb += 1;
1261  }
1262  }
1263 }
1264 
1265 /**
1266  * Convert buffer to SHUTDOWN_COMPLETE
1267  */
1268 void
1270  vlib_buffer_t * b)
1271 {
1272  u16 alloc_bytes = sizeof (sctp_shutdown_association_chunk_t);
1273  alloc_bytes += vnet_sctp_calculate_padding (alloc_bytes);
1274 
1275  u16 chunk_len = alloc_bytes - sizeof (sctp_header_t);
1276 
1277  sctp_shutdown_complete_chunk_t *shutdown_complete =
1278  vlib_buffer_push_uninit (b, alloc_bytes);
1279 
1280  shutdown_complete->sctp_hdr.checksum = 0;
1281  /* No need of host_to_net conversion, already in net-byte order */
1282  shutdown_complete->sctp_hdr.src_port =
1283  sctp_conn->sub_conn[idx].connection.lcl_port;
1284  shutdown_complete->sctp_hdr.dst_port =
1285  sctp_conn->sub_conn[idx].connection.rmt_port;
1286  shutdown_complete->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1287 
1288  vnet_sctp_set_chunk_type (&shutdown_complete->chunk_hdr, SHUTDOWN_COMPLETE);
1289  vnet_sctp_set_chunk_length (&shutdown_complete->chunk_hdr, chunk_len);
1290 
1291  vnet_buffer (b)->sctp.connection_index =
1292  sctp_conn->sub_conn[idx].connection.c_index;
1293  vnet_buffer (b)->sctp.subconn_idx = idx;
1294 }
1295 
1296 void
1298  vlib_buffer_t * b0)
1299 {
1301 
1302  if (sctp_check_outstanding_data_chunks (sctp_conn) > 0)
1303  return;
1304 
1305  sctp_reuse_buffer (vm, b0);
1306 
1307  sctp_prepare_shutdown_complete_chunk (sctp_conn, idx, b0);
1308 }
1309 
1310 /*
1311  * Send INIT
1312  */
1313 void
1315 {
1316  vlib_buffer_t *b;
1317  u32 bi;
1320 
1321  if (PREDICT_FALSE (sctp_conn->init_retransmit_err > SCTP_MAX_INIT_RETRANS))
1322  {
1323  clib_warning ("Reached MAX_INIT_RETRANS times. Aborting connection.");
1324 
1325  session_stream_connect_notify (&sctp_conn->sub_conn
1326  [SCTP_PRIMARY_PATH_IDX].connection, 1);
1327 
1328  sctp_connection_timers_reset (sctp_conn);
1329 
1330  sctp_connection_cleanup (sctp_conn);
1331 
1332  return;
1333  }
1334 
1335  if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
1336  return;
1337 
1338  b = vlib_get_buffer (vm, bi);
1339  u8 idx = SCTP_PRIMARY_PATH_IDX;
1340 
1341  sctp_init_buffer (vm, b);
1342  sctp_prepare_init_chunk (sctp_conn, idx, b);
1343 
1344  sctp_push_ip_hdr (tm, &sctp_conn->sub_conn[idx], b);
1345  sctp_enqueue_to_ip_lookup (vm, b, bi, sctp_conn->sub_conn[idx].c_is_ip4,
1346  sctp_conn->sub_conn[idx].c_fib_index);
1347 
1348  /* Start the T1_INIT timer */
1349  sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T1_INIT,
1350  sctp_conn->sub_conn[idx].RTO);
1351 
1352  /* Change state to COOKIE_WAIT */
1353  sctp_conn->state = SCTP_STATE_COOKIE_WAIT;
1354 
1355  /* Measure RTT with this */
1356  sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now ();
1357 }
1358 
1359 /**
1360  * Push SCTP header and update connection variables
1361  */
1362 static void
1364  sctp_state_t next_state)
1365 {
1366  u16 data_len =
1369  || (b->flags & VLIB_BUFFER_NEXT_PRESENT));
1370 
1371  SCTP_ADV_DBG_OUTPUT ("b->current_length = %u, "
1372  "b->current_data = %p "
1373  "data_len = %u",
1374  b->current_length, b->current_data, data_len);
1375 
1376  u16 bytes_to_add = sizeof (sctp_payload_data_chunk_t);
1377  u16 chunk_length = data_len + bytes_to_add - sizeof (sctp_header_t);
1378 
1379  bytes_to_add += vnet_sctp_calculate_padding (bytes_to_add + data_len);
1380 
1381  sctp_payload_data_chunk_t *data_chunk =
1382  vlib_buffer_push_uninit (b, bytes_to_add);
1383 
1384  u8 idx = sctp_data_subconn_select (sctp_conn);
1386  ("SCTP_CONN = %p, IDX = %u, S_INDEX = %u, C_INDEX = %u, sctp_conn->[...].LCL_PORT = %u, sctp_conn->[...].RMT_PORT = %u",
1387  sctp_conn, idx, sctp_conn->sub_conn[idx].connection.s_index,
1388  sctp_conn->sub_conn[idx].connection.c_index,
1389  sctp_conn->sub_conn[idx].connection.lcl_port,
1390  sctp_conn->sub_conn[idx].connection.rmt_port);
1391  data_chunk->sctp_hdr.checksum = 0;
1392  data_chunk->sctp_hdr.src_port =
1393  sctp_conn->sub_conn[idx].connection.lcl_port;
1394  data_chunk->sctp_hdr.dst_port =
1395  sctp_conn->sub_conn[idx].connection.rmt_port;
1396  data_chunk->sctp_hdr.verification_tag = sctp_conn->remote_tag;
1397 
1398  data_chunk->tsn = clib_host_to_net_u32 (sctp_conn->next_tsn);
1399  data_chunk->stream_id = clib_host_to_net_u16 (0);
1400  data_chunk->stream_seq = clib_host_to_net_u16 (0);
1401 
1402  vnet_sctp_set_chunk_type (&data_chunk->chunk_hdr, DATA);
1403  vnet_sctp_set_chunk_length (&data_chunk->chunk_hdr, chunk_length);
1404 
1405  vnet_sctp_set_bbit (&data_chunk->chunk_hdr);
1406  vnet_sctp_set_ebit (&data_chunk->chunk_hdr);
1407 
1408  SCTP_ADV_DBG_OUTPUT ("POINTER_WITH_DATA = %p, DATA_OFFSET = %u",
1409  b->data, b->current_data);
1410 
1411  if (sctp_conn->sub_conn[idx].state != SCTP_SUBCONN_AWAITING_SACK)
1412  {
1413  sctp_conn->sub_conn[idx].state = SCTP_SUBCONN_AWAITING_SACK;
1414  sctp_conn->last_unacked_tsn = sctp_conn->next_tsn;
1415  }
1416 
1417  sctp_conn->next_tsn += data_len;
1418 
1419  u32 inflight = sctp_conn->next_tsn - sctp_conn->last_unacked_tsn;
1420  /* Section 7.2.2; point (3) */
1421  if (sctp_conn->sub_conn[idx].partially_acked_bytes >=
1422  sctp_conn->sub_conn[idx].cwnd
1423  && inflight >= sctp_conn->sub_conn[idx].cwnd)
1424  {
1425  sctp_conn->sub_conn[idx].cwnd += sctp_conn->sub_conn[idx].PMTU;
1426  sctp_conn->sub_conn[idx].partially_acked_bytes -=
1427  sctp_conn->sub_conn[idx].cwnd;
1428  }
1429 
1430  sctp_conn->sub_conn[idx].last_data_ts = sctp_time_now ();
1431 
1432  vnet_buffer (b)->sctp.connection_index =
1433  sctp_conn->sub_conn[idx].connection.c_index;
1434 
1435  vnet_buffer (b)->sctp.subconn_idx = idx;
1436 }
1437 
1438 u32
1440 {
1441  sctp_connection_t *sctp_conn =
1443 
1444  SCTP_DBG_OUTPUT ("TRANS_CONN = %p, SCTP_CONN = %p, "
1445  "S_INDEX = %u, C_INDEX = %u,"
1446  "trans_conn->LCL_PORT = %u, trans_conn->RMT_PORT = %u",
1447  trans_conn,
1448  sctp_conn,
1449  trans_conn->s_index,
1450  trans_conn->c_index,
1451  trans_conn->lcl_port, trans_conn->rmt_port);
1452 
1453  sctp_push_hdr_i (sctp_conn, b, SCTP_STATE_ESTABLISHED);
1454 
1456 
1457  return 0;
1458 }
1459 
1460 u32
1462  u8 idx,
1463  u32 offset,
1464  u32 max_deq_bytes, vlib_buffer_t ** b)
1465 {
1468  int n_bytes = 0;
1469  u32 bi, available_bytes, seg_size;
1470  u8 *data;
1471 
1472  ASSERT (sctp_conn->state >= SCTP_STATE_ESTABLISHED);
1473  ASSERT (max_deq_bytes != 0);
1474 
1475  /*
1476  * Make sure we can retransmit something
1477  */
1478  available_bytes =
1479  stream_session_tx_fifo_max_dequeue (&sctp_conn->sub_conn[idx].connection);
1480  ASSERT (available_bytes >= offset);
1481  available_bytes -= offset;
1482  if (!available_bytes)
1483  return 0;
1484  max_deq_bytes = clib_min (sctp_conn->sub_conn[idx].cwnd, max_deq_bytes);
1485  max_deq_bytes = clib_min (available_bytes, max_deq_bytes);
1486 
1487  seg_size = max_deq_bytes;
1488 
1489  /*
1490  * Allocate and fill in buffer(s)
1491  */
1492 
1493  if (PREDICT_FALSE (sctp_get_free_buffer_index (tm, &bi)))
1494  return 0;
1495  *b = vlib_get_buffer (vm, bi);
1496  data = sctp_init_buffer (vm, *b);
1497 
1498  /* Easy case, buffer size greater than mss */
1499  if (PREDICT_TRUE (seg_size <= tm->bytes_per_buffer))
1500  {
1501  n_bytes =
1502  stream_session_peek_bytes (&sctp_conn->sub_conn[idx].connection, data,
1503  offset, max_deq_bytes);
1504  ASSERT (n_bytes == max_deq_bytes);
1505  b[0]->current_length = n_bytes;
1506  sctp_push_hdr_i (sctp_conn, *b, sctp_conn->state);
1507  }
1508 
1509  return n_bytes;
1510 }
1511 
1512 void
1514 {
1516  vlib_buffer_t *b = 0;
1517  u32 bi, n_bytes = 0;
1518 
1520  ("SCTP_CONN = %p, IDX = %u, S_INDEX = %u, C_INDEX = %u, sctp_conn->[...].LCL_PORT = %u, sctp_conn->[...].RMT_PORT = %u",
1521  sctp_conn, idx, sctp_conn->sub_conn[idx].connection.s_index,
1522  sctp_conn->sub_conn[idx].connection.c_index,
1523  sctp_conn->sub_conn[idx].connection.lcl_port,
1524  sctp_conn->sub_conn[idx].connection.rmt_port);
1525 
1526  if (sctp_conn->state >= SCTP_STATE_ESTABLISHED)
1527  {
1528  return;
1529  }
1530 
1531  u8 idx = sctp_data_subconn_select (sctp_conn);
1532 
1533  n_bytes =
1534  sctp_prepare_data_retransmit (sctp_conn, idx, 0,
1535  sctp_conn->sub_conn[idx].cwnd, &b);
1536  if (n_bytes > 0)
1537  SCTP_DBG_OUTPUT ("We have data (%u bytes) to retransmit", n_bytes);
1538 
1539  bi = vlib_get_buffer_index (vm, b);
1540 
1541  sctp_enqueue_to_output_now (vm, b, bi,
1542  sctp_conn->sub_conn[idx].connection.is_ip4);
1543 
1544  return;
1545 }
1546 
1547 #if SCTP_DEBUG_STATE_MACHINE
1549 sctp_validate_output_state_machine (sctp_connection_t * sctp_conn,
1550  u8 chunk_type)
1551 {
1552  u8 result = 0;
1553  switch (sctp_conn->state)
1554  {
1555  case SCTP_STATE_CLOSED:
1556  if (chunk_type != INIT && chunk_type != INIT_ACK)
1557  result = 1;
1558  break;
1559  case SCTP_STATE_ESTABLISHED:
1560  if (chunk_type != DATA && chunk_type != HEARTBEAT &&
1561  chunk_type != HEARTBEAT_ACK && chunk_type != SACK &&
1562  chunk_type != COOKIE_ACK && chunk_type != SHUTDOWN)
1563  result = 1;
1564  break;
1565  case SCTP_STATE_COOKIE_WAIT:
1566  if (chunk_type != COOKIE_ECHO)
1567  result = 1;
1568  break;
1569  case SCTP_STATE_SHUTDOWN_SENT:
1570  if (chunk_type != SHUTDOWN_COMPLETE)
1571  result = 1;
1572  break;
1573  case SCTP_STATE_SHUTDOWN_RECEIVED:
1574  if (chunk_type != SHUTDOWN_ACK)
1575  result = 1;
1576  break;
1577  }
1578  return result;
1579 }
1580 #endif
1581 
1584 {
1585  return sctp_conn->sub_conn[idx].is_retransmitting;
1586 }
1587 
1590  vlib_node_runtime_t * node,
1591  vlib_frame_t * from_frame, int is_ip4)
1592 {
1593  u32 n_left_from, next_index, *from, *to_next;
1594  u32 my_thread_index = vm->thread_index;
1595 
1596  from = vlib_frame_vector_args (from_frame);
1597  n_left_from = from_frame->n_vectors;
1598  next_index = node->cached_next_index;
1599  sctp_set_time_now (my_thread_index);
1600 
1601  while (n_left_from > 0)
1602  {
1603  u32 n_left_to_next;
1604 
1605  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1606 
1607  while (n_left_from > 0 && n_left_to_next > 0)
1608  {
1609  u32 bi0;
1610  vlib_buffer_t *b0;
1611  sctp_header_t *sctp_hdr = 0;
1612  sctp_connection_t *sctp_conn;
1613  sctp_tx_trace_t *t0;
1614  sctp_header_t *th0 = 0;
1615  u32 error0 = SCTP_ERROR_PKTS_SENT, next0 =
1617 
1618 #if SCTP_DEBUG_STATE_MACHINE
1619  u16 packet_length = 0;
1620 #endif
1621 
1622  bi0 = from[0];
1623  to_next[0] = bi0;
1624  from += 1;
1625  to_next += 1;
1626  n_left_from -= 1;
1627  n_left_to_next -= 1;
1628 
1629  b0 = vlib_get_buffer (vm, bi0);
1630 
1631  sctp_conn =
1632  sctp_connection_get (vnet_buffer (b0)->sctp.connection_index,
1633  my_thread_index);
1634 
1635  if (PREDICT_FALSE (sctp_conn == 0))
1636  {
1637  error0 = SCTP_ERROR_INVALID_CONNECTION;
1638  next0 = SCTP_OUTPUT_NEXT_DROP;
1639  goto done;
1640  }
1641 
1642  u8 idx = vnet_buffer (b0)->sctp.subconn_idx;
1643 
1644  th0 = vlib_buffer_get_current (b0);
1645 
1646  if (is_ip4)
1647  {
1648  ip4_header_t *iph4 = vlib_buffer_push_ip4 (vm,
1649  b0,
1650  &sctp_conn->sub_conn
1651  [idx].connection.
1652  lcl_ip.ip4,
1653  &sctp_conn->
1654  sub_conn
1655  [idx].connection.
1656  rmt_ip.ip4,
1657  IP_PROTOCOL_SCTP, 1);
1658 
1659  u32 checksum = ip4_sctp_compute_checksum (vm, b0, iph4);
1660 
1661  sctp_hdr = ip4_next_header (iph4);
1662  sctp_hdr->checksum = checksum;
1663 
1664  vnet_buffer (b0)->l4_hdr_offset = (u8 *) th0 - b0->data;
1665 
1667  packet_length = clib_net_to_host_u16 (iph4->length);
1668 #endif
1669  }
1670  else
1671  {
1672  ip6_header_t *iph6 = vlib_buffer_push_ip6 (vm,
1673  b0,
1674  &sctp_conn->sub_conn
1675  [idx].
1676  connection.lcl_ip.
1677  ip6,
1678  &sctp_conn->sub_conn
1679  [idx].
1680  connection.rmt_ip.
1681  ip6,
1683 
1684  int bogus = ~0;
1685  u32 checksum = ip6_sctp_compute_checksum (vm, b0, iph6, &bogus);
1686  ASSERT (!bogus);
1687 
1688  sctp_hdr = ip6_next_header (iph6);
1689  sctp_hdr->checksum = checksum;
1690 
1691  vnet_buffer (b0)->l3_hdr_offset = (u8 *) iph6 - b0->data;
1692  vnet_buffer (b0)->l4_hdr_offset = (u8 *) th0 - b0->data;
1693 
1695  packet_length = clib_net_to_host_u16 (iph6->payload_length);
1696 #endif
1697  }
1698 
1699  sctp_full_hdr_t *full_hdr = (sctp_full_hdr_t *) sctp_hdr;
1700  u8 chunk_type = vnet_sctp_get_chunk_type (&full_hdr->common_hdr);
1701  if (chunk_type >= UNKNOWN)
1702  {
1703  clib_warning
1704  ("Trying to send an unrecognized chunk... something is really bad.");
1705  error0 = SCTP_ERROR_UNKOWN_CHUNK;
1706  next0 = SCTP_OUTPUT_NEXT_DROP;
1707  goto done;
1708  }
1709 
1710 #if SCTP_DEBUG_STATE_MACHINE
1711  u8 is_valid =
1712  (sctp_conn->sub_conn[idx].connection.lcl_port ==
1713  sctp_hdr->src_port
1714  || sctp_conn->sub_conn[idx].connection.lcl_port ==
1715  sctp_hdr->dst_port)
1716  && (sctp_conn->sub_conn[idx].connection.rmt_port ==
1717  sctp_hdr->dst_port
1718  || sctp_conn->sub_conn[idx].connection.rmt_port ==
1719  sctp_hdr->src_port);
1720 
1721  if (!is_valid)
1722  {
1723  SCTP_DBG_STATE_MACHINE ("BUFFER IS INCORRECT: conn_index = %u, "
1724  "packet_length = %u, "
1725  "chunk_type = %u [%s], "
1726  "connection.lcl_port = %u, sctp_hdr->src_port = %u, "
1727  "connection.rmt_port = %u, sctp_hdr->dst_port = %u",
1728  sctp_conn->sub_conn[idx].
1729  connection.c_index, packet_length,
1730  chunk_type,
1731  sctp_chunk_to_string (chunk_type),
1732  sctp_conn->sub_conn[idx].
1733  connection.lcl_port, sctp_hdr->src_port,
1734  sctp_conn->sub_conn[idx].
1735  connection.rmt_port,
1736  sctp_hdr->dst_port);
1737 
1738  error0 = SCTP_ERROR_UNKOWN_CHUNK;
1739  next0 = SCTP_OUTPUT_NEXT_DROP;
1740  goto done;
1741  }
1742 #endif
1744  ("SESSION_INDEX = %u, CONN_INDEX = %u, CURR_CONN_STATE = %u (%s), "
1745  "CHUNK_TYPE = %s, " "SRC_PORT = %u, DST_PORT = %u",
1746  sctp_conn->sub_conn[idx].connection.s_index,
1747  sctp_conn->sub_conn[idx].connection.c_index,
1748  sctp_conn->state, sctp_state_to_string (sctp_conn->state),
1749  sctp_chunk_to_string (chunk_type), full_hdr->hdr.src_port,
1750  full_hdr->hdr.dst_port);
1751 
1752  /* Let's make sure the state-machine does not send anything crazy */
1753 #if SCTP_DEBUG_STATE_MACHINE
1754  if (sctp_validate_output_state_machine (sctp_conn, chunk_type) != 0)
1755  {
1757  ("Sending the wrong chunk (%s) based on state-machine status (%s)",
1758  sctp_chunk_to_string (chunk_type),
1759  sctp_state_to_string (sctp_conn->state));
1760 
1761  error0 = SCTP_ERROR_UNKOWN_CHUNK;
1762  next0 = SCTP_OUTPUT_NEXT_DROP;
1763  goto done;
1764 
1765  }
1766 #endif
1767 
1768  /* Karn's algorithm: RTT measurements MUST NOT be made using
1769  * packets that were retransmitted
1770  */
1771  if (!sctp_is_retransmitting (sctp_conn, idx))
1772  {
1773  /* Measure RTT with this */
1774  if (chunk_type == DATA
1775  && sctp_conn->sub_conn[idx].RTO_pending == 0)
1776  {
1777  sctp_conn->sub_conn[idx].RTO_pending = 1;
1778  sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now ();
1779  }
1780  else
1781  sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now ();
1782  }
1783 
1784  /* Let's take care of TIMERS */
1785  switch (chunk_type)
1786  {
1787  case COOKIE_ECHO:
1788  {
1789  sctp_conn->state = SCTP_STATE_COOKIE_ECHOED;
1790  break;
1791  }
1792  case DATA:
1793  {
1794  SCTP_ADV_DBG_OUTPUT ("PACKET_LENGTH = %u", packet_length);
1795 
1796  sctp_timer_update (sctp_conn, idx, SCTP_TIMER_T3_RXTX,
1797  sctp_conn->sub_conn[idx].RTO);
1798  break;
1799  }
1800  case SHUTDOWN:
1801  {
1802  /* Start the SCTP_TIMER_T2_SHUTDOWN timer */
1803  sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T2_SHUTDOWN,
1804  sctp_conn->sub_conn[idx].RTO);
1805  sctp_conn->state = SCTP_STATE_SHUTDOWN_SENT;
1806  break;
1807  }
1808  case SHUTDOWN_ACK:
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_ACK_SENT;
1814  break;
1815  }
1816  case SHUTDOWN_COMPLETE:
1817  {
1818  sctp_conn->state = SCTP_STATE_CLOSED;
1819  break;
1820  }
1821  }
1822 
1823  vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
1824  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1825  sctp_conn->sub_conn[idx].c_fib_index;
1826 
1827  b0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
1828 
1830  ("SESSION_INDEX = %u, CONNECTION_INDEX = %u, " "NEW_STATE = %s, "
1831  "CHUNK_SENT = %s", sctp_conn->sub_conn[idx].connection.s_index,
1832  sctp_conn->sub_conn[idx].connection.c_index,
1833  sctp_state_to_string (sctp_conn->state),
1834  sctp_chunk_to_string (chunk_type));
1835 
1837 
1838  done:
1839  b0->error = node->errors[error0];
1840  if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1841  {
1842  t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
1843  if (th0)
1844  {
1845  clib_memcpy (&t0->sctp_header, th0,
1846  sizeof (t0->sctp_header));
1847  }
1848  else
1849  {
1850  memset (&t0->sctp_header, 0, sizeof (t0->sctp_header));
1851  }
1852  clib_memcpy (&t0->sctp_connection, sctp_conn,
1853  sizeof (t0->sctp_connection));
1854  }
1855 
1856  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1857  n_left_to_next, bi0, next0);
1858  }
1859 
1860  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1861  }
1862 
1863  return from_frame->n_vectors;
1864 }
1865 
1866 static uword
1868  vlib_frame_t * from_frame)
1869 {
1870  return sctp46_output_inline (vm, node, from_frame, 1 /* is_ip4 */ );
1871 }
1872 
1873 static uword
1875  vlib_frame_t * from_frame)
1876 {
1877  return sctp46_output_inline (vm, node, from_frame, 0 /* is_ip4 */ );
1878 }
1879 
1880 /* *INDENT-OFF* */
1882 {
1883  .function = sctp4_output,.name = "sctp4-output",
1884  /* Takes a vector of packets. */
1885  .vector_size = sizeof (u32),
1886  .n_errors = SCTP_N_ERROR,
1887  .error_strings = sctp_error_strings,
1888  .n_next_nodes = SCTP_OUTPUT_N_NEXT,
1889  .next_nodes = {
1890 #define _(s,n) [SCTP_OUTPUT_NEXT_##s] = n,
1892 #undef _
1893  },
1894  .format_buffer = format_sctp_header,
1895  .format_trace = format_sctp_tx_trace,
1896 };
1897 /* *INDENT-ON* */
1898 
1900 
1901 /* *INDENT-OFF* */
1903 {
1904  .function = sctp6_output,
1905  .name = "sctp6-output",
1906  /* Takes a vector of packets. */
1907  .vector_size = sizeof (u32),
1908  .n_errors = SCTP_N_ERROR,
1909  .error_strings = sctp_error_strings,
1910  .n_next_nodes = SCTP_OUTPUT_N_NEXT,
1911  .next_nodes = {
1912 #define _(s,n) [SCTP_OUTPUT_NEXT_##s] = n,
1914 #undef _
1915  },
1916  .format_buffer = format_sctp_header,
1917  .format_trace = format_sctp_tx_trace,
1918 };
1919 /* *INDENT-ON* */
1920 
1922 
1923 /*
1924  * fd.io coding-style-patch-verification: ON
1925  *
1926  * Local Variables:
1927  * eval: (c-set-style "gnu")
1928  * End:
1929  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:434
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:1161
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:153
u16 sctp_check_outstanding_data_chunks(sctp_connection_t *sctp_conn)
Definition: sctp.c:543
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
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:340
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:164
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:526
#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:1589
#define PREDICT_TRUE(x)
Definition: clib.h:106
#define SCTP_IPV4_ADDRESS_TYPE_LENGTH
Definition: sctp_packet.h:777
u64 as_u64[2]
Definition: ip6_packet.h:51
struct _sctp_sub_connection sctp_sub_connection_t
static int ip4_header_bytes(ip4_header_t *i)
Definition: ip4_packet.h:227
#define NULL
Definition: clib.h:55
#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
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:729
u32 thread_index
Definition: main.h:176
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:412
int i
static u32 sctp_set_time_now(u32 thread_index)
Definition: sctp.h:586
uword ip_csum_t
Definition: ip_packet.h:90
static ip_csum_t ip_csum_with_carry(ip_csum_t sum, ip_csum_t x)
Definition: ip_packet.h:93
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:415
void sctp_compute_mac(sctp_connection_t *sctp_conn, sctp_state_cookie_param_t *state_cookie)
Definition: sctp_output.c:497
static uword sctp6_output(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: sctp_output.c:1874
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:1339
ip6_address_t src_address
Definition: ip6_packet.h:342
VLIB_NODE_FUNCTION_MULTIARCH(sctp4_output_node, sctp4_output)
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:1106
void sctp_prepare_sack_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to SACK.
Definition: sctp_output.c:1123
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:104
ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
Definition: ip_checksum.c:43
static void sctp_init_cwnd(sctp_connection_t *sctp_conn)
Definition: sctp.h:901
#define always_inline
Definition: clib.h:92
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:164
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:182
u8 pre_data[VLIB_BUFFER_PRE_DATA_SIZE]
Space for inserting data before buffer start.
Definition: buffer.h:171
sctp_header_t sctp_hdr
Definition: sctp_packet.h:1338
unsigned long u64
Definition: types.h:89
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:233
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:328
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
Definition: buffer_funcs.h:74
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:1363
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:1513
void sctp_prepare_init_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to INIT.
Definition: sctp_output.c:415
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:688
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:108
static u32 sctp_time_now(void)
Definition: sctp.h:669
static void * vlib_buffer_make_headroom(vlib_buffer_t *b, u8 size)
Make head room, typically for packet headers.
Definition: buffer.h:321
#define MAX_HDRS_LEN
Definition: session.h:31
sctp_init_chunk_t sctp_init_ack_chunk_t
Definition: sctp_packet.h:690
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:191
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:209
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:105
#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
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:364
#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:130
static char * sctp_state_to_string(u8 state)
Definition: sctp.h:365
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:143
enum _sctp_state sctp_state_t
u16 n_vectors
Definition: node.h:344
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:221
vlib_main_t * vm
Definition: buffer.c:294
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
u32 stream_session_tx_fifo_max_dequeue(transport_connection_t *tc)
Definition: session.c:410
#define IP_PROTOCOL_SCTP
Definition: sctp.h:343
void sctp_send_init(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:1314
#define clib_warning(format, args...)
Definition: error.h:59
#define clib_memcpy(a, b, c)
Definition: string.h:75
#define VLIB_BUFFER_TRACE_TRAJECTORY
Compile time buffer trajectory tracing option Turn this on if you run into "bad monkey" contexts...
Definition: buffer.h:544
void sctp_send_cookie_echo(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:598
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:1075
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:1269
#define ARRAY_LEN(x)
Definition: clib.h:59
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:454
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:369
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:467
void sctp_prepare_shutdown_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Convert buffer to SHUTDOWN.
Definition: sctp_output.c:1012
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:456
#define ASSERT(truth)
sctp_opt_params_hdr_t param_hdr
Definition: sctp_packet.h:1313
unsigned int u32
Definition: types.h:88
#define SCTP_PRIMARY_PATH_IDX
Definition: sctp.h:81
long ctx[MAX_CONNS]
Definition: main.c:126
static u8 sctp_is_retransmitting(sctp_connection_t *sctp_conn, u8 idx)
Definition: sctp_output.c:1583
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:126
#define SCTP_CONN_TRACKING_DBG(_fmt, _args...)
Definition: sctp_debug.h:66
format_function_t format_sctp_header
Definition: format.h:102
static void * sctp_init_buffer(vlib_main_t *vm, vlib_buffer_t *b)
Definition: sctp_output.c:271
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:513
sctp_header_t sctp_hdr
Definition: sctp_packet.h:1373
sctp_header_t sctp_header
Definition: sctp_output.c:46
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
u64 uword
Definition: types.h:112
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:55
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:159
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:1200
Definition: defs.h:47
void sctp_send_shutdown_complete(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b0)
Definition: sctp_output.c:1297
static void * vlib_buffer_push_uninit(vlib_buffer_t *b, u8 size)
Prepend uninitialized data to buffer.
Definition: buffer.h:306
static sctp_connection_t * sctp_connection_get(u32 conn_index, u32 thread_index)
Definition: sctp.h:755
unsigned short u16
Definition: types.h:57
u16 payload_length
Definition: ip6_packet.h:333
#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:1461
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:592
void sctp_send_heartbeat(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:1232
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:643
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
sctp_err_cause_param_t err_causes[]
Definition: sctp_packet.h:1340
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
Definition: buffer.h:553
#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:267
#define SCTP_DEBUG_STATE_MACHINE
Definition: sctp_debug.h:27
Linear Congruential Random Number Generator.
#define clib_mem_unaligned(pointer, type)
Definition: types.h:155
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:1439
void sctp_prepare_cookie_echo_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b, u8 reuse_buffer)
Definition: sctp_output.c:560
#define vnet_buffer(b)
Definition: buffer.h:372
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:549
static uword sctp4_output(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: sctp_output.c:1867
#define ENDIANESS_SWAP(x)
Definition: sctp.h:175
#define SCTP_HB_INTERVAL
Definition: sctp.h:466
u8 data[0]
Packet data.
Definition: buffer.h:179
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:432
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:111
static u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:347
#define BITS(x)
Definition: clib.h:58
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:419
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:345
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
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:869
void sctp_send_shutdown(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:1048
Definition: defs.h:46
ip6_address_t dst_address
Definition: ip6_packet.h:342
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:1374