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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
15 #ifndef included_vnet_sctp_h
16 #define included_vnet_sctp_h
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>
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")
34 typedef enum _sctp_timers
36 #define _(sym, str) SCTP_TIMER_##sym,
42 #define SCTP_TIMER_HANDLE_INVALID ((u32) ~0)
45 sctp_timer_to_string (u8 timer_id)
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";
65 typedef enum _sctp_error
67 #define sctp_error(n,s) SCTP_ERROR_##n,
68 #include <vnet/sctp/sctp_error.def>
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))
80 #define MAX_SCTP_CONNECTIONS 32
81 #define MAIN_SCTP_SUB_CONN_IDX 0
83 #if (VLIB_BUFFER_TRACE_TRAJECTORY)
84 #define sctp_trajectory_add_start(b, start) \
86 (*vlib_buffer_trace_trajectory_cb) (b, start); \
89 #define sctp_trajectory_add_start(b, start)
92 enum _sctp_subconn_state
94 SCTP_SUBCONN_STATE_DOWN = 0,
95 SCTP_SUBCONN_STATE_UP,
96 SCTP_SUBCONN_STATE_ALLOW_HB
99 typedef struct _sctp_sub_connection
101 transport_connection_t connection; /**< Common transport data. First! */
102 void *parent; /**< Link to the parent-super connection */
104 u32 error_count; /**< The current error count for this destination. */
105 u32 error_threshold; /**< Current error threshold for this destination,
106 i.e. what value marks the destination down if error count reaches this value. */
107 u32 cwnd; /**< The current congestion window. */
108 u32 ssthresh; /**< The current ssthresh value. */
110 u32 rtt_ts; /**< USED to hold the timestamp of when the packet has been sent */
112 u32 RTO; /**< The current retransmission timeout value. */
113 u32 SRTT; /**< The current smoothed round-trip time. */
114 f32 RTTVAR; /**< The current RTT variation. */
116 u32 partially_acked_bytes; /**< The tracking method for increase of cwnd when in
117 congestion avoidance mode (see Section 7.2.2).*/
119 u8 state; /**< The current state of this destination, i.e., DOWN, UP, ALLOW-HB, NO-HEARTBEAT, etc. */
121 u16 PMTU; /**< The current known path MTU. */
123 u32 timers[SCTP_N_TIMERS]; /**< A timer used by each destination. */
125 u8 RTO_pending; /**< A flag used to track if one of the DATA chunks sent to
126 this address is currently being used to compute an RTT.
127 If this flag is 0, the next DATA chunk sent to this destination
128 should be used to compute an RTT and this flag should be set.
129 Every time the RTT calculation completes (i.e., the DATA chunk is SACK'd),
132 u32 last_seen; /**< The time to which this destination was last sent a packet to.
133 This can be used to determine if a HEARTBEAT is needed. */
135 u8 unacknowledged_hb; /**< Used to track how many unacknowledged heartbeats we had;
136 If more than SCTP_PATH_MAX_RETRANS then connection is considered unreachable. */
138 u8 is_retransmitting; /**< A flag (0 = no, 1 = yes) indicating whether the connection is retransmitting a previous packet */
142 } sctp_sub_connection_t;
146 u32 a_rwnd; /**< Maximum segment size advertised */
150 /* Useful macros to deal with the out_of_order_map (array of bit) */
151 #define SET_BIT(A,k) ( A[(k/32)] |= (1 << (k%32)) )
152 #define CLEAR_BIT(A,k) ( A[(k/32)] &= ~(1 << (k%32)) )
153 #define TEST_BIT(A,k) ( A[(k/32)] & (1 << (k%32)) )
156 _bytes_swap (void *pv, size_t n)
160 for (lo = 0, hi = n - 1; hi > lo; lo++, hi--)
168 #define ENDIANESS_SWAP(x) _bytes_swap(&x, sizeof(x));
170 #define MAX_INFLIGHT_PACKETS 128
171 #define MAX_ENQUEABLE_SACKS 2
173 /* This parameter indicates to the receiver how much increment in
174 * milliseconds the sender wishes the receiver to add to its default
177 #define SUGGESTED_COOKIE_LIFE_SPAN_INCREMENT 1000
179 typedef struct _sctp_connection
181 sctp_sub_connection_t sub_conn[MAX_SCTP_CONNECTIONS]; /**< Common transport data. First! */
183 u8 state; /**< SCTP state as per sctp_state_t */
184 u16 flags; /**< Chunk flag (see sctp_chunks_common_hdr_t) */
186 u32 local_tag; /**< INIT_TAG generated locally */
187 u32 remote_tag; /**< INIT_TAG generated by the remote peer */
189 u32 local_initial_tsn; /**< Initial TSN generated locally */
190 u32 remote_initial_tsn; /**< Initial TSN generated by the remote-peer */
192 u32 peer_cookie_life_span_increment;
194 u32 overall_err_count; /**< The overall association error count. */
195 u32 overall_err_treshold; /**< The threshold for this association that if the Overall Error Count
196 reaches will cause this association to be torn down. */
198 u32 peer_rwnd; /**< Current calculated value of the peer's rwnd. */
200 u32 next_tsn; /**< The next TSN number to be assigned to a new DATA chunk.
201 This is sent in the INIT or INIT ACK chunk to the peer
202 and incremented each time a DATA chunk is assigned a
203 TSN (normally just prior to transmit or during
206 u32 next_tsn_expected; /**< The next TSN number expected to be received. */
208 u32 last_rcvd_tsn; /**< This is the last TSN received in sequence. This value
209 is set initially by taking the peer's initial TSN,
210 received in the INIT or INIT ACK chunk, and
211 subtracting one from it. */
213 u32 out_of_order_map[MAX_INFLIGHT_PACKETS]; /**< An array of bits or bytes indicating which out-of-order
214 TSNs have been received (relative to the Last Rcvd TSN).
215 If no gaps exist, i.e., no out-of-order packets have been received,
216 this array will be set to all zero. */
218 u8 ack_state; /**< This flag indicates if the next received packet is set to be responded to with a SACK.
219 This is initialized to 0. When a packet is received it is incremented.
220 If this value reaches 2 or more, a SACK is sent and the value is reset to 0.
221 Note: This is used only when no DATA chunks are received out-of-order.
222 When DATA chunks are out-of-order, SACKs are not delayed (see Section 6). */
224 u32 a_rwnd; /** This value represents the dedicated buffer space, in number of bytes,
225 the sender of the INIT has reserved in association with this window.
226 During the life of the association, this buffer space SHOULD NOT be lessened
227 (i.e., dedicated buffers taken away from this association);
228 however, an endpoint MAY change the value of a_rwnd it sends in SACK chunks. */
230 u32 smallest_PMTU; /** The smallest PMTU discovered for all of the peer's transport addresses. */
232 u32 rcv_a_rwnd; /**< LOCAL max seg size that includes options. To be updated by congestion algos, etc. */
233 u32 snd_a_rwnd; /**< REMOTE max seg size that includes options. To be updated if peer pushes back on window, etc.*/
235 u8 overall_sending_status; /**< 0 indicates first fragment of a user message
236 1 indicates normal stream
237 2 indicates last fragment of a user message */
239 sctp_options_t rcv_opts;
240 sctp_options_t snd_opts;
242 u32 snd_hdr_length; /**< BASE HEADER LENGTH for the DATA chunk when sending */
243 u8 next_avail_sub_conn; /**< Represent the index of the next free slot in sub_conn */
247 typedef void (sctp_timer_expiration_handler) (u32 conn_index, u32 timer_id);
249 sctp_connection_t *sctp_connection_new (u8 thread_index);
250 void sctp_sub_connection_add_ip4 (u8 thread_index,
251 sctp_ipv4_addr_param_t * ipv4_addr);
252 void sctp_sub_connection_add_ip6 (u8 thread_index,
253 sctp_ipv6_addr_param_t * ipv6_addr);
254 void sctp_connection_close (sctp_connection_t * sctp_conn);
255 void sctp_connection_cleanup (sctp_connection_t * sctp_conn);
256 void sctp_connection_del (sctp_connection_t * sctp_conn);
258 u32 sctp_push_header (transport_connection_t * tconn, vlib_buffer_t * b);
259 void sctp_send_init (sctp_connection_t * sctp_conn);
260 void sctp_send_shutdown (sctp_connection_t * sctp_conn);
261 void sctp_send_shutdown_ack (sctp_connection_t * sctp_conn, u8 idx,
263 void sctp_send_shutdown_complete (sctp_connection_t * sctp_conn, u8 idx,
265 void sctp_send_heartbeat (sctp_connection_t * sctp_conn);
266 void sctp_flush_frame_to_output (vlib_main_t * vm, u8 thread_index,
268 void sctp_flush_frames_to_output (u8 thread_index);
269 void sctp_punt_unknown (vlib_main_t * vm, u8 is_ip4, u8 is_add);
271 format_function_t format_sctp_state;
273 u8 *format_sctp_connection_id (u8 * s, va_list * args);
274 u8 *format_sctp_connection (u8 * s, va_list * args);
275 u8 *format_sctp_scoreboard (u8 * s, va_list * args);
276 u8 *format_sctp_header (u8 * s, va_list * args);
277 u8 *format_sctp_tx_trace (u8 * s, va_list * args);
279 clib_error_t *sctp_init (vlib_main_t * vm);
280 void sctp_connection_timers_init (sctp_connection_t * sctp_conn);
281 void sctp_connection_timers_reset (sctp_connection_t * sctp_conn);
282 void sctp_init_snd_vars (sctp_connection_t * sctp_conn);
283 void sctp_init_mss (sctp_connection_t * sctp_conn);
285 void sctp_prepare_initack_chunk (sctp_connection_t * sctp_conn, u8 idx,
286 vlib_buffer_t * b, ip4_address_t * ip4_addr,
287 ip6_address_t * ip6_addr);
288 void sctp_prepare_cookie_echo_chunk (sctp_connection_t * sctp_conn, u8 idx,
290 sctp_state_cookie_param_t * sc);
291 void sctp_prepare_cookie_ack_chunk (sctp_connection_t * sctp_conn, u8 idx,
293 void sctp_prepare_sack_chunk (sctp_connection_t * sctp_conn, u8 idx,
295 void sctp_prepare_heartbeat_ack_chunk (sctp_connection_t * sctp_conn, u8 idx,
298 u16 sctp_check_outstanding_data_chunks (sctp_connection_t * sctp_conn);
300 #define IP_PROTOCOL_SCTP 132
302 /** SSCTP FSM state definitions as per RFC4960. */
303 #define foreach_sctp_fsm_state \
304 _(CLOSED, "CLOSED") \
305 _(COOKIE_WAIT, "COOKIE_WAIT") \
306 _(COOKIE_ECHOED, "COOKIE_ECHOED") \
307 _(ESTABLISHED, "ESTABLISHED") \
308 _(SHUTDOWN_PENDING, "SHUTDOWN_PENDING") \
309 _(SHUTDOWN_SENT, "SHUTDOWN_SENT") \
310 _(SHUTDOWN_RECEIVED, "SHUTDOWN_RECEIVED") \
311 _(SHUTDOWN_ACK_SENT, "SHUTDOWN_ACK_SENT")
313 typedef enum _sctp_state
315 #define _(sym, str) SCTP_STATE_##sym,
316 foreach_sctp_fsm_state
322 sctp_state_to_string (u8 state)
326 case SCTP_STATE_CLOSED:
327 return "SCTP_STATE_CLOSED";
328 case SCTP_STATE_COOKIE_WAIT:
329 return "SCTP_STATE_COOKIE_WAIT";
330 case SCTP_STATE_COOKIE_ECHOED:
331 return "SCTP_STATE_COOKIE_ECHOED";
332 case SCTP_STATE_ESTABLISHED:
333 return "SCTP_STATE_ESTABLISHED";
334 case SCTP_STATE_SHUTDOWN_PENDING:
335 return "SCTP_STATE_SHUTDOWN_PENDING";
336 case SCTP_STATE_SHUTDOWN_SENT:
337 return "SCTP_STATE_SHUTDOWN_SENT";
338 case SCTP_STATE_SHUTDOWN_RECEIVED:
339 return "SCTP_STATE_SHUTDOWN_RECEIVED";
340 case SCTP_STATE_SHUTDOWN_ACK_SENT:
341 return "SCTP_STATE_SHUTDOWN_ACK_SENT";
347 sctp_chunk_to_string (u8 type)
362 return "HEARTBEAT_ACK";
368 return "SHUTDOWN_ACK";
369 case OPERATION_ERROR:
370 return "OPERATION_ERROR";
372 return "COOKIE_ECHO";
379 case SHUTDOWN_COMPLETE:
380 return "SHUTDOWN_COMPLETE";
386 sctp_optparam_type_to_string (u8 type)
390 case SCTP_IPV4_ADDRESS_TYPE:
391 return "SCTP_IPV4_ADDRESS_TYPE";
392 case SCTP_IPV6_ADDRESS_TYPE:
393 return "SCTP_IPV6_ADDRESS_TYPE";
394 case SCTP_STATE_COOKIE_TYPE:
395 return "SCTP_STATE_COOKIE_TYPE";
396 case SCTP_UNRECOGNIZED_TYPE:
397 return "SCTP_UNRECOGNIZED_TYPE";
398 case SCTP_COOKIE_PRESERVATIVE_TYPE:
399 return "SCTP_COOKIE_PRESERVATIVE_TYPE";
400 case SCTP_HOSTNAME_ADDRESS_TYPE:
401 return "SCTP_HOSTNAME_ADDRESS_TYPE";
402 case SCTP_SUPPORTED_ADDRESS_TYPES:
403 return "SCTP_SUPPORTED_ADDRESS_TYPES";
408 #define SCTP_TICK 0.001 /**< SCTP tick period (s) */
409 #define SHZ (u32) (1/SCTP_TICK) /**< SCTP tick frequency */
410 #define SCTP_TSTAMP_RESOLUTION SCTP_TICK /**< Time stamp resolution */
412 /* As per RFC4960, page 83 */
413 #define SCTP_RTO_INIT 3 * SHZ /* 3 seconds */
414 #define SCTP_RTO_MIN 1 * SHZ /* 1 second */
415 #define SCTP_RTO_MAX 60 * SHZ /* 60 seconds */
416 #define SCTP_RTO_BURST 4
417 #define SCTP_RTO_ALPHA 1/8
418 #define SCTP_RTO_BETA 1/4
419 #define SCTP_VALID_COOKIE_LIFE 60 * SHZ /* 60 seconds */
420 #define SCTP_ASSOCIATION_MAX_RETRANS 10 // the overall connection
421 #define SCTP_PATH_MAX_RETRANS 5 // number of attempts per destination address
422 #define SCTP_MAX_INIT_RETRANS 8 // number of attempts
423 #define SCTP_HB_INTERVAL 30 * SHZ
424 #define SCTP_HB_MAX_BURST 1
426 #define SCTP_TO_TIMER_TICK SCTP_TICK*10 /* Period for converting from SCTP_TICK */
428 typedef struct _sctp_lookup_dispatch
431 } sctp_lookup_dispatch_t;
433 typedef struct _sctp_main
435 /* Per-worker thread SCTP connection pools */
436 sctp_connection_t **connections;
438 /* Pool of listeners. */
439 sctp_connection_t *listener_pool;
441 /** Dispatch table by state and flags */
442 sctp_lookup_dispatch_t dispatch_table[SCTP_N_STATES][64];
444 u8 log2_tstamp_clocks_per_tick;
445 f64 tstamp_ticks_per_clock;
448 /** per-worker tx buffer free lists */
450 /** per-worker tx frames to SCTP 4/6 output nodes */
451 vlib_frame_t **tx_frames[2];
452 /** per-worker tx frames to ip 4/6 lookup nodes */
453 vlib_frame_t **ip_lookup_tx_frames[2];
455 /* Per worker-thread timer wheel for connections timers */
456 tw_timer_wheel_16t_2w_512sl_t *timer_wheels;
458 /* Pool of half-open connections on which we've sent a SYN */
459 sctp_connection_t *half_open_connections;
460 clib_spinlock_t half_open_lock;
462 /* TODO: Congestion control algorithms registered */
463 /* sctp_cc_algorithm_t *cc_algos; */
465 /* Flag that indicates if stack is on or off */
468 /** Number of preallocated connections */
469 u32 preallocated_connections;
471 /** Transport table (preallocation) size parameters */
472 u32 local_endpoints_table_memory;
473 u32 local_endpoints_table_buckets;
475 /** Vectors of src addresses. Optional unless one needs > 63K active-opens */
476 ip4_address_t *ip4_src_addresses;
477 u32 last_v4_address_rotor;
478 u32 last_v6_address_rotor;
479 ip6_address_t *ip6_src_addresses;
481 /** vlib buffer size */
482 u32 bytes_per_buffer;
489 extern sctp_main_t sctp_main;
490 extern vlib_node_registration_t sctp4_input_node;
491 extern vlib_node_registration_t sctp6_input_node;
492 extern vlib_node_registration_t sctp4_output_node;
493 extern vlib_node_registration_t sctp6_output_node;
495 always_inline sctp_main_t *
496 vnet_get_sctp_main ()
501 always_inline sctp_header_t *
502 sctp_buffer_hdr (vlib_buffer_t * b)
504 ASSERT ((signed) b->current_data >= (signed) -VLIB_BUFFER_PRE_DATA_SIZE);
505 return (sctp_header_t *) (b->data + b->current_data
506 + vnet_buffer (b)->sctp.hdr_offset);
509 clib_error_t *vnet_sctp_enable_disable (vlib_main_t * vm, u8 is_en);
511 always_inline sctp_connection_t *
512 sctp_half_open_connection_get (u32 conn_index)
514 sctp_connection_t *tc = 0;
515 clib_spinlock_lock_if_init (&sctp_main.half_open_lock);
516 if (!pool_is_free_index (sctp_main.half_open_connections, conn_index))
517 tc = pool_elt_at_index (sctp_main.half_open_connections, conn_index);
518 tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].parent = tc;
519 clib_spinlock_unlock_if_init (&sctp_main.half_open_lock);
524 * Cleanup half-open connection
528 sctp_half_open_connection_del (sctp_connection_t * tc)
530 sctp_main_t *tm = vnet_get_sctp_main ();
531 clib_spinlock_lock_if_init (&tm->half_open_lock);
532 pool_put_index (tm->half_open_connections,
533 tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].c_c_index);
535 memset (tc, 0xFA, sizeof (*tc));
536 clib_spinlock_unlock_if_init (&tm->half_open_lock);
540 sctp_set_time_now (u32 thread_index)
542 sctp_main.time_now[thread_index] = clib_cpu_time_now ()
543 * sctp_main.tstamp_ticks_per_clock;
544 return sctp_main.time_now[thread_index];
548 sctp_timer_set (sctp_connection_t * tc, u8 conn_idx, u8 timer_id,
551 ASSERT (tc->sub_conn[conn_idx].connection.thread_index ==
552 vlib_get_thread_index ());
553 ASSERT (tc->sub_conn[conn_idx].timers[timer_id] ==
554 SCTP_TIMER_HANDLE_INVALID);
556 sctp_sub_connection_t *sub = &tc->sub_conn[conn_idx];
557 sub->timers[timer_id] =
558 tw_timer_start_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
559 sub->c_c_index, timer_id, interval);
563 sctp_timer_reset (sctp_connection_t * tc, u8 conn_idx, u8 timer_id)
565 ASSERT (tc->sub_conn[conn_idx].c_thread_index == vlib_get_thread_index ());
566 if (tc->sub_conn[conn_idx].timers[timer_id] == SCTP_TIMER_HANDLE_INVALID)
569 sctp_sub_connection_t *sub = &tc->sub_conn[conn_idx];
571 tw_timer_stop_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
572 sub->timers[timer_id]);
573 sub->timers[timer_id] = SCTP_TIMER_HANDLE_INVALID;
577 * Try to cleanup half-open connection
579 * If called from a thread that doesn't own tc, the call won't have any
582 * @param tc - connection to be cleaned up
583 * @return non-zero if cleanup failed.
586 sctp_half_open_connection_cleanup (sctp_connection_t * tc)
588 /* Make sure this is the owning thread */
589 if (tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].c_thread_index !=
590 vlib_get_thread_index ())
592 sctp_timer_reset (tc, MAIN_SCTP_SUB_CONN_IDX, SCTP_TIMER_T1_INIT);
593 sctp_half_open_connection_del (tc);
600 return sizeof (sctp_header_t);
603 always_inline sctp_connection_t *
604 sctp_get_connection_from_transport (transport_connection_t * tconn)
606 ASSERT (tconn != NULL);
608 sctp_sub_connection_t *sub = (sctp_sub_connection_t *) tconn;
611 SCTP_ADV_DBG ("sub == NULL");
612 if (sub->parent == NULL)
613 SCTP_ADV_DBG ("sub->parent == NULL");
615 return (sctp_connection_t *) sub->parent;
621 return sctp_main.time_now[vlib_get_thread_index ()];
624 #define ABS(x) ((x) > 0) ? (x) : -(x);
627 sctp_calculate_rto (sctp_connection_t * sctp_conn, u8 conn_idx)
629 /* See RFC4960, 6.3.1. RTO Calculation */
632 u32 now = sctp_time_now ();
633 u32 prev_ts = sctp_conn->sub_conn[conn_idx].rtt_ts;
634 u32 R = prev_ts - now;
636 if (sctp_conn->sub_conn[conn_idx].RTO == 0) // C1: Let's initialize our RTO
638 sctp_conn->sub_conn[conn_idx].RTO = SCTP_RTO_MIN;
642 if (sctp_conn->sub_conn[conn_idx].RTO == SCTP_RTO_MIN && sctp_conn->sub_conn[conn_idx].SRTT == 0) // C2: First RTT calculation
644 sctp_conn->sub_conn[conn_idx].SRTT = R;
648 RTTVAR = 100e-3; /* 100 ms */
650 sctp_conn->sub_conn[conn_idx].RTTVAR = RTTVAR;
652 else // C3: RTT already exists; let's recalculate
654 RTTVAR = (1 - SCTP_RTO_BETA) * sctp_conn->sub_conn[conn_idx].RTTVAR +
655 SCTP_RTO_BETA * ABS (sctp_conn->sub_conn[conn_idx].SRTT - R);
658 RTTVAR = 100e-3; /* 100 ms */
660 sctp_conn->sub_conn[conn_idx].RTTVAR = RTTVAR;
662 sctp_conn->sub_conn[conn_idx].SRTT =
663 (1 - SCTP_RTO_ALPHA) * sctp_conn->sub_conn[conn_idx].SRTT +
668 sctp_conn->sub_conn[conn_idx].SRTT +
669 4 * sctp_conn->sub_conn[conn_idx].RTTVAR;
670 if (RTO < SCTP_RTO_MIN) // C6
673 if (RTO > SCTP_RTO_MAX) // C7
676 sctp_conn->sub_conn[conn_idx].RTO = RTO;
680 sctp_timer_update (sctp_connection_t * tc, u8 conn_idx, u8 timer_id,
683 ASSERT (tc->sub_conn[conn_idx].connection.thread_index ==
684 vlib_get_thread_index ());
685 sctp_sub_connection_t *sub = &tc->sub_conn[conn_idx];
687 if (tc->sub_conn[conn_idx].timers[timer_id] != SCTP_TIMER_HANDLE_INVALID)
688 tw_timer_stop_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
689 sub->timers[timer_id]);
691 tc->sub_conn[conn_idx].timers[timer_id] =
692 tw_timer_start_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
693 sub->c_c_index, timer_id, interval);
696 always_inline sctp_connection_t *
697 sctp_listener_get (u32 tli)
699 return pool_elt_at_index (sctp_main.listener_pool, tli);
704 always_inline sctp_connection_t *
705 sctp_connection_get (u32 conn_index, u32 thread_index)
708 (pool_is_free_index (sctp_main.connections[thread_index], conn_index)))
710 return pool_elt_at_index (sctp_main.connections[thread_index], conn_index);
713 #define SELECT_MAX_RETRIES 8
716 sctp_data_subconn_select (sctp_connection_t * sctp_conn)
719 u8 state = SCTP_SUBCONN_STATE_DOWN;
720 u32 sub = MAIN_SCTP_SUB_CONN_IDX;
721 u32 data_subconn_seed = random_default_seed ();
723 while (state == SCTP_SUBCONN_STATE_DOWN && i < SELECT_MAX_RETRIES)
725 u32 sub = random_u32 (&data_subconn_seed) % MAX_SCTP_CONNECTIONS;
726 if (sctp_conn->sub_conn[sub].state == SCTP_SUBCONN_STATE_UP)
734 sctp_sub_conn_id_via_ip6h (sctp_connection_t * sctp_conn, ip6_header_t * ip6h)
738 for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
740 if (sctp_conn->sub_conn[i].connection.lcl_ip.ip6.as_u64[0] ==
741 ip6h->dst_address.as_u64[0] &&
742 sctp_conn->sub_conn[i].connection.lcl_ip.ip6.as_u64[1] ==
743 ip6h->dst_address.as_u64[1] &&
744 sctp_conn->sub_conn[i].connection.rmt_ip.ip6.as_u64[0] ==
745 ip6h->src_address.as_u64[0] &&
746 sctp_conn->sub_conn[i].connection.rmt_ip.ip6.as_u64[1] ==
747 ip6h->src_address.as_u64[1])
750 clib_warning ("Did not find a sub-connection; defaulting to %u",
751 MAIN_SCTP_SUB_CONN_IDX);
752 return MAIN_SCTP_SUB_CONN_IDX;
756 sctp_sub_conn_id_via_ip4h (sctp_connection_t * sctp_conn, ip4_header_t * ip4h)
760 for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
762 if (sctp_conn->sub_conn[i].connection.lcl_ip.ip4.as_u32 ==
763 ip4h->dst_address.as_u32
764 && sctp_conn->sub_conn[i].connection.rmt_ip.ip4.as_u32 ==
765 ip4h->src_address.as_u32)
768 clib_warning ("Did not find a sub-connection; defaulting to %u",
769 MAIN_SCTP_SUB_CONN_IDX);
770 return MAIN_SCTP_SUB_CONN_IDX;
774 * Push SCTP header to buffer
776 * @param vm - vlib_main
777 * @param b - buffer to write the header to
778 * @param sp_net - source port net order
779 * @param dp_net - destination port net order
780 * @param sctp_hdr_opts_len - header and options length in bytes
782 * @return - pointer to start of SCTP header
785 vlib_buffer_push_sctp_net_order (vlib_buffer_t * b, u16 sp, u16 dp,
786 u8 sctp_hdr_opts_len)
788 sctp_full_hdr_t *full_hdr;
790 full_hdr = vlib_buffer_push_uninit (b, sctp_hdr_opts_len);
792 full_hdr->hdr.src_port = sp;
793 full_hdr->hdr.dst_port = dp;
794 full_hdr->hdr.checksum = 0;
799 * Push SCTP header to buffer
801 * @param b - buffer to write the header to
802 * @param sp_net - source port net order
803 * @param dp_net - destination port net order
804 * @param sctp_hdr_opts_len - header and options length in bytes
806 * @return - pointer to start of SCTP header
809 vlib_buffer_push_sctp (vlib_buffer_t * b, u16 sp_net, u16 dp_net,
810 u8 sctp_hdr_opts_len)
812 return vlib_buffer_push_sctp_net_order (b, sp_net, dp_net,
817 * fd.io coding-style-patch-verification: ON
820 * eval: (c-set-style "gnu")