SCTP stack (RFC4960)
[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   _(T5_SHUTDOWN_GUARD, "T5_SHUTDOWN_GUARD")
32
33 typedef enum _sctp_timers
34 {
35 #define _(sym, str) SCTP_TIMER_##sym,
36   foreach_sctp_timer
37 #undef _
38   SCTP_N_TIMERS
39 } sctp_timers_e;
40
41 #define SCTP_TIMER_HANDLE_INVALID ((u32) ~0)
42
43 typedef enum _sctp_error
44 {
45 #define sctp_error(n,s) SCTP_ERROR_##n,
46 #include <vnet/sctp/sctp_error.def>
47 #undef sctp_error
48   SCTP_N_ERROR,
49 } sctp_error_t;
50
51 #define NO_FLAG 0
52
53 #define IS_T_BIT_SET(var) ((var) & (1))
54 #define IS_E_BIT_SET(var) ((var) & (1))
55 #define IS_B_BIT_SET(var) ((var) & (1<<1))
56 #define IS_U_BIT_SET(var) ((var) & (1<<2))
57
58 #define MAX_SCTP_CONNECTIONS 32
59 #define MAIN_SCTP_SUB_CONN_IDX 0
60
61 #if (VLIB_BUFFER_TRACE_TRAJECTORY)
62 #define sctp_trajectory_add_start(b, start)                     \
63 {                                                               \
64     (*vlib_buffer_trace_trajectory_cb) (b, start);              \
65 }
66 #else
67 #define sctp_trajectory_add_start(b, start)
68 #endif
69
70 typedef struct _sctp_sub_connection
71 {
72   transport_connection_t connection;          /**< Common transport data. First! */
73   void *parent;                                                         /**< Link to the parent-super connection */
74   u32 timers[SCTP_N_TIMERS];            /**< Timer handles into timer wheel */
75
76 } sctp_sub_connection_t;
77
78 typedef struct
79 {
80   u32 a_rwnd;           /**< Maximum segment size advertised */
81
82 } sctp_options_t;
83
84 typedef struct _sctp_connection
85 {
86   sctp_sub_connection_t sub_conn[MAX_SCTP_CONNECTIONS];        /**< Common transport data. First! */
87
88   u8 state;                     /**< SCTP state as per sctp_state_t */
89   u16 flags;            /**< Chunk flag (see sctp_chunks_common_hdr_t) */
90   u32 local_tag;        /**< INIT_TAG generated locally */
91   u32 remote_tag;       /**< INIT_TAG generated by the remote peer */
92   u16 life_span_inc;
93
94   /** Send sequence variables RFC4960 */
95   u32 snd_una;          /**< oldest unacknowledged sequence number */
96   u32 snd_una_max;      /**< newest unacknowledged sequence number + 1*/
97   u32 snd_wl1;          /**< seq number used for last snd.wnd update */
98   u32 snd_wl2;          /**< ack number used for last snd.wnd update */
99   u32 snd_nxt;          /**< next seq number to be sent */
100
101   /** Receive sequence variables RFC4960 */
102   u32 rcv_nxt;          /**< next sequence number expected */
103   u32 rcv_las;          /**< rcv_nxt at last ack sent/rcv_wnd update */
104   u32 iss;              /**< initial sent sequence */
105   u32 irs;              /**< initial remote sequence */
106
107   /* RTT and RTO */
108   u32 rto;              /**< Retransmission timeout */
109   u32 rto_boff;         /**< Index for RTO backoff */
110   u32 srtt;             /**< Smoothed RTT */
111   u32 rttvar;           /**< Smoothed mean RTT difference. Approximates variance */
112   u32 rtt_ts;           /**< Timestamp for tracked ACK */
113   u32 rtt_seq;          /**< Sequence number for tracked ACK */
114
115   u32 a_rwnd;                   /** Constrained by medium / IP / etc. */
116   u32 rcv_a_rwnd;               /**< LOCAL max seg size that includes options. To be updated by congestion algos, etc. */
117   u32 snd_a_rwnd;               /**< REMOTE max seg size that includes options. To be updated if peer pushes back on window, etc.*/
118   sctp_options_t rcv_opts;
119   sctp_options_t snd_opts;
120   u32 snd_hdr_length;   /**< BASE HEADER LENGTH for the DATA chunk when sending */
121
122   u8 next_avail_sub_conn; /**< Represent the index of the next free slot in sub_conn */
123 } sctp_connection_t;
124
125 typedef void (timer_expiration_handler) (u32 index);
126
127 sctp_connection_t *sctp_connection_new (u8 thread_index);
128 void sctp_sub_connection_add_ip4 (u8 thread_index,
129                                   sctp_ipv4_addr_param_t * ipv4_addr);
130 void sctp_sub_connection_add_ip6 (u8 thread_index,
131                                   sctp_ipv6_addr_param_t * ipv6_addr);
132 void sctp_connection_close (sctp_connection_t * tc);
133 void sctp_connection_cleanup (sctp_connection_t * tc);
134 void sctp_connection_del (sctp_connection_t * tc);
135
136 u32 sctp_push_header (transport_connection_t * tconn, vlib_buffer_t * b);
137 void sctp_send_init (sctp_connection_t * tc);
138 void sctp_send_shutdown (sctp_connection_t * tc);
139 void sctp_send_shutdown_ack (sctp_connection_t * tc);
140 void sctp_send_shutdown_complete (sctp_connection_t * tc);
141 void sctp_flush_frame_to_output (vlib_main_t * vm, u8 thread_index,
142                                  u8 is_ip4);
143 void sctp_flush_frames_to_output (u8 thread_index);
144 void sctp_punt_unknown (vlib_main_t * vm, u8 is_ip4, u8 is_add);
145
146 format_function_t format_sctp_state;
147
148 u8 *format_sctp_connection_id (u8 * s, va_list * args);
149 u8 *format_sctp_connection (u8 * s, va_list * args);
150 u8 *format_sctp_scoreboard (u8 * s, va_list * args);
151 u8 *format_sctp_header (u8 * s, va_list * args);
152 u8 *format_sctp_tx_trace (u8 * s, va_list * args);
153
154 clib_error_t *sctp_init (vlib_main_t * vm);
155 void sctp_connection_timers_init (sctp_connection_t * tc);
156 void sctp_connection_timers_reset (sctp_connection_t * tc);
157 void sctp_init_snd_vars (sctp_connection_t * tc);
158 void sctp_connection_init_vars (sctp_connection_t * tc);
159
160 void sctp_prepare_initack_chunk (sctp_connection_t * ts, vlib_buffer_t * b,
161                                  ip4_address_t * ip4_addr,
162                                  ip6_address_t * ip6_addr);
163 void sctp_prepare_cookie_echo_chunk (sctp_connection_t * tc,
164                                      vlib_buffer_t * b,
165                                      sctp_state_cookie_param_t * sc);
166 void sctp_prepare_cookie_ack_chunk (sctp_connection_t * tc,
167                                     vlib_buffer_t * b);
168 void sctp_prepare_sack_chunk (sctp_connection_t * tc, vlib_buffer_t * b);
169
170 u16 sctp_check_outstanding_data_chunks (sctp_connection_t * tc);
171
172 #define SCTP_TICK 0.001                 /**< SCTP tick period (s) */
173 #define STHZ (u32) (1/SCTP_TICK)                /**< SCTP tick frequency */
174 #define SCTP_TSTAMP_RESOLUTION SCTP_TICK        /**< Time stamp resolution */
175 #define SCTP_PAWS_IDLE 24 * 24 * 60 * 60 * THZ /**< 24 days */
176 #define SCTP_FIB_RECHECK_PERIOD 1 * THZ /**< Recheck every 1s */
177 #define SCTP_MAX_OPTION_SPACE 40
178
179 #define SCTP_DUPACK_THRESHOLD   3
180 #define SCTP_MAX_RX_FIFO_SIZE   4 << 20
181 #define SCTP_MIN_RX_FIFO_SIZE   4 << 10
182 #define SCTP_IW_N_SEGMENTS      10
183 #define SCTP_ALWAYS_ACK         1       /**< On/off delayed acks */
184 #define SCTP_USE_SACKS          1       /**< Disable only for testing */
185
186 #define IP_PROTOCOL_SCTP        132
187
188 /** SSCTP FSM state definitions as per RFC4960. */
189 #define foreach_sctp_fsm_state                \
190   _(CLOSED, "CLOSED")                         \
191   _(COOKIE_WAIT, "COOKIE_WAIT")               \
192   _(COOKIE_ECHOED, "COOKIE_ECHOED")           \
193   _(ESTABLISHED, "ESTABLISHED")               \
194   _(SHUTDOWN_PENDING, "SHUTDOWN_PENDING")     \
195   _(SHUTDOWN_SENT, "SHUTDOWN_SENT")           \
196   _(SHUTDOWN_RECEIVED, "SHUTDOWN_RECEIVED")   \
197   _(SHUTDOWN_ACK_SENT, "SHUTDOWN_ACK_SENT")
198
199 typedef enum _sctp_state
200 {
201 #define _(sym, str) SCTP_STATE_##sym,
202   foreach_sctp_fsm_state
203 #undef _
204   SCTP_N_STATES
205 } sctp_state_t;
206
207 always_inline char *
208 sctp_state_to_string (u8 state)
209 {
210   switch (state)
211     {
212     case SCTP_STATE_CLOSED:
213       return "SCTP_STATE_CLOSED";
214     case SCTP_STATE_COOKIE_WAIT:
215       return "SCTP_STATE_COOKIE_WAIT";
216     case SCTP_STATE_COOKIE_ECHOED:
217       return "SCTP_STATE_COOKIE_ECHOED";
218     case SCTP_STATE_ESTABLISHED:
219       return "SCTP_STATE_ESTABLISHED";
220     case SCTP_STATE_SHUTDOWN_PENDING:
221       return "SCTP_STATE_SHUTDOWN_PENDING";
222     case SCTP_STATE_SHUTDOWN_SENT:
223       return "SCTP_STATE_SHUTDOWN_SENT";
224     case SCTP_STATE_SHUTDOWN_RECEIVED:
225       return "SCTP_STATE_SHUTDOWN_RECEIVED";
226     case SCTP_STATE_SHUTDOWN_ACK_SENT:
227       return "SCTP_STATE_SHUTDOWN_ACK_SENT";
228     }
229   return NULL;
230 }
231
232 always_inline char *
233 sctp_chunk_to_string (u8 type)
234 {
235   switch (type)
236     {
237     case DATA:
238       return "DATA";
239     case INIT:
240       return "INIT";
241     case INIT_ACK:
242       return "INIT_ACK";
243     case SACK:
244       return "SACK";
245     case HEARTBEAT:
246       return "HEARTBEAT";
247     case HEARTBEAT_ACK:
248       return "HEARTBEAT_ACK";
249     case ABORT:
250       return "ABORT";
251     case SHUTDOWN:
252       return "SHUTDOWN";
253     case SHUTDOWN_ACK:
254       return "SHUTDOWN_ACK";
255     case OPERATION_ERROR:
256       return "OPERATION_ERROR";
257     case COOKIE_ECHO:
258       return "COOKIE_ECHO";
259     case COOKIE_ACK:
260       return "COOKIE_ACK";
261     case ECNE:
262       return "ECNE";
263     case CWR:
264       return "CWR";
265     case SHUTDOWN_COMPLETE:
266       return "SHUTDOWN_COMPLETE";
267     }
268   return NULL;
269 }
270
271 always_inline char *
272 sctp_optparam_type_to_string (u8 type)
273 {
274   switch (type)
275     {
276     case SCTP_IPV4_ADDRESS_TYPE:
277       return "SCTP_IPV4_ADDRESS_TYPE";
278     case SCTP_IPV6_ADDRESS_TYPE:
279       return "SCTP_IPV6_ADDRESS_TYPE";
280     case SCTP_STATE_COOKIE_TYPE:
281       return "SCTP_STATE_COOKIE_TYPE";
282     case SCTP_UNRECOGNIZED_TYPE:
283       return "SCTP_UNRECOGNIZED_TYPE";
284     case SCTP_COOKIE_PRESERVATIVE_TYPE:
285       return "SCTP_COOKIE_PRESERVATIVE_TYPE";
286     case SCTP_HOSTNAME_ADDRESS_TYPE:
287       return "SCTP_HOSTNAME_ADDRESS_TYPE";
288     case SCTP_SUPPORTED_ADDRESS_TYPES:
289       return "SCTP_SUPPORTED_ADDRESS_TYPES";
290     }
291   return NULL;
292 }
293
294 #define SCTP_TICK 0.001                 /**< SCTP tick period (s) */
295 #define SHZ (u32) (1/SCTP_TICK)         /**< SCTP tick frequency */
296
297 /* As per RFC4960, page 83 */
298 #define SCTP_RTO_INIT 3 * SHZ   /* 3 seconds */
299 #define SCTP_RTO_MIN 1 * SHZ    /* 1 second */
300 #define SCTP_RTO_MAX 60 * SHZ   /* 60 seconds */
301 #define SCTP_RTO_BURST  4
302 #define SCTP_RTO_ALPHA 1/8
303 #define SCTP_RTO_BETA 1/4
304 #define SCTP_VALID_COOKIE_LIFE 60 * SHZ /* 60 seconds */
305 #define SCTP_ASSOCIATION_MAX_RETRANS 10
306
307 #define SCTP_TO_TIMER_TICK       SCTP_TICK*10   /* Period for converting from SCTP_TICK */
308
309 typedef struct _sctp_lookup_dispatch
310 {
311   u8 next, error;
312 } sctp_lookup_dispatch_t;
313
314 typedef struct _sctp_main
315 {
316   /* Per-worker thread SCTP connection pools */
317   sctp_connection_t **connections;
318
319   /* Pool of listeners. */
320   sctp_connection_t *listener_pool;
321
322           /** Dispatch table by state and flags */
323   sctp_lookup_dispatch_t dispatch_table[SCTP_N_STATES][64];
324
325   u8 log2_tstamp_clocks_per_tick;
326   f64 tstamp_ticks_per_clock;
327   u32 *time_now;
328
329           /** per-worker tx buffer free lists */
330   u32 **tx_buffers;
331           /** per-worker tx frames to SCTP 4/6 output nodes */
332   vlib_frame_t **tx_frames[2];
333           /** per-worker tx frames to ip 4/6 lookup nodes */
334   vlib_frame_t **ip_lookup_tx_frames[2];
335
336   /* Per worker-thread timer wheel for connections timers */
337   tw_timer_wheel_16t_2w_512sl_t *timer_wheels;
338
339   /* Pool of half-open connections on which we've sent a SYN */
340   sctp_connection_t *half_open_connections;
341   clib_spinlock_t half_open_lock;
342
343   /* TODO: Congestion control algorithms registered */
344   /* sctp_cc_algorithm_t *cc_algos; */
345
346   /* Flag that indicates if stack is on or off */
347   u8 is_enabled;
348
349           /** Number of preallocated connections */
350   u32 preallocated_connections;
351
352           /** Transport table (preallocation) size parameters */
353   u32 local_endpoints_table_memory;
354   u32 local_endpoints_table_buckets;
355
356           /** Vectors of src addresses. Optional unless one needs > 63K active-opens */
357   ip4_address_t *ip4_src_addresses;
358   u32 last_v4_address_rotor;
359   u32 last_v6_address_rotor;
360   ip6_address_t *ip6_src_addresses;
361
362           /** vlib buffer size */
363   u32 bytes_per_buffer;
364
365   u8 punt_unknown4;
366   u8 punt_unknown6;
367
368 } sctp_main_t;
369
370 extern sctp_main_t sctp_main;
371 extern vlib_node_registration_t sctp4_input_node;
372 extern vlib_node_registration_t sctp6_input_node;
373 extern vlib_node_registration_t sctp4_output_node;
374 extern vlib_node_registration_t sctp6_output_node;
375
376 always_inline sctp_main_t *
377 vnet_get_sctp_main ()
378 {
379   return &sctp_main;
380 }
381
382 always_inline sctp_header_t *
383 sctp_buffer_hdr (vlib_buffer_t * b)
384 {
385   ASSERT ((signed) b->current_data >= (signed) -VLIB_BUFFER_PRE_DATA_SIZE);
386   return (sctp_header_t *) (b->data + b->current_data
387                             + vnet_buffer (b)->sctp.hdr_offset);
388 }
389
390 clib_error_t *vnet_sctp_enable_disable (vlib_main_t * vm, u8 is_en);
391
392 always_inline sctp_connection_t *
393 sctp_half_open_connection_get (u32 conn_index)
394 {
395   sctp_connection_t *tc = 0;
396   clib_spinlock_lock_if_init (&sctp_main.half_open_lock);
397   if (!pool_is_free_index (sctp_main.half_open_connections, conn_index))
398     tc = pool_elt_at_index (sctp_main.half_open_connections, conn_index);
399   tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].parent = tc;
400   clib_spinlock_unlock_if_init (&sctp_main.half_open_lock);
401   return tc;
402 }
403
404 /**
405  * Cleanup half-open connection
406  *
407  */
408 always_inline void
409 sctp_half_open_connection_del (sctp_connection_t * tc)
410 {
411   sctp_main_t *tm = vnet_get_sctp_main ();
412   clib_spinlock_lock_if_init (&tm->half_open_lock);
413   pool_put_index (tm->half_open_connections,
414                   tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].c_c_index);
415   if (CLIB_DEBUG)
416     memset (tc, 0xFA, sizeof (*tc));
417   clib_spinlock_unlock_if_init (&tm->half_open_lock);
418 }
419
420 always_inline u32
421 sctp_set_time_now (u32 thread_index)
422 {
423   sctp_main.time_now[thread_index] = clib_cpu_time_now ()
424     * sctp_main.tstamp_ticks_per_clock;
425   return sctp_main.time_now[thread_index];
426 }
427
428 always_inline void
429 sctp_timer_set (sctp_connection_t * tc, u8 conn_idx, u8 timer_id,
430                 u32 interval)
431 {
432   ASSERT (tc->sub_conn[conn_idx].connection.thread_index ==
433           vlib_get_thread_index ());
434   ASSERT (tc->sub_conn[conn_idx].timers[timer_id] ==
435           SCTP_TIMER_HANDLE_INVALID);
436
437   sctp_sub_connection_t *sub = &tc->sub_conn[conn_idx];
438   tc->sub_conn[conn_idx].timers[timer_id] =
439     tw_timer_start_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
440                                  sub->c_c_index, timer_id, interval);
441 }
442
443 always_inline void
444 sctp_timer_reset (sctp_connection_t * tc, u8 conn_idx, u8 timer_id)
445 {
446   ASSERT (tc->sub_conn[conn_idx].c_thread_index == vlib_get_thread_index ());
447   if (tc->sub_conn[conn_idx].timers[timer_id] == SCTP_TIMER_HANDLE_INVALID)
448     return;
449
450   sctp_sub_connection_t *sub = &tc->sub_conn[conn_idx];
451
452   tw_timer_stop_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
453                               sub->timers[timer_id]);
454   sub->timers[timer_id] = SCTP_TIMER_HANDLE_INVALID;
455 }
456
457 always_inline void
458 sctp_update_time (f64 now, u32 thread_index)
459 {
460   sctp_set_time_now (thread_index);
461   tw_timer_expire_timers_16t_2w_512sl (&sctp_main.timer_wheels[thread_index],
462                                        now);
463   sctp_flush_frames_to_output (thread_index);
464 }
465
466 /**
467  * Try to cleanup half-open connection
468  *
469  * If called from a thread that doesn't own tc, the call won't have any
470  * effect.
471  *
472  * @param tc - connection to be cleaned up
473  * @return non-zero if cleanup failed.
474  */
475 always_inline int
476 sctp_half_open_connection_cleanup (sctp_connection_t * tc)
477 {
478   /* Make sure this is the owning thread */
479   if (tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].c_thread_index !=
480       vlib_get_thread_index ())
481     return 1;
482   sctp_timer_reset (tc, MAIN_SCTP_SUB_CONN_IDX, SCTP_TIMER_T1_INIT);
483   sctp_half_open_connection_del (tc);
484   return 0;
485 }
486
487 always_inline u32
488 sctp_header_bytes ()
489 {
490   return sizeof (sctp_header_t);
491 }
492
493 always_inline sctp_connection_t *
494 sctp_get_connection_from_transport (transport_connection_t * tconn)
495 {
496   ASSERT (tconn != NULL);
497
498   sctp_sub_connection_t *sub = (sctp_sub_connection_t *) tconn;
499 #if SCTP_ADV_DEBUG
500   if (sub == NULL)
501     SCTP_ADV_DBG ("sub == NULL");
502   if (sub->parent == NULL)
503     SCTP_ADV_DBG ("sub->parent == NULL");
504 #endif
505   return (sctp_connection_t *) sub->parent;
506 }
507
508 always_inline u32
509 sctp_time_now (void)
510 {
511   return sctp_main.time_now[vlib_get_thread_index ()];
512 }
513
514 always_inline void
515 sctp_timer_update (sctp_connection_t * tc, u8 conn_idx, u8 timer_id,
516                    u32 interval)
517 {
518   ASSERT (tc->sub_conn[conn_idx].connection.thread_index ==
519           vlib_get_thread_index ());
520   sctp_sub_connection_t *sub = &tc->sub_conn[conn_idx];
521
522   if (tc->sub_conn[conn_idx].timers[timer_id] != SCTP_TIMER_HANDLE_INVALID)
523     tw_timer_stop_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
524                                 sub->timers[timer_id]);
525   tc->sub_conn[conn_idx].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 sctp_connection_t *
531 sctp_listener_get (u32 tli)
532 {
533   return pool_elt_at_index (sctp_main.listener_pool, tli);
534 }
535
536 #endif
537
538 always_inline sctp_connection_t *
539 sctp_connection_get (u32 conn_index, u32 thread_index)
540 {
541   if (PREDICT_FALSE
542       (pool_is_free_index (sctp_main.connections[thread_index], conn_index)))
543     return 0;
544   return pool_elt_at_index (sctp_main.connections[thread_index], conn_index);
545 }
546
547 always_inline u8
548 sctp_pick_conn_idx_on_chunk (sctp_chunk_type chunk_type)
549 {
550   u8 idx = MAIN_SCTP_SUB_CONN_IDX;
551
552   switch (chunk_type)
553     {
554     case DATA:
555     case INIT:
556     case INIT_ACK:
557     case SACK:
558     case HEARTBEAT:
559     case HEARTBEAT_ACK:
560     case ABORT:
561     case SHUTDOWN:
562     case SHUTDOWN_ACK:
563     case OPERATION_ERROR:
564     case COOKIE_ECHO:
565     case COOKIE_ACK:
566     case ECNE:
567     case CWR:
568     case SHUTDOWN_COMPLETE:
569       idx = MAIN_SCTP_SUB_CONN_IDX;
570     }
571   return idx;
572 }
573
574 always_inline u8
575 sctp_pick_conn_idx_on_state (sctp_state_t state)
576 {
577   u8 idx = MAIN_SCTP_SUB_CONN_IDX;
578
579   switch (state)
580     {
581     case SCTP_STATE_CLOSED:
582     case SCTP_STATE_COOKIE_WAIT:
583     case SCTP_STATE_COOKIE_ECHOED:
584     case SCTP_STATE_ESTABLISHED:
585     case SCTP_STATE_SHUTDOWN_PENDING:
586     case SCTP_STATE_SHUTDOWN_SENT:
587     case SCTP_STATE_SHUTDOWN_RECEIVED:
588     case SCTP_STATE_SHUTDOWN_ACK_SENT:
589       idx = MAIN_SCTP_SUB_CONN_IDX;
590     default:
591       idx = MAIN_SCTP_SUB_CONN_IDX;
592     }
593   return idx;
594 }
595
596 /**
597  * Push SCTP header to buffer
598  *
599  * @param vm - vlib_main
600  * @param b - buffer to write the header to
601  * @param sp_net - source port net order
602  * @param dp_net - destination port net order
603  * @param sctp_hdr_opts_len - header and options length in bytes
604  *
605  * @return - pointer to start of SCTP header
606  */
607 always_inline void *
608 vlib_buffer_push_sctp_net_order (vlib_buffer_t * b, u16 sp, u16 dp,
609                                  u8 sctp_hdr_opts_len)
610 {
611   sctp_full_hdr_t *full_hdr;
612
613   full_hdr = vlib_buffer_push_uninit (b, sctp_hdr_opts_len);
614
615   full_hdr->hdr.src_port = sp;
616   full_hdr->hdr.dst_port = dp;
617   full_hdr->hdr.checksum = 0;
618   return full_hdr;
619 }
620
621 /**
622  * Push SCTP header to buffer
623  *
624  * @param b - buffer to write the header to
625  * @param sp_net - source port net order
626  * @param dp_net - destination port net order
627  * @param sctp_hdr_opts_len - header and options length in bytes
628  *
629  * @return - pointer to start of SCTP header
630  */
631 always_inline void *
632 vlib_buffer_push_sctp (vlib_buffer_t * b, u16 sp_net, u16 dp_net,
633                        u8 sctp_hdr_opts_len)
634 {
635   return vlib_buffer_push_sctp_net_order (b, sp_net, dp_net,
636                                           sctp_hdr_opts_len);
637 }
638
639 /*
640  * fd.io coding-style-patch-verification: ON
641  *
642  * Local Variables:
643  * eval: (c-set-style "gnu")
644  * End:
645  */