FD.io VPP  v19.04-6-g6f05f72
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 */
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  u32 sctp4_established_phase_node_index;
534  u32 sctp6_established_phase_node_index;
535 } sctp_main_t;
536 
537 extern sctp_main_t sctp_main;
542 
545 {
546  return &sctp_main;
547 }
548 
551 {
552  ASSERT ((signed) b->current_data >= (signed) -VLIB_BUFFER_PRE_DATA_SIZE);
553  return (sctp_header_t *) (b->data + b->current_data
554  + vnet_buffer (b)->sctp.hdr_offset);
555 }
556 
558 
561 {
562  sctp_connection_t *tc = 0;
563  clib_spinlock_lock_if_init (&sctp_main.half_open_lock);
564  if (!pool_is_free_index (sctp_main.half_open_connections, conn_index))
565  tc = pool_elt_at_index (sctp_main.half_open_connections, conn_index);
566  tc->sub_conn[SCTP_PRIMARY_PATH_IDX].subconn_idx = SCTP_PRIMARY_PATH_IDX;
567  clib_spinlock_unlock_if_init (&sctp_main.half_open_lock);
568  return tc;
569 }
570 
571 /**
572  * Cleanup half-open connection
573  *
574  */
575 always_inline void
577 {
579  clib_spinlock_lock_if_init (&sctp_main->half_open_lock);
580  pool_put_index (sctp_main->half_open_connections,
581  tc->sub_conn[SCTP_PRIMARY_PATH_IDX].c_c_index);
582  if (CLIB_DEBUG)
583  clib_memset (tc, 0xFA, sizeof (*tc));
584  clib_spinlock_unlock_if_init (&sctp_main->half_open_lock);
585 }
586 
588 sctp_set_time_now (u32 thread_index)
589 {
590  sctp_main.time_now[thread_index] = clib_cpu_time_now ()
591  * sctp_main.tstamp_ticks_per_clock;
592  return sctp_main.time_now[thread_index];
593 }
594 
595 always_inline void
596 sctp_timer_set (sctp_connection_t * tc, u8 conn_idx, u8 timer_id,
597  u32 interval)
598 {
599  ASSERT (tc->sub_conn[conn_idx].connection.thread_index ==
601  ASSERT (tc->sub_conn[conn_idx].timers[timer_id] ==
603 
604  sctp_sub_connection_t *sub = &tc->sub_conn[conn_idx];
605  sub->timers[timer_id] =
606  tw_timer_start_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
607  sub->c_c_index, timer_id, interval);
608 }
609 
610 always_inline void
611 sctp_timer_reset (sctp_connection_t * tc, u8 conn_idx, u8 timer_id)
612 {
613  ASSERT (tc->sub_conn[conn_idx].c_thread_index == vlib_get_thread_index ());
614  if (tc->sub_conn[conn_idx].timers[timer_id] == SCTP_TIMER_HANDLE_INVALID)
615  return;
616 
617  sctp_sub_connection_t *sub = &tc->sub_conn[conn_idx];
618 
619  tw_timer_stop_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
620  sub->timers[timer_id]);
621  sub->timers[timer_id] = SCTP_TIMER_HANDLE_INVALID;
622 }
623 
624 /**
625  * Try to cleanup half-open connection
626  *
627  * If called from a thread that doesn't own tc, the call won't have any
628  * effect.
629  *
630  * @param tc - connection to be cleaned up
631  * @return non-zero if cleanup failed.
632  */
633 always_inline int
635 {
636  /* Make sure this is the owning thread */
637  if (tc->sub_conn[SCTP_PRIMARY_PATH_IDX].c_thread_index !=
639  return 1;
640  sctp_timer_reset (tc, SCTP_PRIMARY_PATH_IDX, SCTP_TIMER_T1_INIT);
642  return 0;
643 }
644 
647 {
648  return sizeof (sctp_header_t);
649 }
650 
653 {
654  ASSERT (tconn != NULL);
655 
657 #if SCTP_ADV_DEBUG
658  if (sub == NULL)
659  SCTP_ADV_DBG ("sub == NULL");
660  if (sub->parent == NULL)
661  SCTP_ADV_DBG ("sub->parent == NULL");
662 #endif
663  if (sub->subconn_idx > 0)
664  return (sctp_connection_t *) sub -
665  (sizeof (sctp_sub_connection_t) * (sub->subconn_idx - 1));
666 
667  return (sctp_connection_t *) sub;
668 }
669 
672 {
673  return sctp_main.time_now[vlib_get_thread_index ()];
674 }
675 
676 #define ABS(x) ((x) > 0) ? (x) : -(x);
677 
678 always_inline void
679 sctp_calculate_rto (sctp_connection_t * sctp_conn, u8 conn_idx)
680 {
681  /* See RFC4960, 6.3.1. RTO Calculation */
682  u64 RTO = 0;
683  f64 RTTVAR = 0;
684  u64 now = sctp_time_now ();
685  u64 prev_ts = sctp_conn->sub_conn[conn_idx].rtt_ts;
686  u64 R = prev_ts - now;
687 
688  if (sctp_conn->sub_conn[conn_idx].RTO == 0) // C1: Let's initialize our RTO
689  {
690  sctp_conn->sub_conn[conn_idx].RTO = SCTP_RTO_MIN;
691  return;
692  }
693 
694  if (sctp_conn->sub_conn[conn_idx].RTO == SCTP_RTO_MIN && sctp_conn->sub_conn[conn_idx].SRTT == 0) // C2: First RTT calculation
695  {
696  sctp_conn->sub_conn[conn_idx].SRTT = R;
697  RTTVAR = R / 2;
698 
699  if (RTTVAR == 0)
700  RTTVAR = 100e-3; /* 100 ms */
701 
702  sctp_conn->sub_conn[conn_idx].RTTVAR = RTTVAR;
703  }
704  else // C3: RTT already exists; let's recalculate
705  {
706  RTTVAR = (1 - SCTP_RTO_BETA) * sctp_conn->sub_conn[conn_idx].RTTVAR +
707  SCTP_RTO_BETA * ABS (sctp_conn->sub_conn[conn_idx].SRTT - R);
708 
709  if (RTTVAR == 0)
710  RTTVAR = 100e-3; /* 100 ms */
711 
712  sctp_conn->sub_conn[conn_idx].RTTVAR = RTTVAR;
713 
714  sctp_conn->sub_conn[conn_idx].SRTT =
715  (1 - SCTP_RTO_ALPHA) * sctp_conn->sub_conn[conn_idx].SRTT +
716  SCTP_RTO_ALPHA * R;
717  }
718 
719  RTO =
720  sctp_conn->sub_conn[conn_idx].SRTT +
721  4 * sctp_conn->sub_conn[conn_idx].RTTVAR;
722  if (RTO < SCTP_RTO_MIN) // C6
723  RTO = SCTP_RTO_MIN;
724 
725  if (RTO > SCTP_RTO_MAX) // C7
726  RTO = SCTP_RTO_MAX;
727 
728  sctp_conn->sub_conn[conn_idx].RTO = RTO;
729 }
730 
731 always_inline void
732 sctp_timer_update (sctp_connection_t * tc, u8 conn_idx, u8 timer_id,
733  u32 interval)
734 {
735  ASSERT (tc->sub_conn[conn_idx].connection.thread_index ==
737  sctp_sub_connection_t *sub = &tc->sub_conn[conn_idx];
738 
739  if (tc->sub_conn[conn_idx].timers[timer_id] != SCTP_TIMER_HANDLE_INVALID)
740  tw_timer_stop_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
741  sub->timers[timer_id]);
742 
743  tc->sub_conn[conn_idx].timers[timer_id] =
744  tw_timer_start_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
745  sub->c_c_index, timer_id, interval);
746 }
747 
750 {
751  return pool_elt_at_index (sctp_main.listener_pool, tli);
752 }
753 
754 #endif
755 
757 sctp_connection_get (u32 conn_index, u32 thread_index)
758 {
759  if (PREDICT_FALSE
760  (pool_is_free_index (sctp_main.connections[thread_index], conn_index)))
761  return 0;
762  return pool_elt_at_index (sctp_main.connections[thread_index], conn_index);
763 }
764 
765 #define SELECT_MAX_RETRIES 8
766 
769 {
771  u8 i, cwnd = sctp_conn->sub_conn[SCTP_PRIMARY_PATH_IDX].cwnd;
772  for (i = 1; i < MAX_SCTP_CONNECTIONS; i++)
773  {
774  if (sctp_conn->sub_conn[i].state == SCTP_SUBCONN_STATE_DOWN)
775  continue;
776 
777  if (sctp_conn->sub_conn[i].cwnd > cwnd)
778  {
779  sub = i;
780  cwnd = sctp_conn->sub_conn[i].cwnd;
781  }
782  }
783  return sub;
784 }
785 
788 {
789  u8 i;
790 
791  for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
792  {
793  if (sctp_conn->sub_conn[i].connection.lcl_ip.ip6.as_u64[0] ==
794  ip6h->dst_address.as_u64[0] &&
795  sctp_conn->sub_conn[i].connection.lcl_ip.ip6.as_u64[1] ==
796  ip6h->dst_address.as_u64[1] &&
797  sctp_conn->sub_conn[i].connection.rmt_ip.ip6.as_u64[0] ==
798  ip6h->src_address.as_u64[0] &&
799  sctp_conn->sub_conn[i].connection.rmt_ip.ip6.as_u64[1] ==
800  ip6h->src_address.as_u64[1])
801  return i;
802  }
803  clib_warning ("Did not find a sub-connection; defaulting to %u",
805  return SCTP_PRIMARY_PATH_IDX;
806 }
807 
810 {
811  u8 i;
812 
813  for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
814  {
815  if (sctp_conn->sub_conn[i].connection.lcl_ip.ip4.as_u32 ==
816  ip4h->dst_address.as_u32
817  && sctp_conn->sub_conn[i].connection.rmt_ip.ip4.as_u32 ==
818  ip4h->src_address.as_u32)
819  return i;
820  }
821  clib_warning ("Did not find a sub-connection; defaulting to %u",
823  return SCTP_PRIMARY_PATH_IDX;
824 }
825 
826 /**
827  * Push SCTP header to buffer
828  *
829  * @param vm - vlib_main
830  * @param b - buffer to write the header to
831  * @param sp_net - source port net order
832  * @param dp_net - destination port net order
833  * @param sctp_hdr_opts_len - header and options length in bytes
834  *
835  * @return - pointer to start of SCTP header
836  */
837 always_inline void *
839  u8 sctp_hdr_opts_len)
840 {
841  sctp_full_hdr_t *full_hdr;
842 
843  full_hdr = vlib_buffer_push_uninit (b, sctp_hdr_opts_len);
844 
845  full_hdr->hdr.src_port = sp;
846  full_hdr->hdr.dst_port = dp;
847  full_hdr->hdr.checksum = 0;
848  return full_hdr;
849 }
850 
851 /**
852  * Push SCTP header to buffer
853  *
854  * @param b - buffer to write the header to
855  * @param sp_net - source port net order
856  * @param dp_net - destination port net order
857  * @param sctp_hdr_opts_len - header and options length in bytes
858  *
859  * @return - pointer to start of SCTP header
860  */
861 always_inline void *
863  u8 sctp_hdr_opts_len)
864 {
865  return vlib_buffer_push_sctp_net_order (b, sp_net, dp_net,
866  sctp_hdr_opts_len);
867 }
868 
871 {
872  u8 i;
873 
874  for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
875  {
876  if (sctp_conn->sub_conn[i].state == SCTP_SUBCONN_STATE_DOWN)
877  return i;
878  }
879  return MAX_SCTP_CONNECTIONS;
880 }
881 
882 always_inline void
884 {
885  u8 i;
886  u8 smallest_pmtu_index = SCTP_PRIMARY_PATH_IDX;
887 
888  for (i = 1; i < MAX_SCTP_CONNECTIONS; i++)
889  {
890  if (sctp_conn->sub_conn[i].state != SCTP_SUBCONN_STATE_DOWN)
891  {
892  if (sctp_conn->sub_conn[i].PMTU <
893  sctp_conn->sub_conn[smallest_pmtu_index].PMTU)
894  smallest_pmtu_index = i;
895  }
896  }
897 
898  sctp_conn->smallest_PMTU_idx = smallest_pmtu_index;
899 }
900 
901 /* As per RFC4960; section 7.2.1: Slow-Start */
902 always_inline void
904 {
905  u8 i;
906  for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
907  {
908  /* Section 7.2.1; point (1) */
909  sctp_conn->sub_conn[i].cwnd =
910  clib_min (4 * sctp_conn->sub_conn[i].PMTU,
911  clib_max (2 * sctp_conn->sub_conn[i].PMTU, 4380));
912 
913  /* Section 7.2.1; point (3) */
914  sctp_conn->sub_conn[i].ssthresh = SCTP_INITIAL_SSHTRESH;
915 
916  /* Section 7.2.2; point (1) */
917  sctp_conn->sub_conn[i].partially_acked_bytes = 0;
918  }
919 }
920 
923 {
924  return 0;
925 }
926 
929 {
930  if (sctp_conn->sub_conn[idx].cwnd == 0)
931  return 1;
932  return 0;
933 }
934 
935 /* As per RFC4960; section 7.2.1: Slow-Start */
936 always_inline void
938 {
939  u8 i;
940  u32 inflight = sctp_conn->next_tsn - sctp_conn->last_unacked_tsn;
941 
942  for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
943  {
944  /* Section 7.2.1; point (2) */
945  if (sctp_conn->sub_conn[i].is_retransmitting)
946  {
947  sctp_conn->sub_conn[i].cwnd = 1 * sctp_conn->sub_conn[i].PMTU;
948  continue;
949  }
950 
951  /* Section 7.2.2; point (4) */
952  if (sctp_conn->sub_conn[i].last_data_ts >
954  {
955  sctp_conn->sub_conn[i].cwnd =
956  clib_max (sctp_conn->sub_conn[i].cwnd / 2,
957  4 * sctp_conn->sub_conn[i].PMTU);
958  continue;
959  }
960 
961  /* Section 7.2.1; point (5) */
962  if (sctp_conn->sub_conn[i].cwnd <= sctp_conn->sub_conn[i].ssthresh)
963  {
964  if (!cwnd_fully_utilized (sctp_conn, i))
965  continue;
966 
967  if (sctp_in_cong_recovery (sctp_conn, i))
968  continue;
969 
970  sctp_conn->sub_conn[i].cwnd =
971  clib_min (sctp_conn->sub_conn[i].PMTU, 1);
972  }
973 
974  /* Section 6.1; point (D) */
975  if ((inflight + SCTP_RTO_BURST * sctp_conn->sub_conn[i].PMTU) <
976  sctp_conn->sub_conn[i].cwnd)
977  sctp_conn->sub_conn[i].cwnd =
978  inflight + SCTP_RTO_BURST * sctp_conn->sub_conn[i].PMTU;
979  }
980 }
981 
982 /*
983  * fd.io coding-style-patch-verification: ON
984  *
985  * Local Variables:
986  * eval: (c-set-style "gnu")
987  * End:
988  */
void sctp_flush_frame_to_output(vlib_main_t *vm, u8 thread_index, u8 is_ip4)
Flush tx frame populated by retransmits and timer pops.
Definition: sctp_output.c:24
#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:596
vmrglw vmrglh hi
static void update_cwnd(sctp_connection_t *sctp_conn)
Definition: sctp.h:937
static u8 sctp_sub_conn_id_via_ip4h(sctp_connection_t *sctp_conn, ip4_header_t *ip4h)
Definition: sctp.h:809
void sctp_flush_frames_to_output(u8 thread_index)
Flush v4 and v6 sctp and ip-lookup tx frames for thread index.
Definition: sctp_output.c:57
#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
u64 as_u64[2]
Definition: ip6_packet.h:51
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
unsigned long u64
Definition: types.h:89
void sctp_send_init(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:1285
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
static u64 sctp_time_now(void)
Definition: sctp.h:671
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:51
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)
u8 data[0]
Packet data.
Definition: buffer.h:181
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:497
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
void sctp_prepare_abort_for_collision(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b, ip4_address_t *ip4_addr, ip6_address_t *ip6_addr)
Convert buffer to ABORT.
Definition: sctp_output.c:659
#define SCTP_DATA_IDLE_INTERVAL
Definition: sctp.h:468
static void update_smallest_pmtu_idx(sctp_connection_t *sctp_conn)
Definition: sctp.h:883
u8 *( format_function_t)(u8 *s, va_list *args)
Definition: format.h:48
static void sctp_calculate_rto(sctp_connection_t *sctp_conn, u8 conn_idx)
Definition: sctp.h:679
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:576
ip6_address_t src_address
Definition: ip6_packet.h:385
unsigned char u8
Definition: types.h:56
#define ABS(x)
Definition: sctp.h:676
static sctp_main_t * vnet_get_sctp_main()
Definition: sctp.h:544
double f64
Definition: types.h:142
vlib_node_registration_t sctp6_input_node
(constructor) VLIB_REGISTER_NODE (sctp6_input_node)
Definition: sctp_input.c:2297
void sctp_init_snd_vars(sctp_connection_t *sctp_conn)
Initialize connection send variables.
Definition: sctp.c:255
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:903
#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:700
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:1094
static int sctp_half_open_connection_cleanup(sctp_connection_t *tc)
Try to cleanup half-open connection.
Definition: sctp.h:634
unsigned int u32
Definition: types.h:88
static ct_connection_t * connections
#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:1492
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:1132
static void sctp_timer_reset(sctp_connection_t *tc, u8 conn_idx, u8 timer_id)
Definition: sctp.h:611
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:514
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:652
#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:838
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:588
static char * sctp_timer_to_string(u8 timer_id)
Definition: sctp.h:45
#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)
static u8 sctp_next_avail_subconn(sctp_connection_t *sctp_conn)
Definition: sctp.h:870
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:1418
struct _transport_connection transport_connection_t
#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:646
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:1268
void sctp_prepare_operation_error(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b, u8 err_cause)
Convert buffer to ERROR.
Definition: sctp_output.c:614
static sctp_connection_t * sctp_half_open_connection_get(u32 conn_index)
Definition: sctp.h:560
#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
u8 is_add
Definition: ipsec_gre.api:36
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:862
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:840
void sctp_prepare_cookie_echo_chunk(sctp_connection_t *sctp_conn, u8 idx, vlib_buffer_t *b, u8 reuse_buffer)
Definition: sctp_output.c:531
static void sctp_timer_update(sctp_connection_t *tc, u8 conn_idx, u8 timer_id, u32 interval)
Definition: sctp.h:732
struct _vlib_node_registration vlib_node_registration_t
static u8 cwnd_fully_utilized(sctp_connection_t *sctp_conn, u8 idx)
Definition: sctp.h:928
static void * vlib_buffer_push_uninit(vlib_buffer_t *b, u8 size)
Prepend uninitialized data to buffer.
Definition: buffer.h:335
static sctp_connection_t * sctp_connection_get(u32 conn_index, u32 thread_index)
Definition: sctp.h:757
#define SCTP_IPV4_ADDRESS_TYPE
Definition: sctp_packet.h:776
void sctp_send_cookie_echo(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:569
u8 * format_sctp_header(u8 *s, va_list *args)
Definition: sctp_format.c:20
VLIB buffer representation.
Definition: buffer.h:102
void sctp_connection_del(sctp_connection_t *sctp_conn)
#define SCTP_RTO_ALPHA
Definition: sctp.h:460
#define vnet_buffer(b)
Definition: buffer.h:369
void sctp_send_heartbeat(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:1203
static char * sctp_chunk_to_string(u8 type)
Definition: sctp.h:390
void( sctp_timer_expiration_handler)(u32 conn_index, u32 timer_id)
Definition: sctp.h:259
static u8 sctp_sub_conn_id_via_ip6h(sctp_connection_t *sctp_conn, ip6_header_t *ip6h)
Definition: sctp.h:787
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:749
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:2277
#define SCTP_RTO_BURST
Definition: sctp.h:459
static u8 sctp_data_subconn_select(sctp_connection_t *sctp_conn)
Definition: sctp.h:768
sctp_header_t hdr
Definition: sctp_packet.h:260
void sctp_send_shutdown(sctp_connection_t *sctp_conn)
Definition: sctp_output.c:1019
static sctp_header_t * sctp_buffer_hdr(vlib_buffer_t *b)
Definition: sctp.h:550
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:922
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:1077
format_function_t format_sctp_state
Definition: sctp.h:302
ip6_address_t dst_address
Definition: ip6_packet.h:385
#define SCTP_SUPPORTED_ADDRESS_TYPES
Definition: sctp_packet.h:785