FD.io VPP  v19.01.3-6-g70449b9b9
Vector Packet Processing
sctp.h
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 #ifndef included_vnet_sctp_h
16 #define included_vnet_sctp_h
17 
18 #include <vnet/vnet.h>
19 #include <vnet/ip/ip.h>
20 #include <vnet/sctp/sctp_timer.h>
21 #include <vnet/sctp/sctp_packet.h>
22 #include <vnet/session/transport.h>
23 #include <vnet/session/session.h>
24 
25 /* SCTP timers */
26 #define foreach_sctp_timer \
27  _(T1_INIT, "T1_INIT") \
28  _(T1_COOKIE, "T1_COOKIE") \
29  _(T2_SHUTDOWN, "T2_SHUTDOWN") \
30  _(T3_RXTX, "T3_RXTX") \
31  _(T4_HEARTBEAT, "T4_HB") \
32  _(T5_SHUTDOWN_GUARD, "T5_SHUTDOWN_GUARD")
33 
34 typedef enum _sctp_timers
35 {
36 #define _(sym, str) SCTP_TIMER_##sym,
38 #undef _
41 
42 #define SCTP_TIMER_HANDLE_INVALID ((u32) ~0)
43 
44 always_inline char *
46 {
47  switch (timer_id)
48  {
49  case SCTP_TIMER_T1_INIT:
50  return "SCTP_TIMER_T1_INIT";
51  case SCTP_TIMER_T1_COOKIE:
52  return "SCTP_TIMER_T1_COOKIE";
53  case SCTP_TIMER_T2_SHUTDOWN:
54  return "SCTP_TIMER_T2_SHUTDOWN";
55  case SCTP_TIMER_T3_RXTX:
56  return "SCTP_TIMER_T3_RXTX";
57  case SCTP_TIMER_T4_HEARTBEAT:
58  return "SCTP_TIMER_T4_HEARTBEAT";
59  case SCTP_TIMER_T5_SHUTDOWN_GUARD:
60  return "SCTP_TIMER_T5_SHUTDOWN_GUARD";
61  }
62  return NULL;
63 }
64 
65 typedef enum _sctp_error
66 {
67 #define sctp_error(n,s) SCTP_ERROR_##n,
68 #include <vnet/sctp/sctp_error.def>
69 #undef sctp_error
71 } sctp_error_t;
72 
73 #define NO_FLAG 0
74 
75 #define IS_T_BIT_SET(var) ((var) & (1))
76 #define IS_E_BIT_SET(var) ((var) & (1))
77 #define IS_B_BIT_SET(var) ((var) & (1<<1))
78 #define IS_U_BIT_SET(var) ((var) & (1<<2))
79 
80 #define MAX_SCTP_CONNECTIONS 8
81 #define SCTP_PRIMARY_PATH_IDX 0
82 
83 #if (VLIB_BUFFER_TRACE_TRAJECTORY)
84 #define sctp_trajectory_add_start(b, start) \
85 { \
86  (*vlib_buffer_trace_trajectory_cb) (b, start); \
87 }
88 #else
89 #define sctp_trajectory_add_start(b, start)
90 #endif
91 
92 enum _sctp_subconn_state
93 {
99 };
100 
101 #define SCTP_INITIAL_SSHTRESH 65535
102 typedef struct _sctp_sub_connection
103 {
104  transport_connection_t connection; /**< Common transport data. First! */
105 
106  u8 subconn_idx; /**< This indicates the position of this sub-connection in the super-set container of connections pool */
107  u32 error_count; /**< The current error count for this destination. */
108  u32 error_threshold; /**< Current error threshold for this destination,
109  i.e. what value marks the destination down if error count reaches this value. */
110  u32 cwnd; /**< Congestion control window (cwnd, in bytes), which is adjusted by
111  the sender based on observed network conditions. */
112  u32 ssthresh; /**< Slow-start threshold (in bytes), which is used by the
113  sender to distinguish slow-start and congestion avoidance phases. */
114 
115  u64 rtt_ts; /**< USED to hold the timestamp of when the packet has been sent */
116 
117  u32 RTO; /**< The current retransmission timeout value. */
118  u64 SRTT; /**< The current smoothed round-trip time. */
119  f64 RTTVAR; /**< The current RTT variation. */
120 
121  u32 partially_acked_bytes; /**< The tracking method for increase of cwnd when in
122  congestion avoidance mode (see Section 7.2.2).*/
123 
124  u8 state; /**< The current state of this destination, i.e., DOWN, UP, ALLOW-HB, NO-HEARTBEAT, etc. */
125 
126  u16 PMTU; /**< The current known path MTU. */
127 
128  u32 timers[SCTP_N_TIMERS]; /**< A timer used by each destination. */
129 
130  u8 RTO_pending; /**< A flag used to track if one of the DATA chunks sent to
131  this address is currently being used to compute an RTT.
132  If this flag is 0, the next DATA chunk sent to this destination
133  should be used to compute an RTT and this flag should be set.
134  Every time the RTT calculation completes (i.e., the DATA chunk is SACK'd),
135  clear this flag. */
136 
137  u64 last_seen; /**< The time to which this destination was last sent a packet to.
138  This can be used to determine if a HEARTBEAT is needed. */
139 
140  u64 last_data_ts; /**< Used to hold the timestamp value of last time we sent a DATA chunk */
141 
142  u8 unacknowledged_hb; /**< Used to track how many unacknowledged heartbeats we had;
143  If more than SCTP_PATH_MAX_RETRANS then connection is considered unreachable. */
144 
145  u8 is_retransmitting; /**< A flag (0 = no, 1 = yes) indicating whether the connection is retransmitting a previous packet */
146 
147  u8 enqueue_state; /**< if set to 1 indicates that DATA is still being handled hence cannot shutdown this connection yet */
148 
150 
151 typedef struct
152 {
153  u32 a_rwnd; /**< Maximum segment size advertised */
154 
156 
157 /* Useful macros to deal with the out_of_order_map (array of bit) */
158 #define SET_BIT(A,k) ( A[(k/32)] |= (1 << (k%32)) )
159 #define CLEAR_BIT(A,k) ( A[(k/32)] &= ~(1 << (k%32)) )
160 #define TEST_BIT(A,k) ( A[(k/32)] & (1 << (k%32)) )
161 
162 always_inline void
163 _bytes_swap (void *pv, size_t n)
164 {
165  char *p = pv;
166  size_t lo, hi;
167  for (lo = 0, hi = n - 1; hi > lo; lo++, hi--)
168  {
169  char tmp = p[lo];
170  p[lo] = p[hi];
171  p[hi] = tmp;
172  }
173 }
174 
175 #define ENDIANESS_SWAP(x) _bytes_swap(&x, sizeof(x));
176 
177 #define MAX_INFLIGHT_PACKETS 128
178 #define MAX_ENQUEABLE_SACKS 2
179 
180 /* This parameter indicates to the receiver how much increment in
181  * milliseconds the sender wishes the receiver to add to its default
182  * cookie life-span.
183  */
184 #define SUGGESTED_COOKIE_LIFE_SPAN_INCREMENT 1000
185 
186 typedef struct _sctp_user_configuration
187 {
188  u8 never_delay_sack;
189  u8 never_bundle;
190 
192 
193 typedef struct _sctp_connection
194 {
195  /** Required for pool_get_aligned */
196  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
197 
198  sctp_sub_connection_t sub_conn[MAX_SCTP_CONNECTIONS]; /**< Common transport data. First! */
199  sctp_user_configuration_t conn_config; /**< Allows tuning of some SCTP behaviors */
200 
201  u8 state; /**< SCTP state as per sctp_state_t */
202  u16 flags; /**< Chunk flag (see sctp_chunks_common_hdr_t) */
203 
204  u32 local_tag; /**< INIT_TAG generated locally */
205  u32 remote_tag; /**< INIT_TAG generated by the remote peer */
206 
207  u32 local_initial_tsn; /**< Initial TSN generated locally */
208  u32 remote_initial_tsn; /**< Initial TSN generated by the remote-peer */
209 
210  u32 peer_cookie_life_span_increment;
211 
212  u32 overall_err_count; /**< The overall association error count. */
213  u32 overall_err_treshold; /**< The threshold for this association that if the Overall Error Count
214  reaches will cause this association to be torn down. */
215 
216  u8 init_retransmit_err; /**< Error counter for the INIT transmission phase */
217 
218  u32 peer_rwnd; /**< Current calculated value of the peer's rwnd. */
219 
220  u32 next_tsn; /**< The next TSN number to be assigned to a new DATA chunk.
221  This is sent in the INIT or INIT ACK chunk to the peer
222  and incremented each time a DATA chunk is assigned a
223  TSN (normally just prior to transmit or during
224  fragmentation). */
225 
226  u32 last_unacked_tsn; /** < Last TSN number still unacked */
227  u32 next_tsn_expected; /**< The next TSN number expected to be received. */
228 
229  u32 last_rcvd_tsn; /**< This is the last TSN received in sequence. This value
230  is set initially by taking the peer's initial TSN,
231  received in the INIT or INIT ACK chunk, and
232  subtracting one from it. */
233 
234  u32 out_of_order_map[MAX_INFLIGHT_PACKETS]; /**< An array of bits or bytes indicating which out-of-order
235  TSNs have been received (relative to the Last Rcvd TSN).
236  If no gaps exist, i.e., no out-of-order packets have been received,
237  this array will be set to all zero. */
238 
239  u8 ack_state; /**< This flag indicates if the next received packet is set to be responded to with a SACK.
240  This is initialized to 0. When a packet is received it is incremented.
241  If this value reaches 2 or more, a SACK is sent and the value is reset to 0.
242  Note: This is used only when no DATA chunks are received out-of-order.
243  When DATA chunks are out-of-order, SACKs are not delayed (see Section 6). */
244 
245  u8 smallest_PMTU_idx; /** The index of the sub-connection with the smallest PMTU discovered across all peer's transport addresses. */
246 
247  u8 overall_sending_status; /**< 0 indicates first fragment of a user message
248  1 indicates normal stream
249  2 indicates last fragment of a user message */
250 
251  u8 forming_association_changed; /**< This is a flag indicating whether the original association has been modified during
252  the life-span of the association itself. For instance, a new sub-connection might have been added. */
253 
254  sctp_state_cookie_param_t cookie_param; /**< Temporary location to save cookie information; it can be used to
255  when timeout expires and sending again a COOKIE is require. */
256 
258 
259 typedef void (sctp_timer_expiration_handler) (u32 conn_index, u32 timer_id);
260 
262 
263 u8
265  ip4_address_t * lcl_addr,
266  ip4_address_t * rmt_addr);
267 
268 u8
270  ip6_address_t * lcl_addr,
271  ip6_address_t * rmt_addr);
272 
273 u8
275  ip4_address_t * rmt_addr);
276 
277 u8
279  ip6_address_t * rmt_addr);
280 
282 
283 void sctp_connection_close (sctp_connection_t * sctp_conn);
284 void sctp_connection_cleanup (sctp_connection_t * sctp_conn);
285 void sctp_connection_del (sctp_connection_t * sctp_conn);
286 
288 void sctp_send_init (sctp_connection_t * sctp_conn);
289 void sctp_send_cookie_echo (sctp_connection_t * sctp_conn);
290 void sctp_send_shutdown (sctp_connection_t * sctp_conn);
291 void sctp_send_shutdown_ack (sctp_connection_t * sctp_conn, u8 idx,
292  vlib_buffer_t * b);
293 void sctp_send_shutdown_complete (sctp_connection_t * sctp_conn, u8 idx,
294  vlib_buffer_t * b0);
295 void sctp_send_heartbeat (sctp_connection_t * sctp_conn);
296 void sctp_data_retransmit (sctp_connection_t * sctp_conn);
297 void sctp_flush_frame_to_output (vlib_main_t * vm, u8 thread_index,
298  u8 is_ip4);
299 void sctp_flush_frames_to_output (u8 thread_index);
300 void sctp_punt_unknown (vlib_main_t * vm, u8 is_ip4, u8 is_add);
301 
303 
304 u8 *format_sctp_connection_id (u8 * s, va_list * args);
305 u8 *format_sctp_connection (u8 * s, va_list * args);
306 u8 *format_sctp_scoreboard (u8 * s, va_list * args);
307 u8 *format_sctp_header (u8 * s, va_list * args);
308 u8 *format_sctp_tx_trace (u8 * s, va_list * args);
309 
313 void sctp_init_snd_vars (sctp_connection_t * sctp_conn);
314 void sctp_init_mss (sctp_connection_t * sctp_conn);
315 
316 void sctp_prepare_initack_chunk (sctp_connection_t * sctp_conn, u8 idx,
317  vlib_buffer_t * b, ip4_address_t * ip4_addr,
318  u8 add_ip4, ip6_address_t * ip6_addr,
319  u8 add_ip6);
321  u8 idx, vlib_buffer_t * b,
322  ip4_address_t * ip4_addr,
323  ip6_address_t * ip6_addr);
325  vlib_buffer_t * b,
326  ip4_address_t * ip4_addr,
327  ip6_address_t * ip6_addr);
328 void sctp_prepare_operation_error (sctp_connection_t * sctp_conn, u8 idx,
329  vlib_buffer_t * b, u8 err_cause);
331  vlib_buffer_t * b, u8 reuse_buffer);
332 void sctp_prepare_cookie_ack_chunk (sctp_connection_t * sctp_conn, u8 idx,
333  vlib_buffer_t * b);
334 void sctp_prepare_sack_chunk (sctp_connection_t * sctp_conn, u8 idx,
335  vlib_buffer_t * b);
337  vlib_buffer_t * b);
338 
340 
341 void sctp_api_reference (void);
342 
343 #define IP_PROTOCOL_SCTP 132
344 
345 /** SSCTP FSM state definitions as per RFC4960. */
346 #define foreach_sctp_fsm_state \
347  _(CLOSED, "CLOSED") \
348  _(COOKIE_WAIT, "COOKIE_WAIT") \
349  _(COOKIE_ECHOED, "COOKIE_ECHOED") \
350  _(ESTABLISHED, "ESTABLISHED") \
351  _(SHUTDOWN_PENDING, "SHUTDOWN_PENDING") \
352  _(SHUTDOWN_SENT, "SHUTDOWN_SENT") \
353  _(SHUTDOWN_RECEIVED, "SHUTDOWN_RECEIVED") \
354  _(SHUTDOWN_ACK_SENT, "SHUTDOWN_ACK_SENT")
355 
356 typedef enum _sctp_state
357 {
358 #define _(sym, str) SCTP_STATE_##sym,
360 #undef _
362 } sctp_state_t;
363 
364 always_inline char *
366 {
367  switch (state)
368  {
369  case SCTP_STATE_CLOSED:
370  return "SCTP_STATE_CLOSED";
371  case SCTP_STATE_COOKIE_WAIT:
372  return "SCTP_STATE_COOKIE_WAIT";
373  case SCTP_STATE_COOKIE_ECHOED:
374  return "SCTP_STATE_COOKIE_ECHOED";
375  case SCTP_STATE_ESTABLISHED:
376  return "SCTP_STATE_ESTABLISHED";
377  case SCTP_STATE_SHUTDOWN_PENDING:
378  return "SCTP_STATE_SHUTDOWN_PENDING";
379  case SCTP_STATE_SHUTDOWN_SENT:
380  return "SCTP_STATE_SHUTDOWN_SENT";
381  case SCTP_STATE_SHUTDOWN_RECEIVED:
382  return "SCTP_STATE_SHUTDOWN_RECEIVED";
383  case SCTP_STATE_SHUTDOWN_ACK_SENT:
384  return "SCTP_STATE_SHUTDOWN_ACK_SENT";
385  }
386  return NULL;
387 }
388 
389 always_inline char *
391 {
392  switch (type)
393  {
394  case DATA:
395  return "DATA";
396  case INIT:
397  return "INIT";
398  case INIT_ACK:
399  return "INIT_ACK";
400  case SACK:
401  return "SACK";
402  case HEARTBEAT:
403  return "HEARTBEAT";
404  case HEARTBEAT_ACK:
405  return "HEARTBEAT_ACK";
406  case ABORT:
407  return "ABORT";
408  case SHUTDOWN:
409  return "SHUTDOWN";
410  case SHUTDOWN_ACK:
411  return "SHUTDOWN_ACK";
412  case OPERATION_ERROR:
413  return "OPERATION_ERROR";
414  case COOKIE_ECHO:
415  return "COOKIE_ECHO";
416  case COOKIE_ACK:
417  return "COOKIE_ACK";
418  case ECNE:
419  return "ECNE";
420  case CWR:
421  return "CWR";
422  case SHUTDOWN_COMPLETE:
423  return "SHUTDOWN_COMPLETE";
424  }
425  return NULL;
426 }
427 
428 always_inline char *
430 {
431  switch (type)
432  {
434  return "SCTP_IPV4_ADDRESS_TYPE";
436  return "SCTP_IPV6_ADDRESS_TYPE";
438  return "SCTP_STATE_COOKIE_TYPE";
440  return "SCTP_UNRECOGNIZED_TYPE";
442  return "SCTP_COOKIE_PRESERVATIVE_TYPE";
444  return "SCTP_HOSTNAME_ADDRESS_TYPE";
446  return "SCTP_SUPPORTED_ADDRESS_TYPES";
447  }
448  return NULL;
449 }
450 
451 #define SCTP_TICK 0.001 /**< SCTP tick period (s) */
452 #define SHZ (u32) (1/SCTP_TICK) /**< SCTP tick frequency */
453 #define SCTP_TSTAMP_RESOLUTION SCTP_TICK /**< Time stamp resolution */
454 
455 /* As per RFC4960, page 83 */
456 #define SCTP_RTO_INIT 3 * SHZ /* 3 seconds */
457 #define SCTP_RTO_MIN 1 * SHZ /* 1 second */
458 #define SCTP_RTO_MAX 60 * SHZ /* 60 seconds */
459 #define SCTP_RTO_BURST 4
460 #define SCTP_RTO_ALPHA 1/8
461 #define SCTP_RTO_BETA 1/4
462 #define SCTP_VALID_COOKIE_LIFE 60 * SHZ /* 60 seconds */
463 #define SCTP_ASSOCIATION_MAX_RETRANS 10 // the overall connection
464 #define SCTP_PATH_MAX_RETRANS 5 // number of attempts per destination address
465 #define SCTP_MAX_INIT_RETRANS 8 // number of attempts
466 #define SCTP_HB_INTERVAL 30 * SHZ
467 #define SCTP_HB_MAX_BURST 1
468 #define SCTP_DATA_IDLE_INTERVAL 15 * SHZ /* 15 seconds; the time-interval after which the connetion is considered IDLE */
469 #define SCTP_TO_TIMER_TICK SCTP_TICK*10 /* Period for converting from SCTP_TICK */
470 
471 #define SCTP_CONN_RECOVERY 1 << 1
472 #define SCTP_FAST_RECOVERY 1 << 2
473 
474 typedef struct _sctp_lookup_dispatch
475 {
476  u8 next, error;
478 
479 typedef struct _sctp_main
480 {
481  /* Per-worker thread SCTP connection pools */
482  sctp_connection_t **connections;
483 
484  /* Pool of listeners. */
485  sctp_connection_t *listener_pool;
486 
487  /** Dispatch table by state and flags */
488  sctp_lookup_dispatch_t dispatch_table[SCTP_N_STATES][64];
489 
490  u8 log2_tstamp_clocks_per_tick;
491  f64 tstamp_ticks_per_clock;
492  u64 *time_now;
493 
494  /** per-worker tx buffer free lists */
495  u32 **tx_buffers;
496  /** per-worker tx frames to SCTP 4/6 output nodes */
497  vlib_frame_t **tx_frames[2];
498  /** per-worker tx frames to ip 4/6 lookup nodes */
499  vlib_frame_t **ip_lookup_tx_frames[2];
500 
501  /* Per worker-thread timer wheel for connections timers */
502  tw_timer_wheel_16t_2w_512sl_t *timer_wheels;
503 
504  /* Pool of half-open connections on which we've sent a SYN */
505  sctp_connection_t *half_open_connections;
506  clib_spinlock_t half_open_lock;
507 
508  /* TODO: Congestion control algorithms registered */
509  /* sctp_cc_algorithm_t *cc_algos; */
510 
511  /* Flag that indicates if stack is on or off */
512  u8 is_enabled;
513 
514  /** Number of preallocated connections */
515  u32 preallocated_connections;
516 
517  /** Transport table (preallocation) size parameters */
518  u32 local_endpoints_table_memory;
519  u32 local_endpoints_table_buckets;
520 
521  /** Vectors of src addresses. Optional unless one needs > 63K active-opens */
522  ip4_address_t *ip4_src_addresses;
523  u32 last_v4_address_rotor;
524  u32 last_v6_address_rotor;
525  ip6_address_t *ip6_src_addresses;
526 
527  /** vlib buffer size */
528  u32 bytes_per_buffer;
529 
530  u8 punt_unknown4;
531  u8 punt_unknown6;
532 
533 } sctp_main_t;
534 
535 extern sctp_main_t sctp_main;
540 
543 {
544  return &sctp_main;
545 }
546 
549 {
550  ASSERT ((signed) b->current_data >= (signed) -VLIB_BUFFER_PRE_DATA_SIZE);
551  return (sctp_header_t *) (b->data + b->current_data
552  + vnet_buffer (b)->sctp.hdr_offset);
553 }
554 
556 
559 {
560  sctp_connection_t *tc = 0;
561  clib_spinlock_lock_if_init (&sctp_main.half_open_lock);
562  if (!pool_is_free_index (sctp_main.half_open_connections, conn_index))
563  tc = pool_elt_at_index (sctp_main.half_open_connections, conn_index);
564  tc->sub_conn[SCTP_PRIMARY_PATH_IDX].subconn_idx = SCTP_PRIMARY_PATH_IDX;
565  clib_spinlock_unlock_if_init (&sctp_main.half_open_lock);
566  return tc;
567 }
568 
569 /**
570  * Cleanup half-open connection
571  *
572  */
573 always_inline void
575 {
577  clib_spinlock_lock_if_init (&sctp_main->half_open_lock);
578  pool_put_index (sctp_main->half_open_connections,
579  tc->sub_conn[SCTP_PRIMARY_PATH_IDX].c_c_index);
580  if (CLIB_DEBUG)
581  clib_memset (tc, 0xFA, sizeof (*tc));
582  clib_spinlock_unlock_if_init (&sctp_main->half_open_lock);
583 }
584 
586 sctp_set_time_now (u32 thread_index)
587 {
588  sctp_main.time_now[thread_index] = clib_cpu_time_now ()
589  * sctp_main.tstamp_ticks_per_clock;
590  return sctp_main.time_now[thread_index];
591 }
592 
593 always_inline void
594 sctp_timer_set (sctp_connection_t * tc, u8 conn_idx, u8 timer_id,
595  u32 interval)
596 {
597  ASSERT (tc->sub_conn[conn_idx].connection.thread_index ==
599  ASSERT (tc->sub_conn[conn_idx].timers[timer_id] ==
601 
602  sctp_sub_connection_t *sub = &tc->sub_conn[conn_idx];
603  sub->timers[timer_id] =
604  tw_timer_start_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
605  sub->c_c_index, timer_id, interval);
606 }
607 
608 always_inline void
609 sctp_timer_reset (sctp_connection_t * tc, u8 conn_idx, u8 timer_id)
610 {
611  ASSERT (tc->sub_conn[conn_idx].c_thread_index == vlib_get_thread_index ());
612  if (tc->sub_conn[conn_idx].timers[timer_id] == SCTP_TIMER_HANDLE_INVALID)
613  return;
614 
615  sctp_sub_connection_t *sub = &tc->sub_conn[conn_idx];
616 
617  tw_timer_stop_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
618  sub->timers[timer_id]);
619  sub->timers[timer_id] = SCTP_TIMER_HANDLE_INVALID;
620 }
621 
622 /**
623  * Try to cleanup half-open connection
624  *
625  * If called from a thread that doesn't own tc, the call won't have any
626  * effect.
627  *
628  * @param tc - connection to be cleaned up
629  * @return non-zero if cleanup failed.
630  */
631 always_inline int
633 {
634  /* Make sure this is the owning thread */
635  if (tc->sub_conn[SCTP_PRIMARY_PATH_IDX].c_thread_index !=
637  return 1;
638  sctp_timer_reset (tc, SCTP_PRIMARY_PATH_IDX, SCTP_TIMER_T1_INIT);
640  return 0;
641 }
642 
645 {
646  return sizeof (sctp_header_t);
647 }
648 
651 {
652  ASSERT (tconn != NULL);
653 
655 #if SCTP_ADV_DEBUG
656  if (sub == NULL)
657  SCTP_ADV_DBG ("sub == NULL");
658  if (sub->parent == NULL)
659  SCTP_ADV_DBG ("sub->parent == NULL");
660 #endif
661  if (sub->subconn_idx > 0)
662  return (sctp_connection_t *) sub -
663  (sizeof (sctp_sub_connection_t) * (sub->subconn_idx - 1));
664 
665  return (sctp_connection_t *) sub;
666 }
667 
670 {
671  return sctp_main.time_now[vlib_get_thread_index ()];
672 }
673 
674 #define ABS(x) ((x) > 0) ? (x) : -(x);
675 
676 always_inline void
677 sctp_calculate_rto (sctp_connection_t * sctp_conn, u8 conn_idx)
678 {
679  /* See RFC4960, 6.3.1. RTO Calculation */
680  u64 RTO = 0;
681  f64 RTTVAR = 0;
682  u64 now = sctp_time_now ();
683  u64 prev_ts = sctp_conn->sub_conn[conn_idx].rtt_ts;
684  u64 R = prev_ts - now;
685 
686  if (sctp_conn->sub_conn[conn_idx].RTO == 0) // C1: Let's initialize our RTO
687  {
688  sctp_conn->sub_conn[conn_idx].RTO = SCTP_RTO_MIN;
689  return;
690  }
691 
692  if (sctp_conn->sub_conn[conn_idx].RTO == SCTP_RTO_MIN && sctp_conn->sub_conn[conn_idx].SRTT == 0) // C2: First RTT calculation
693  {
694  sctp_conn->sub_conn[conn_idx].SRTT = R;
695  RTTVAR = R / 2;
696 
697  if (RTTVAR == 0)
698  RTTVAR = 100e-3; /* 100 ms */
699 
700  sctp_conn->sub_conn[conn_idx].RTTVAR = RTTVAR;
701  }
702  else // C3: RTT already exists; let's recalculate
703  {
704  RTTVAR = (1 - SCTP_RTO_BETA) * sctp_conn->sub_conn[conn_idx].RTTVAR +
705  SCTP_RTO_BETA * ABS (sctp_conn->sub_conn[conn_idx].SRTT - R);
706 
707  if (RTTVAR == 0)
708  RTTVAR = 100e-3; /* 100 ms */
709 
710  sctp_conn->sub_conn[conn_idx].RTTVAR = RTTVAR;
711 
712  sctp_conn->sub_conn[conn_idx].SRTT =
713  (1 - SCTP_RTO_ALPHA) * sctp_conn->sub_conn[conn_idx].SRTT +
714  SCTP_RTO_ALPHA * R;
715  }
716 
717  RTO =
718  sctp_conn->sub_conn[conn_idx].SRTT +
719  4 * sctp_conn->sub_conn[conn_idx].RTTVAR;
720  if (RTO < SCTP_RTO_MIN) // C6
721  RTO = SCTP_RTO_MIN;
722 
723  if (RTO > SCTP_RTO_MAX) // C7
724  RTO = SCTP_RTO_MAX;
725 
726  sctp_conn->sub_conn[conn_idx].RTO = RTO;
727 }
728 
729 always_inline void
730 sctp_timer_update (sctp_connection_t * tc, u8 conn_idx, u8 timer_id,
731  u32 interval)
732 {
733  ASSERT (tc->sub_conn[conn_idx].connection.thread_index ==
735  sctp_sub_connection_t *sub = &tc->sub_conn[conn_idx];
736 
737  if (tc->sub_conn[conn_idx].timers[timer_id] != SCTP_TIMER_HANDLE_INVALID)
738  tw_timer_stop_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
739  sub->timers[timer_id]);
740 
741  tc->sub_conn[conn_idx].timers[timer_id] =
742  tw_timer_start_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
743  sub->c_c_index, timer_id, interval);
744 }
745 
748 {
749  return pool_elt_at_index (sctp_main.listener_pool, tli);
750 }
751 
752 #endif
753 
755 sctp_connection_get (u32 conn_index, u32 thread_index)
756 {
757  if (PREDICT_FALSE
758  (pool_is_free_index (sctp_main.connections[thread_index], conn_index)))
759  return 0;
760  return pool_elt_at_index (sctp_main.connections[thread_index], conn_index);
761 }
762 
763 #define SELECT_MAX_RETRIES 8
764 
767 {
769  u8 i, cwnd = sctp_conn->sub_conn[SCTP_PRIMARY_PATH_IDX].cwnd;
770  for (i = 1; i < MAX_SCTP_CONNECTIONS; i++)
771  {
772  if (sctp_conn->sub_conn[i].state == SCTP_SUBCONN_STATE_DOWN)
773  continue;
774 
775  if (sctp_conn->sub_conn[i].cwnd > cwnd)
776  {
777  sub = i;
778  cwnd = sctp_conn->sub_conn[i].cwnd;
779  }
780  }
781  return sub;
782 }
783 
786 {
787  u8 i;
788 
789  for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
790  {
791  if (sctp_conn->sub_conn[i].connection.lcl_ip.ip6.as_u64[0] ==
792  ip6h->dst_address.as_u64[0] &&
793  sctp_conn->sub_conn[i].connection.lcl_ip.ip6.as_u64[1] ==
794  ip6h->dst_address.as_u64[1] &&
795  sctp_conn->sub_conn[i].connection.rmt_ip.ip6.as_u64[0] ==
796  ip6h->src_address.as_u64[0] &&
797  sctp_conn->sub_conn[i].connection.rmt_ip.ip6.as_u64[1] ==
798  ip6h->src_address.as_u64[1])
799  return i;
800  }
801  clib_warning ("Did not find a sub-connection; defaulting to %u",
803  return SCTP_PRIMARY_PATH_IDX;
804 }
805 
808 {
809  u8 i;
810 
811  for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
812  {
813  if (sctp_conn->sub_conn[i].connection.lcl_ip.ip4.as_u32 ==
814  ip4h->dst_address.as_u32
815  && sctp_conn->sub_conn[i].connection.rmt_ip.ip4.as_u32 ==
816  ip4h->src_address.as_u32)
817  return i;
818  }
819  clib_warning ("Did not find a sub-connection; defaulting to %u",
821  return SCTP_PRIMARY_PATH_IDX;
822 }
823 
824 /**
825  * Push SCTP header to buffer
826  *
827  * @param vm - vlib_main
828  * @param b - buffer to write the header to
829  * @param sp_net - source port net order
830  * @param dp_net - destination port net order
831  * @param sctp_hdr_opts_len - header and options length in bytes
832  *
833  * @return - pointer to start of SCTP header
834  */
835 always_inline void *
837  u8 sctp_hdr_opts_len)
838 {
839  sctp_full_hdr_t *full_hdr;
840 
841  full_hdr = vlib_buffer_push_uninit (b, sctp_hdr_opts_len);
842 
843  full_hdr->hdr.src_port = sp;
844  full_hdr->hdr.dst_port = dp;
845  full_hdr->hdr.checksum = 0;
846  return full_hdr;
847 }
848 
849 /**
850  * Push SCTP header to buffer
851  *
852  * @param b - buffer to write the header to
853  * @param sp_net - source port net order
854  * @param dp_net - destination port net order
855  * @param sctp_hdr_opts_len - header and options length in bytes
856  *
857  * @return - pointer to start of SCTP header
858  */
859 always_inline void *
861  u8 sctp_hdr_opts_len)
862 {
863  return vlib_buffer_push_sctp_net_order (b, sp_net, dp_net,
864  sctp_hdr_opts_len);
865 }
866 
869 {
870  u8 i;
871 
872  for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
873  {
874  if (sctp_conn->sub_conn[i].state == SCTP_SUBCONN_STATE_DOWN)
875  return i;
876  }
877  return MAX_SCTP_CONNECTIONS;
878 }
879 
880 always_inline void
882 {
883  u8 i;
884  u8 smallest_pmtu_index = SCTP_PRIMARY_PATH_IDX;
885 
886  for (i = 1; i < MAX_SCTP_CONNECTIONS; i++)
887  {
888  if (sctp_conn->sub_conn[i].state != SCTP_SUBCONN_STATE_DOWN)
889  {
890  if (sctp_conn->sub_conn[i].PMTU <
891  sctp_conn->sub_conn[smallest_pmtu_index].PMTU)
892  smallest_pmtu_index = i;
893  }
894  }
895 
896  sctp_conn->smallest_PMTU_idx = smallest_pmtu_index;
897 }
898 
899 /* As per RFC4960; section 7.2.1: Slow-Start */
900 always_inline void
902 {
903  u8 i;
904  for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
905  {
906  /* Section 7.2.1; point (1) */
907  sctp_conn->sub_conn[i].cwnd =
908  clib_min (4 * sctp_conn->sub_conn[i].PMTU,
909  clib_max (2 * sctp_conn->sub_conn[i].PMTU, 4380));
910 
911  /* Section 7.2.1; point (3) */
912  sctp_conn->sub_conn[i].ssthresh = SCTP_INITIAL_SSHTRESH;
913 
914  /* Section 7.2.2; point (1) */
915  sctp_conn->sub_conn[i].partially_acked_bytes = 0;
916  }
917 }
918 
921 {
922  return 0;
923 }
924 
927 {
928  if (sctp_conn->sub_conn[idx].cwnd == 0)
929  return 1;
930  return 0;
931 }
932 
933 /* As per RFC4960; section 7.2.1: Slow-Start */
934 always_inline void
936 {
937  u8 i;
938  u32 inflight = sctp_conn->next_tsn - sctp_conn->last_unacked_tsn;
939 
940  for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
941  {
942  /* Section 7.2.1; point (2) */
943  if (sctp_conn->sub_conn[i].is_retransmitting)
944  {
945  sctp_conn->sub_conn[i].cwnd = 1 * sctp_conn->sub_conn[i].PMTU;
946  continue;
947  }
948 
949  /* Section 7.2.2; point (4) */
950  if (sctp_conn->sub_conn[i].last_data_ts >
952  {
953  sctp_conn->sub_conn[i].cwnd =
954  clib_max (sctp_conn->sub_conn[i].cwnd / 2,
955  4 * sctp_conn->sub_conn[i].PMTU);
956  continue;
957  }
958 
959  /* Section 7.2.1; point (5) */
960  if (sctp_conn->sub_conn[i].cwnd <= sctp_conn->sub_conn[i].ssthresh)
961  {
962  if (!cwnd_fully_utilized (sctp_conn, i))
963  continue;
964 
965  if (sctp_in_cong_recovery (sctp_conn, i))
966  continue;
967 
968  sctp_conn->sub_conn[i].cwnd =
969  clib_min (sctp_conn->sub_conn[i].PMTU, 1);
970  }
971 
972  /* Section 6.1; point (D) */
973  if ((inflight + SCTP_RTO_BURST * sctp_conn->sub_conn[i].PMTU) <
974  sctp_conn->sub_conn[i].cwnd)
975  sctp_conn->sub_conn[i].cwnd =
976  inflight + SCTP_RTO_BURST * sctp_conn->sub_conn[i].PMTU;
977  }
978 }
979 
980 /*
981  * fd.io coding-style-patch-verification: ON
982  *
983  * Local Variables:
984  * eval: (c-set-style "gnu")
985  * End:
986  */
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
#define MAX_INFLIGHT_PACKETS
Definition: sctp.h:177
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
vmrglw vmrglh hi
static void update_cwnd(sctp_connection_t *sctp_conn)
Definition: sctp.h:935
static u8 sctp_sub_conn_id_via_ip4h(sctp_connection_t *sctp_conn, ip4_header_t *ip4h)
Definition: sctp.h:807
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
#define CLIB_CACHE_LINE_ALIGN_MARK(mark)
Definition: cache.h:60
u32 flags
Definition: vhost_user.h:115
#define clib_min(x, y)
Definition: clib.h:295
u8 sctp_sub_connection_add_ip4(vlib_main_t *vm, ip4_address_t *lcl_addr, ip4_address_t *rmt_addr)
Definition: sctp.c:295
static char * sctp_optparam_type_to_string(u8 type)
Definition: sctp.h:429
u8 * format_sctp_scoreboard(u8 *s, va_list *args)
ip4_address_t src_address
Definition: ip4_packet.h:170
struct _transport_connection transport_connection_t
u64 as_u64[2]
Definition: ip6_packet.h:51
unsigned long u64
Definition: types.h:89
void sctp_send_init(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:1316
clib_error_t * vnet_sctp_enable_disable(vlib_main_t *vm, u8 is_en)
struct _sctp_sub_connection sctp_sub_connection_t
#define NULL
Definition: clib.h:58
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static u64 sctp_time_now(void)
Definition: sctp.h:669
void sctp_connection_cleanup(sctp_connection_t *sctp_conn)
Cleans up connection state.
Definition: sctp.c:528
#define VLIB_BUFFER_PRE_DATA_SIZE
Definition: buffer.h:52
static_always_inline void clib_spinlock_unlock_if_init(clib_spinlock_t *p)
Definition: lock.h:98
#define foreach_sctp_fsm_state
SSCTP FSM state definitions as per RFC4960.
Definition: sctp.h:346
#define SCTP_ADV_DBG(_fmt, _args...)
Definition: sctp_debug.h:45
vlib_node_registration_t sctp6_output_node
(constructor) VLIB_REGISTER_NODE (sctp6_output_node)
Definition: sctp_output.c:1910
static u64 clib_cpu_time_now(void)
Definition: time.h:75
u8 * format_sctp_connection(u8 *s, va_list *args)
Definition: sctp.c:233
u8 sctp_sub_connection_add_ip6(vlib_main_t *vm, ip6_address_t *lcl_addr, ip6_address_t *rmt_addr)
Definition: sctp.c:352
enum _sctp_timers sctp_timers_e
int i
#define SCTP_HOSTNAME_ADDRESS_TYPE
Definition: sctp_packet.h:784
void sctp_prepare_cookie_ack_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Definition: sctp_output.c:528
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
#define SCTP_DATA_IDLE_INTERVAL
Definition: sctp.h:468
static void update_smallest_pmtu_idx(sctp_connection_t *sctp_conn)
Definition: sctp.h:881
static void sctp_calculate_rto(sctp_connection_t *sctp_conn, u8 conn_idx)
Definition: sctp.h:677
void sctp_init_mss(sctp_connection_t *sctp_conn)
struct _sctp_user_configuration sctp_user_configuration_t
static void sctp_half_open_connection_del(sctp_connection_t *tc)
Cleanup half-open connection.
Definition: sctp.h:574
ip6_address_t src_address
Definition: ip6_packet.h:378
unsigned char u8
Definition: types.h:56
#define ABS(x)
Definition: sctp.h:674
static sctp_main_t * vnet_get_sctp_main()
Definition: sctp.h:542
double f64
Definition: types.h:142
vlib_node_registration_t sctp6_input_node
(constructor) VLIB_REGISTER_NODE (sctp6_input_node)
Definition: sctp_input.c:2359
u8 *() format_function_t(u8 *s, va_list *args)
Definition: format.h:48
void sctp_init_snd_vars(sctp_connection_t *sctp_conn)
Initialize connection send variables.
Definition: sctp.c:255
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
struct _sctp_lookup_dispatch sctp_lookup_dispatch_t
#define SCTP_RTO_MAX
Definition: sctp.h:458
static void sctp_init_cwnd(sctp_connection_t *sctp_conn)
Definition: sctp.h:901
#define always_inline
Definition: clib.h:98
ip4_address_t dst_address
Definition: ip4_packet.h:170
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
static timer_callback_t * timers
Definition: timer.c:61
#define SCTP_RTO_MIN
Definition: sctp.h:457
vhost_vring_state_t state
Definition: vhost_user.h:120
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
static int sctp_half_open_connection_cleanup(sctp_connection_t *tc)
Try to cleanup half-open connection.
Definition: sctp.h:632
unsigned int u32
Definition: types.h:88
#define SCTP_STATE_COOKIE_TYPE
Definition: sctp_packet.h:780
#define SCTP_UNRECOGNIZED_TYPE
Definition: sctp_packet.h:781
void sctp_data_retransmit(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:1521
enum _sctp_error sctp_error_t
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_timer_reset(sctp_connection_t *tc, u8 conn_idx, u8 timer_id)
Definition: sctp.h:609
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:511
u8 sctp_sub_connection_del_ip4(ip4_address_t *lcl_addr, ip4_address_t *rmt_addr)
Definition: sctp.c:318
static sctp_connection_t * sctp_get_connection_from_transport(transport_connection_t *tconn)
Definition: sctp.h:650
#define foreach_sctp_timer
Definition: sctp.h:26
lo
static void * vlib_buffer_push_sctp_net_order(vlib_buffer_t *b, u16 sp, u16 dp, u8 sctp_hdr_opts_len)
Push SCTP header to buffer.
Definition: sctp.h:836
unsigned short u16
Definition: types.h:57
u8 * format_sctp_tx_trace(u8 *s, va_list *args)
Definition: sctp_format.c:26
void sctp_connection_close(sctp_connection_t *sctp_conn)
Definition: sctp.c:580
#define PREDICT_FALSE(x)
Definition: clib.h:111
struct _sctp_connection sctp_connection_t
#define SCTP_IPV6_ADDRESS_TYPE
Definition: sctp_packet.h:778
static u64 sctp_set_time_now(u32 thread_index)
Definition: sctp.h:586
static char * sctp_timer_to_string(u8 timer_id)
Definition: sctp.h:45
void() sctp_timer_expiration_handler(u32 conn_index, u32 timer_id)
Definition: sctp.h:259
#define MAX_SCTP_CONNECTIONS
Definition: sctp.h:80
static char * sctp_state_to_string(u8 state)
Definition: sctp.h:365
vlib_node_registration_t sctp4_output_node
(constructor) VLIB_REGISTER_NODE (sctp4_output_node)
Definition: sctp_output.c:1889
static u8 sctp_next_avail_subconn(sctp_connection_t *sctp_conn)
Definition: sctp.h:868
enum _sctp_state sctp_state_t
#define SCTP_INITIAL_SSHTRESH
Definition: sctp.h:101
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:212
void sctp_api_reference(void)
Definition: sctp_api.c:137
sctp_connection_t * sctp_connection_new(u8 thread_index)
Definition: sctp.c:426
#define clib_warning(format, args...)
Definition: error.h:59
void sctp_connection_timers_reset(sctp_connection_t *sctp_conn)
Stop all connection timers.
Definition: sctp.c:160
u32 sctp_push_header(transport_connection_t *tconn, vlib_buffer_t *b)
Definition: sctp_output.c:1447
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:283
void sctp_punt_unknown(vlib_main_t *vm, u8 is_ip4, u8 is_add)
Definition: sctp.c:97
u8 * format_sctp_connection_id(u8 *s, va_list *args)
Definition: sctp.c:189
static u32 sctp_header_bytes()
Definition: sctp.h:644
u8 sctp_configure(sctp_user_configuration_t config)
Definition: sctp.c:411
void sctp_send_shutdown_complete(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b0)
Definition: sctp_output.c:1299
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
static sctp_connection_t * sctp_half_open_connection_get(u32 conn_index)
Definition: sctp.h:558
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:311
#define ASSERT(truth)
#define SCTP_PRIMARY_PATH_IDX
Definition: sctp.h:81
sctp_main_t sctp_main
Definition: sctp.c:18
static void * vlib_buffer_push_sctp(vlib_buffer_t *b, u16 sp_net, u16 dp_net, u8 sctp_hdr_opts_len)
Push SCTP header to buffer.
Definition: sctp.h:860
clib_error_t * sctp_init(vlib_main_t *vm)
Definition: sctp.c:968
#define SCTP_RTO_BETA
Definition: sctp.h:461
#define clib_max(x, y)
Definition: clib.h:288
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_prepare_cookie_echo_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b, u8 reuse_buffer)
Definition: sctp_output.c:562
static void sctp_timer_update(sctp_connection_t *tc, u8 conn_idx, u8 timer_id, u32 interval)
Definition: sctp.h:730
struct _vlib_node_registration vlib_node_registration_t
static u8 cwnd_fully_utilized(sctp_connection_t *sctp_conn, u8 idx)
Definition: sctp.h:926
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
#define SCTP_IPV4_ADDRESS_TYPE
Definition: sctp_packet.h:776
void sctp_send_cookie_echo(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:600
u8 * format_sctp_header(u8 *s, va_list *args)
Definition: sctp_format.c:20
void sctp_connection_del(sctp_connection_t *sctp_conn)
#define SCTP_RTO_ALPHA
Definition: sctp.h:460
#define vnet_buffer(b)
Definition: buffer.h:368
void sctp_send_heartbeat(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:1234
static char * sctp_chunk_to_string(u8 type)
Definition: sctp.h:390
static u8 sctp_sub_conn_id_via_ip6h(sctp_connection_t *sctp_conn, ip6_header_t *ip6h)
Definition: sctp.h:785
u8 data[0]
Packet data.
Definition: buffer.h:176
void sctp_connection_timers_init(sctp_connection_t *sctp_conn)
Initialize all connection timers as invalid.
Definition: sctp.c:140
#define SCTP_COOKIE_PRESERVATIVE_TYPE
Definition: sctp_packet.h:782
static sctp_connection_t * sctp_listener_get(u32 tli)
Definition: sctp.h:747
u8 sctp_sub_connection_del_ip6(ip6_address_t *lcl_addr, ip6_address_t *rmt_addr)
Definition: sctp.c:375
#define SCTP_TIMER_HANDLE_INVALID
Definition: sctp.h:42
u32 a_rwnd
Maximum segment size advertised.
Definition: sctp.h:153
vlib_node_registration_t sctp4_input_node
(constructor) VLIB_REGISTER_NODE (sctp4_input_node)
Definition: sctp_input.c:2358
#define SCTP_RTO_BURST
Definition: sctp.h:459
static u8 sctp_data_subconn_select(sctp_connection_t *sctp_conn)
Definition: sctp.h:766
sctp_header_t hdr
Definition: sctp_packet.h:260
void sctp_send_shutdown(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:1050
static sctp_header_t * sctp_buffer_hdr(vlib_buffer_t *b)
Definition: sctp.h:548
static_always_inline void clib_spinlock_lock_if_init(clib_spinlock_t *p)
Definition: lock.h:82
static u8 sctp_in_cong_recovery(sctp_connection_t *sctp_conn, u8 idx)
Definition: sctp.h:920
u16 sctp_check_outstanding_data_chunks(sctp_connection_t *sctp_conn)
Definition: sctp.c:558
void sctp_send_shutdown_ack(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b)
Definition: sctp_output.c:1108
format_function_t format_sctp_state
Definition: sctp.h:302
ip6_address_t dst_address
Definition: ip6_packet.h:378
#define SCTP_SUPPORTED_ADDRESS_TYPES
Definition: sctp_packet.h:785