SCTP: calculate RTO / RTT and RTTVAR as per RFC
[vpp.git] / src / vnet / sctp / sctp.h
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,
37   foreach_sctp_timer
38 #undef _
39   SCTP_N_TIMERS
40 } sctp_timers_e;
41
42 #define SCTP_TIMER_HANDLE_INVALID ((u32) ~0)
43
44 typedef enum _sctp_error
45 {
46 #define sctp_error(n,s) SCTP_ERROR_##n,
47 #include <vnet/sctp/sctp_error.def>
48 #undef sctp_error
49   SCTP_N_ERROR,
50 } sctp_error_t;
51
52 #define NO_FLAG 0
53
54 #define IS_T_BIT_SET(var) ((var) & (1))
55 #define IS_E_BIT_SET(var) ((var) & (1))
56 #define IS_B_BIT_SET(var) ((var) & (1<<1))
57 #define IS_U_BIT_SET(var) ((var) & (1<<2))
58
59 #define MAX_SCTP_CONNECTIONS 32
60 #define MAIN_SCTP_SUB_CONN_IDX 0
61
62 #if (VLIB_BUFFER_TRACE_TRAJECTORY)
63 #define sctp_trajectory_add_start(b, start)                     \
64 {                                                               \
65     (*vlib_buffer_trace_trajectory_cb) (b, start);              \
66 }
67 #else
68 #define sctp_trajectory_add_start(b, start)
69 #endif
70
71 typedef struct _sctp_sub_connection
72 {
73   transport_connection_t connection;          /**< Common transport data. First! */
74   void *parent;                                                         /**< Link to the parent-super connection */
75
76   u32 error_count; /**< The current error count for this destination. */
77   u32 error_threshold; /**< Current error threshold for this destination,
78                                 i.e. what value marks the destination down if error count reaches this value. */
79   u32 cwnd; /**< The current congestion window. */
80   u32 ssthresh; /**< The current ssthresh value. */
81
82   u32 rtt_ts;   /**< USED to hold the timestamp of when the packet has been sent */
83
84   u32 RTO; /**< The current retransmission timeout value. */
85   u32 SRTT; /**< The current smoothed round-trip time. */
86   f32 RTTVAR; /**< The current RTT variation. */
87
88   u32 partially_acked_bytes; /**< The tracking method for increase of cwnd when in
89                                   congestion avoidance mode (see Section 7.2.2).*/
90
91   u8 state; /**< The current state of this destination, i.e., DOWN, UP, ALLOW-HB, NO-HEARTBEAT, etc. */
92
93   u16 PMTU; /**< The current known path MTU. */
94
95   u32 timers[SCTP_N_TIMERS]; /**< A timer used by each destination. */
96
97   u8 RTO_pending; /**< A flag used to track if one of the DATA chunks sent to
98                                   this address is currently being used to compute an RTT.
99                                   If this flag is 0, the next DATA chunk sent to this destination
100                                   should be used to compute an RTT and this flag should be set.
101                                   Every time the RTT calculation completes (i.e., the DATA chunk is SACK'd),
102                                   clear this flag. */
103
104   u32 last_time; /**< The time to which this destination was last sent a packet to.
105                                   This can be used to determine if a HEARTBEAT is needed. */
106
107 } sctp_sub_connection_t;
108
109 typedef struct
110 {
111   u32 a_rwnd; /**< Maximum segment size advertised */
112
113 } sctp_options_t;
114
115 /* Useful macros to deal with the out_of_order_map (array of bit) */
116 #define SET_BIT(A,k)     ( A[(k/32)] |= (1 << (k%32)) )
117 #define CLEAR_BIT(A,k)   ( A[(k/32)] &= ~(1 << (k%32)) )
118 #define TEST_BIT(A,k)    ( A[(k/32)] & (1 << (k%32)) )
119
120 always_inline void
121 _bytes_swap (void *pv, size_t n)
122 {
123   char *p = pv;
124   size_t lo, hi;
125   for (lo = 0, hi = n - 1; hi > lo; lo++, hi--)
126     {
127       char tmp = p[lo];
128       p[lo] = p[hi];
129       p[hi] = tmp;
130     }
131 }
132
133 #define ENDIANESS_SWAP(x) _bytes_swap(&x, sizeof(x));
134
135 #define MAX_INFLIGHT_PACKETS    128
136 #define MAX_ENQUEABLE_SACKS 2
137
138 /* This parameter indicates to the receiver how much increment in
139  * milliseconds the sender wishes the receiver to add to its default
140  * cookie life-span.
141  */
142 #define SUGGESTED_COOKIE_LIFE_SPAN_INCREMENT 1000
143
144 typedef struct _sctp_connection
145 {
146   sctp_sub_connection_t sub_conn[MAX_SCTP_CONNECTIONS]; /**< Common transport data. First! */
147
148   u8 state;                     /**< SCTP state as per sctp_state_t */
149   u16 flags;            /**< Chunk flag (see sctp_chunks_common_hdr_t) */
150
151   u32 local_tag;        /**< INIT_TAG generated locally */
152   u32 remote_tag;       /**< INIT_TAG generated by the remote peer */
153
154   u32 local_initial_tsn; /**< Initial TSN generated locally */
155   u32 remote_initial_tsn; /**< Initial TSN generated by the remote-peer */
156
157   u32 peer_cookie_life_span_increment;
158
159   u32 overall_err_count; /**< The overall association error count. */
160   u32 overall_err_treshold; /**< The threshold for this association that if the Overall Error Count
161                                   reaches will cause this association to be torn down. */
162
163   u32 peer_rwnd; /**< Current calculated value of the peer's rwnd. */
164
165   u32 next_tsn; /**< The next TSN number to be assigned to a new DATA chunk.
166                  This is sent in the INIT or INIT ACK chunk to the peer
167                  and incremented each time a DATA chunk is assigned a
168                  TSN (normally just prior to transmit or during
169                  fragmentation). */
170
171   u32 next_tsn_expected; /**< The next TSN number expected to be received. */
172
173   u32 last_rcvd_tsn; /**< This is the last TSN received in sequence. This value
174                          is set initially by taking the peer's initial TSN,
175                  received in the INIT or INIT ACK chunk, and
176                  subtracting one from it. */
177
178   u32 out_of_order_map[MAX_INFLIGHT_PACKETS]; /**< An array of bits or bytes indicating which out-of-order
179                                 TSNs have been received (relative to the Last Rcvd TSN).
180                                 If no gaps exist, i.e., no out-of-order packets have been received,
181                                 this array will be set to all zero. */
182
183   u8 ack_state; /**< This flag indicates if the next received packet is set to be responded to with a SACK.
184                                 This is initialized to 0. When a packet is received it is incremented.
185                                 If this value reaches 2 or more, a SACK is sent and the value is reset to 0.
186                                 Note: This is used only when no DATA chunks are received out-of-order.
187                                 When DATA chunks are out-of-order, SACKs are not delayed (see Section 6). */
188
189   u32 a_rwnd; /** This value represents the dedicated buffer space, in number of bytes,
190                                 the sender of the INIT has reserved in association with this window.
191                                 During the life of the association, this buffer space SHOULD NOT be lessened
192                                 (i.e., dedicated buffers taken away from this association);
193                                 however, an endpoint MAY change the value of a_rwnd it sends in SACK chunks. */
194
195   u32 smallest_PMTU; /** The smallest PMTU discovered for all of the peer's transport addresses. */
196
197   u32 rcv_a_rwnd;               /**< LOCAL max seg size that includes options. To be updated by congestion algos, etc. */
198   u32 snd_a_rwnd;               /**< REMOTE max seg size that includes options. To be updated if peer pushes back on window, etc.*/
199
200   u8 overall_sending_status; /**< 0 indicates first fragment of a user message
201                                                                   1 indicates normal stream
202                                                                   2 indicates last fragment of a user message */
203
204   sctp_options_t rcv_opts;
205   sctp_options_t snd_opts;
206
207   u32 snd_hdr_length;   /**< BASE HEADER LENGTH for the DATA chunk when sending */
208   u8 next_avail_sub_conn; /**< Represent the index of the next free slot in sub_conn */
209
210 } sctp_connection_t;
211
212 typedef void (sctp_timer_expiration_handler) (u32 conn_index, u32 timer_id);
213
214 sctp_connection_t *sctp_connection_new (u8 thread_index);
215 void sctp_sub_connection_add_ip4 (u8 thread_index,
216                                   sctp_ipv4_addr_param_t * ipv4_addr);
217 void sctp_sub_connection_add_ip6 (u8 thread_index,
218                                   sctp_ipv6_addr_param_t * ipv6_addr);
219 void sctp_connection_close (sctp_connection_t * tc);
220 void sctp_connection_cleanup (sctp_connection_t * tc);
221 void sctp_connection_del (sctp_connection_t * tc);
222
223 u32 sctp_push_header (transport_connection_t * tconn, vlib_buffer_t * b);
224 void sctp_send_init (sctp_connection_t * tc);
225 void sctp_send_shutdown (sctp_connection_t * tc);
226 void sctp_send_shutdown_ack (sctp_connection_t * tc);
227 void sctp_send_shutdown_complete (sctp_connection_t * tc);
228 void sctp_flush_frame_to_output (vlib_main_t * vm, u8 thread_index,
229                                  u8 is_ip4);
230 void sctp_flush_frames_to_output (u8 thread_index);
231 void sctp_punt_unknown (vlib_main_t * vm, u8 is_ip4, u8 is_add);
232
233 format_function_t format_sctp_state;
234
235 u8 *format_sctp_connection_id (u8 * s, va_list * args);
236 u8 *format_sctp_connection (u8 * s, va_list * args);
237 u8 *format_sctp_scoreboard (u8 * s, va_list * args);
238 u8 *format_sctp_header (u8 * s, va_list * args);
239 u8 *format_sctp_tx_trace (u8 * s, va_list * args);
240
241 clib_error_t *sctp_init (vlib_main_t * vm);
242 void sctp_connection_timers_init (sctp_connection_t * tc);
243 void sctp_connection_timers_reset (sctp_connection_t * tc);
244 void sctp_init_snd_vars (sctp_connection_t * tc);
245 void sctp_init_mss (sctp_connection_t * tc);
246
247 void sctp_prepare_initack_chunk (sctp_connection_t * ts, vlib_buffer_t * b,
248                                  ip4_address_t * ip4_addr,
249                                  ip6_address_t * ip6_addr);
250 void sctp_prepare_cookie_echo_chunk (sctp_connection_t * tc,
251                                      vlib_buffer_t * b,
252                                      sctp_state_cookie_param_t * sc);
253 void sctp_prepare_cookie_ack_chunk (sctp_connection_t * tc,
254                                     vlib_buffer_t * b);
255 void sctp_prepare_sack_chunk (sctp_connection_t * tc, vlib_buffer_t * b);
256
257 u16 sctp_check_outstanding_data_chunks (sctp_connection_t * tc);
258
259 #define SCTP_TICK 0.001                 /**< SCTP tick period (s) */
260 #define STHZ (u32) (1/SCTP_TICK)                /**< SCTP tick frequency */
261 #define SCTP_TSTAMP_RESOLUTION SCTP_TICK        /**< Time stamp resolution */
262 #define SCTP_PAWS_IDLE 24 * 24 * 60 * 60 * THZ /**< 24 days */
263 #define SCTP_FIB_RECHECK_PERIOD 1 * THZ /**< Recheck every 1s */
264 #define SCTP_MAX_OPTION_SPACE 40
265
266 #define SCTP_DUPACK_THRESHOLD   3
267 #define SCTP_MAX_RX_FIFO_SIZE   4 << 20
268 #define SCTP_MIN_RX_FIFO_SIZE   4 << 10
269 #define SCTP_IW_N_SEGMENTS      10
270 #define SCTP_ALWAYS_ACK         1       /**< On/off delayed acks */
271 #define SCTP_USE_SACKS          1       /**< Disable only for testing */
272
273 #define IP_PROTOCOL_SCTP        132
274
275 /** SSCTP FSM state definitions as per RFC4960. */
276 #define foreach_sctp_fsm_state                \
277   _(CLOSED, "CLOSED")                         \
278   _(COOKIE_WAIT, "COOKIE_WAIT")               \
279   _(COOKIE_ECHOED, "COOKIE_ECHOED")           \
280   _(ESTABLISHED, "ESTABLISHED")               \
281   _(SHUTDOWN_PENDING, "SHUTDOWN_PENDING")     \
282   _(SHUTDOWN_SENT, "SHUTDOWN_SENT")           \
283   _(SHUTDOWN_RECEIVED, "SHUTDOWN_RECEIVED")   \
284   _(SHUTDOWN_ACK_SENT, "SHUTDOWN_ACK_SENT")
285
286 typedef enum _sctp_state
287 {
288 #define _(sym, str) SCTP_STATE_##sym,
289   foreach_sctp_fsm_state
290 #undef _
291   SCTP_N_STATES
292 } sctp_state_t;
293
294 always_inline char *
295 sctp_state_to_string (u8 state)
296 {
297   switch (state)
298     {
299     case SCTP_STATE_CLOSED:
300       return "SCTP_STATE_CLOSED";
301     case SCTP_STATE_COOKIE_WAIT:
302       return "SCTP_STATE_COOKIE_WAIT";
303     case SCTP_STATE_COOKIE_ECHOED:
304       return "SCTP_STATE_COOKIE_ECHOED";
305     case SCTP_STATE_ESTABLISHED:
306       return "SCTP_STATE_ESTABLISHED";
307     case SCTP_STATE_SHUTDOWN_PENDING:
308       return "SCTP_STATE_SHUTDOWN_PENDING";
309     case SCTP_STATE_SHUTDOWN_SENT:
310       return "SCTP_STATE_SHUTDOWN_SENT";
311     case SCTP_STATE_SHUTDOWN_RECEIVED:
312       return "SCTP_STATE_SHUTDOWN_RECEIVED";
313     case SCTP_STATE_SHUTDOWN_ACK_SENT:
314       return "SCTP_STATE_SHUTDOWN_ACK_SENT";
315     }
316   return NULL;
317 }
318
319 always_inline char *
320 sctp_chunk_to_string (u8 type)
321 {
322   switch (type)
323     {
324     case DATA:
325       return "DATA";
326     case INIT:
327       return "INIT";
328     case INIT_ACK:
329       return "INIT_ACK";
330     case SACK:
331       return "SACK";
332     case HEARTBEAT:
333       return "HEARTBEAT";
334     case HEARTBEAT_ACK:
335       return "HEARTBEAT_ACK";
336     case ABORT:
337       return "ABORT";
338     case SHUTDOWN:
339       return "SHUTDOWN";
340     case SHUTDOWN_ACK:
341       return "SHUTDOWN_ACK";
342     case OPERATION_ERROR:
343       return "OPERATION_ERROR";
344     case COOKIE_ECHO:
345       return "COOKIE_ECHO";
346     case COOKIE_ACK:
347       return "COOKIE_ACK";
348     case ECNE:
349       return "ECNE";
350     case CWR:
351       return "CWR";
352     case SHUTDOWN_COMPLETE:
353       return "SHUTDOWN_COMPLETE";
354     }
355   return NULL;
356 }
357
358 always_inline char *
359 sctp_optparam_type_to_string (u8 type)
360 {
361   switch (type)
362     {
363     case SCTP_IPV4_ADDRESS_TYPE:
364       return "SCTP_IPV4_ADDRESS_TYPE";
365     case SCTP_IPV6_ADDRESS_TYPE:
366       return "SCTP_IPV6_ADDRESS_TYPE";
367     case SCTP_STATE_COOKIE_TYPE:
368       return "SCTP_STATE_COOKIE_TYPE";
369     case SCTP_UNRECOGNIZED_TYPE:
370       return "SCTP_UNRECOGNIZED_TYPE";
371     case SCTP_COOKIE_PRESERVATIVE_TYPE:
372       return "SCTP_COOKIE_PRESERVATIVE_TYPE";
373     case SCTP_HOSTNAME_ADDRESS_TYPE:
374       return "SCTP_HOSTNAME_ADDRESS_TYPE";
375     case SCTP_SUPPORTED_ADDRESS_TYPES:
376       return "SCTP_SUPPORTED_ADDRESS_TYPES";
377     }
378   return NULL;
379 }
380
381 #define SCTP_TICK 0.001                 /**< SCTP tick period (s) */
382 #define SHZ (u32) (1/SCTP_TICK)         /**< SCTP tick frequency */
383
384 /* As per RFC4960, page 83 */
385 #define SCTP_RTO_INIT 3 * SHZ   /* 3 seconds */
386 #define SCTP_RTO_MIN 1 * SHZ    /* 1 second */
387 #define SCTP_RTO_MAX 60 * SHZ   /* 60 seconds */
388 #define SCTP_RTO_BURST  4
389 #define SCTP_RTO_ALPHA 1/8
390 #define SCTP_RTO_BETA 1/4
391 #define SCTP_VALID_COOKIE_LIFE 60 * SHZ /* 60 seconds */
392 #define SCTP_ASSOCIATION_MAX_RETRANS 10
393
394 #define SCTP_TO_TIMER_TICK       SCTP_TICK*10   /* Period for converting from SCTP_TICK */
395
396 typedef struct _sctp_lookup_dispatch
397 {
398   u8 next, error;
399 } sctp_lookup_dispatch_t;
400
401 typedef struct _sctp_main
402 {
403   /* Per-worker thread SCTP connection pools */
404   sctp_connection_t **connections;
405
406   /* Pool of listeners. */
407   sctp_connection_t *listener_pool;
408
409           /** Dispatch table by state and flags */
410   sctp_lookup_dispatch_t dispatch_table[SCTP_N_STATES][64];
411
412   u8 log2_tstamp_clocks_per_tick;
413   f64 tstamp_ticks_per_clock;
414   u32 *time_now;
415
416           /** per-worker tx buffer free lists */
417   u32 **tx_buffers;
418           /** per-worker tx frames to SCTP 4/6 output nodes */
419   vlib_frame_t **tx_frames[2];
420           /** per-worker tx frames to ip 4/6 lookup nodes */
421   vlib_frame_t **ip_lookup_tx_frames[2];
422
423   /* Per worker-thread timer wheel for connections timers */
424   tw_timer_wheel_16t_2w_512sl_t *timer_wheels;
425
426   /* Pool of half-open connections on which we've sent a SYN */
427   sctp_connection_t *half_open_connections;
428   clib_spinlock_t half_open_lock;
429
430   /* TODO: Congestion control algorithms registered */
431   /* sctp_cc_algorithm_t *cc_algos; */
432
433   /* Flag that indicates if stack is on or off */
434   u8 is_enabled;
435
436           /** Number of preallocated connections */
437   u32 preallocated_connections;
438
439           /** Transport table (preallocation) size parameters */
440   u32 local_endpoints_table_memory;
441   u32 local_endpoints_table_buckets;
442
443           /** Vectors of src addresses. Optional unless one needs > 63K active-opens */
444   ip4_address_t *ip4_src_addresses;
445   u32 last_v4_address_rotor;
446   u32 last_v6_address_rotor;
447   ip6_address_t *ip6_src_addresses;
448
449           /** vlib buffer size */
450   u32 bytes_per_buffer;
451
452   u8 punt_unknown4;
453   u8 punt_unknown6;
454
455 } sctp_main_t;
456
457 extern sctp_main_t sctp_main;
458 extern vlib_node_registration_t sctp4_input_node;
459 extern vlib_node_registration_t sctp6_input_node;
460 extern vlib_node_registration_t sctp4_output_node;
461 extern vlib_node_registration_t sctp6_output_node;
462
463 always_inline sctp_main_t *
464 vnet_get_sctp_main ()
465 {
466   return &sctp_main;
467 }
468
469 always_inline sctp_header_t *
470 sctp_buffer_hdr (vlib_buffer_t * b)
471 {
472   ASSERT ((signed) b->current_data >= (signed) -VLIB_BUFFER_PRE_DATA_SIZE);
473   return (sctp_header_t *) (b->data + b->current_data
474                             + vnet_buffer (b)->sctp.hdr_offset);
475 }
476
477 clib_error_t *vnet_sctp_enable_disable (vlib_main_t * vm, u8 is_en);
478
479 always_inline sctp_connection_t *
480 sctp_half_open_connection_get (u32 conn_index)
481 {
482   sctp_connection_t *tc = 0;
483   clib_spinlock_lock_if_init (&sctp_main.half_open_lock);
484   if (!pool_is_free_index (sctp_main.half_open_connections, conn_index))
485     tc = pool_elt_at_index (sctp_main.half_open_connections, conn_index);
486   tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].parent = tc;
487   clib_spinlock_unlock_if_init (&sctp_main.half_open_lock);
488   return tc;
489 }
490
491 /**
492  * Cleanup half-open connection
493  *
494  */
495 always_inline void
496 sctp_half_open_connection_del (sctp_connection_t * tc)
497 {
498   sctp_main_t *tm = vnet_get_sctp_main ();
499   clib_spinlock_lock_if_init (&tm->half_open_lock);
500   pool_put_index (tm->half_open_connections,
501                   tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].c_c_index);
502   if (CLIB_DEBUG)
503     memset (tc, 0xFA, sizeof (*tc));
504   clib_spinlock_unlock_if_init (&tm->half_open_lock);
505 }
506
507 always_inline u32
508 sctp_set_time_now (u32 thread_index)
509 {
510   sctp_main.time_now[thread_index] = clib_cpu_time_now ()
511     * sctp_main.tstamp_ticks_per_clock;
512   return sctp_main.time_now[thread_index];
513 }
514
515 always_inline void
516 sctp_timer_set (sctp_connection_t * tc, u8 conn_idx, u8 timer_id,
517                 u32 interval)
518 {
519   ASSERT (tc->sub_conn[conn_idx].connection.thread_index ==
520           vlib_get_thread_index ());
521   ASSERT (tc->sub_conn[conn_idx].timers[timer_id] ==
522           SCTP_TIMER_HANDLE_INVALID);
523
524   sctp_sub_connection_t *sub = &tc->sub_conn[conn_idx];
525   sub->timers[timer_id] =
526     tw_timer_start_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
527                                  sub->c_c_index, timer_id, interval);
528 }
529
530 always_inline void
531 sctp_timer_reset (sctp_connection_t * tc, u8 conn_idx, u8 timer_id)
532 {
533   ASSERT (tc->sub_conn[conn_idx].c_thread_index == vlib_get_thread_index ());
534   if (tc->sub_conn[conn_idx].timers[timer_id] == SCTP_TIMER_HANDLE_INVALID)
535     return;
536
537   sctp_sub_connection_t *sub = &tc->sub_conn[conn_idx];
538
539   tw_timer_stop_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
540                               sub->timers[timer_id]);
541   sub->timers[timer_id] = SCTP_TIMER_HANDLE_INVALID;
542 }
543
544 /**
545  * Try to cleanup half-open connection
546  *
547  * If called from a thread that doesn't own tc, the call won't have any
548  * effect.
549  *
550  * @param tc - connection to be cleaned up
551  * @return non-zero if cleanup failed.
552  */
553 always_inline int
554 sctp_half_open_connection_cleanup (sctp_connection_t * tc)
555 {
556   /* Make sure this is the owning thread */
557   if (tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].c_thread_index !=
558       vlib_get_thread_index ())
559     return 1;
560   sctp_timer_reset (tc, MAIN_SCTP_SUB_CONN_IDX, SCTP_TIMER_T1_INIT);
561   sctp_half_open_connection_del (tc);
562   return 0;
563 }
564
565 always_inline u32
566 sctp_header_bytes ()
567 {
568   return sizeof (sctp_header_t);
569 }
570
571 always_inline sctp_connection_t *
572 sctp_get_connection_from_transport (transport_connection_t * tconn)
573 {
574   ASSERT (tconn != NULL);
575
576   sctp_sub_connection_t *sub = (sctp_sub_connection_t *) tconn;
577 #if SCTP_ADV_DEBUG
578   if (sub == NULL)
579     SCTP_ADV_DBG ("sub == NULL");
580   if (sub->parent == NULL)
581     SCTP_ADV_DBG ("sub->parent == NULL");
582 #endif
583   return (sctp_connection_t *) sub->parent;
584 }
585
586 always_inline u32
587 sctp_time_now (void)
588 {
589   return sctp_main.time_now[vlib_get_thread_index ()];
590 }
591
592 #define ABS(x) ((x) > 0) ? (x) : -(x);
593
594 always_inline void
595 sctp_calculate_rto (sctp_connection_t * sctp_conn, u8 conn_idx)
596 {
597   /* See RFC4960, 6.3.1.  RTO Calculation */
598   u32 RTO = 0;
599   f32 RTTVAR = 0;
600   u32 now = sctp_time_now ();
601   u32 prev_ts = sctp_conn->sub_conn[conn_idx].rtt_ts;
602   u32 R = prev_ts - now;
603
604   if (sctp_conn->sub_conn[conn_idx].RTO == 0)   // C1: Let's initialize our RTO
605     {
606       sctp_conn->sub_conn[conn_idx].RTO = SCTP_RTO_MIN;
607       return;
608     }
609
610   if (sctp_conn->sub_conn[conn_idx].RTO == SCTP_RTO_MIN && sctp_conn->sub_conn[conn_idx].SRTT == 0)     // C2: First RTT calculation
611     {
612       sctp_conn->sub_conn[conn_idx].SRTT = R;
613       RTTVAR = R / 2;
614
615       if (RTTVAR == 0)
616         RTTVAR = 100e-3;        /* 100 ms */
617
618       sctp_conn->sub_conn[conn_idx].RTTVAR = RTTVAR;
619     }
620   else                          // C3: RTT already exists; let's recalculate
621     {
622       RTTVAR = (1 - SCTP_RTO_BETA) * sctp_conn->sub_conn[conn_idx].RTTVAR +
623         SCTP_RTO_BETA * ABS (sctp_conn->sub_conn[conn_idx].SRTT - R);
624
625       if (RTTVAR == 0)
626         RTTVAR = 100e-3;        /* 100 ms */
627
628       sctp_conn->sub_conn[conn_idx].RTTVAR = RTTVAR;
629
630       sctp_conn->sub_conn[conn_idx].SRTT =
631         (1 - SCTP_RTO_ALPHA) * sctp_conn->sub_conn[conn_idx].SRTT +
632         SCTP_RTO_ALPHA * R;
633     }
634
635   RTO =
636     sctp_conn->sub_conn[conn_idx].SRTT +
637     4 * sctp_conn->sub_conn[conn_idx].RTTVAR;
638   if (RTO < SCTP_RTO_MIN)       // C6
639     RTO = SCTP_RTO_MIN;
640
641   if (RTO > SCTP_RTO_MAX)       // C7
642     RTO = SCTP_RTO_MAX;
643
644   sctp_conn->sub_conn[conn_idx].RTO = RTO;
645 }
646
647 always_inline void
648 sctp_timer_update (sctp_connection_t * tc, u8 conn_idx, u8 timer_id,
649                    u32 interval)
650 {
651   ASSERT (tc->sub_conn[conn_idx].connection.thread_index ==
652           vlib_get_thread_index ());
653   sctp_sub_connection_t *sub = &tc->sub_conn[conn_idx];
654
655   if (tc->sub_conn[conn_idx].timers[timer_id] != SCTP_TIMER_HANDLE_INVALID)
656     tw_timer_stop_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
657                                 sub->timers[timer_id]);
658
659   tc->sub_conn[conn_idx].timers[timer_id] =
660     tw_timer_start_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
661                                  sub->c_c_index, timer_id, interval);
662 }
663
664 always_inline sctp_connection_t *
665 sctp_listener_get (u32 tli)
666 {
667   return pool_elt_at_index (sctp_main.listener_pool, tli);
668 }
669
670 #endif
671
672 always_inline sctp_connection_t *
673 sctp_connection_get (u32 conn_index, u32 thread_index)
674 {
675   if (PREDICT_FALSE
676       (pool_is_free_index (sctp_main.connections[thread_index], conn_index)))
677     return 0;
678   return pool_elt_at_index (sctp_main.connections[thread_index], conn_index);
679 }
680
681 always_inline u8
682 sctp_pick_conn_idx_on_chunk (sctp_chunk_type chunk_type)
683 {
684   u8 idx = MAIN_SCTP_SUB_CONN_IDX;
685
686   switch (chunk_type)
687     {
688     case DATA:
689     case INIT:
690     case INIT_ACK:
691     case SACK:
692     case HEARTBEAT:
693     case HEARTBEAT_ACK:
694     case ABORT:
695     case SHUTDOWN:
696     case SHUTDOWN_ACK:
697     case OPERATION_ERROR:
698     case COOKIE_ECHO:
699     case COOKIE_ACK:
700     case ECNE:
701     case CWR:
702     case SHUTDOWN_COMPLETE:
703       idx = MAIN_SCTP_SUB_CONN_IDX;
704     }
705   return idx;
706 }
707
708 always_inline u8
709 sctp_pick_conn_idx_on_state (sctp_state_t state)
710 {
711   u8 idx = MAIN_SCTP_SUB_CONN_IDX;
712
713   switch (state)
714     {
715     case SCTP_STATE_CLOSED:
716     case SCTP_STATE_COOKIE_WAIT:
717     case SCTP_STATE_COOKIE_ECHOED:
718     case SCTP_STATE_ESTABLISHED:
719     case SCTP_STATE_SHUTDOWN_PENDING:
720     case SCTP_STATE_SHUTDOWN_SENT:
721     case SCTP_STATE_SHUTDOWN_RECEIVED:
722     case SCTP_STATE_SHUTDOWN_ACK_SENT:
723       idx = MAIN_SCTP_SUB_CONN_IDX;
724     default:
725       idx = MAIN_SCTP_SUB_CONN_IDX;
726     }
727   return idx;
728 }
729
730 /**
731  * Push SCTP header to buffer
732  *
733  * @param vm - vlib_main
734  * @param b - buffer to write the header to
735  * @param sp_net - source port net order
736  * @param dp_net - destination port net order
737  * @param sctp_hdr_opts_len - header and options length in bytes
738  *
739  * @return - pointer to start of SCTP header
740  */
741 always_inline void *
742 vlib_buffer_push_sctp_net_order (vlib_buffer_t * b, u16 sp, u16 dp,
743                                  u8 sctp_hdr_opts_len)
744 {
745   sctp_full_hdr_t *full_hdr;
746
747   full_hdr = vlib_buffer_push_uninit (b, sctp_hdr_opts_len);
748
749   full_hdr->hdr.src_port = sp;
750   full_hdr->hdr.dst_port = dp;
751   full_hdr->hdr.checksum = 0;
752   return full_hdr;
753 }
754
755 /**
756  * Push SCTP header to buffer
757  *
758  * @param b - buffer to write the header to
759  * @param sp_net - source port net order
760  * @param dp_net - destination port net order
761  * @param sctp_hdr_opts_len - header and options length in bytes
762  *
763  * @return - pointer to start of SCTP header
764  */
765 always_inline void *
766 vlib_buffer_push_sctp (vlib_buffer_t * b, u16 sp_net, u16 dp_net,
767                        u8 sctp_hdr_opts_len)
768 {
769   return vlib_buffer_push_sctp_net_order (b, sp_net, dp_net,
770                                           sctp_hdr_opts_len);
771 }
772
773 /*
774  * fd.io coding-style-patch-verification: ON
775  *
776  * Local Variables:
777  * eval: (c-set-style "gnu")
778  * End:
779  */