ffe3e1b195f7d9ee2c8339f78dcbfb32c2f710ee
[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 always_inline char *
45 sctp_timer_to_string (u8 timer_id)
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
70   SCTP_N_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 {
94   SCTP_SUBCONN_STATE_DOWN = 0,
95   SCTP_SUBCONN_STATE_UP,
96   SCTP_SUBCONN_STATE_ALLOW_HB,
97   SCTP_SUBCONN_AWAITING_SACK,
98   SCTP_SUBCONN_SACK_RECEIVED
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   u32 rtt_ts;   /**< USED to hold the timestamp of when the packet has been sent */
116
117   u32 RTO; /**< The current retransmission timeout value. */
118   u32 SRTT; /**< The current smoothed round-trip time. */
119   f32 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   u32 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   u32 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
149 } sctp_sub_connection_t;
150
151 typedef struct
152 {
153   u32 a_rwnd; /**< Maximum segment size advertised */
154
155 } sctp_options_t;
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
191 } sctp_user_configuration_t;
192
193 typedef struct _sctp_connection
194 {
195   sctp_sub_connection_t sub_conn[MAX_SCTP_CONNECTIONS]; /**< Common transport data. First! */
196   sctp_user_configuration_t conn_config; /**< Allows tuning of some SCTP behaviors */
197
198   u8 state;                     /**< SCTP state as per sctp_state_t */
199   u16 flags;            /**< Chunk flag (see sctp_chunks_common_hdr_t) */
200
201   u32 local_tag;        /**< INIT_TAG generated locally */
202   u32 remote_tag;       /**< INIT_TAG generated by the remote peer */
203
204   u32 local_initial_tsn; /**< Initial TSN generated locally */
205   u32 remote_initial_tsn; /**< Initial TSN generated by the remote-peer */
206
207   u32 peer_cookie_life_span_increment;
208
209   u32 overall_err_count; /**< The overall association error count. */
210   u32 overall_err_treshold; /**< The threshold for this association that if the Overall Error Count
211                                   reaches will cause this association to be torn down. */
212
213   u8 init_retransmit_err; /**< Error counter for the INIT transmission phase */
214
215   u32 peer_rwnd; /**< Current calculated value of the peer's rwnd. */
216
217   u32 next_tsn; /**< The next TSN number to be assigned to a new DATA chunk.
218                  This is sent in the INIT or INIT ACK chunk to the peer
219                  and incremented each time a DATA chunk is assigned a
220                  TSN (normally just prior to transmit or during
221                  fragmentation). */
222
223   u32 last_unacked_tsn; /** < Last TSN number still unacked */
224   u32 next_tsn_expected; /**< The next TSN number expected to be received. */
225
226   u32 last_rcvd_tsn; /**< This is the last TSN received in sequence. This value
227                          is set initially by taking the peer's initial TSN,
228                  received in the INIT or INIT ACK chunk, and
229                  subtracting one from it. */
230
231   u32 out_of_order_map[MAX_INFLIGHT_PACKETS]; /**< An array of bits or bytes indicating which out-of-order
232                                 TSNs have been received (relative to the Last Rcvd TSN).
233                                 If no gaps exist, i.e., no out-of-order packets have been received,
234                                 this array will be set to all zero. */
235
236   u8 ack_state; /**< This flag indicates if the next received packet is set to be responded to with a SACK.
237                                 This is initialized to 0. When a packet is received it is incremented.
238                                 If this value reaches 2 or more, a SACK is sent and the value is reset to 0.
239                                 Note: This is used only when no DATA chunks are received out-of-order.
240                                 When DATA chunks are out-of-order, SACKs are not delayed (see Section 6). */
241
242   u8 smallest_PMTU_idx; /** The index of the sub-connection with the smallest PMTU discovered across all peer's transport addresses. */
243
244   u8 overall_sending_status; /**< 0 indicates first fragment of a user message
245                                                                   1 indicates normal stream
246                                                                   2 indicates last fragment of a user message */
247
248   u8 forming_association_changed; /**< This is a flag indicating whether the original association has been modified during
249                                   the life-span of the association itself. For instance, a new sub-connection might have been added. */
250
251   sctp_state_cookie_param_t cookie_param; /**< Temporary location to save cookie information; it can be used to
252                                   when timeout expires and sending again a COOKIE is require. */
253
254 } sctp_connection_t;
255
256 typedef void (sctp_timer_expiration_handler) (u32 conn_index, u32 timer_id);
257
258 sctp_connection_t *sctp_connection_new (u8 thread_index);
259
260 u8
261 sctp_sub_connection_add_ip4 (vlib_main_t * vm,
262                              ip4_address_t * lcl_addr,
263                              ip4_address_t * rmt_addr);
264
265 u8
266 sctp_sub_connection_add_ip6 (vlib_main_t * vm,
267                              ip6_address_t * lcl_addr,
268                              ip6_address_t * rmt_addr);
269
270 u8
271 sctp_sub_connection_del_ip4 (ip4_address_t * lcl_addr,
272                              ip4_address_t * rmt_addr);
273
274 u8
275 sctp_sub_connection_del_ip6 (ip6_address_t * lcl_addr,
276                              ip6_address_t * rmt_addr);
277
278 u8 sctp_configure (sctp_user_configuration_t config);
279
280 void sctp_connection_close (sctp_connection_t * sctp_conn);
281 void sctp_connection_cleanup (sctp_connection_t * sctp_conn);
282 void sctp_connection_del (sctp_connection_t * sctp_conn);
283
284 u32 sctp_push_header (transport_connection_t * tconn, vlib_buffer_t * b);
285 void sctp_send_init (sctp_connection_t * sctp_conn);
286 void sctp_send_cookie_echo (sctp_connection_t * sctp_conn);
287 void sctp_send_shutdown (sctp_connection_t * sctp_conn);
288 void sctp_send_shutdown_ack (sctp_connection_t * sctp_conn, u8 idx,
289                              vlib_buffer_t * b);
290 void sctp_send_shutdown_complete (sctp_connection_t * sctp_conn, u8 idx,
291                                   vlib_buffer_t * b0);
292 void sctp_send_heartbeat (sctp_connection_t * sctp_conn);
293 void sctp_data_retransmit (sctp_connection_t * sctp_conn);
294 void sctp_flush_frame_to_output (vlib_main_t * vm, u8 thread_index,
295                                  u8 is_ip4);
296 void sctp_flush_frames_to_output (u8 thread_index);
297 void sctp_punt_unknown (vlib_main_t * vm, u8 is_ip4, u8 is_add);
298
299 format_function_t format_sctp_state;
300
301 u8 *format_sctp_connection_id (u8 * s, va_list * args);
302 u8 *format_sctp_connection (u8 * s, va_list * args);
303 u8 *format_sctp_scoreboard (u8 * s, va_list * args);
304 u8 *format_sctp_header (u8 * s, va_list * args);
305 u8 *format_sctp_tx_trace (u8 * s, va_list * args);
306
307 clib_error_t *sctp_init (vlib_main_t * vm);
308 void sctp_connection_timers_init (sctp_connection_t * sctp_conn);
309 void sctp_connection_timers_reset (sctp_connection_t * sctp_conn);
310 void sctp_init_snd_vars (sctp_connection_t * sctp_conn);
311 void sctp_init_mss (sctp_connection_t * sctp_conn);
312
313 void sctp_prepare_initack_chunk (sctp_connection_t * sctp_conn, u8 idx,
314                                  vlib_buffer_t * b, ip4_address_t * ip4_addr,
315                                  u8 add_ip4, ip6_address_t * ip6_addr,
316                                  u8 add_ip6);
317 void sctp_prepare_initack_chunk_for_collision (sctp_connection_t * sctp_conn,
318                                                u8 idx, vlib_buffer_t * b,
319                                                ip4_address_t * ip4_addr,
320                                                ip6_address_t * ip6_addr);
321 void sctp_prepare_abort_for_collision (sctp_connection_t * sctp_conn, u8 idx,
322                                        vlib_buffer_t * b,
323                                        ip4_address_t * ip4_addr,
324                                        ip6_address_t * ip6_addr);
325 void sctp_prepare_operation_error (sctp_connection_t * sctp_conn, u8 idx,
326                                    vlib_buffer_t * b, u8 err_cause);
327 void sctp_prepare_cookie_echo_chunk (sctp_connection_t * sctp_conn, u8 idx,
328                                      vlib_buffer_t * b, u8 reuse_buffer);
329 void sctp_prepare_cookie_ack_chunk (sctp_connection_t * sctp_conn, u8 idx,
330                                     vlib_buffer_t * b);
331 void sctp_prepare_sack_chunk (sctp_connection_t * sctp_conn, u8 idx,
332                               vlib_buffer_t * b);
333 void sctp_prepare_heartbeat_ack_chunk (sctp_connection_t * sctp_conn, u8 idx,
334                                        vlib_buffer_t * b);
335
336 u16 sctp_check_outstanding_data_chunks (sctp_connection_t * sctp_conn);
337
338 void sctp_api_reference (void);
339
340 #define IP_PROTOCOL_SCTP        132
341
342 /** SSCTP FSM state definitions as per RFC4960. */
343 #define foreach_sctp_fsm_state                \
344   _(CLOSED, "CLOSED")                         \
345   _(COOKIE_WAIT, "COOKIE_WAIT")               \
346   _(COOKIE_ECHOED, "COOKIE_ECHOED")           \
347   _(ESTABLISHED, "ESTABLISHED")               \
348   _(SHUTDOWN_PENDING, "SHUTDOWN_PENDING")     \
349   _(SHUTDOWN_SENT, "SHUTDOWN_SENT")           \
350   _(SHUTDOWN_RECEIVED, "SHUTDOWN_RECEIVED")   \
351   _(SHUTDOWN_ACK_SENT, "SHUTDOWN_ACK_SENT")
352
353 typedef enum _sctp_state
354 {
355 #define _(sym, str) SCTP_STATE_##sym,
356   foreach_sctp_fsm_state
357 #undef _
358   SCTP_N_STATES
359 } sctp_state_t;
360
361 always_inline char *
362 sctp_state_to_string (u8 state)
363 {
364   switch (state)
365     {
366     case SCTP_STATE_CLOSED:
367       return "SCTP_STATE_CLOSED";
368     case SCTP_STATE_COOKIE_WAIT:
369       return "SCTP_STATE_COOKIE_WAIT";
370     case SCTP_STATE_COOKIE_ECHOED:
371       return "SCTP_STATE_COOKIE_ECHOED";
372     case SCTP_STATE_ESTABLISHED:
373       return "SCTP_STATE_ESTABLISHED";
374     case SCTP_STATE_SHUTDOWN_PENDING:
375       return "SCTP_STATE_SHUTDOWN_PENDING";
376     case SCTP_STATE_SHUTDOWN_SENT:
377       return "SCTP_STATE_SHUTDOWN_SENT";
378     case SCTP_STATE_SHUTDOWN_RECEIVED:
379       return "SCTP_STATE_SHUTDOWN_RECEIVED";
380     case SCTP_STATE_SHUTDOWN_ACK_SENT:
381       return "SCTP_STATE_SHUTDOWN_ACK_SENT";
382     }
383   return NULL;
384 }
385
386 always_inline char *
387 sctp_chunk_to_string (u8 type)
388 {
389   switch (type)
390     {
391     case DATA:
392       return "DATA";
393     case INIT:
394       return "INIT";
395     case INIT_ACK:
396       return "INIT_ACK";
397     case SACK:
398       return "SACK";
399     case HEARTBEAT:
400       return "HEARTBEAT";
401     case HEARTBEAT_ACK:
402       return "HEARTBEAT_ACK";
403     case ABORT:
404       return "ABORT";
405     case SHUTDOWN:
406       return "SHUTDOWN";
407     case SHUTDOWN_ACK:
408       return "SHUTDOWN_ACK";
409     case OPERATION_ERROR:
410       return "OPERATION_ERROR";
411     case COOKIE_ECHO:
412       return "COOKIE_ECHO";
413     case COOKIE_ACK:
414       return "COOKIE_ACK";
415     case ECNE:
416       return "ECNE";
417     case CWR:
418       return "CWR";
419     case SHUTDOWN_COMPLETE:
420       return "SHUTDOWN_COMPLETE";
421     }
422   return NULL;
423 }
424
425 always_inline char *
426 sctp_optparam_type_to_string (u8 type)
427 {
428   switch (type)
429     {
430     case SCTP_IPV4_ADDRESS_TYPE:
431       return "SCTP_IPV4_ADDRESS_TYPE";
432     case SCTP_IPV6_ADDRESS_TYPE:
433       return "SCTP_IPV6_ADDRESS_TYPE";
434     case SCTP_STATE_COOKIE_TYPE:
435       return "SCTP_STATE_COOKIE_TYPE";
436     case SCTP_UNRECOGNIZED_TYPE:
437       return "SCTP_UNRECOGNIZED_TYPE";
438     case SCTP_COOKIE_PRESERVATIVE_TYPE:
439       return "SCTP_COOKIE_PRESERVATIVE_TYPE";
440     case SCTP_HOSTNAME_ADDRESS_TYPE:
441       return "SCTP_HOSTNAME_ADDRESS_TYPE";
442     case SCTP_SUPPORTED_ADDRESS_TYPES:
443       return "SCTP_SUPPORTED_ADDRESS_TYPES";
444     }
445   return NULL;
446 }
447
448 #define SCTP_TICK 0.001                 /**< SCTP tick period (s) */
449 #define SHZ (u32) (1/SCTP_TICK)         /**< SCTP tick frequency */
450 #define SCTP_TSTAMP_RESOLUTION SCTP_TICK        /**< Time stamp resolution */
451
452 /* As per RFC4960, page 83 */
453 #define SCTP_RTO_INIT 3 * SHZ   /* 3 seconds */
454 #define SCTP_RTO_MIN 1 * SHZ    /* 1 second */
455 #define SCTP_RTO_MAX 60 * SHZ   /* 60 seconds */
456 #define SCTP_RTO_BURST 4
457 #define SCTP_RTO_ALPHA 1/8
458 #define SCTP_RTO_BETA 1/4
459 #define SCTP_VALID_COOKIE_LIFE 60 * SHZ /* 60 seconds */
460 #define SCTP_ASSOCIATION_MAX_RETRANS 10 // the overall connection
461 #define SCTP_PATH_MAX_RETRANS 5 // number of attempts per destination address
462 #define SCTP_MAX_INIT_RETRANS 8 // number of attempts
463 #define SCTP_HB_INTERVAL 30 * SHZ
464 #define SCTP_HB_MAX_BURST 1
465 #define SCTP_DATA_IDLE_INTERVAL 15 * SHZ        /* 15 seconds; the time-interval after which the connetion is considered IDLE */
466 #define SCTP_TO_TIMER_TICK       SCTP_TICK*10   /* Period for converting from SCTP_TICK */
467
468 #define SCTP_CONN_RECOVERY 1 << 1
469 #define SCTP_FAST_RECOVERY 1 << 2
470
471 typedef struct _sctp_lookup_dispatch
472 {
473   u8 next, error;
474 } sctp_lookup_dispatch_t;
475
476 typedef struct _sctp_main
477 {
478   /* Per-worker thread SCTP connection pools */
479   sctp_connection_t **connections;
480
481   /* Pool of listeners. */
482   sctp_connection_t *listener_pool;
483
484           /** Dispatch table by state and flags */
485   sctp_lookup_dispatch_t dispatch_table[SCTP_N_STATES][64];
486
487   u8 log2_tstamp_clocks_per_tick;
488   f64 tstamp_ticks_per_clock;
489   u32 *time_now;
490
491           /** per-worker tx buffer free lists */
492   u32 **tx_buffers;
493           /** per-worker tx frames to SCTP 4/6 output nodes */
494   vlib_frame_t **tx_frames[2];
495           /** per-worker tx frames to ip 4/6 lookup nodes */
496   vlib_frame_t **ip_lookup_tx_frames[2];
497
498   /* Per worker-thread timer wheel for connections timers */
499   tw_timer_wheel_16t_2w_512sl_t *timer_wheels;
500
501   /* Pool of half-open connections on which we've sent a SYN */
502   sctp_connection_t *half_open_connections;
503   clib_spinlock_t half_open_lock;
504
505   /* TODO: Congestion control algorithms registered */
506   /* sctp_cc_algorithm_t *cc_algos; */
507
508   /* Flag that indicates if stack is on or off */
509   u8 is_enabled;
510
511           /** Number of preallocated connections */
512   u32 preallocated_connections;
513
514           /** Transport table (preallocation) size parameters */
515   u32 local_endpoints_table_memory;
516   u32 local_endpoints_table_buckets;
517
518           /** Vectors of src addresses. Optional unless one needs > 63K active-opens */
519   ip4_address_t *ip4_src_addresses;
520   u32 last_v4_address_rotor;
521   u32 last_v6_address_rotor;
522   ip6_address_t *ip6_src_addresses;
523
524           /** vlib buffer size */
525   u32 bytes_per_buffer;
526
527   u8 punt_unknown4;
528   u8 punt_unknown6;
529
530 } sctp_main_t;
531
532 extern sctp_main_t sctp_main;
533 extern vlib_node_registration_t sctp4_input_node;
534 extern vlib_node_registration_t sctp6_input_node;
535 extern vlib_node_registration_t sctp4_output_node;
536 extern vlib_node_registration_t sctp6_output_node;
537
538 always_inline sctp_main_t *
539 vnet_get_sctp_main ()
540 {
541   return &sctp_main;
542 }
543
544 always_inline sctp_header_t *
545 sctp_buffer_hdr (vlib_buffer_t * b)
546 {
547   ASSERT ((signed) b->current_data >= (signed) -VLIB_BUFFER_PRE_DATA_SIZE);
548   return (sctp_header_t *) (b->data + b->current_data
549                             + vnet_buffer (b)->sctp.hdr_offset);
550 }
551
552 clib_error_t *vnet_sctp_enable_disable (vlib_main_t * vm, u8 is_en);
553
554 always_inline sctp_connection_t *
555 sctp_half_open_connection_get (u32 conn_index)
556 {
557   sctp_connection_t *tc = 0;
558   clib_spinlock_lock_if_init (&sctp_main.half_open_lock);
559   if (!pool_is_free_index (sctp_main.half_open_connections, conn_index))
560     tc = pool_elt_at_index (sctp_main.half_open_connections, conn_index);
561   tc->sub_conn[SCTP_PRIMARY_PATH_IDX].subconn_idx = SCTP_PRIMARY_PATH_IDX;
562   clib_spinlock_unlock_if_init (&sctp_main.half_open_lock);
563   return tc;
564 }
565
566 /**
567  * Cleanup half-open connection
568  *
569  */
570 always_inline void
571 sctp_half_open_connection_del (sctp_connection_t * tc)
572 {
573   sctp_main_t *sctp_main = vnet_get_sctp_main ();
574   clib_spinlock_lock_if_init (&sctp_main->half_open_lock);
575   pool_put_index (sctp_main->half_open_connections,
576                   tc->sub_conn[SCTP_PRIMARY_PATH_IDX].c_c_index);
577   if (CLIB_DEBUG)
578     memset (tc, 0xFA, sizeof (*tc));
579   clib_spinlock_unlock_if_init (&sctp_main->half_open_lock);
580 }
581
582 always_inline u32
583 sctp_set_time_now (u32 thread_index)
584 {
585   sctp_main.time_now[thread_index] = clib_cpu_time_now ()
586     * sctp_main.tstamp_ticks_per_clock;
587   return sctp_main.time_now[thread_index];
588 }
589
590 always_inline void
591 sctp_timer_set (sctp_connection_t * tc, u8 conn_idx, u8 timer_id,
592                 u32 interval)
593 {
594   ASSERT (tc->sub_conn[conn_idx].connection.thread_index ==
595           vlib_get_thread_index ());
596   ASSERT (tc->sub_conn[conn_idx].timers[timer_id] ==
597           SCTP_TIMER_HANDLE_INVALID);
598
599   sctp_sub_connection_t *sub = &tc->sub_conn[conn_idx];
600   sub->timers[timer_id] =
601     tw_timer_start_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
602                                  sub->c_c_index, timer_id, interval);
603 }
604
605 always_inline void
606 sctp_timer_reset (sctp_connection_t * tc, u8 conn_idx, u8 timer_id)
607 {
608   ASSERT (tc->sub_conn[conn_idx].c_thread_index == vlib_get_thread_index ());
609   if (tc->sub_conn[conn_idx].timers[timer_id] == SCTP_TIMER_HANDLE_INVALID)
610     return;
611
612   sctp_sub_connection_t *sub = &tc->sub_conn[conn_idx];
613
614   tw_timer_stop_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
615                               sub->timers[timer_id]);
616   sub->timers[timer_id] = SCTP_TIMER_HANDLE_INVALID;
617 }
618
619 /**
620  * Try to cleanup half-open connection
621  *
622  * If called from a thread that doesn't own tc, the call won't have any
623  * effect.
624  *
625  * @param tc - connection to be cleaned up
626  * @return non-zero if cleanup failed.
627  */
628 always_inline int
629 sctp_half_open_connection_cleanup (sctp_connection_t * tc)
630 {
631   /* Make sure this is the owning thread */
632   if (tc->sub_conn[SCTP_PRIMARY_PATH_IDX].c_thread_index !=
633       vlib_get_thread_index ())
634     return 1;
635   sctp_timer_reset (tc, SCTP_PRIMARY_PATH_IDX, SCTP_TIMER_T1_INIT);
636   sctp_half_open_connection_del (tc);
637   return 0;
638 }
639
640 always_inline u32
641 sctp_header_bytes ()
642 {
643   return sizeof (sctp_header_t);
644 }
645
646 always_inline sctp_connection_t *
647 sctp_get_connection_from_transport (transport_connection_t * tconn)
648 {
649   ASSERT (tconn != NULL);
650
651   sctp_sub_connection_t *sub = (sctp_sub_connection_t *) tconn;
652 #if SCTP_ADV_DEBUG
653   if (sub == NULL)
654     SCTP_ADV_DBG ("sub == NULL");
655   if (sub->parent == NULL)
656     SCTP_ADV_DBG ("sub->parent == NULL");
657 #endif
658   if (sub->subconn_idx > 0)
659     return (sctp_connection_t *) sub -
660       (sizeof (sctp_sub_connection_t) * (sub->subconn_idx - 1));
661
662   return (sctp_connection_t *) sub;
663 }
664
665 always_inline u32
666 sctp_time_now (void)
667 {
668   return sctp_main.time_now[vlib_get_thread_index ()];
669 }
670
671 #define ABS(x) ((x) > 0) ? (x) : -(x);
672
673 always_inline void
674 sctp_calculate_rto (sctp_connection_t * sctp_conn, u8 conn_idx)
675 {
676   /* See RFC4960, 6.3.1.  RTO Calculation */
677   u32 RTO = 0;
678   f32 RTTVAR = 0;
679   u32 now = sctp_time_now ();
680   u32 prev_ts = sctp_conn->sub_conn[conn_idx].rtt_ts;
681   u32 R = prev_ts - now;
682
683   if (sctp_conn->sub_conn[conn_idx].RTO == 0)   // C1: Let's initialize our RTO
684     {
685       sctp_conn->sub_conn[conn_idx].RTO = SCTP_RTO_MIN;
686       return;
687     }
688
689   if (sctp_conn->sub_conn[conn_idx].RTO == SCTP_RTO_MIN && sctp_conn->sub_conn[conn_idx].SRTT == 0)     // C2: First RTT calculation
690     {
691       sctp_conn->sub_conn[conn_idx].SRTT = R;
692       RTTVAR = R / 2;
693
694       if (RTTVAR == 0)
695         RTTVAR = 100e-3;        /* 100 ms */
696
697       sctp_conn->sub_conn[conn_idx].RTTVAR = RTTVAR;
698     }
699   else                          // C3: RTT already exists; let's recalculate
700     {
701       RTTVAR = (1 - SCTP_RTO_BETA) * sctp_conn->sub_conn[conn_idx].RTTVAR +
702         SCTP_RTO_BETA * ABS (sctp_conn->sub_conn[conn_idx].SRTT - R);
703
704       if (RTTVAR == 0)
705         RTTVAR = 100e-3;        /* 100 ms */
706
707       sctp_conn->sub_conn[conn_idx].RTTVAR = RTTVAR;
708
709       sctp_conn->sub_conn[conn_idx].SRTT =
710         (1 - SCTP_RTO_ALPHA) * sctp_conn->sub_conn[conn_idx].SRTT +
711         SCTP_RTO_ALPHA * R;
712     }
713
714   RTO =
715     sctp_conn->sub_conn[conn_idx].SRTT +
716     4 * sctp_conn->sub_conn[conn_idx].RTTVAR;
717   if (RTO < SCTP_RTO_MIN)       // C6
718     RTO = SCTP_RTO_MIN;
719
720   if (RTO > SCTP_RTO_MAX)       // C7
721     RTO = SCTP_RTO_MAX;
722
723   sctp_conn->sub_conn[conn_idx].RTO = RTO;
724 }
725
726 always_inline void
727 sctp_timer_update (sctp_connection_t * tc, u8 conn_idx, u8 timer_id,
728                    u32 interval)
729 {
730   ASSERT (tc->sub_conn[conn_idx].connection.thread_index ==
731           vlib_get_thread_index ());
732   sctp_sub_connection_t *sub = &tc->sub_conn[conn_idx];
733
734   if (tc->sub_conn[conn_idx].timers[timer_id] != SCTP_TIMER_HANDLE_INVALID)
735     tw_timer_stop_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
736                                 sub->timers[timer_id]);
737
738   tc->sub_conn[conn_idx].timers[timer_id] =
739     tw_timer_start_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
740                                  sub->c_c_index, timer_id, interval);
741 }
742
743 always_inline sctp_connection_t *
744 sctp_listener_get (u32 tli)
745 {
746   return pool_elt_at_index (sctp_main.listener_pool, tli);
747 }
748
749 #endif
750
751 always_inline sctp_connection_t *
752 sctp_connection_get (u32 conn_index, u32 thread_index)
753 {
754   if (PREDICT_FALSE
755       (pool_is_free_index (sctp_main.connections[thread_index], conn_index)))
756     return 0;
757   return pool_elt_at_index (sctp_main.connections[thread_index], conn_index);
758 }
759
760 #define SELECT_MAX_RETRIES 8
761
762 always_inline u8
763 sctp_data_subconn_select (sctp_connection_t * sctp_conn)
764 {
765   u32 sub = SCTP_PRIMARY_PATH_IDX;
766   u8 i, cwnd = sctp_conn->sub_conn[SCTP_PRIMARY_PATH_IDX].cwnd;
767   for (i = 1; i < MAX_SCTP_CONNECTIONS; i++)
768     {
769       if (sctp_conn->sub_conn[i].state == SCTP_SUBCONN_STATE_DOWN)
770         continue;
771
772       if (sctp_conn->sub_conn[i].cwnd > cwnd)
773         {
774           sub = i;
775           cwnd = sctp_conn->sub_conn[i].cwnd;
776         }
777     }
778   return sub;
779 }
780
781 always_inline u8
782 sctp_sub_conn_id_via_ip6h (sctp_connection_t * sctp_conn, ip6_header_t * ip6h)
783 {
784   u8 i;
785
786   for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
787     {
788       if (sctp_conn->sub_conn[i].connection.lcl_ip.ip6.as_u64[0] ==
789           ip6h->dst_address.as_u64[0] &&
790           sctp_conn->sub_conn[i].connection.lcl_ip.ip6.as_u64[1] ==
791           ip6h->dst_address.as_u64[1] &&
792           sctp_conn->sub_conn[i].connection.rmt_ip.ip6.as_u64[0] ==
793           ip6h->src_address.as_u64[0] &&
794           sctp_conn->sub_conn[i].connection.rmt_ip.ip6.as_u64[1] ==
795           ip6h->src_address.as_u64[1])
796         return i;
797     }
798   clib_warning ("Did not find a sub-connection; defaulting to %u",
799                 SCTP_PRIMARY_PATH_IDX);
800   return SCTP_PRIMARY_PATH_IDX;
801 }
802
803 always_inline u8
804 sctp_sub_conn_id_via_ip4h (sctp_connection_t * sctp_conn, ip4_header_t * ip4h)
805 {
806   u8 i;
807
808   for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
809     {
810       if (sctp_conn->sub_conn[i].connection.lcl_ip.ip4.as_u32 ==
811           ip4h->dst_address.as_u32
812           && sctp_conn->sub_conn[i].connection.rmt_ip.ip4.as_u32 ==
813           ip4h->src_address.as_u32)
814         return i;
815     }
816   clib_warning ("Did not find a sub-connection; defaulting to %u",
817                 SCTP_PRIMARY_PATH_IDX);
818   return SCTP_PRIMARY_PATH_IDX;
819 }
820
821 /**
822  * Push SCTP header to buffer
823  *
824  * @param vm - vlib_main
825  * @param b - buffer to write the header to
826  * @param sp_net - source port net order
827  * @param dp_net - destination port net order
828  * @param sctp_hdr_opts_len - header and options length in bytes
829  *
830  * @return - pointer to start of SCTP header
831  */
832 always_inline void *
833 vlib_buffer_push_sctp_net_order (vlib_buffer_t * b, u16 sp, u16 dp,
834                                  u8 sctp_hdr_opts_len)
835 {
836   sctp_full_hdr_t *full_hdr;
837
838   full_hdr = vlib_buffer_push_uninit (b, sctp_hdr_opts_len);
839
840   full_hdr->hdr.src_port = sp;
841   full_hdr->hdr.dst_port = dp;
842   full_hdr->hdr.checksum = 0;
843   return full_hdr;
844 }
845
846 /**
847  * Push SCTP header to buffer
848  *
849  * @param b - buffer to write the header to
850  * @param sp_net - source port net order
851  * @param dp_net - destination port net order
852  * @param sctp_hdr_opts_len - header and options length in bytes
853  *
854  * @return - pointer to start of SCTP header
855  */
856 always_inline void *
857 vlib_buffer_push_sctp (vlib_buffer_t * b, u16 sp_net, u16 dp_net,
858                        u8 sctp_hdr_opts_len)
859 {
860   return vlib_buffer_push_sctp_net_order (b, sp_net, dp_net,
861                                           sctp_hdr_opts_len);
862 }
863
864 always_inline u8
865 sctp_next_avail_subconn (sctp_connection_t * sctp_conn)
866 {
867   u8 i;
868
869   for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
870     {
871       if (sctp_conn->sub_conn[i].state == SCTP_SUBCONN_STATE_DOWN)
872         return i;
873     }
874   return MAX_SCTP_CONNECTIONS;
875 }
876
877 always_inline void
878 update_smallest_pmtu_idx (sctp_connection_t * sctp_conn)
879 {
880   u8 i;
881   u8 smallest_pmtu_index = SCTP_PRIMARY_PATH_IDX;
882
883   for (i = 1; i < MAX_SCTP_CONNECTIONS; i++)
884     {
885       if (sctp_conn->sub_conn[i].state != SCTP_SUBCONN_STATE_DOWN)
886         {
887           if (sctp_conn->sub_conn[i].PMTU <
888               sctp_conn->sub_conn[smallest_pmtu_index].PMTU)
889             smallest_pmtu_index = i;
890         }
891     }
892
893   sctp_conn->smallest_PMTU_idx = smallest_pmtu_index;
894 }
895
896 /* As per RFC4960; section 7.2.1: Slow-Start */
897 always_inline void
898 sctp_init_cwnd (sctp_connection_t * sctp_conn)
899 {
900   u8 i;
901   for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
902     {
903       /* Section 7.2.1; point (1) */
904       sctp_conn->sub_conn[i].cwnd =
905         clib_min (4 * sctp_conn->sub_conn[i].PMTU,
906                   clib_max (2 * sctp_conn->sub_conn[i].PMTU, 4380));
907
908       /* Section 7.2.1; point (3) */
909       sctp_conn->sub_conn[i].ssthresh = SCTP_INITIAL_SSHTRESH;
910
911       /* Section 7.2.2; point (1) */
912       sctp_conn->sub_conn[i].partially_acked_bytes = 0;
913     }
914 }
915
916 always_inline u8
917 sctp_in_cong_recovery (sctp_connection_t * sctp_conn, u8 idx)
918 {
919   return 0;
920 }
921
922 always_inline u8
923 cwnd_fully_utilized (sctp_connection_t * sctp_conn, u8 idx)
924 {
925   if (sctp_conn->sub_conn[idx].cwnd == 0)
926     return 1;
927   return 0;
928 }
929
930 /* As per RFC4960; section 7.2.1: Slow-Start */
931 always_inline void
932 update_cwnd (sctp_connection_t * sctp_conn)
933 {
934   u8 i;
935   u32 inflight = sctp_conn->next_tsn - sctp_conn->last_unacked_tsn;
936
937   for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
938     {
939       /* Section 7.2.1; point (2) */
940       if (sctp_conn->sub_conn[i].is_retransmitting)
941         {
942           sctp_conn->sub_conn[i].cwnd = 1 * sctp_conn->sub_conn[i].PMTU;
943           continue;
944         }
945
946       /* Section 7.2.2; point (4) */
947       if (sctp_conn->sub_conn[i].last_data_ts >
948           sctp_time_now () + SCTP_DATA_IDLE_INTERVAL)
949         {
950           sctp_conn->sub_conn[i].cwnd =
951             clib_max (sctp_conn->sub_conn[i].cwnd / 2,
952                       4 * sctp_conn->sub_conn[i].PMTU);
953           continue;
954         }
955
956       /* Section 7.2.1; point (5) */
957       if (sctp_conn->sub_conn[i].cwnd <= sctp_conn->sub_conn[i].ssthresh)
958         {
959           if (!cwnd_fully_utilized (sctp_conn, i))
960             continue;
961
962           if (sctp_in_cong_recovery (sctp_conn, i))
963             continue;
964
965           sctp_conn->sub_conn[i].cwnd =
966             clib_min (sctp_conn->sub_conn[i].PMTU, 1);
967         }
968
969       /* Section 6.1; point (D) */
970       if ((inflight + SCTP_RTO_BURST * sctp_conn->sub_conn[i].PMTU) <
971           sctp_conn->sub_conn[i].cwnd)
972         sctp_conn->sub_conn[i].cwnd =
973           inflight + SCTP_RTO_BURST * sctp_conn->sub_conn[i].PMTU;
974     }
975 }
976
977 /*
978  * fd.io coding-style-patch-verification: ON
979  *
980  * Local Variables:
981  * eval: (c-set-style "gnu")
982  * End:
983  */