tcp: timestamp adjustment
[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   sctp_connection_t *tc = sctp_listener_get (tci);
717   return format (s, "%U", format_sctp_connection_id, tc);
718 }
719
720 void
721 sctp_expired_timers_cb (u32 conn_index, u32 timer_id)
722 {
723   sctp_connection_t *sctp_conn;
724
725   SCTP_DBG ("%s expired", sctp_timer_to_string (timer_id));
726
727   sctp_conn = sctp_connection_get (conn_index, vlib_get_thread_index ());
728   /* note: the connection may have already disappeared */
729   if (PREDICT_FALSE (sctp_conn == 0))
730     return;
731
732   if (sctp_conn->sub_conn[conn_index].unacknowledged_hb >
733       SCTP_PATH_MAX_RETRANS)
734     {
735       // The remote-peer is considered to be unreachable hence shutting down
736       u8 i, total_subs_down = 1;
737       for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
738         {
739           if (sctp_conn->sub_conn[i].state == SCTP_SUBCONN_STATE_DOWN)
740             continue;
741
742           u32 now = sctp_time_now ();
743           if (now > (sctp_conn->sub_conn[i].last_seen + SCTP_HB_INTERVAL))
744             {
745               total_subs_down += 1;
746               sctp_conn->sub_conn[i].state = SCTP_SUBCONN_STATE_DOWN;
747             }
748         }
749
750       if (total_subs_down == MAX_SCTP_CONNECTIONS)
751         {
752           /* Start cleanup. App wasn't notified yet so use delete notify as
753            * opposed to delete to cleanup session layer state. */
754           session_transport_delete_notify (&sctp_conn->sub_conn
755                                            [SCTP_PRIMARY_PATH_IDX].connection);
756
757           sctp_connection_timers_reset (sctp_conn);
758
759           sctp_connection_cleanup (sctp_conn);
760         }
761       return;
762     }
763
764   switch (timer_id)
765     {
766     case SCTP_TIMER_T1_INIT:
767       sctp_send_init (sctp_conn);
768       break;
769     case SCTP_TIMER_T1_COOKIE:
770       sctp_send_cookie_echo (sctp_conn);
771       break;
772     case SCTP_TIMER_T2_SHUTDOWN:
773       sctp_send_shutdown (sctp_conn);
774       break;
775     case SCTP_TIMER_T3_RXTX:
776       sctp_timer_reset (sctp_conn, conn_index, timer_id);
777       sctp_conn->flags |= SCTP_CONN_RECOVERY;
778       sctp_data_retransmit (sctp_conn);
779       break;
780     case SCTP_TIMER_T4_HEARTBEAT:
781       sctp_timer_reset (sctp_conn, conn_index, timer_id);
782       goto heartbeat;
783     }
784   return;
785
786 heartbeat:
787   sctp_send_heartbeat (sctp_conn);
788 }
789
790 static void
791 sctp_expired_timers_dispatch (u32 * expired_timers)
792 {
793   int i;
794   u32 connection_index, timer_id;
795
796   for (i = 0; i < vec_len (expired_timers); i++)
797     {
798       /* Get session index and timer id */
799       connection_index = expired_timers[i] & 0x0FFFFFFF;
800       timer_id = expired_timers[i] >> 28;
801
802       SCTP_DBG ("Expired timer ID: %u", timer_id);
803
804       /* Handle expiration */
805       sctp_expired_timers_cb (connection_index, timer_id);
806     }
807 }
808
809 void
810 sctp_initialize_timer_wheels (sctp_main_t * tm)
811 {
812   tw_timer_wheel_16t_2w_512sl_t *tw;
813   /* *INDENT-OFF* */
814   foreach_vlib_main (({
815     tw = &tm->timer_wheels[ii];
816     tw_timer_wheel_init_16t_2w_512sl (tw, sctp_expired_timers_dispatch,
817                                       100e-3 /* timer period 100ms */ , ~0);
818     tw->last_run_time = vlib_time_now (this_vlib_main);
819   }));
820   /* *INDENT-ON* */
821 }
822
823 clib_error_t *
824 sctp_main_enable (vlib_main_t * vm)
825 {
826   sctp_main_t *tm = vnet_get_sctp_main ();
827   vlib_thread_main_t *vtm = vlib_get_thread_main ();
828   clib_error_t *error = 0;
829   u32 num_threads;
830   int thread;
831   sctp_connection_t *sctp_conn __attribute__ ((unused));
832   u32 preallocated_connections_per_thread;
833
834   if ((error = vlib_call_init_function (vm, ip_main_init)))
835     return error;
836   if ((error = vlib_call_init_function (vm, ip4_lookup_init)))
837     return error;
838   if ((error = vlib_call_init_function (vm, ip6_lookup_init)))
839     return error;
840
841   /*
842    * Registrations
843    */
844
845   ip4_register_protocol (IP_PROTOCOL_SCTP, sctp4_input_node.index);
846   ip6_register_protocol (IP_PROTOCOL_SCTP, sctp6_input_node.index);
847
848   /*
849    * Initialize data structures
850    */
851
852   num_threads = 1 /* main thread */  + vtm->n_threads;
853   vec_validate (tm->connections, num_threads - 1);
854
855   /*
856    * Preallocate connections. Assume that thread 0 won't
857    * use preallocated threads when running multi-core
858    */
859   if (num_threads == 1)
860     {
861       thread = 0;
862       preallocated_connections_per_thread = tm->preallocated_connections;
863     }
864   else
865     {
866       thread = 1;
867       preallocated_connections_per_thread =
868         tm->preallocated_connections / (num_threads - 1);
869     }
870   for (; thread < num_threads; thread++)
871     {
872       if (preallocated_connections_per_thread)
873         pool_init_fixed (tm->connections[thread],
874                          preallocated_connections_per_thread);
875     }
876
877   /* Initialize per worker thread tx buffers (used for control messages) */
878   vec_validate (tm->tx_buffers, num_threads - 1);
879
880   /* Initialize timer wheels */
881   vec_validate (tm->timer_wheels, num_threads - 1);
882   sctp_initialize_timer_wheels (tm);
883
884   /* Initialize clocks per tick for SCTP timestamp. Used to compute
885    * monotonically increasing timestamps. */
886   tm->tstamp_ticks_per_clock = vm->clib_time.seconds_per_clock
887     / SCTP_TSTAMP_RESOLUTION;
888
889   if (num_threads > 1)
890     {
891       clib_spinlock_init (&tm->half_open_lock);
892     }
893
894   vec_validate (tm->tx_frames[0], num_threads - 1);
895   vec_validate (tm->tx_frames[1], num_threads - 1);
896   vec_validate (tm->ip_lookup_tx_frames[0], num_threads - 1);
897   vec_validate (tm->ip_lookup_tx_frames[1], num_threads - 1);
898
899   tm->bytes_per_buffer = vlib_buffer_get_default_data_size (vm);
900
901   vec_validate (tm->time_now, num_threads - 1);
902   return error;
903 }
904
905 clib_error_t *
906 sctp_transport_enable_disable (vlib_main_t * vm, u8 is_en)
907 {
908   if (is_en)
909     {
910       if (sctp_main.is_enabled)
911         return 0;
912
913       return sctp_main_enable (vm);
914     }
915   else
916     {
917       sctp_main.is_enabled = 0;
918     }
919
920   return 0;
921 }
922
923 transport_connection_t *
924 sctp_half_open_session_get_transport (u32 conn_index)
925 {
926   sctp_connection_t *sctp_conn = sctp_half_open_connection_get (conn_index);
927   return &sctp_conn->sub_conn[SCTP_PRIMARY_PATH_IDX].connection;
928 }
929
930 u8 *
931 format_sctp_half_open (u8 * s, va_list * args)
932 {
933   u32 tci = va_arg (*args, u32);
934   sctp_connection_t *sctp_conn = sctp_half_open_connection_get (tci);
935   return format (s, "%U", format_sctp_connection_id, sctp_conn);
936 }
937
938 void
939 sctp_update_time (f64 now, u8 thread_index)
940 {
941   sctp_set_time_now (thread_index);
942   tw_timer_expire_timers_16t_2w_512sl (&sctp_main.timer_wheels[thread_index],
943                                        now);
944   sctp_flush_frames_to_output (thread_index);
945 }
946
947 /* *INDENT-OFF* */
948 static const transport_proto_vft_t sctp_proto = {
949   .enable = sctp_transport_enable_disable,
950   .start_listen = sctp_session_bind,
951   .stop_listen = sctp_session_unbind,
952   .connect = sctp_session_open,
953   .close = sctp_session_close,
954   .cleanup = sctp_session_cleanup,
955   .push_header = sctp_push_header,
956   .send_mss = sctp_session_send_mss,
957   .send_space = sctp_session_send_space,
958   .update_time = sctp_update_time,
959   .get_connection = sctp_session_get_transport,
960   .get_listener = sctp_session_get_listener,
961   .get_half_open = sctp_half_open_session_get_transport,
962   .format_connection = format_sctp_session,
963   .format_listener = format_sctp_listener_session,
964   .format_half_open = format_sctp_half_open,
965   .transport_options = {
966     .tx_type = TRANSPORT_TX_DEQUEUE,
967     .service_type = TRANSPORT_SERVICE_VC,
968   },
969 };
970 /* *INDENT-ON* */
971
972 clib_error_t *
973 sctp_enable_disable (vlib_main_t * vm, u8 is_en)
974 {
975   sctp_main_t *sm = vnet_get_sctp_main ();
976   ip_main_t *im = &ip_main;
977   ip_protocol_info_t *pi;
978   vlib_node_t *node;
979
980   if (!sm->is_init && is_en)
981     {
982       node = vlib_get_node_by_name (vm, (u8 *) "sctp4-established");
983       sm->sctp4_established_phase_node_index = node->index;
984
985       node = vlib_get_node_by_name (vm, (u8 *) "sctp6-established");
986       sm->sctp6_established_phase_node_index = node->index;
987
988       sm->is_init = 1;
989
990       /* Register with IP for header parsing */
991       pi = ip_get_protocol_info (im, IP_PROTOCOL_SCTP);
992       if (pi == 0)
993         return clib_error_return (0, "SCTP protocol info AWOL");
994       pi->format_header = format_sctp_header;
995       pi->unformat_pg_edit = unformat_pg_sctp_header;
996
997       /* Register as transport with session layer */
998       transport_register_protocol (TRANSPORT_PROTO_SCTP, &sctp_proto,
999                                    FIB_PROTOCOL_IP4, sctp4_output_node.index);
1000       transport_register_protocol (TRANSPORT_PROTO_SCTP, &sctp_proto,
1001                                    FIB_PROTOCOL_IP6, sctp6_output_node.index);
1002     }
1003
1004   sctp_transport_enable_disable (vm, is_en);
1005   return 0;
1006 }
1007
1008 static u8 *
1009 sctp_format_buffer_opaque_helper (const vlib_buffer_t * b, u8 * s)
1010 {
1011   sctp_buffer_opaque_t *o = sctp_buffer_opaque (b);
1012
1013   s = format (s,
1014               "sctp.connection_index: %d, sctp.sid: %d, sctp.ssn: %d, "
1015               "sctp.tsn: %d, sctp.hdr_offset: %d",
1016               o->sctp.connection_index,
1017               (u32) (o->sctp.sid),
1018               (u32) (o->sctp.ssn),
1019               (u32) (o->sctp.tsn), (u32) (o->sctp.hdr_offset));
1020   vec_add1 (s, '\n');
1021
1022   s = format
1023     (s, "sctp.data_offset: %d, sctp.data_len: %d, sctp.subconn_idx: %d, "
1024      "sctp.flags: 0x%x",
1025      (u32) (o->sctp.data_offset),
1026      (u32) (o->sctp.data_len),
1027      (u32) (o->sctp.subconn_idx), (u32) (o->sctp.flags));
1028   vec_add1 (s, '\n');
1029   return s;
1030 }
1031
1032 clib_error_t *
1033 sctp_init (vlib_main_t * vm)
1034 {
1035   sctp_main_t *sm = vnet_get_sctp_main ();
1036
1037   /* Session layer, and by implication SCTP, are disabled by default */
1038   sm->is_enabled = 0;
1039   sm->is_init = 0;
1040
1041   /* initialize binary API */
1042   sctp_plugin_api_hookup (vm);
1043
1044   vnet_register_format_buffer_opaque_helper
1045     (sctp_format_buffer_opaque_helper);
1046   return 0;
1047 }
1048
1049 VLIB_INIT_FUNCTION (sctp_init);
1050
1051 static clib_error_t *
1052 show_sctp_punt_fn (vlib_main_t * vm, unformat_input_t * input,
1053                    vlib_cli_command_t * cmd_arg)
1054 {
1055   sctp_main_t *tm = &sctp_main;
1056   if (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1057     return clib_error_return (0, "unknown input `%U'", format_unformat_error,
1058                               input);
1059   vlib_cli_output (vm, "IPv4 UDP punt: %s",
1060                    tm->punt_unknown4 ? "enabled" : "disabled");
1061   vlib_cli_output (vm, "IPv6 UDP punt: %s",
1062                    tm->punt_unknown6 ? "enabled" : "disabled");
1063   return 0;
1064 }
1065 /* *INDENT-OFF* */
1066 VLIB_CLI_COMMAND (show_tcp_punt_command, static) =
1067 {
1068   .path = "show sctp punt",
1069   .short_help = "show sctp punt",
1070   .function = show_sctp_punt_fn,
1071 };
1072 /* *INDENT-ON* */
1073
1074 static clib_error_t *
1075 sctp_fn (vlib_main_t * vm, unformat_input_t * input,
1076          vlib_cli_command_t * cmd_arg)
1077 {
1078   unformat_input_t _line_input, *line_input = &_line_input;
1079   clib_error_t *error;
1080   u8 is_en;
1081
1082   if (!unformat_user (input, unformat_line_input, line_input))
1083     return clib_error_return (0, "expected enable | disable");
1084
1085   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1086     {
1087       if (unformat (line_input, "enable"))
1088         is_en = 1;
1089       else if (unformat (line_input, "disable"))
1090         is_en = 0;
1091       else
1092         {
1093           error = clib_error_return (0, "unknown input `%U'",
1094                                      format_unformat_error, line_input);
1095           unformat_free (line_input);
1096           return error;
1097         }
1098     }
1099
1100   unformat_free (line_input);
1101
1102   return sctp_enable_disable (vm, is_en);
1103 }
1104
1105 /* *INDENT-OFF* */
1106 VLIB_CLI_COMMAND (show_sctp_command, static) =
1107 {
1108   .path = "sctp",
1109   .short_help = "sctp [enable | disable]",
1110   .function = sctp_fn,
1111 };
1112
1113 /* *INDENT-OFF* */
1114 VLIB_PLUGIN_REGISTER () =
1115 {
1116   .version = VPP_BUILD_VER,
1117   .description = "Stream Control Transmission Protocol (SCTP)",
1118   .default_disabled = 1,
1119 };
1120 /* *INDENT-ON* */
1121
1122 /*
1123  * fd.io coding-style-patch-verification: ON
1124  *
1125  * Local Variables:
1126  * eval: (c-set-style "gnu")
1127  * End:
1128  */