452b6bf22cc92b3e24ef621d5398168478fa8eb7
[vpp.git] / src / plugins / sctp / sctp.c
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
16 #include <vnet/plugin/plugin.h>
17 #include <vpp/app/version.h>
18
19 #include <sctp/sctp.h>
20 #include <sctp/sctp_debug.h>
21
22 sctp_main_t sctp_main;
23
24 static u32
25 sctp_connection_bind (u32 session_index, transport_endpoint_t * tep)
26 {
27   sctp_main_t *tm = &sctp_main;
28   sctp_connection_t *listener;
29   void *iface_ip;
30   u32 mtu = 1460;
31
32   pool_get (tm->listener_pool, listener);
33   clib_memset (listener, 0, sizeof (*listener));
34
35   listener->sub_conn[SCTP_PRIMARY_PATH_IDX].subconn_idx =
36     SCTP_PRIMARY_PATH_IDX;
37   listener->sub_conn[SCTP_PRIMARY_PATH_IDX].c_c_index =
38     listener - tm->listener_pool;
39   listener->sub_conn[SCTP_PRIMARY_PATH_IDX].connection.lcl_port = tep->port;
40
41   /* If we are provided a sw_if_index, bind using one of its IPs */
42   if (ip_is_zero (&tep->ip, 1) && tep->sw_if_index != ENDPOINT_INVALID_INDEX)
43     {
44       if ((iface_ip = ip_interface_get_first_ip (tep->sw_if_index,
45                                                  tep->is_ip4)))
46         ip_set (&tep->ip, iface_ip, tep->is_ip4);
47     }
48   ip_copy (&listener->sub_conn[SCTP_PRIMARY_PATH_IDX].connection.lcl_ip,
49            &tep->ip, tep->is_ip4);
50
51   if (tep->sw_if_index != ENDPOINT_INVALID_INDEX)
52     mtu = tep->is_ip4 ? vnet_sw_interface_get_mtu (vnet_get_main (),
53                                                    tep->sw_if_index,
54                                                    VNET_MTU_IP4) :
55       vnet_sw_interface_get_mtu (vnet_get_main (), tep->sw_if_index,
56                                  VNET_MTU_IP6);
57
58   listener->sub_conn[SCTP_PRIMARY_PATH_IDX].PMTU = mtu;
59   listener->sub_conn[SCTP_PRIMARY_PATH_IDX].connection.is_ip4 = tep->is_ip4;
60   listener->sub_conn[SCTP_PRIMARY_PATH_IDX].connection.proto =
61     TRANSPORT_PROTO_SCTP;
62   listener->sub_conn[SCTP_PRIMARY_PATH_IDX].c_s_index = session_index;
63   listener->sub_conn[SCTP_PRIMARY_PATH_IDX].connection.fib_index =
64     tep->fib_index;
65   listener->state = SCTP_STATE_CLOSED;
66
67   sctp_connection_timers_init (listener);
68
69   return listener->sub_conn[SCTP_PRIMARY_PATH_IDX].c_c_index;
70 }
71
72 u32
73 sctp_session_bind (u32 session_index, transport_endpoint_t * tep)
74 {
75   return sctp_connection_bind (session_index, tep);
76 }
77
78 static void
79 sctp_connection_unbind (u32 listener_index)
80 {
81   sctp_main_t *tm = vnet_get_sctp_main ();
82   sctp_connection_t *sctp_conn;
83
84   sctp_conn = pool_elt_at_index (tm->listener_pool, listener_index);
85
86   /* Poison the entry */
87   if (CLIB_DEBUG > 0)
88     clib_memset (sctp_conn, 0xFA, sizeof (*sctp_conn));
89
90   pool_put_index (tm->listener_pool, listener_index);
91 }
92
93 u32
94 sctp_session_unbind (u32 listener_index)
95 {
96   sctp_connection_unbind (listener_index);
97   return 0;
98 }
99
100 void
101 sctp_punt_unknown (vlib_main_t * vm, u8 is_ip4, u8 is_add)
102 {
103   sctp_main_t *tm = &sctp_main;
104   if (is_ip4)
105     tm->punt_unknown4 = is_add;
106   else
107     tm->punt_unknown6 = is_add;
108 }
109
110 static int
111 sctp_alloc_custom_local_endpoint (sctp_main_t * tm, ip46_address_t * lcl_addr,
112                                   u16 * lcl_port, u8 is_ip4)
113 {
114   int index, port;
115   if (is_ip4)
116     {
117       index = tm->last_v4_address_rotor++;
118       if (tm->last_v4_address_rotor >= vec_len (tm->ip4_src_addresses))
119         tm->last_v4_address_rotor = 0;
120       lcl_addr->ip4.as_u32 = tm->ip4_src_addresses[index].as_u32;
121     }
122   else
123     {
124       index = tm->last_v6_address_rotor++;
125       if (tm->last_v6_address_rotor >= vec_len (tm->ip6_src_addresses))
126         tm->last_v6_address_rotor = 0;
127       clib_memcpy (&lcl_addr->ip6, &tm->ip6_src_addresses[index],
128                    sizeof (ip6_address_t));
129     }
130   port = transport_alloc_local_port (TRANSPORT_PROTO_SCTP, lcl_addr);
131   if (port < 1)
132     {
133       clib_warning ("Failed to allocate src port");
134       return -1;
135     }
136   *lcl_port = port;
137   return 0;
138 }
139
140 /**
141  * Initialize all connection timers as invalid
142  */
143 void
144 sctp_connection_timers_init (sctp_connection_t * sctp_conn)
145 {
146   int i, j;
147
148   /* Set all to invalid */
149   for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
150     {
151       sctp_conn->sub_conn[i].RTO = SCTP_RTO_INIT;
152
153       for (j = 0; j < SCTP_N_TIMERS; j++)
154         {
155           sctp_conn->sub_conn[i].timers[j] = SCTP_TIMER_HANDLE_INVALID;
156         }
157     }
158 }
159
160 /**
161  * Stop all connection timers
162  */
163 void
164 sctp_connection_timers_reset (sctp_connection_t * sctp_conn)
165 {
166   int i, j;
167   for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
168     {
169       for (j = 0; j < SCTP_N_TIMERS; j++)
170         sctp_timer_reset (sctp_conn, i, j);
171     }
172 }
173
174 const char *sctp_fsm_states[] = {
175 #define _(sym, str) str,
176   foreach_sctp_fsm_state
177 #undef _
178 };
179
180 u8 *
181 format_sctp_state (u8 * s, va_list * args)
182 {
183   u32 state = va_arg (*args, u32);
184
185   if (state < SCTP_N_STATES)
186     s = format (s, "%s", sctp_fsm_states[state]);
187   else
188     s = format (s, "UNKNOWN (%d (0x%x))", state, state);
189   return s;
190 }
191
192 u8 *
193 format_sctp_connection_id (u8 * s, va_list * args)
194 {
195   sctp_connection_t *sctp_conn = va_arg (*args, sctp_connection_t *);
196   if (!sctp_conn)
197     return s;
198
199   u8 i;
200   for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
201     {
202       if (i > 0 && sctp_conn->sub_conn[i].state == SCTP_SUBCONN_STATE_DOWN)
203         continue;
204       if (sctp_conn->sub_conn[i].connection.is_ip4)
205         {
206           s = format (s, "[#%d][%s] %U:%d->%U:%d",
207                       sctp_conn->sub_conn[i].connection.thread_index,
208                       "S",
209                       format_ip4_address,
210                       &sctp_conn->sub_conn[i].connection.lcl_ip.ip4,
211                       clib_net_to_host_u16 (sctp_conn->sub_conn[i].
212                                             connection.lcl_port),
213                       format_ip4_address,
214                       &sctp_conn->sub_conn[i].connection.rmt_ip.ip4,
215                       clib_net_to_host_u16 (sctp_conn->sub_conn[i].
216                                             connection.rmt_port));
217         }
218       else
219         {
220           s = format (s, "[#%d][%s] %U:%d->%U:%d",
221                       sctp_conn->sub_conn[i].connection.thread_index,
222                       "S",
223                       format_ip6_address,
224                       &sctp_conn->sub_conn[i].connection.lcl_ip.ip6,
225                       clib_net_to_host_u16 (sctp_conn->sub_conn[i].
226                                             connection.lcl_port),
227                       format_ip6_address,
228                       &sctp_conn->sub_conn[i].connection.rmt_ip.ip6,
229                       clib_net_to_host_u16 (sctp_conn->sub_conn[i].
230                                             connection.rmt_port));
231         }
232     }
233   return s;
234 }
235
236 u8 *
237 format_sctp_connection (u8 * s, va_list * args)
238 {
239   sctp_connection_t *sctp_conn = va_arg (*args, sctp_connection_t *);
240   u32 verbose = va_arg (*args, u32);
241
242   if (!sctp_conn)
243     return s;
244   s = format (s, "%-50U", format_sctp_connection_id, sctp_conn);
245   if (verbose)
246     {
247       s = format (s, "%-15U", format_sctp_state, sctp_conn->state);
248       if (verbose > 1)
249         s = format (s, "\n");
250     }
251
252   return s;
253 }
254
255 /**
256  * Initialize connection send variables.
257  */
258 void
259 sctp_init_snd_vars (sctp_connection_t * sctp_conn)
260 {
261   u32 time_now;
262   /*
263    * We use the time to randomize iss and for setting up the initial
264    * timestamp. Make sure it's updated otherwise syn and ack in the
265    * handshake may make it look as if time has flown in the opposite
266    * direction for us.
267    */
268
269   sctp_set_time_now (vlib_get_thread_index ());
270   time_now = sctp_time_now ();
271
272   sctp_conn->local_initial_tsn = random_u32 (&time_now);
273   sctp_conn->last_unacked_tsn = sctp_conn->local_initial_tsn;
274   sctp_conn->next_tsn = sctp_conn->local_initial_tsn + 1;
275
276   sctp_conn->remote_initial_tsn = 0x0;
277   sctp_conn->last_rcvd_tsn = sctp_conn->remote_initial_tsn;
278 }
279
280 always_inline sctp_connection_t *
281 sctp_sub_connection_add (u8 thread_index)
282 {
283   sctp_main_t *tm = vnet_get_sctp_main ();
284   sctp_connection_t *sctp_conn = tm->connections[thread_index];
285
286   u8 subconn_idx = sctp_next_avail_subconn (sctp_conn);
287
288   ASSERT (subconn_idx < MAX_SCTP_CONNECTIONS);
289
290   sctp_conn->sub_conn[subconn_idx].connection.c_index =
291     sctp_conn->sub_conn[SCTP_PRIMARY_PATH_IDX].connection.c_index;
292   sctp_conn->sub_conn[subconn_idx].connection.thread_index = thread_index;
293   sctp_conn->sub_conn[subconn_idx].subconn_idx = subconn_idx;
294
295   return sctp_conn;
296 }
297
298 u8
299 sctp_sub_connection_add_ip4 (vlib_main_t * vm,
300                              ip4_address_t * lcl_addr,
301                              ip4_address_t * rmt_addr)
302 {
303   sctp_connection_t *sctp_conn = sctp_sub_connection_add (vm->thread_index);
304
305   u8 subconn_idx = sctp_next_avail_subconn (sctp_conn);
306
307   if (subconn_idx == MAX_SCTP_CONNECTIONS)
308     return SCTP_ERROR_MAX_CONNECTIONS;
309
310   clib_memcpy (&sctp_conn->sub_conn[subconn_idx].connection.lcl_ip,
311                &lcl_addr, sizeof (lcl_addr));
312
313   clib_memcpy (&sctp_conn->sub_conn[subconn_idx].connection.rmt_ip,
314                &rmt_addr, sizeof (rmt_addr));
315
316   sctp_conn->forming_association_changed = 1;
317
318   return SCTP_ERROR_NONE;
319 }
320
321 u8
322 sctp_sub_connection_del_ip4 (ip4_address_t * lcl_addr,
323                              ip4_address_t * rmt_addr)
324 {
325   sctp_main_t *sctp_main = vnet_get_sctp_main ();
326
327   u32 thread_idx = vlib_get_thread_index ();
328   u8 i;
329
330   ASSERT (thread_idx == 0);
331
332   for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
333     {
334       sctp_connection_t *sctp_conn = sctp_main->connections[thread_idx];
335       sctp_sub_connection_t *sub_conn =
336         &sctp_main->connections[thread_idx]->sub_conn[i];
337       ip46_address_t *lcl_ip =
338         &sctp_main->connections[thread_idx]->sub_conn[i].connection.lcl_ip;
339       ip46_address_t *rmt_ip =
340         &sctp_main->connections[thread_idx]->sub_conn[i].connection.rmt_ip;
341
342       if (!sub_conn->connection.is_ip4)
343         continue;
344       if (lcl_ip->ip4.as_u32 == lcl_addr->as_u32 &&
345           rmt_ip->ip4.as_u32 == rmt_addr->as_u32)
346         {
347           sub_conn->state = SCTP_SUBCONN_STATE_DOWN;
348           sctp_conn->forming_association_changed = 1;
349           break;
350         }
351     }
352   return SCTP_ERROR_NONE;
353 }
354
355 u8
356 sctp_sub_connection_add_ip6 (vlib_main_t * vm,
357                              ip6_address_t * lcl_addr,
358                              ip6_address_t * rmt_addr)
359 {
360   sctp_connection_t *sctp_conn = sctp_sub_connection_add (vm->thread_index);
361
362   u8 subconn_idx = sctp_next_avail_subconn (sctp_conn);
363
364   if (subconn_idx == MAX_SCTP_CONNECTIONS)
365     return SCTP_ERROR_MAX_CONNECTIONS;
366
367   clib_memcpy (&sctp_conn->sub_conn[subconn_idx].connection.lcl_ip,
368                &lcl_addr, sizeof (lcl_addr));
369
370   clib_memcpy (&sctp_conn->sub_conn[subconn_idx].connection.rmt_ip,
371                &rmt_addr, sizeof (rmt_addr));
372
373   sctp_conn->forming_association_changed = 1;
374
375   return SCTP_ERROR_NONE;
376 }
377
378 u8
379 sctp_sub_connection_del_ip6 (ip6_address_t * lcl_addr,
380                              ip6_address_t * rmt_addr)
381 {
382   sctp_main_t *sctp_main = vnet_get_sctp_main ();
383
384   u32 thread_idx = vlib_get_thread_index ();
385   u8 i;
386
387   ASSERT (thread_idx == 0);
388
389   for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
390     {
391       sctp_connection_t *sctp_conn = sctp_main->connections[thread_idx];
392       sctp_sub_connection_t *sub_conn =
393         &sctp_main->connections[thread_idx]->sub_conn[i];
394       ip46_address_t *lcl_ip =
395         &sctp_main->connections[thread_idx]->sub_conn[i].connection.lcl_ip;
396       ip46_address_t *rmt_ip =
397         &sctp_main->connections[thread_idx]->sub_conn[i].connection.rmt_ip;
398
399       if (!sub_conn->connection.is_ip4)
400         continue;
401       if ((lcl_ip->ip6.as_u64[0] == lcl_addr->as_u64[0]
402            && lcl_ip->ip6.as_u64[1] == lcl_addr->as_u64[1])
403           && (rmt_ip->ip6.as_u64[0] == rmt_addr->as_u64[0]
404               && rmt_ip->ip6.as_u64[1] == rmt_addr->as_u64[1]))
405         {
406           sub_conn->state = SCTP_SUBCONN_STATE_DOWN;
407           sctp_conn->forming_association_changed = 1;
408           break;
409         }
410     }
411   return SCTP_ERROR_NONE;
412 }
413
414 u8
415 sctp_configure (sctp_user_configuration_t config)
416 {
417   sctp_main_t *sctp_main = vnet_get_sctp_main ();
418
419   u32 thread_idx = vlib_get_thread_index ();
420
421   sctp_main->connections[thread_idx]->conn_config.never_delay_sack =
422     config.never_delay_sack;
423   sctp_main->connections[thread_idx]->conn_config.never_bundle =
424     config.never_bundle;
425
426   return 0;
427 }
428
429 sctp_connection_t *
430 sctp_connection_new (u8 thread_index)
431 {
432   sctp_main_t *sctp_main = vnet_get_sctp_main ();
433   sctp_connection_t *sctp_conn;
434
435   pool_get (sctp_main->connections[thread_index], sctp_conn);
436   clib_memset (sctp_conn, 0, sizeof (*sctp_conn));
437   sctp_conn->sub_conn[SCTP_PRIMARY_PATH_IDX].subconn_idx =
438     SCTP_PRIMARY_PATH_IDX;
439   sctp_conn->sub_conn[SCTP_PRIMARY_PATH_IDX].c_c_index =
440     sctp_conn - sctp_main->connections[thread_index];
441   sctp_conn->sub_conn[SCTP_PRIMARY_PATH_IDX].c_thread_index = thread_index;
442   sctp_conn->local_tag = 0;
443
444   return sctp_conn;
445 }
446
447 sctp_connection_t *
448 sctp_half_open_connection_new (u8 thread_index)
449 {
450   sctp_main_t *tm = vnet_get_sctp_main ();
451   sctp_connection_t *sctp_conn = 0;
452   ASSERT (vlib_get_thread_index () == 0);
453   pool_get (tm->half_open_connections, sctp_conn);
454   clib_memset (sctp_conn, 0, sizeof (*sctp_conn));
455   sctp_conn->sub_conn[SCTP_PRIMARY_PATH_IDX].c_c_index =
456     sctp_conn - tm->half_open_connections;
457   sctp_conn->sub_conn[SCTP_PRIMARY_PATH_IDX].subconn_idx =
458     SCTP_PRIMARY_PATH_IDX;
459   return sctp_conn;
460 }
461
462 static inline int
463 sctp_connection_open (transport_endpoint_cfg_t * rmt)
464 {
465   sctp_main_t *tm = vnet_get_sctp_main ();
466   sctp_connection_t *sctp_conn;
467   ip46_address_t lcl_addr;
468   u16 lcl_port;
469   uword thread_id;
470   u32 mtu = 1460;
471   int rv;
472
473   u8 idx = SCTP_PRIMARY_PATH_IDX;
474
475   /*
476    * Allocate local endpoint
477    */
478   if ((rmt->is_ip4 && vec_len (tm->ip4_src_addresses))
479       || (!rmt->is_ip4 && vec_len (tm->ip6_src_addresses)))
480     rv = sctp_alloc_custom_local_endpoint (tm, &lcl_addr, &lcl_port,
481                                            rmt->is_ip4);
482   else
483     rv = transport_alloc_local_endpoint (TRANSPORT_PROTO_SCTP,
484                                          rmt, &lcl_addr, &lcl_port);
485
486   if (rv)
487     return -1;
488
489   /*
490    * Create connection and send INIT CHUNK
491    */
492   thread_id = vlib_get_thread_index ();
493   ASSERT (thread_id == 0);
494
495   clib_spinlock_lock_if_init (&tm->half_open_lock);
496   sctp_conn = sctp_half_open_connection_new (thread_id);
497   if (rmt->peer.sw_if_index != ENDPOINT_INVALID_INDEX)
498     mtu = rmt->is_ip4 ? vnet_sw_interface_get_mtu (vnet_get_main (),
499                                                    rmt->peer.sw_if_index,
500                                                    VNET_MTU_IP4) :
501       vnet_sw_interface_get_mtu (vnet_get_main (), rmt->peer.sw_if_index,
502                                  VNET_MTU_IP6);
503   sctp_conn->sub_conn[idx].PMTU = mtu;
504
505   transport_connection_t *trans_conn = &sctp_conn->sub_conn[idx].connection;
506   ip_copy (&trans_conn->rmt_ip, &rmt->ip, rmt->is_ip4);
507   ip_copy (&trans_conn->lcl_ip, &lcl_addr, rmt->is_ip4);
508   sctp_conn->sub_conn[idx].subconn_idx = idx;
509   trans_conn->rmt_port = rmt->port;
510   trans_conn->lcl_port = clib_host_to_net_u16 (lcl_port);
511   trans_conn->is_ip4 = rmt->is_ip4;
512   trans_conn->proto = TRANSPORT_PROTO_SCTP;
513   trans_conn->fib_index = rmt->fib_index;
514
515   sctp_connection_timers_init (sctp_conn);
516   /* The other connection vars will be initialized after INIT_ACK chunk received */
517   sctp_init_snd_vars (sctp_conn);
518
519   sctp_send_init (sctp_conn);
520
521   clib_spinlock_unlock_if_init (&tm->half_open_lock);
522
523   return sctp_conn->sub_conn[idx].connection.c_index;
524 }
525
526 /**
527  * Cleans up connection state.
528  *
529  * No notifications.
530  */
531 void
532 sctp_connection_cleanup (sctp_connection_t * sctp_conn)
533 {
534   sctp_main_t *tm = &sctp_main;
535   u8 i;
536
537   /* Cleanup local endpoint if this was an active connect */
538   for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
539     transport_endpoint_cleanup (TRANSPORT_PROTO_SCTP,
540                                 &sctp_conn->sub_conn[i].connection.lcl_ip,
541                                 sctp_conn->sub_conn[i].connection.lcl_port);
542
543   int thread_index =
544     sctp_conn->sub_conn[SCTP_PRIMARY_PATH_IDX].connection.thread_index;
545
546   /* Make sure all timers are cleared */
547   sctp_connection_timers_reset (sctp_conn);
548
549   /* Poison the entry */
550   if (CLIB_DEBUG > 0)
551     clib_memset (sctp_conn, 0xFA, sizeof (*sctp_conn));
552   pool_put (tm->connections[thread_index], sctp_conn);
553 }
554
555 int
556 sctp_session_open (transport_endpoint_cfg_t * tep)
557 {
558   return sctp_connection_open (tep);
559 }
560
561 u16
562 sctp_check_outstanding_data_chunks (sctp_connection_t * sctp_conn)
563 {
564   u8 i;
565   for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
566     {
567       if (sctp_conn->sub_conn[i].state == SCTP_SUBCONN_STATE_DOWN)
568         continue;
569
570       if (sctp_conn->sub_conn[i].is_retransmitting == 1 ||
571           sctp_conn->sub_conn[i].enqueue_state != SCTP_ERROR_ENQUEUED)
572         {
573           SCTP_DBG_OUTPUT
574             ("Connection %u has still DATA to be enqueued inboud / outboud",
575              sctp_conn->sub_conn[i].connection.c_index);
576           return 1;
577         }
578
579     }
580   return 0;                     /* Indicates no more data to be read/sent */
581 }
582
583 void
584 sctp_connection_close (sctp_connection_t * sctp_conn)
585 {
586   SCTP_DBG ("Closing connection %u...",
587             sctp_conn->sub_conn[SCTP_PRIMARY_PATH_IDX].connection.c_index);
588
589   sctp_conn->state = SCTP_STATE_SHUTDOWN_PENDING;
590
591   sctp_send_shutdown (sctp_conn);
592 }
593
594 void
595 sctp_session_close (u32 conn_index, u32 thread_index)
596 {
597   ASSERT (thread_index == 0);
598
599   sctp_connection_t *sctp_conn =
600     sctp_connection_get (conn_index, thread_index);
601   if (sctp_conn != NULL)
602     sctp_connection_close (sctp_conn);
603 }
604
605 void
606 sctp_session_cleanup (u32 conn_index, u32 thread_index)
607 {
608   sctp_connection_t *sctp_conn =
609     sctp_connection_get (conn_index, thread_index);
610
611   if (sctp_conn != NULL)
612     {
613       sctp_connection_timers_reset (sctp_conn);
614       /* Wait for the session tx events to clear */
615       sctp_conn->state = SCTP_STATE_CLOSED;
616     }
617 }
618
619 /**
620  * Compute maximum segment size for session layer.
621  */
622 u16
623 sctp_session_send_mss (transport_connection_t * trans_conn)
624 {
625   sctp_connection_t *sctp_conn =
626     sctp_get_connection_from_transport (trans_conn);
627
628   if (sctp_conn == NULL)
629     {
630       SCTP_DBG ("sctp_conn == NULL");
631       return 0;
632     }
633
634   update_cwnd (sctp_conn);
635   update_smallest_pmtu_idx (sctp_conn);
636
637   u8 idx = sctp_data_subconn_select (sctp_conn);
638   return sctp_conn->sub_conn[idx].cwnd;
639 }
640
641 u16
642 sctp_snd_space (sctp_connection_t * sctp_conn)
643 {
644   /* RFC 4096 Section 6.1; point (A) */
645   if (sctp_conn->peer_rwnd == 0)
646     return 0;
647
648   u8 idx = sctp_data_subconn_select (sctp_conn);
649
650   u32 available_wnd =
651     clib_min (sctp_conn->peer_rwnd, sctp_conn->sub_conn[idx].cwnd);
652   int flight_size = (int) (sctp_conn->next_tsn - sctp_conn->last_unacked_tsn);
653
654   if (available_wnd <= flight_size)
655     return 0;
656
657   /* Finally, let's subtract the DATA chunk headers overhead */
658   return available_wnd -
659     flight_size -
660     sizeof (sctp_payload_data_chunk_t) - sizeof (sctp_full_hdr_t);
661 }
662
663 /**
664  * Compute TX window session is allowed to fill.
665  */
666 u32
667 sctp_session_send_space (transport_connection_t * trans_conn)
668 {
669   sctp_connection_t *sctp_conn =
670     sctp_get_connection_from_transport (trans_conn);
671
672   return sctp_snd_space (sctp_conn);
673 }
674
675 transport_connection_t *
676 sctp_session_get_transport (u32 conn_index, u32 thread_index)
677 {
678   sctp_connection_t *sctp_conn =
679     sctp_connection_get (conn_index, thread_index);
680
681   if (PREDICT_TRUE (sctp_conn != NULL))
682     return &sctp_conn->sub_conn[SCTP_PRIMARY_PATH_IDX].connection;
683
684   return NULL;
685 }
686
687 transport_connection_t *
688 sctp_session_get_listener (u32 listener_index)
689 {
690   sctp_main_t *tm = vnet_get_sctp_main ();
691   sctp_connection_t *sctp_conn;
692   sctp_conn = pool_elt_at_index (tm->listener_pool, listener_index);
693   return &sctp_conn->sub_conn[SCTP_PRIMARY_PATH_IDX].connection;
694 }
695
696 u8 *
697 format_sctp_session (u8 * s, va_list * args)
698 {
699   u32 tci = va_arg (*args, u32);
700   u32 thread_index = va_arg (*args, u32);
701   u32 verbose = va_arg (*args, u32);
702   sctp_connection_t *tc;
703
704   tc = sctp_connection_get (tci, thread_index);
705   if (tc)
706     s = format (s, "%U", format_sctp_connection, tc, verbose);
707   else
708     s = format (s, "empty\n");
709   return s;
710 }
711
712 u8 *
713 format_sctp_listener_session (u8 * s, va_list * args)
714 {
715   u32 tci = va_arg (*args, u32);
716   u32 __clib_unused thread_index = va_arg (*args, u32);
717   sctp_connection_t *tc = sctp_listener_get (tci);
718   return format (s, "%U", format_sctp_connection_id, tc);
719 }
720
721 void
722 sctp_expired_timers_cb (u32 conn_index, u32 timer_id)
723 {
724   sctp_connection_t *sctp_conn;
725
726   SCTP_DBG ("%s expired", sctp_timer_to_string (timer_id));
727
728   sctp_conn = sctp_connection_get (conn_index, vlib_get_thread_index ());
729   /* note: the connection may have already disappeared */
730   if (PREDICT_FALSE (sctp_conn == 0))
731     return;
732
733   if (sctp_conn->sub_conn[conn_index].unacknowledged_hb >
734       SCTP_PATH_MAX_RETRANS)
735     {
736       // The remote-peer is considered to be unreachable hence shutting down
737       u8 i, total_subs_down = 1;
738       for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
739         {
740           if (sctp_conn->sub_conn[i].state == SCTP_SUBCONN_STATE_DOWN)
741             continue;
742
743           u32 now = sctp_time_now ();
744           if (now > (sctp_conn->sub_conn[i].last_seen + SCTP_HB_INTERVAL))
745             {
746               total_subs_down += 1;
747               sctp_conn->sub_conn[i].state = SCTP_SUBCONN_STATE_DOWN;
748             }
749         }
750
751       if (total_subs_down == MAX_SCTP_CONNECTIONS)
752         {
753           /* Start cleanup. App wasn't notified yet so use delete notify as
754            * opposed to delete to cleanup session layer state. */
755           session_transport_delete_notify (&sctp_conn->sub_conn
756                                            [SCTP_PRIMARY_PATH_IDX].connection);
757
758           sctp_connection_timers_reset (sctp_conn);
759
760           sctp_connection_cleanup (sctp_conn);
761         }
762       return;
763     }
764
765   switch (timer_id)
766     {
767     case SCTP_TIMER_T1_INIT:
768       sctp_send_init (sctp_conn);
769       break;
770     case SCTP_TIMER_T1_COOKIE:
771       sctp_send_cookie_echo (sctp_conn);
772       break;
773     case SCTP_TIMER_T2_SHUTDOWN:
774       sctp_send_shutdown (sctp_conn);
775       break;
776     case SCTP_TIMER_T3_RXTX:
777       sctp_timer_reset (sctp_conn, conn_index, timer_id);
778       sctp_conn->flags |= SCTP_CONN_RECOVERY;
779       sctp_data_retransmit (sctp_conn);
780       break;
781     case SCTP_TIMER_T4_HEARTBEAT:
782       sctp_timer_reset (sctp_conn, conn_index, timer_id);
783       goto heartbeat;
784     }
785   return;
786
787 heartbeat:
788   sctp_send_heartbeat (sctp_conn);
789 }
790
791 static void
792 sctp_expired_timers_dispatch (u32 * expired_timers)
793 {
794   int i;
795   u32 connection_index, timer_id;
796
797   for (i = 0; i < vec_len (expired_timers); i++)
798     {
799       /* Get session index and timer id */
800       connection_index = expired_timers[i] & 0x0FFFFFFF;
801       timer_id = expired_timers[i] >> 28;
802
803       SCTP_DBG ("Expired timer ID: %u", timer_id);
804
805       /* Handle expiration */
806       sctp_expired_timers_cb (connection_index, timer_id);
807     }
808 }
809
810 void
811 sctp_initialize_timer_wheels (sctp_main_t * tm)
812 {
813   tw_timer_wheel_16t_2w_512sl_t *tw;
814   /* *INDENT-OFF* */
815   foreach_vlib_main (({
816     tw = &tm->timer_wheels[ii];
817     tw_timer_wheel_init_16t_2w_512sl (tw, sctp_expired_timers_dispatch,
818                                       100e-3 /* timer period 100ms */ , ~0);
819     tw->last_run_time = vlib_time_now (this_vlib_main);
820   }));
821   /* *INDENT-ON* */
822 }
823
824 clib_error_t *
825 sctp_main_enable (vlib_main_t * vm)
826 {
827   sctp_main_t *tm = vnet_get_sctp_main ();
828   vlib_thread_main_t *vtm = vlib_get_thread_main ();
829   clib_error_t *error = 0;
830   u32 num_threads;
831   int thread;
832   sctp_connection_t *sctp_conn __attribute__ ((unused));
833   u32 preallocated_connections_per_thread;
834
835   if ((error = vlib_call_init_function (vm, ip_main_init)))
836     return error;
837   if ((error = vlib_call_init_function (vm, ip4_lookup_init)))
838     return error;
839   if ((error = vlib_call_init_function (vm, ip6_lookup_init)))
840     return error;
841
842   /*
843    * Registrations
844    */
845
846   ip4_register_protocol (IP_PROTOCOL_SCTP, sctp4_input_node.index);
847   ip6_register_protocol (IP_PROTOCOL_SCTP, sctp6_input_node.index);
848
849   /*
850    * Initialize data structures
851    */
852
853   num_threads = 1 /* main thread */  + vtm->n_threads;
854   vec_validate (tm->connections, num_threads - 1);
855
856   /*
857    * Preallocate connections. Assume that thread 0 won't
858    * use preallocated threads when running multi-core
859    */
860   if (num_threads == 1)
861     {
862       thread = 0;
863       preallocated_connections_per_thread = tm->preallocated_connections;
864     }
865   else
866     {
867       thread = 1;
868       preallocated_connections_per_thread =
869         tm->preallocated_connections / (num_threads - 1);
870     }
871   for (; thread < num_threads; thread++)
872     {
873       if (preallocated_connections_per_thread)
874         pool_init_fixed (tm->connections[thread],
875                          preallocated_connections_per_thread);
876     }
877
878   /* Initialize per worker thread tx buffers (used for control messages) */
879   vec_validate (tm->tx_buffers, num_threads - 1);
880
881   /* Initialize timer wheels */
882   vec_validate (tm->timer_wheels, num_threads - 1);
883   sctp_initialize_timer_wheels (tm);
884
885   /* Initialize clocks per tick for SCTP timestamp. Used to compute
886    * monotonically increasing timestamps. */
887   tm->tstamp_ticks_per_clock = vm->clib_time.seconds_per_clock
888     / SCTP_TSTAMP_RESOLUTION;
889
890   if (num_threads > 1)
891     {
892       clib_spinlock_init (&tm->half_open_lock);
893     }
894
895   vec_validate (tm->tx_frames[0], num_threads - 1);
896   vec_validate (tm->tx_frames[1], num_threads - 1);
897   vec_validate (tm->ip_lookup_tx_frames[0], num_threads - 1);
898   vec_validate (tm->ip_lookup_tx_frames[1], num_threads - 1);
899
900   tm->bytes_per_buffer = vlib_buffer_get_default_data_size (vm);
901
902   vec_validate (tm->time_now, num_threads - 1);
903   return error;
904 }
905
906 clib_error_t *
907 sctp_transport_enable_disable (vlib_main_t * vm, u8 is_en)
908 {
909   if (is_en)
910     {
911       if (sctp_main.is_enabled)
912         return 0;
913
914       return sctp_main_enable (vm);
915     }
916   else
917     {
918       sctp_main.is_enabled = 0;
919     }
920
921   return 0;
922 }
923
924 transport_connection_t *
925 sctp_half_open_session_get_transport (u32 conn_index)
926 {
927   sctp_connection_t *sctp_conn = sctp_half_open_connection_get (conn_index);
928   return &sctp_conn->sub_conn[SCTP_PRIMARY_PATH_IDX].connection;
929 }
930
931 u8 *
932 format_sctp_half_open (u8 * s, va_list * args)
933 {
934   u32 tci = va_arg (*args, u32);
935   u32 __clib_unused thread_index = va_arg (*args, u32);
936   sctp_connection_t *sctp_conn = sctp_half_open_connection_get (tci);
937   return format (s, "%U", format_sctp_connection_id, sctp_conn);
938 }
939
940 void
941 sctp_update_time (f64 now, u8 thread_index)
942 {
943   sctp_set_time_now (thread_index);
944   tw_timer_expire_timers_16t_2w_512sl (&sctp_main.timer_wheels[thread_index],
945                                        now);
946   sctp_flush_frames_to_output (thread_index);
947 }
948
949 /* *INDENT-OFF* */
950 static const transport_proto_vft_t sctp_proto = {
951   .enable = sctp_transport_enable_disable,
952   .start_listen = sctp_session_bind,
953   .stop_listen = sctp_session_unbind,
954   .connect = sctp_session_open,
955   .close = sctp_session_close,
956   .cleanup = sctp_session_cleanup,
957   .push_header = sctp_push_header,
958   .send_mss = sctp_session_send_mss,
959   .send_space = sctp_session_send_space,
960   .update_time = sctp_update_time,
961   .get_connection = sctp_session_get_transport,
962   .get_listener = sctp_session_get_listener,
963   .get_half_open = sctp_half_open_session_get_transport,
964   .format_connection = format_sctp_session,
965   .format_listener = format_sctp_listener_session,
966   .format_half_open = format_sctp_half_open,
967   .transport_options = {
968     .tx_type = TRANSPORT_TX_DEQUEUE,
969     .service_type = TRANSPORT_SERVICE_VC,
970   },
971 };
972 /* *INDENT-ON* */
973
974 clib_error_t *
975 sctp_enable_disable (vlib_main_t * vm, u8 is_en)
976 {
977   sctp_main_t *sm = vnet_get_sctp_main ();
978   ip_main_t *im = &ip_main;
979   ip_protocol_info_t *pi;
980   vlib_node_t *node;
981
982   if (!sm->is_init && is_en)
983     {
984       node = vlib_get_node_by_name (vm, (u8 *) "sctp4-established");
985       sm->sctp4_established_phase_node_index = node->index;
986
987       node = vlib_get_node_by_name (vm, (u8 *) "sctp6-established");
988       sm->sctp6_established_phase_node_index = node->index;
989
990       sm->is_init = 1;
991
992       /* Register with IP for header parsing */
993       pi = ip_get_protocol_info (im, IP_PROTOCOL_SCTP);
994       if (pi == 0)
995         return clib_error_return (0, "SCTP protocol info AWOL");
996       pi->format_header = format_sctp_header;
997       pi->unformat_pg_edit = unformat_pg_sctp_header;
998
999       /* Register as transport with session layer */
1000       transport_register_protocol (TRANSPORT_PROTO_SCTP, &sctp_proto,
1001                                    FIB_PROTOCOL_IP4, sctp4_output_node.index);
1002       transport_register_protocol (TRANSPORT_PROTO_SCTP, &sctp_proto,
1003                                    FIB_PROTOCOL_IP6, sctp6_output_node.index);
1004     }
1005
1006   sctp_transport_enable_disable (vm, is_en);
1007   return 0;
1008 }
1009
1010 static u8 *
1011 sctp_format_buffer_opaque_helper (const vlib_buffer_t * b, u8 * s)
1012 {
1013   sctp_buffer_opaque_t *o = sctp_buffer_opaque (b);
1014
1015   s = format (s,
1016               "sctp.connection_index: %d, sctp.sid: %d, sctp.ssn: %d, "
1017               "sctp.tsn: %d, sctp.hdr_offset: %d",
1018               o->sctp.connection_index,
1019               (u32) (o->sctp.sid),
1020               (u32) (o->sctp.ssn),
1021               (u32) (o->sctp.tsn), (u32) (o->sctp.hdr_offset));
1022   vec_add1 (s, '\n');
1023
1024   s = format
1025     (s, "sctp.data_offset: %d, sctp.data_len: %d, sctp.subconn_idx: %d, "
1026      "sctp.flags: 0x%x",
1027      (u32) (o->sctp.data_offset),
1028      (u32) (o->sctp.data_len),
1029      (u32) (o->sctp.subconn_idx), (u32) (o->sctp.flags));
1030   vec_add1 (s, '\n');
1031   return s;
1032 }
1033
1034 clib_error_t *
1035 sctp_init (vlib_main_t * vm)
1036 {
1037   sctp_main_t *sm = vnet_get_sctp_main ();
1038
1039   /* Session layer, and by implication SCTP, are disabled by default */
1040   sm->is_enabled = 0;
1041   sm->is_init = 0;
1042
1043   /* initialize binary API */
1044   sctp_plugin_api_hookup (vm);
1045
1046   vnet_register_format_buffer_opaque_helper
1047     (sctp_format_buffer_opaque_helper);
1048   return 0;
1049 }
1050
1051 VLIB_INIT_FUNCTION (sctp_init);
1052
1053 static clib_error_t *
1054 show_sctp_punt_fn (vlib_main_t * vm, unformat_input_t * input,
1055                    vlib_cli_command_t * cmd_arg)
1056 {
1057   sctp_main_t *tm = &sctp_main;
1058   if (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1059     return clib_error_return (0, "unknown input `%U'", format_unformat_error,
1060                               input);
1061   vlib_cli_output (vm, "IPv4 UDP punt: %s",
1062                    tm->punt_unknown4 ? "enabled" : "disabled");
1063   vlib_cli_output (vm, "IPv6 UDP punt: %s",
1064                    tm->punt_unknown6 ? "enabled" : "disabled");
1065   return 0;
1066 }
1067 /* *INDENT-OFF* */
1068 VLIB_CLI_COMMAND (show_tcp_punt_command, static) =
1069 {
1070   .path = "show sctp punt",
1071   .short_help = "show sctp punt",
1072   .function = show_sctp_punt_fn,
1073 };
1074 /* *INDENT-ON* */
1075
1076 static clib_error_t *
1077 sctp_fn (vlib_main_t * vm, unformat_input_t * input,
1078          vlib_cli_command_t * cmd_arg)
1079 {
1080   unformat_input_t _line_input, *line_input = &_line_input;
1081   clib_error_t *error;
1082   u8 is_en;
1083
1084   if (!unformat_user (input, unformat_line_input, line_input))
1085     return clib_error_return (0, "expected enable | disable");
1086
1087   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1088     {
1089       if (unformat (line_input, "enable"))
1090         is_en = 1;
1091       else if (unformat (line_input, "disable"))
1092         is_en = 0;
1093       else
1094         {
1095           error = clib_error_return (0, "unknown input `%U'",
1096                                      format_unformat_error, line_input);
1097           unformat_free (line_input);
1098           return error;
1099         }
1100     }
1101
1102   unformat_free (line_input);
1103
1104   return sctp_enable_disable (vm, is_en);
1105 }
1106
1107 /* *INDENT-OFF* */
1108 VLIB_CLI_COMMAND (show_sctp_command, static) =
1109 {
1110   .path = "sctp",
1111   .short_help = "sctp [enable | disable]",
1112   .function = sctp_fn,
1113 };
1114
1115 /* *INDENT-OFF* */
1116 VLIB_PLUGIN_REGISTER () =
1117 {
1118   .version = VPP_BUILD_VER,
1119   .description = "Stream Control Transmission Protocol (SCTP)",
1120   .default_disabled = 1,
1121 };
1122 /* *INDENT-ON* */
1123
1124 /*
1125  * fd.io coding-style-patch-verification: ON
1126  *
1127  * Local Variables:
1128  * eval: (c-set-style "gnu")
1129  * End:
1130  */