f379e6998391fa07026b4afca4f4d91fb389a0a4
[vpp.git] / src / vnet / tcp / tcp.c
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
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/tcp/tcp.h>
17 #include <vnet/session/session.h>
18 #include <vnet/fib/fib.h>
19 #include <vnet/dpo/load_balance.h>
20 #include <math.h>
21
22 tcp_main_t tcp_main;
23
24 static u32
25 tcp_connection_bind (u32 session_index, ip46_address_t * ip,
26                      u16 port_host_byte_order, u8 is_ip4)
27 {
28   tcp_main_t *tm = &tcp_main;
29   tcp_connection_t *listener;
30
31   pool_get (tm->listener_pool, listener);
32   memset (listener, 0, sizeof (*listener));
33
34   listener->c_c_index = listener - tm->listener_pool;
35   listener->c_lcl_port = clib_host_to_net_u16 (port_host_byte_order);
36
37   if (is_ip4)
38     {
39       listener->c_lcl_ip4.as_u32 = ip->ip4.as_u32;
40       listener->c_is_ip4 = 1;
41       listener->c_proto = SESSION_TYPE_IP4_TCP;
42     }
43   else
44     {
45       clib_memcpy (&listener->c_lcl_ip6, &ip->ip6, sizeof (ip6_address_t));
46       listener->c_proto = SESSION_TYPE_IP6_TCP;
47     }
48
49   listener->c_s_index = session_index;
50   listener->state = TCP_STATE_LISTEN;
51
52   tcp_connection_timers_init (listener);
53
54   TCP_EVT_DBG (TCP_EVT_BIND, listener);
55
56   return listener->c_c_index;
57 }
58
59 u32
60 tcp_session_bind_ip4 (u32 session_index, ip46_address_t * ip,
61                       u16 port_host_byte_order)
62 {
63   return tcp_connection_bind (session_index, ip, port_host_byte_order, 1);
64 }
65
66 u32
67 tcp_session_bind_ip6 (u32 session_index, ip46_address_t * ip,
68                       u16 port_host_byte_order)
69 {
70   return tcp_connection_bind (session_index, ip, port_host_byte_order, 0);
71 }
72
73 static void
74 tcp_connection_unbind (u32 listener_index)
75 {
76   tcp_main_t *tm = vnet_get_tcp_main ();
77   tcp_connection_t *tc;
78
79   tc = pool_elt_at_index (tm->listener_pool, listener_index);
80
81   TCP_EVT_DBG (TCP_EVT_UNBIND, tc);
82
83   /* Poison the entry */
84   if (CLIB_DEBUG > 0)
85     memset (tc, 0xFA, sizeof (*tc));
86
87   pool_put_index (tm->listener_pool, listener_index);
88 }
89
90 u32
91 tcp_session_unbind (u32 listener_index)
92 {
93   tcp_connection_unbind (listener_index);
94   return 0;
95 }
96
97 transport_connection_t *
98 tcp_session_get_listener (u32 listener_index)
99 {
100   tcp_main_t *tm = vnet_get_tcp_main ();
101   tcp_connection_t *tc;
102   tc = pool_elt_at_index (tm->listener_pool, listener_index);
103   return &tc->connection;
104 }
105
106 /**
107  * Cleans up connection state.
108  *
109  * No notifications.
110  */
111 void
112 tcp_connection_cleanup (tcp_connection_t * tc)
113 {
114   tcp_main_t *tm = &tcp_main;
115   u32 tepi;
116   transport_endpoint_t *tep;
117
118   /* Cleanup local endpoint if this was an active connect */
119   tepi = transport_endpoint_lookup (&tm->local_endpoints_table, &tc->c_lcl_ip,
120                                     tc->c_lcl_port);
121
122   /*XXX lock */
123   if (tepi != TRANSPORT_ENDPOINT_INVALID_INDEX)
124     {
125       tep = pool_elt_at_index (tm->local_endpoints, tepi);
126       transport_endpoint_table_del (&tm->local_endpoints_table, tep);
127       pool_put (tm->local_endpoints, tep);
128     }
129
130   /* Make sure all timers are cleared */
131   tcp_connection_timers_reset (tc);
132
133   /* Check if half-open */
134   if (tc->state == TCP_STATE_SYN_SENT)
135     {
136       /* Poison the entry */
137       if (CLIB_DEBUG > 0)
138         memset (tc, 0xFA, sizeof (*tc));
139       pool_put (tm->half_open_connections, tc);
140     }
141   else
142     {
143       int thread_index = tc->c_thread_index;
144       /* Poison the entry */
145       if (CLIB_DEBUG > 0)
146         memset (tc, 0xFA, sizeof (*tc));
147       pool_put (tm->connections[thread_index], tc);
148     }
149 }
150
151 /**
152  * Connection removal.
153  *
154  * This should be called only once connection enters CLOSED state. Note
155  * that it notifies the session of the removal event, so if the goal is to
156  * just remove the connection, call tcp_connection_cleanup instead.
157  */
158 void
159 tcp_connection_del (tcp_connection_t * tc)
160 {
161   TCP_EVT_DBG (TCP_EVT_DELETE, tc);
162   stream_session_delete_notify (&tc->connection);
163   tcp_connection_cleanup (tc);
164 }
165
166 /** Notify session that connection has been reset.
167  *
168  * Switch state to closed and wait for session to call cleanup.
169  */
170 void
171 tcp_connection_reset (tcp_connection_t * tc)
172 {
173   switch (tc->state)
174     {
175     case TCP_STATE_SYN_RCVD:
176       /* Cleanup everything. App wasn't notified yet */
177       stream_session_delete_notify (&tc->connection);
178       tcp_connection_cleanup (tc);
179       break;
180     case TCP_STATE_SYN_SENT:
181     case TCP_STATE_ESTABLISHED:
182     case TCP_STATE_CLOSE_WAIT:
183     case TCP_STATE_FIN_WAIT_1:
184     case TCP_STATE_FIN_WAIT_2:
185     case TCP_STATE_CLOSING:
186       tc->state = TCP_STATE_CLOSED;
187
188       /* Make sure all timers are cleared */
189       tcp_connection_timers_reset (tc);
190       stream_session_reset_notify (&tc->connection);
191
192       /* Wait for cleanup from session layer but not forever */
193       tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_CLEANUP_TIME);
194       break;
195     case TCP_STATE_CLOSED:
196       return;
197     }
198 }
199
200 /**
201  * Begin connection closing procedure.
202  *
203  * If at the end the connection is not in CLOSED state, it is not removed.
204  * Instead, we rely on on TCP to advance through state machine to either
205  * 1) LAST_ACK (passive close) whereby when the last ACK is received
206  * tcp_connection_del is called. This notifies session of the delete and
207  * calls cleanup.
208  * 2) TIME_WAIT (active close) whereby after 2MSL the 2MSL timer triggers
209  * and cleanup is called.
210  *
211  * N.B. Half-close connections are not supported
212  */
213 void
214 tcp_connection_close (tcp_connection_t * tc)
215 {
216   TCP_EVT_DBG (TCP_EVT_CLOSE, tc);
217
218   /* Send FIN if needed */
219   if (tc->state == TCP_STATE_ESTABLISHED
220       || tc->state == TCP_STATE_SYN_RCVD || tc->state == TCP_STATE_CLOSE_WAIT)
221     tcp_send_fin (tc);
222
223   /* Switch state */
224   if (tc->state == TCP_STATE_ESTABLISHED || tc->state == TCP_STATE_SYN_RCVD)
225     tc->state = TCP_STATE_FIN_WAIT_1;
226   else if (tc->state == TCP_STATE_SYN_SENT)
227     tc->state = TCP_STATE_CLOSED;
228   else if (tc->state == TCP_STATE_CLOSE_WAIT)
229     tc->state = TCP_STATE_LAST_ACK;
230
231   /* If in CLOSED and WAITCLOSE timer is not set, delete connection now */
232   if (tc->timers[TCP_TIMER_WAITCLOSE] == TCP_TIMER_HANDLE_INVALID
233       && tc->state == TCP_STATE_CLOSED)
234     tcp_connection_del (tc);
235 }
236
237 void
238 tcp_session_close (u32 conn_index, u32 thread_index)
239 {
240   tcp_connection_t *tc;
241   tc = tcp_connection_get (conn_index, thread_index);
242   tcp_connection_close (tc);
243 }
244
245 void
246 tcp_session_cleanup (u32 conn_index, u32 thread_index)
247 {
248   tcp_connection_t *tc;
249   tc = tcp_connection_get (conn_index, thread_index);
250
251   /* Wait for the session tx events to clear */
252   tc->state = TCP_STATE_CLOSED;
253   tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, TCP_CLEANUP_TIME);
254 }
255
256 void *
257 ip_interface_get_first_ip (u32 sw_if_index, u8 is_ip4)
258 {
259   ip_lookup_main_t *lm4 = &ip4_main.lookup_main;
260   ip_lookup_main_t *lm6 = &ip6_main.lookup_main;
261   ip_interface_address_t *ia = 0;
262
263   if (is_ip4)
264     {
265       /* *INDENT-OFF* */
266       foreach_ip_interface_address (lm4, ia, sw_if_index, 1 /* unnumbered */ ,
267       ({
268         return ip_interface_address_get_address (lm4, ia);
269       }));
270       /* *INDENT-ON* */
271     }
272   else
273     {
274       /* *INDENT-OFF* */
275       foreach_ip_interface_address (lm6, ia, sw_if_index, 1 /* unnumbered */ ,
276       ({
277         return ip_interface_address_get_address (lm6, ia);
278       }));
279       /* *INDENT-ON* */
280     }
281
282   return 0;
283 }
284
285 #define PORT_MASK ((1 << 16)- 1)
286 /**
287  * Allocate local port and add if successful add entry to local endpoint
288  * table to mark the pair as used.
289  */
290 u16
291 tcp_allocate_local_port (tcp_main_t * tm, ip46_address_t * ip)
292 {
293   transport_endpoint_t *tep;
294   u32 time_now, tei;
295   u16 min = 1024, max = 65535;  /* XXX configurable ? */
296   int tries;
297
298   tries = max - min;
299   time_now = tcp_time_now ();
300
301   /* Only support active opens from thread 0 */
302   ASSERT (vlib_get_thread_index () == 0);
303
304   /* Start at random point or max */
305   pool_get (tm->local_endpoints, tep);
306   clib_memcpy (&tep->ip, ip, sizeof (*ip));
307
308   /* Search for first free slot */
309   for (; tries >= 0; tries--)
310     {
311       u16 port = 0;
312
313       /* Find a port in the specified range */
314       while (1)
315         {
316           port = random_u32 (&time_now) & PORT_MASK;
317           if (PREDICT_TRUE (port >= min && port < max))
318             break;
319         }
320
321       tep->port = port;
322
323       /* Look it up */
324       tei = transport_endpoint_lookup (&tm->local_endpoints_table, &tep->ip,
325                                        tep->port);
326       /* If not found, we're done */
327       if (tei == TRANSPORT_ENDPOINT_INVALID_INDEX)
328         {
329           transport_endpoint_table_add (&tm->local_endpoints_table, tep,
330                                         tep - tm->local_endpoints);
331           return tep->port;
332         }
333     }
334   /* No free ports */
335   pool_put (tm->local_endpoints, tep);
336   return -1;
337 }
338
339 /**
340  * Initialize all connection timers as invalid
341  */
342 void
343 tcp_connection_timers_init (tcp_connection_t * tc)
344 {
345   int i;
346
347   /* Set all to invalid */
348   for (i = 0; i < TCP_N_TIMERS; i++)
349     {
350       tc->timers[i] = TCP_TIMER_HANDLE_INVALID;
351     }
352
353   tc->rto = TCP_RTO_INIT;
354 }
355
356 /**
357  * Stop all connection timers
358  */
359 void
360 tcp_connection_timers_reset (tcp_connection_t * tc)
361 {
362   int i;
363   for (i = 0; i < TCP_N_TIMERS; i++)
364     {
365       tcp_timer_reset (tc, i);
366     }
367 }
368
369 #if 0
370 typedef struct ip4_tcp_hdr
371 {
372   ip4_header_t ip;
373   tcp_header_t tcp;
374 } ip4_tcp_hdr_t;
375
376 typedef struct ip6_tcp_hdr
377 {
378   ip6_header_t ip;
379   tcp_header_t tcp;
380 } ip6_tcp_hdr_t;
381
382 static void
383 tcp_connection_select_lb_bucket (tcp_connection_t * tc, const dpo_id_t * dpo,
384                                  dpo_id_t * result)
385 {
386   const dpo_id_t *choice;
387   load_balance_t *lb;
388   int hash;
389
390   lb = load_balance_get (dpo->dpoi_index);
391   if (tc->c_is_ip4)
392     {
393       ip4_tcp_hdr_t hdr;
394       memset (&hdr, 0, sizeof (hdr));
395       hdr.ip.protocol = IP_PROTOCOL_TCP;
396       hdr.ip.address_pair.src.as_u32 = tc->c_lcl_ip.ip4.as_u32;
397       hdr.ip.address_pair.dst.as_u32 = tc->c_rmt_ip.ip4.as_u32;
398       hdr.tcp.src_port = tc->c_lcl_port;
399       hdr.tcp.dst_port = tc->c_rmt_port;
400       hash = ip4_compute_flow_hash (&hdr.ip, lb->lb_hash_config);
401     }
402   else
403     {
404       ip6_tcp_hdr_t hdr;
405       memset (&hdr, 0, sizeof (hdr));
406       hdr.ip.protocol = IP_PROTOCOL_TCP;
407       clib_memcpy (&hdr.ip.src_address, &tc->c_lcl_ip.ip6,
408                    sizeof (ip6_address_t));
409       clib_memcpy (&hdr.ip.dst_address, &tc->c_rmt_ip.ip6,
410                    sizeof (ip6_address_t));
411       hdr.tcp.src_port = tc->c_lcl_port;
412       hdr.tcp.dst_port = tc->c_rmt_port;
413       hash = ip6_compute_flow_hash (&hdr.ip, lb->lb_hash_config);
414     }
415   choice = load_balance_get_bucket_i (lb, hash & lb->lb_n_buckets_minus_1);
416   dpo_copy (result, choice);
417 }
418
419 fib_node_index_t
420 tcp_lookup_rmt_in_fib (tcp_connection_t * tc)
421 {
422   fib_prefix_t prefix;
423
424   clib_memcpy (&prefix.fp_addr, &tc->c_rmt_ip, sizeof (prefix.fp_addr));
425   prefix.fp_proto = tc->c_is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
426   prefix.fp_len = tc->c_is_ip4 ? 32 : 128;
427   return fib_table_lookup (0, &prefix);
428 }
429
430 static int
431 tcp_connection_stack_on_fib_entry (tcp_connection_t * tc)
432 {
433   dpo_id_t choice = DPO_INVALID;
434   u32 output_node_index;
435   fib_entry_t *fe;
436
437   fe = fib_entry_get (tc->c_rmt_fei);
438   if (fe->fe_lb.dpoi_type != DPO_LOAD_BALANCE)
439     return -1;
440
441   tcp_connection_select_lb_bucket (tc, &fe->fe_lb, &choice);
442
443   output_node_index =
444     tc->c_is_ip4 ? tcp4_output_node.index : tcp6_output_node.index;
445   dpo_stack_from_node (output_node_index, &tc->c_rmt_dpo, &choice);
446   return 0;
447 }
448
449 /** Stack tcp connection on peer's fib entry.
450  *
451  * This ultimately populates the dpo the connection will use to send packets.
452  */
453 static void
454 tcp_connection_fib_attach (tcp_connection_t * tc)
455 {
456   tc->c_rmt_fei = tcp_lookup_rmt_in_fib (tc);
457
458   ASSERT (tc->c_rmt_fei != FIB_NODE_INDEX_INVALID);
459
460   tcp_connection_stack_on_fib_entry (tc);
461 }
462 #endif /* 0 */
463
464 /** Initialize tcp connection variables
465  *
466  * Should be called after having received a msg from the peer, i.e., a SYN or
467  * a SYNACK, such that connection options have already been exchanged. */
468 void
469 tcp_connection_init_vars (tcp_connection_t * tc)
470 {
471   tcp_connection_timers_init (tc);
472   tcp_init_mss (tc);
473   scoreboard_init (&tc->sack_sb);
474   tcp_cc_init (tc);
475   //  tcp_connection_fib_attach (tc);
476 }
477
478 int
479 tcp_connection_open (ip46_address_t * rmt_addr, u16 rmt_port, u8 is_ip4)
480 {
481   tcp_main_t *tm = vnet_get_tcp_main ();
482   tcp_connection_t *tc;
483   fib_prefix_t prefix;
484   fib_node_index_t fei;
485   u32 sw_if_index;
486   ip46_address_t lcl_addr;
487   u16 lcl_port;
488
489   /*
490    * Find the local address and allocate port
491    */
492   memset (&lcl_addr, 0, sizeof (lcl_addr));
493
494   /* Find a FIB path to the destination */
495   clib_memcpy (&prefix.fp_addr, rmt_addr, sizeof (*rmt_addr));
496   prefix.fp_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
497   prefix.fp_len = is_ip4 ? 32 : 128;
498
499   fei = fib_table_lookup (0, &prefix);
500
501   /* Couldn't find route to destination. Bail out. */
502   if (fei == FIB_NODE_INDEX_INVALID)
503     return -1;
504
505   sw_if_index = fib_entry_get_resolving_interface (fei);
506
507   if (sw_if_index == (u32) ~ 0)
508     return -1;
509
510   if (is_ip4)
511     {
512       ip4_address_t *ip4;
513       int index;
514       if (vec_len (tm->ip4_src_addresses))
515         {
516           index = tm->last_v4_address_rotor++;
517           if (tm->last_v4_address_rotor >= vec_len (tm->ip4_src_addresses))
518             tm->last_v4_address_rotor = 0;
519           lcl_addr.ip4.as_u32 = tm->ip4_src_addresses[index].as_u32;
520         }
521       else
522         {
523           ip4 = ip_interface_get_first_ip (sw_if_index, 1);
524           lcl_addr.ip4.as_u32 = ip4->as_u32;
525         }
526     }
527   else
528     {
529       ip6_address_t *ip6;
530       int index;
531
532       if (vec_len (tm->ip6_src_addresses))
533         {
534           index = tm->last_v6_address_rotor++;
535           if (tm->last_v6_address_rotor >= vec_len (tm->ip6_src_addresses))
536             tm->last_v6_address_rotor = 0;
537           clib_memcpy (&lcl_addr.ip6, &tm->ip6_src_addresses[index],
538                        sizeof (*ip6));
539         }
540       else
541         {
542           ip6 = ip_interface_get_first_ip (sw_if_index, 0);
543           clib_memcpy (&lcl_addr.ip6, ip6, sizeof (*ip6));
544         }
545     }
546
547   /* Allocate source port */
548   lcl_port = tcp_allocate_local_port (tm, &lcl_addr);
549   if (lcl_port < 1)
550     {
551       clib_warning ("Failed to allocate src port");
552       return -1;
553     }
554
555   /*
556    * Create connection and send SYN
557    */
558
559   pool_get (tm->half_open_connections, tc);
560   memset (tc, 0, sizeof (*tc));
561
562   clib_memcpy (&tc->c_rmt_ip, rmt_addr, sizeof (ip46_address_t));
563   clib_memcpy (&tc->c_lcl_ip, &lcl_addr, sizeof (ip46_address_t));
564   tc->c_rmt_port = clib_host_to_net_u16 (rmt_port);
565   tc->c_lcl_port = clib_host_to_net_u16 (lcl_port);
566   tc->c_c_index = tc - tm->half_open_connections;
567   tc->c_is_ip4 = is_ip4;
568   tc->c_proto = is_ip4 ? SESSION_TYPE_IP4_TCP : SESSION_TYPE_IP6_TCP;
569
570   /* The other connection vars will be initialized after SYN ACK */
571   tcp_connection_timers_init (tc);
572
573   tcp_send_syn (tc);
574
575   tc->state = TCP_STATE_SYN_SENT;
576
577   TCP_EVT_DBG (TCP_EVT_OPEN, tc);
578
579   return tc->c_c_index;
580 }
581
582 int
583 tcp_session_open_ip4 (ip46_address_t * addr, u16 port)
584 {
585   return tcp_connection_open (addr, port, 1);
586 }
587
588 int
589 tcp_session_open_ip6 (ip46_address_t * addr, u16 port)
590 {
591   return tcp_connection_open (addr, port, 0);
592 }
593
594 const char *tcp_dbg_evt_str[] = {
595 #define _(sym, str) str,
596   foreach_tcp_dbg_evt
597 #undef _
598 };
599
600 const char *tcp_fsm_states[] = {
601 #define _(sym, str) str,
602   foreach_tcp_fsm_state
603 #undef _
604 };
605
606 u8 *
607 format_tcp_state (u8 * s, va_list * args)
608 {
609   u32 state = va_arg (*args, u32);
610
611   if (state < TCP_N_STATES)
612     s = format (s, "%s", tcp_fsm_states[state]);
613   else
614     s = format (s, "UNKNOWN (%d (0x%x))", state, state);
615   return s;
616 }
617
618 const char *tcp_conn_timers[] = {
619 #define _(sym, str) str,
620   foreach_tcp_timer
621 #undef _
622 };
623
624 u8 *
625 format_tcp_timers (u8 * s, va_list * args)
626 {
627   tcp_connection_t *tc = va_arg (*args, tcp_connection_t *);
628   int i, last = -1;
629
630   for (i = 0; i < TCP_N_TIMERS; i++)
631     if (tc->timers[i] != TCP_TIMER_HANDLE_INVALID)
632       last = i;
633
634   s = format (s, "[");
635   for (i = 0; i < last; i++)
636     {
637       if (tc->timers[i] != TCP_TIMER_HANDLE_INVALID)
638         s = format (s, "%s,", tcp_conn_timers[i]);
639     }
640
641   if (last >= 0)
642     s = format (s, "%s]", tcp_conn_timers[i]);
643   else
644     s = format (s, "]");
645
646   return s;
647 }
648
649 u8 *
650 format_tcp_congestion_status (u8 * s, va_list * args)
651 {
652   tcp_connection_t *tc = va_arg (*args, tcp_connection_t *);
653   if (tcp_in_recovery (tc))
654     s = format (s, "recovery");
655   else if (tcp_in_fastrecovery (tc))
656     s = format (s, "fastrecovery");
657   else
658     s = format (s, "none");
659   return s;
660 }
661
662 u8 *
663 format_tcp_vars (u8 * s, va_list * args)
664 {
665   tcp_connection_t *tc = va_arg (*args, tcp_connection_t *);
666   s = format (s, " snd_una %u snd_nxt %u snd_una_max %u",
667               tc->snd_una - tc->iss, tc->snd_nxt - tc->iss,
668               tc->snd_una_max - tc->iss);
669   s = format (s, " rcv_nxt %u rcv_las %u\n",
670               tc->rcv_nxt - tc->irs, tc->rcv_las - tc->irs);
671   s = format (s, " snd_wnd %u rcv_wnd %u snd_wl1 %u snd_wl2 %u\n",
672               tc->snd_wnd, tc->rcv_wnd, tc->snd_wl1 - tc->irs,
673               tc->snd_wl2 - tc->iss);
674   s = format (s, " flight size %u send space %u rcv_wnd_av %d\n",
675               tcp_flight_size (tc), tcp_available_snd_space (tc),
676               tcp_rcv_wnd_available (tc));
677   s = format (s, " cong %U ", format_tcp_congestion_status, tc);
678   s = format (s, "cwnd %u ssthresh %u rtx_bytes %u bytes_acked %u\n",
679               tc->cwnd, tc->ssthresh, tc->snd_rxt_bytes, tc->bytes_acked);
680   s = format (s, " prev_ssthresh %u snd_congestion %u dupack %u",
681               tc->prev_ssthresh, tc->snd_congestion - tc->iss,
682               tc->rcv_dupacks);
683   s = format (s, " limited_transmit %u\n", tc->limited_transmit - tc->iss);
684   s = format (s, " tsecr %u tsecr_last_ack %u\n", tc->rcv_opts.tsecr,
685               tc->tsecr_last_ack);
686   s = format (s, " rto %u rto_boff %u srtt %u rttvar %u rtt_ts %u ", tc->rto,
687               tc->rto_boff, tc->srtt, tc->rttvar, tc->rtt_ts);
688   s = format (s, "rtt_seq %u\n", tc->rtt_seq);
689   s = format (s, " tsval_recent %u tsval_recent_age %u\n", tc->tsval_recent,
690               tcp_time_now () - tc->tsval_recent_age);
691   s = format (s, " scoreboard: %U\n", format_tcp_scoreboard, &tc->sack_sb);
692   if (vec_len (tc->snd_sacks))
693     s = format (s, " sacks tx: %U\n", format_tcp_sacks, tc);
694
695   return s;
696 }
697
698 u8 *
699 format_tcp_connection_id (u8 * s, va_list * args)
700 {
701   tcp_connection_t *tc = va_arg (*args, tcp_connection_t *);
702   if (!tc)
703     return s;
704   if (tc->c_is_ip4)
705     {
706       s = format (s, "[#%d][%s] %U:%d->%U:%d", tc->c_thread_index, "T",
707                   format_ip4_address, &tc->c_lcl_ip4,
708                   clib_net_to_host_u16 (tc->c_lcl_port), format_ip4_address,
709                   &tc->c_rmt_ip4, clib_net_to_host_u16 (tc->c_rmt_port));
710     }
711   else
712     {
713       s = format (s, "[#%d][%s] %U:%d->%U:%d", tc->c_thread_index, "T",
714                   format_ip6_address, &tc->c_lcl_ip6,
715                   clib_net_to_host_u16 (tc->c_lcl_port), format_ip6_address,
716                   &tc->c_rmt_ip6, clib_net_to_host_u16 (tc->c_rmt_port));
717     }
718
719   return s;
720 }
721
722 u8 *
723 format_tcp_connection (u8 * s, va_list * args)
724 {
725   tcp_connection_t *tc = va_arg (*args, tcp_connection_t *);
726   u32 verbose = va_arg (*args, u32);
727
728   s = format (s, "%-50U", format_tcp_connection_id, tc);
729   if (verbose)
730     {
731       s = format (s, "%-15U", format_tcp_state, tc->state);
732       if (verbose > 1)
733         s = format (s, " %U\n%U", format_tcp_timers, tc, format_tcp_vars, tc);
734     }
735   return s;
736 }
737
738 u8 *
739 format_tcp_session (u8 * s, va_list * args)
740 {
741   u32 tci = va_arg (*args, u32);
742   u32 thread_index = va_arg (*args, u32);
743   u32 verbose = va_arg (*args, u32);
744   tcp_connection_t *tc;
745
746   tc = tcp_connection_get (tci, thread_index);
747   if (tc)
748     s = format (s, "%U", format_tcp_connection, tc, verbose);
749   else
750     s = format (s, "empty");
751   return s;
752 }
753
754 u8 *
755 format_tcp_listener_session (u8 * s, va_list * args)
756 {
757   u32 tci = va_arg (*args, u32);
758   tcp_connection_t *tc = tcp_listener_get (tci);
759   return format (s, "%U", format_tcp_connection_id, tc);
760 }
761
762 u8 *
763 format_tcp_half_open_session (u8 * s, va_list * args)
764 {
765   u32 tci = va_arg (*args, u32);
766   tcp_connection_t *tc = tcp_half_open_connection_get (tci);
767   return format (s, "%U", format_tcp_connection_id, tc);
768 }
769
770 u8 *
771 format_tcp_sacks (u8 * s, va_list * args)
772 {
773   tcp_connection_t *tc = va_arg (*args, tcp_connection_t *);
774   sack_block_t *sacks = tc->snd_sacks;
775   sack_block_t *block;
776   int i, len = 0;
777
778   len = vec_len (sacks);
779   for (i = 0; i < len - 1; i++)
780     {
781       block = &sacks[i];
782       s = format (s, " start %u end %u\n", block->start - tc->irs,
783                   block->end - tc->irs);
784     }
785   if (len)
786     {
787       block = &sacks[len - 1];
788       s = format (s, " start %u end %u", block->start - tc->irs,
789                   block->end - tc->irs);
790     }
791   return s;
792 }
793
794 u8 *
795 format_tcp_sack_hole (u8 * s, va_list * args)
796 {
797   sack_scoreboard_hole_t *hole = va_arg (*args, sack_scoreboard_hole_t *);
798   s = format (s, "[%u, %u]", hole->start, hole->end);
799   return s;
800 }
801
802 u8 *
803 format_tcp_scoreboard (u8 * s, va_list * args)
804 {
805   sack_scoreboard_t *sb = va_arg (*args, sack_scoreboard_t *);
806   sack_scoreboard_hole_t *hole;
807   s = format (s, "sacked_bytes %u last_sacked_bytes %u lost_bytes %u\n",
808               sb->sacked_bytes, sb->last_sacked_bytes, sb->lost_bytes);
809   s = format (s, " last_bytes_delivered %u high_sacked %u snd_una_adv %u\n",
810               sb->last_bytes_delivered, sb->high_sacked, sb->snd_una_adv);
811   s = format (s, " cur_rxt_hole %u high_rxt %u rescue_rxt %u",
812               sb->cur_rxt_hole, sb->high_rxt, sb->rescue_rxt);
813
814   hole = scoreboard_first_hole (sb);
815   if (hole)
816     s = format (s, "\n head %u tail %u holes:\n", sb->head, sb->tail);
817
818   while (hole)
819     {
820       s = format (s, "%U", format_tcp_sack_hole, hole);
821       hole = scoreboard_next_hole (sb, hole);
822     }
823   return s;
824 }
825
826 transport_connection_t *
827 tcp_session_get_transport (u32 conn_index, u32 thread_index)
828 {
829   tcp_connection_t *tc = tcp_connection_get (conn_index, thread_index);
830   return &tc->connection;
831 }
832
833 transport_connection_t *
834 tcp_half_open_session_get_transport (u32 conn_index)
835 {
836   tcp_connection_t *tc = tcp_half_open_connection_get (conn_index);
837   return &tc->connection;
838 }
839
840 /**
841  * Compute maximum segment size for session layer.
842  *
843  * Since the result needs to be the actual data length, it first computes
844  * the tcp options to be used in the next burst and subtracts their
845  * length from the connection's snd_mss.
846  */
847 u16
848 tcp_session_send_mss (transport_connection_t * trans_conn)
849 {
850   tcp_connection_t *tc = (tcp_connection_t *) trans_conn;
851
852   /* Ensure snd_mss does accurately reflect the amount of data we can push
853    * in a segment. This also makes sure that options are updated according to
854    * the current state of the connection. */
855   tcp_update_snd_mss (tc);
856
857   return tc->snd_mss;
858 }
859
860 always_inline u32
861 tcp_round_snd_space (tcp_connection_t * tc, u32 snd_space)
862 {
863   if (PREDICT_FALSE (tc->snd_wnd < tc->snd_mss))
864     {
865       return tc->snd_wnd <= snd_space ? tc->snd_wnd : 0;
866     }
867
868   /* If we can't write at least a segment, don't try at all */
869   if (PREDICT_FALSE (snd_space < tc->snd_mss))
870     {
871       if (snd_space > clib_min (tc->mss, tc->rcv_opts.mss) - TCP_HDR_LEN_MAX)
872         return snd_space;
873       return 0;
874     }
875
876   /* round down to mss multiple */
877   return snd_space - (snd_space % tc->snd_mss);
878 }
879
880 /**
881  * Compute tx window session is allowed to fill.
882  *
883  * Takes into account available send space, snd_mss and the congestion
884  * state of the connection. If possible, the value returned is a multiple
885  * of snd_mss.
886  *
887  * @param tc tcp connection
888  * @return number of bytes session is allowed to write
889  */
890 u32
891 tcp_snd_space (tcp_connection_t * tc)
892 {
893   int snd_space, snt_limited;
894
895   if (PREDICT_TRUE (tcp_in_cong_recovery (tc) == 0))
896     {
897       snd_space = tcp_available_snd_space (tc);
898
899       /* If we haven't gotten dupacks or if we did and have gotten sacked
900        * bytes then we can still send as per Limited Transmit (RFC3042) */
901       if (PREDICT_FALSE (tc->rcv_dupacks != 0
902                          && (tcp_opts_sack_permitted (tc)
903                              && tc->sack_sb.last_sacked_bytes == 0)))
904         {
905           if (tc->rcv_dupacks == 1 && tc->limited_transmit != tc->snd_nxt)
906             tc->limited_transmit = tc->snd_nxt;
907           ASSERT (seq_leq (tc->limited_transmit, tc->snd_nxt));
908
909           snt_limited = tc->snd_nxt - tc->limited_transmit;
910           snd_space = clib_max (2 * tc->snd_mss - snt_limited, 0);
911         }
912       return tcp_round_snd_space (tc, snd_space);
913     }
914
915   if (tcp_in_recovery (tc))
916     {
917       tc->snd_nxt = tc->snd_una_max;
918       snd_space = tcp_available_wnd (tc) - tc->snd_rxt_bytes
919         - (tc->snd_una_max - tc->snd_congestion);
920       if (snd_space <= 0 || (tc->snd_una_max - tc->snd_una) >= tc->snd_wnd)
921         return 0;
922       return tcp_round_snd_space (tc, snd_space);
923     }
924
925   /* If in fast recovery, send 1 SMSS if wnd allows */
926   if (tcp_in_fastrecovery (tc)
927       && tcp_available_snd_space (tc) && !tcp_fastrecovery_sent_1_smss (tc))
928     {
929       tcp_fastrecovery_1_smss_on (tc);
930       return tc->snd_mss;
931     }
932
933   return 0;
934 }
935
936 u32
937 tcp_session_send_space (transport_connection_t * trans_conn)
938 {
939   tcp_connection_t *tc = (tcp_connection_t *) trans_conn;
940   return tcp_snd_space (tc);
941 }
942
943 i32
944 tcp_rcv_wnd_available (tcp_connection_t * tc)
945 {
946   return (i32) tc->rcv_wnd - (tc->rcv_nxt - tc->rcv_las);
947 }
948
949 u32
950 tcp_session_tx_fifo_offset (transport_connection_t * trans_conn)
951 {
952   tcp_connection_t *tc = (tcp_connection_t *) trans_conn;
953
954   ASSERT (seq_geq (tc->snd_nxt, tc->snd_una));
955
956   /* This still works if fast retransmit is on */
957   return (tc->snd_nxt - tc->snd_una);
958 }
959
960 /* *INDENT-OFF* */
961 const static transport_proto_vft_t tcp4_proto = {
962   .bind = tcp_session_bind_ip4,
963   .unbind = tcp_session_unbind,
964   .push_header = tcp_push_header,
965   .get_connection = tcp_session_get_transport,
966   .get_listener = tcp_session_get_listener,
967   .get_half_open = tcp_half_open_session_get_transport,
968   .open = tcp_session_open_ip4,
969   .close = tcp_session_close,
970   .cleanup = tcp_session_cleanup,
971   .send_mss = tcp_session_send_mss,
972   .send_space = tcp_session_send_space,
973   .tx_fifo_offset = tcp_session_tx_fifo_offset,
974   .format_connection = format_tcp_session,
975   .format_listener = format_tcp_listener_session,
976   .format_half_open = format_tcp_half_open_session,
977 };
978
979 const static transport_proto_vft_t tcp6_proto = {
980   .bind = tcp_session_bind_ip6,
981   .unbind = tcp_session_unbind,
982   .push_header = tcp_push_header,
983   .get_connection = tcp_session_get_transport,
984   .get_listener = tcp_session_get_listener,
985   .get_half_open = tcp_half_open_session_get_transport,
986   .open = tcp_session_open_ip6,
987   .close = tcp_session_close,
988   .cleanup = tcp_session_cleanup,
989   .send_mss = tcp_session_send_mss,
990   .send_space = tcp_session_send_space,
991   .tx_fifo_offset = tcp_session_tx_fifo_offset,
992   .format_connection = format_tcp_session,
993   .format_listener = format_tcp_listener_session,
994   .format_half_open = format_tcp_half_open_session,
995 };
996 /* *INDENT-ON* */
997
998 void
999 tcp_timer_keep_handler (u32 conn_index)
1000 {
1001   u32 thread_index = vlib_get_thread_index ();
1002   tcp_connection_t *tc;
1003
1004   tc = tcp_connection_get (conn_index, thread_index);
1005   tc->timers[TCP_TIMER_KEEP] = TCP_TIMER_HANDLE_INVALID;
1006
1007   tcp_connection_close (tc);
1008 }
1009
1010 void
1011 tcp_timer_establish_handler (u32 conn_index)
1012 {
1013   tcp_connection_t *tc;
1014   u8 sst;
1015
1016   tc = tcp_half_open_connection_get (conn_index);
1017   tc->timers[TCP_TIMER_ESTABLISH] = TCP_TIMER_HANDLE_INVALID;
1018
1019   ASSERT (tc->state == TCP_STATE_SYN_SENT);
1020
1021   sst = tc->c_is_ip4 ? SESSION_TYPE_IP4_TCP : SESSION_TYPE_IP6_TCP;
1022   stream_session_connect_notify (&tc->connection, sst, 1 /* fail */ );
1023
1024   tcp_connection_cleanup (tc);
1025 }
1026
1027 void
1028 tcp_timer_waitclose_handler (u32 conn_index)
1029 {
1030   u32 thread_index = vlib_get_thread_index ();
1031   tcp_connection_t *tc;
1032
1033   tc = tcp_connection_get (conn_index, thread_index);
1034   tc->timers[TCP_TIMER_WAITCLOSE] = TCP_TIMER_HANDLE_INVALID;
1035
1036   /* Session didn't come back with a close(). Send FIN either way
1037    * and switch to LAST_ACK. */
1038   if (tc->state == TCP_STATE_CLOSE_WAIT)
1039     {
1040       if (tc->flags & TCP_CONN_FINSNT)
1041         {
1042           clib_warning ("FIN was sent and still in CLOSE WAIT. Weird!");
1043         }
1044
1045       tcp_send_fin (tc);
1046       tc->state = TCP_STATE_LAST_ACK;
1047
1048       /* Make sure we don't wait in LAST ACK forever */
1049       tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_2MSL_TIME);
1050
1051       /* Don't delete the connection yet */
1052       return;
1053     }
1054
1055   tcp_connection_del (tc);
1056 }
1057
1058 /* *INDENT-OFF* */
1059 static timer_expiration_handler *timer_expiration_handlers[TCP_N_TIMERS] =
1060 {
1061     tcp_timer_retransmit_handler,
1062     tcp_timer_delack_handler,
1063     tcp_timer_persist_handler,
1064     tcp_timer_keep_handler,
1065     tcp_timer_waitclose_handler,
1066     tcp_timer_retransmit_syn_handler,
1067     tcp_timer_establish_handler
1068 };
1069 /* *INDENT-ON* */
1070
1071 static void
1072 tcp_expired_timers_dispatch (u32 * expired_timers)
1073 {
1074   int i;
1075   u32 connection_index, timer_id;
1076
1077   for (i = 0; i < vec_len (expired_timers); i++)
1078     {
1079       /* Get session index and timer id */
1080       connection_index = expired_timers[i] & 0x0FFFFFFF;
1081       timer_id = expired_timers[i] >> 28;
1082
1083       TCP_EVT_DBG (TCP_EVT_TIMER_POP, connection_index, timer_id);
1084
1085       /* Handle expiration */
1086       (*timer_expiration_handlers[timer_id]) (connection_index);
1087     }
1088 }
1089
1090 void
1091 tcp_initialize_timer_wheels (tcp_main_t * tm)
1092 {
1093   tw_timer_wheel_16t_2w_512sl_t *tw;
1094   /* *INDENT-OFF* */
1095   foreach_vlib_main (({
1096     tw = &tm->timer_wheels[ii];
1097     tw_timer_wheel_init_16t_2w_512sl (tw, tcp_expired_timers_dispatch,
1098                                       100e-3 /* timer period 100ms */ , ~0);
1099     tw->last_run_time = vlib_time_now (this_vlib_main);
1100   }));
1101   /* *INDENT-ON* */
1102 }
1103
1104 clib_error_t *
1105 tcp_main_enable (vlib_main_t * vm)
1106 {
1107   tcp_main_t *tm = vnet_get_tcp_main ();
1108   ip_protocol_info_t *pi;
1109   ip_main_t *im = &ip_main;
1110   vlib_thread_main_t *vtm = vlib_get_thread_main ();
1111   clib_error_t *error = 0;
1112   u32 num_threads;
1113   int thread, i;
1114   tcp_connection_t *tc __attribute__ ((unused));
1115
1116   if ((error = vlib_call_init_function (vm, ip_main_init)))
1117     return error;
1118   if ((error = vlib_call_init_function (vm, ip4_lookup_init)))
1119     return error;
1120   if ((error = vlib_call_init_function (vm, ip6_lookup_init)))
1121     return error;
1122
1123   /*
1124    * Registrations
1125    */
1126
1127   /* Register with IP */
1128   pi = ip_get_protocol_info (im, IP_PROTOCOL_TCP);
1129   if (pi == 0)
1130     return clib_error_return (0, "TCP protocol info AWOL");
1131   pi->format_header = format_tcp_header;
1132   pi->unformat_pg_edit = unformat_pg_tcp_header;
1133
1134   ip4_register_protocol (IP_PROTOCOL_TCP, tcp4_input_node.index);
1135
1136   /* Register as transport with URI */
1137   session_register_transport (SESSION_TYPE_IP4_TCP, &tcp4_proto);
1138   session_register_transport (SESSION_TYPE_IP6_TCP, &tcp6_proto);
1139
1140   /*
1141    * Initialize data structures
1142    */
1143
1144   num_threads = 1 /* main thread */  + vtm->n_threads;
1145   vec_validate (tm->connections, num_threads - 1);
1146
1147   /*
1148    * Preallocate connections
1149    */
1150   for (thread = 0; thread < num_threads; thread++)
1151     {
1152       for (i = 0; i < tm->preallocated_connections; i++)
1153         pool_get (tm->connections[thread], tc);
1154
1155       for (i = 0; i < tm->preallocated_connections; i++)
1156         pool_put_index (tm->connections[thread], i);
1157     }
1158
1159   /*
1160    * Preallocate half-open connections
1161    */
1162   for (i = 0; i < tm->preallocated_half_open_connections; i++)
1163     pool_get (tm->half_open_connections, tc);
1164
1165   for (i = 0; i < tm->preallocated_half_open_connections; i++)
1166     pool_put_index (tm->half_open_connections, i);
1167
1168   /* Initialize per worker thread tx buffers (used for control messages) */
1169   vec_validate (tm->tx_buffers, num_threads - 1);
1170
1171   /* Initialize timer wheels */
1172   vec_validate (tm->timer_wheels, num_threads - 1);
1173   tcp_initialize_timer_wheels (tm);
1174
1175   /* Initialize clocks per tick for TCP timestamp. Used to compute
1176    * monotonically increasing timestamps. */
1177   tm->tstamp_ticks_per_clock = vm->clib_time.seconds_per_clock
1178     / TCP_TSTAMP_RESOLUTION;
1179
1180   clib_bihash_init_24_8 (&tm->local_endpoints_table, "local endpoint table",
1181                          200000 /* $$$$ config parameter nbuckets */ ,
1182                          (64 << 20) /*$$$ config parameter table size */ );
1183
1184   return error;
1185 }
1186
1187 clib_error_t *
1188 vnet_tcp_enable_disable (vlib_main_t * vm, u8 is_en)
1189 {
1190   if (is_en)
1191     {
1192       if (tcp_main.is_enabled)
1193         return 0;
1194
1195       return tcp_main_enable (vm);
1196     }
1197   else
1198     {
1199       tcp_main.is_enabled = 0;
1200     }
1201
1202   return 0;
1203 }
1204
1205 clib_error_t *
1206 tcp_init (vlib_main_t * vm)
1207 {
1208   tcp_main_t *tm = vnet_get_tcp_main ();
1209
1210   tm->vnet_main = vnet_get_main ();
1211   tm->is_enabled = 0;
1212
1213   return 0;
1214 }
1215
1216 VLIB_INIT_FUNCTION (tcp_init);
1217
1218
1219 static clib_error_t *
1220 tcp_config_fn (vlib_main_t * vm, unformat_input_t * input)
1221 {
1222   tcp_main_t *tm = vnet_get_tcp_main ();
1223
1224   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1225     {
1226       if (unformat
1227           (input, "preallocated-connections %d",
1228            &tm->preallocated_connections))
1229         ;
1230       else if (unformat (input, "preallocated-half-open-connections %d",
1231                          &tm->preallocated_half_open_connections))
1232         ;
1233       else
1234         return clib_error_return (0, "unknown input `%U'",
1235                                   format_unformat_error, input);
1236     }
1237   return 0;
1238 }
1239
1240 VLIB_CONFIG_FUNCTION (tcp_config_fn, "tcp");
1241
1242 static clib_error_t *
1243 tcp_src_address (vlib_main_t * vm,
1244                  unformat_input_t * input, vlib_cli_command_t * cmd_arg)
1245 {
1246   tcp_main_t *tm = vnet_get_tcp_main ();
1247   ip4_address_t v4start, v4end;
1248   ip6_address_t v6start, v6end;
1249   int v4set = 0;
1250   int v6set = 0;
1251
1252   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1253     {
1254       if (unformat (input, "%U - %U", unformat_ip4_address, &v4start,
1255                     unformat_ip4_address, &v4end))
1256         v4set = 1;
1257       else if (unformat (input, "%U", unformat_ip4_address, &v4start))
1258         {
1259           memcpy (&v4end, &v4start, sizeof (v4start));
1260           v4set = 1;
1261         }
1262       else if (unformat (input, "%U - %U", unformat_ip6_address, &v6start,
1263                          unformat_ip4_address, &v6end))
1264         v6set = 1;
1265       else if (unformat (input, "%U", unformat_ip6_address, &v6start))
1266         {
1267           memcpy (&v6end, &v6start, sizeof (v4start));
1268           v6set = 1;
1269         }
1270       else
1271         break;
1272     }
1273
1274   if (!v4set && !v6set)
1275     return clib_error_return (0, "at least one v4 or v6 address required");
1276
1277   if (v4set)
1278     {
1279       u32 tmp;
1280
1281       do
1282         {
1283           vec_add1 (tm->ip4_src_addresses, v4start);
1284           tmp = clib_net_to_host_u32 (v4start.as_u32);
1285           tmp++;
1286           v4start.as_u32 = clib_host_to_net_u32 (tmp);
1287         }
1288       while (clib_host_to_net_u32 (v4start.as_u32) <=
1289              clib_host_to_net_u32 (v4end.as_u32));
1290     }
1291   if (v6set)
1292     {
1293       clib_warning ("v6 src address list unimplemented...");
1294     }
1295   return 0;
1296 }
1297
1298 /* *INDENT-OFF* */
1299 VLIB_CLI_COMMAND (tcp_src_address_command, static) =
1300 {
1301   .path = "tcp src-address",
1302   .short_help = "tcp src-address <ip-addr> [- <ip-addr>] add src address range",
1303   .function = tcp_src_address,
1304 };
1305 /* *INDENT-ON* */
1306
1307
1308
1309 /*
1310  * fd.io coding-style-patch-verification: ON
1311  *
1312  * Local Variables:
1313  * eval: (c-set-style "gnu")
1314  * End:
1315  */