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