tcp: move features to separate files
[vpp.git] / src / vnet / tcp / tcp.c
1 /*
2  * Copyright (c) 2016-2019 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 /**
17  * @file
18  * @brief TCP host stack utilities
19  */
20
21 #include <vnet/tcp/tcp.h>
22 #include <vnet/tcp/tcp_inlines.h>
23 #include <vnet/session/session.h>
24 #include <vnet/fib/fib.h>
25 #include <vnet/dpo/load_balance.h>
26 #include <math.h>
27
28 tcp_main_t tcp_main;
29
30 typedef struct
31 {
32   fib_protocol_t nh_proto;
33   vnet_link_t link_type;
34   ip46_address_t ip;
35   u32 sw_if_index;
36   u8 is_add;
37 } tcp_add_del_adj_args_t;
38
39 static void
40 tcp_add_del_adj_cb (tcp_add_del_adj_args_t * args)
41 {
42   u32 ai;
43   if (args->is_add)
44     {
45       adj_nbr_add_or_lock (args->nh_proto, args->link_type, &args->ip,
46                            args->sw_if_index);
47     }
48   else
49     {
50       ai = adj_nbr_find (FIB_PROTOCOL_IP6, VNET_LINK_IP6, &args->ip,
51                          args->sw_if_index);
52       if (ai != ADJ_INDEX_INVALID)
53         adj_unlock (ai);
54     }
55 }
56
57 static void
58 tcp_add_del_adjacency (tcp_connection_t * tc, u8 is_add)
59 {
60   tcp_add_del_adj_args_t args = {
61     .nh_proto = FIB_PROTOCOL_IP6,
62     .link_type = VNET_LINK_IP6,
63     .ip = tc->c_rmt_ip,
64     .sw_if_index = tc->sw_if_index,
65     .is_add = is_add
66   };
67   vlib_rpc_call_main_thread (tcp_add_del_adj_cb, (u8 *) & args,
68                              sizeof (args));
69 }
70
71 static void
72 tcp_cc_init (tcp_connection_t * tc)
73 {
74   tc->cc_algo->init (tc);
75 }
76
77 static void
78 tcp_cc_cleanup (tcp_connection_t * tc)
79 {
80   if (tc->cc_algo->cleanup)
81     tc->cc_algo->cleanup (tc);
82 }
83
84 void
85 tcp_cc_algo_register (tcp_cc_algorithm_type_e type,
86                       const tcp_cc_algorithm_t * vft)
87 {
88   tcp_main_t *tm = vnet_get_tcp_main ();
89   vec_validate (tm->cc_algos, type);
90
91   tm->cc_algos[type] = *vft;
92   hash_set_mem (tm->cc_algo_by_name, vft->name, type);
93 }
94
95 tcp_cc_algorithm_t *
96 tcp_cc_algo_get (tcp_cc_algorithm_type_e type)
97 {
98   tcp_main_t *tm = vnet_get_tcp_main ();
99   return &tm->cc_algos[type];
100 }
101
102 tcp_cc_algorithm_type_e
103 tcp_cc_algo_new_type (const tcp_cc_algorithm_t * vft)
104 {
105   tcp_main_t *tm = vnet_get_tcp_main ();
106   tcp_cc_algo_register (++tm->cc_last_type, vft);
107   return tm->cc_last_type;
108 }
109
110 static u32
111 tcp_connection_bind (u32 session_index, transport_endpoint_t * lcl)
112 {
113   tcp_main_t *tm = &tcp_main;
114   tcp_connection_t *listener;
115   void *iface_ip;
116
117   pool_get (tm->listener_pool, listener);
118   clib_memset (listener, 0, sizeof (*listener));
119
120   listener->c_c_index = listener - tm->listener_pool;
121   listener->c_lcl_port = lcl->port;
122
123   /* If we are provided a sw_if_index, bind using one of its ips */
124   if (ip_is_zero (&lcl->ip, 1) && lcl->sw_if_index != ENDPOINT_INVALID_INDEX)
125     {
126       if ((iface_ip = ip_interface_get_first_ip (lcl->sw_if_index,
127                                                  lcl->is_ip4)))
128         ip_set (&lcl->ip, iface_ip, lcl->is_ip4);
129     }
130   ip_copy (&listener->c_lcl_ip, &lcl->ip, lcl->is_ip4);
131   listener->c_is_ip4 = lcl->is_ip4;
132   listener->c_proto = TRANSPORT_PROTO_TCP;
133   listener->c_s_index = session_index;
134   listener->c_fib_index = lcl->fib_index;
135   listener->state = TCP_STATE_LISTEN;
136   listener->cc_algo = tcp_cc_algo_get (tcp_cfg.cc_algo);
137
138   tcp_connection_timers_init (listener);
139
140   TCP_EVT (TCP_EVT_BIND, listener);
141
142   return listener->c_c_index;
143 }
144
145 static u32
146 tcp_session_bind (u32 session_index, transport_endpoint_t * tep)
147 {
148   return tcp_connection_bind (session_index, tep);
149 }
150
151 static void
152 tcp_connection_unbind (u32 listener_index)
153 {
154   tcp_main_t *tm = vnet_get_tcp_main ();
155   tcp_connection_t *tc;
156
157   tc = pool_elt_at_index (tm->listener_pool, listener_index);
158
159   TCP_EVT (TCP_EVT_UNBIND, tc);
160
161   /* Poison the entry */
162   if (CLIB_DEBUG > 0)
163     clib_memset (tc, 0xFA, sizeof (*tc));
164
165   pool_put_index (tm->listener_pool, listener_index);
166 }
167
168 static u32
169 tcp_session_unbind (u32 listener_index)
170 {
171   tcp_connection_unbind (listener_index);
172   return 0;
173 }
174
175 static transport_connection_t *
176 tcp_session_get_listener (u32 listener_index)
177 {
178   tcp_main_t *tm = vnet_get_tcp_main ();
179   tcp_connection_t *tc;
180   tc = pool_elt_at_index (tm->listener_pool, listener_index);
181   return &tc->connection;
182 }
183
184 /**
185  * Cleanup half-open connection
186  *
187  */
188 static void
189 tcp_half_open_connection_del (tcp_connection_t * tc)
190 {
191   tcp_main_t *tm = vnet_get_tcp_main ();
192   clib_spinlock_lock_if_init (&tm->half_open_lock);
193   if (CLIB_DEBUG)
194     clib_memset (tc, 0xFA, sizeof (*tc));
195   pool_put (tm->half_open_connections, tc);
196   clib_spinlock_unlock_if_init (&tm->half_open_lock);
197 }
198
199 /**
200  * Try to cleanup half-open connection
201  *
202  * If called from a thread that doesn't own tc, the call won't have any
203  * effect.
204  *
205  * @param tc - connection to be cleaned up
206  * @return non-zero if cleanup failed.
207  */
208 int
209 tcp_half_open_connection_cleanup (tcp_connection_t * tc)
210 {
211   /* Make sure this is the owning thread */
212   if (tc->c_thread_index != vlib_get_thread_index ())
213     return 1;
214   tcp_timer_reset (tc, TCP_TIMER_RETRANSMIT_SYN);
215   tcp_half_open_connection_del (tc);
216   return 0;
217 }
218
219 static tcp_connection_t *
220 tcp_half_open_connection_new (void)
221 {
222   tcp_main_t *tm = vnet_get_tcp_main ();
223   tcp_connection_t *tc = 0;
224   ASSERT (vlib_get_thread_index () == 0);
225   pool_get (tm->half_open_connections, tc);
226   clib_memset (tc, 0, sizeof (*tc));
227   tc->c_c_index = tc - tm->half_open_connections;
228   return tc;
229 }
230
231 /**
232  * Cleans up connection state.
233  *
234  * No notifications.
235  */
236 void
237 tcp_connection_cleanup (tcp_connection_t * tc)
238 {
239   TCP_EVT (TCP_EVT_DELETE, tc);
240
241   /* Cleanup local endpoint if this was an active connect */
242   if (!(tc->cfg_flags & TCP_CFG_F_NO_ENDPOINT))
243     transport_endpoint_cleanup (TRANSPORT_PROTO_TCP, &tc->c_lcl_ip,
244                                 tc->c_lcl_port);
245
246   /* Check if connection is not yet fully established */
247   if (tc->state == TCP_STATE_SYN_SENT)
248     {
249       /* Try to remove the half-open connection. If this is not the owning
250        * thread, tc won't be removed. Retransmit or establish timers will
251        * eventually expire and call again cleanup on the right thread. */
252       if (tcp_half_open_connection_cleanup (tc))
253         tc->flags |= TCP_CONN_HALF_OPEN_DONE;
254     }
255   else
256     {
257       /* Make sure all timers are cleared */
258       tcp_connection_timers_reset (tc);
259
260       if (!tc->c_is_ip4 && ip6_address_is_link_local_unicast (&tc->c_rmt_ip6))
261         tcp_add_del_adjacency (tc, 0);
262
263       tcp_cc_cleanup (tc);
264       vec_free (tc->snd_sacks);
265       vec_free (tc->snd_sacks_fl);
266       vec_free (tc->rcv_opts.sacks);
267       pool_free (tc->sack_sb.holes);
268
269       if (tc->cfg_flags & TCP_CFG_F_RATE_SAMPLE)
270         tcp_bt_cleanup (tc);
271
272       tcp_connection_free (tc);
273     }
274 }
275
276 /**
277  * Connection removal.
278  *
279  * This should be called only once connection enters CLOSED state. Note
280  * that it notifies the session of the removal event, so if the goal is to
281  * just remove the connection, call tcp_connection_cleanup instead.
282  */
283 void
284 tcp_connection_del (tcp_connection_t * tc)
285 {
286   session_transport_delete_notify (&tc->connection);
287   tcp_connection_cleanup (tc);
288 }
289
290 tcp_connection_t *
291 tcp_connection_alloc (u8 thread_index)
292 {
293   tcp_worker_ctx_t *wrk = tcp_get_worker (thread_index);
294   tcp_connection_t *tc;
295
296   pool_get (wrk->connections, tc);
297   clib_memset (tc, 0, sizeof (*tc));
298   tc->c_c_index = tc - wrk->connections;
299   tc->c_thread_index = thread_index;
300   return tc;
301 }
302
303 tcp_connection_t *
304 tcp_connection_alloc_w_base (u8 thread_index, tcp_connection_t * base)
305 {
306   tcp_worker_ctx_t *wrk = tcp_get_worker (thread_index);
307   tcp_connection_t *tc;
308
309   pool_get (wrk->connections, tc);
310   clib_memcpy_fast (tc, base, sizeof (*tc));
311   tc->c_c_index = tc - wrk->connections;
312   tc->c_thread_index = thread_index;
313   return tc;
314 }
315
316 void
317 tcp_connection_free (tcp_connection_t * tc)
318 {
319   tcp_worker_ctx_t *wrk = tcp_get_worker (tc->c_thread_index);
320   if (CLIB_DEBUG)
321     {
322       clib_memset (tc, 0xFA, sizeof (*tc));
323       pool_put (wrk->connections, tc);
324       return;
325     }
326   pool_put (wrk->connections, tc);
327 }
328
329 void
330 tcp_program_cleanup (tcp_worker_ctx_t * wrk, tcp_connection_t * tc)
331 {
332   tcp_cleanup_req_t *req;
333   clib_time_type_t now;
334
335   now = transport_time_now (tc->c_thread_index);
336   clib_fifo_add2 (wrk->pending_cleanups, req);
337   req->connection_index = tc->c_c_index;
338   req->free_time = now + tcp_cfg.cleanup_time;
339 }
340
341 /**
342  * Begin connection closing procedure.
343  *
344  * If at the end the connection is not in CLOSED state, it is not removed.
345  * Instead, we rely on on TCP to advance through state machine to either
346  * 1) LAST_ACK (passive close) whereby when the last ACK is received
347  * tcp_connection_del is called. This notifies session of the delete and
348  * calls cleanup.
349  * 2) TIME_WAIT (active close) whereby after 2MSL the 2MSL timer triggers
350  * and cleanup is called.
351  *
352  * N.B. Half-close connections are not supported
353  */
354 void
355 tcp_connection_close (tcp_connection_t * tc)
356 {
357   TCP_EVT (TCP_EVT_CLOSE, tc);
358
359   /* Send/Program FIN if needed and switch state */
360   switch (tc->state)
361     {
362     case TCP_STATE_SYN_SENT:
363       /* Try to cleanup. If not on the right thread, mark as half-open done.
364        * Connection will be cleaned up when establish timer pops */
365       tcp_connection_cleanup (tc);
366       break;
367     case TCP_STATE_SYN_RCVD:
368       tcp_connection_timers_reset (tc);
369       tcp_send_fin (tc);
370       tcp_connection_set_state (tc, TCP_STATE_FIN_WAIT_1);
371       tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.finwait1_time);
372       break;
373     case TCP_STATE_ESTABLISHED:
374       /* If closing with unread data, reset the connection */
375       if (transport_max_rx_dequeue (&tc->connection))
376         {
377           tcp_send_reset (tc);
378           tcp_connection_timers_reset (tc);
379           tcp_connection_set_state (tc, TCP_STATE_CLOSED);
380           session_transport_closed_notify (&tc->connection);
381           tcp_program_cleanup (tcp_get_worker (tc->c_thread_index), tc);
382           tcp_worker_stats_inc (tc->c_thread_index, rst_unread, 1);
383           break;
384         }
385       if (!transport_max_tx_dequeue (&tc->connection))
386         tcp_send_fin (tc);
387       else
388         tc->flags |= TCP_CONN_FINPNDG;
389       tcp_connection_set_state (tc, TCP_STATE_FIN_WAIT_1);
390       /* Set a timer in case the peer stops responding. Otherwise the
391        * connection will be stuck here forever. */
392       ASSERT (tc->timers[TCP_TIMER_WAITCLOSE] == TCP_TIMER_HANDLE_INVALID);
393       tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.finwait1_time);
394       break;
395     case TCP_STATE_CLOSE_WAIT:
396       if (!transport_max_tx_dequeue (&tc->connection))
397         {
398           tcp_send_fin (tc);
399           tcp_connection_timers_reset (tc);
400           tcp_connection_set_state (tc, TCP_STATE_LAST_ACK);
401           tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.lastack_time);
402         }
403       else
404         tc->flags |= TCP_CONN_FINPNDG;
405       break;
406     case TCP_STATE_FIN_WAIT_1:
407       tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.finwait1_time);
408       break;
409     case TCP_STATE_CLOSED:
410       /* Cleanup should've been programmed already */
411       break;
412     default:
413       TCP_DBG ("state: %u", tc->state);
414     }
415 }
416
417 static void
418 tcp_session_close (u32 conn_index, u32 thread_index)
419 {
420   tcp_connection_t *tc;
421   tc = tcp_connection_get (conn_index, thread_index);
422   tcp_connection_close (tc);
423 }
424
425 static void
426 tcp_session_cleanup (u32 conn_index, u32 thread_index)
427 {
428   tcp_connection_t *tc;
429   tc = tcp_connection_get (conn_index, thread_index);
430   if (!tc)
431     return;
432   tcp_connection_set_state (tc, TCP_STATE_CLOSED);
433   tcp_connection_cleanup (tc);
434 }
435
436 static void
437 tcp_session_reset (u32 conn_index, u32 thread_index)
438 {
439   tcp_connection_t *tc;
440   tc = tcp_connection_get (conn_index, thread_index);
441   tcp_send_reset (tc);
442   tcp_connection_timers_reset (tc);
443   tcp_cong_recovery_off (tc);
444   tcp_connection_set_state (tc, TCP_STATE_CLOSED);
445   session_transport_closed_notify (&tc->connection);
446   tcp_program_cleanup (tcp_get_worker (thread_index), tc);
447 }
448
449 /**
450  * Initialize all connection timers as invalid
451  */
452 void
453 tcp_connection_timers_init (tcp_connection_t * tc)
454 {
455   int i;
456
457   /* Set all to invalid */
458   for (i = 0; i < TCP_N_TIMERS; i++)
459     {
460       tc->timers[i] = TCP_TIMER_HANDLE_INVALID;
461     }
462
463   tc->rto = TCP_RTO_INIT;
464 }
465
466 /**
467  * Stop all connection timers
468  */
469 void
470 tcp_connection_timers_reset (tcp_connection_t * tc)
471 {
472   int i;
473   for (i = 0; i < TCP_N_TIMERS; i++)
474     {
475       tcp_timer_reset (tc, i);
476     }
477 }
478
479 #if 0
480 typedef struct ip4_tcp_hdr
481 {
482   ip4_header_t ip;
483   tcp_header_t tcp;
484 } ip4_tcp_hdr_t;
485
486 typedef struct ip6_tcp_hdr
487 {
488   ip6_header_t ip;
489   tcp_header_t tcp;
490 } ip6_tcp_hdr_t;
491
492 static void
493 tcp_connection_select_lb_bucket (tcp_connection_t * tc, const dpo_id_t * dpo,
494                                  dpo_id_t * result)
495 {
496   const dpo_id_t *choice;
497   load_balance_t *lb;
498   int hash;
499
500   lb = load_balance_get (dpo->dpoi_index);
501   if (tc->c_is_ip4)
502     {
503       ip4_tcp_hdr_t hdr;
504       clib_memset (&hdr, 0, sizeof (hdr));
505       hdr.ip.protocol = IP_PROTOCOL_TCP;
506       hdr.ip.address_pair.src.as_u32 = tc->c_lcl_ip.ip4.as_u32;
507       hdr.ip.address_pair.dst.as_u32 = tc->c_rmt_ip.ip4.as_u32;
508       hdr.tcp.src_port = tc->c_lcl_port;
509       hdr.tcp.dst_port = tc->c_rmt_port;
510       hash = ip4_compute_flow_hash (&hdr.ip, lb->lb_hash_config);
511     }
512   else
513     {
514       ip6_tcp_hdr_t hdr;
515       clib_memset (&hdr, 0, sizeof (hdr));
516       hdr.ip.protocol = IP_PROTOCOL_TCP;
517       clib_memcpy_fast (&hdr.ip.src_address, &tc->c_lcl_ip.ip6,
518                         sizeof (ip6_address_t));
519       clib_memcpy_fast (&hdr.ip.dst_address, &tc->c_rmt_ip.ip6,
520                         sizeof (ip6_address_t));
521       hdr.tcp.src_port = tc->c_lcl_port;
522       hdr.tcp.dst_port = tc->c_rmt_port;
523       hash = ip6_compute_flow_hash (&hdr.ip, lb->lb_hash_config);
524     }
525   choice = load_balance_get_bucket_i (lb, hash & lb->lb_n_buckets_minus_1);
526   dpo_copy (result, choice);
527 }
528
529 fib_node_index_t
530 tcp_lookup_rmt_in_fib (tcp_connection_t * tc)
531 {
532   fib_prefix_t prefix;
533   u32 fib_index;
534
535   clib_memcpy_fast (&prefix.fp_addr, &tc->c_rmt_ip, sizeof (prefix.fp_addr));
536   prefix.fp_proto = tc->c_is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
537   prefix.fp_len = tc->c_is_ip4 ? 32 : 128;
538   fib_index = fib_table_find (prefix.fp_proto, tc->c_fib_index);
539   return fib_table_lookup (fib_index, &prefix);
540 }
541
542 static int
543 tcp_connection_stack_on_fib_entry (tcp_connection_t * tc)
544 {
545   dpo_id_t choice = DPO_INVALID;
546   u32 output_node_index;
547   fib_entry_t *fe;
548
549   fe = fib_entry_get (tc->c_rmt_fei);
550   if (fe->fe_lb.dpoi_type != DPO_LOAD_BALANCE)
551     return -1;
552
553   tcp_connection_select_lb_bucket (tc, &fe->fe_lb, &choice);
554
555   output_node_index =
556     tc->c_is_ip4 ? tcp4_output_node.index : tcp6_output_node.index;
557   dpo_stack_from_node (output_node_index, &tc->c_rmt_dpo, &choice);
558   return 0;
559 }
560
561 /** Stack tcp connection on peer's fib entry.
562  *
563  * This ultimately populates the dpo the connection will use to send packets.
564  */
565 static void
566 tcp_connection_fib_attach (tcp_connection_t * tc)
567 {
568   tc->c_rmt_fei = tcp_lookup_rmt_in_fib (tc);
569
570   ASSERT (tc->c_rmt_fei != FIB_NODE_INDEX_INVALID);
571
572   tcp_connection_stack_on_fib_entry (tc);
573 }
574 #endif /* 0 */
575
576 /**
577  * Generate random iss as per rfc6528
578  */
579 static u32
580 tcp_generate_random_iss (tcp_connection_t * tc)
581 {
582   tcp_main_t *tm = &tcp_main;
583   u64 tmp;
584
585   if (tc->c_is_ip4)
586     tmp = (u64) tc->c_lcl_ip.ip4.as_u32 << 32 | (u64) tc->c_rmt_ip.ip4.as_u32;
587   else
588     tmp = tc->c_lcl_ip.ip6.as_u64[0] ^ tc->c_lcl_ip.ip6.as_u64[1]
589       ^ tc->c_rmt_ip.ip6.as_u64[0] ^ tc->c_rmt_ip.ip6.as_u64[1];
590
591   tmp ^= tm->iss_seed.first | ((u64) tc->c_lcl_port << 16 | tc->c_rmt_port);
592   tmp ^= tm->iss_seed.second;
593   tmp = clib_xxhash (tmp) + clib_cpu_time_now ();
594   return ((tmp >> 32) ^ (tmp & 0xffffffff));
595 }
596
597 /**
598  * Initialize max segment size we're able to process.
599  *
600  * The value is constrained by the output interface's MTU and by the size
601  * of the IP and TCP headers (see RFC6691). It is also what we advertise
602  * to our peer.
603  */
604 static void
605 tcp_init_rcv_mss (tcp_connection_t * tc)
606 {
607   u8 ip_hdr_len;
608
609   /* Already provided at connection init time */
610   if (tc->mss)
611     return;
612
613   ip_hdr_len = tc->c_is_ip4 ? sizeof (ip4_header_t) : sizeof (ip6_header_t);
614   tc->mss = tcp_cfg.default_mtu - sizeof (tcp_header_t) - ip_hdr_len;
615 }
616
617 static void
618 tcp_init_mss (tcp_connection_t * tc)
619 {
620   u16 default_min_mss = 536;
621
622   tcp_init_rcv_mss (tc);
623
624   /* TODO consider PMTU discovery */
625   tc->snd_mss = clib_min (tc->rcv_opts.mss, tc->mss);
626
627   if (tc->snd_mss < 45)
628     {
629       /* Assume that at least the min default mss works */
630       tc->snd_mss = default_min_mss;
631       tc->rcv_opts.mss = default_min_mss;
632     }
633
634   /* We should have enough space for 40 bytes of options */
635   ASSERT (tc->snd_mss > 45);
636
637   /* If we use timestamp option, account for it */
638   if (tcp_opts_tstamp (&tc->rcv_opts))
639     tc->snd_mss -= TCP_OPTION_LEN_TIMESTAMP;
640 }
641
642 /**
643  * Initialize connection send variables.
644  */
645 void
646 tcp_init_snd_vars (tcp_connection_t * tc)
647 {
648   /*
649    * We use the time to randomize iss and for setting up the initial
650    * timestamp. Make sure it's updated otherwise syn and ack in the
651    * handshake may make it look as if time has flown in the opposite
652    * direction for us.
653    */
654   tcp_set_time_now (tcp_get_worker (vlib_get_thread_index ()));
655
656   tcp_init_rcv_mss (tc);
657   tc->iss = tcp_generate_random_iss (tc);
658   tc->snd_una = tc->iss;
659   tc->snd_nxt = tc->iss + 1;
660   tc->snd_una_max = tc->snd_nxt;
661   tc->srtt = 100;               /* 100 ms */
662
663   if (!tcp_cfg.csum_offload)
664     tc->cfg_flags |= TCP_CFG_F_NO_CSUM_OFFLOAD;
665 }
666
667 void
668 tcp_enable_pacing (tcp_connection_t * tc)
669 {
670   u32 byte_rate;
671   byte_rate = tc->cwnd / (tc->srtt * TCP_TICK);
672   transport_connection_tx_pacer_init (&tc->connection, byte_rate, tc->cwnd);
673   tc->mrtt_us = (u32) ~ 0;
674 }
675
676 /** Initialize tcp connection variables
677  *
678  * Should be called after having received a msg from the peer, i.e., a SYN or
679  * a SYNACK, such that connection options have already been exchanged. */
680 void
681 tcp_connection_init_vars (tcp_connection_t * tc)
682 {
683   tcp_connection_timers_init (tc);
684   tcp_init_mss (tc);
685   scoreboard_init (&tc->sack_sb);
686   if (tc->state == TCP_STATE_SYN_RCVD)
687     tcp_init_snd_vars (tc);
688
689   tcp_cc_init (tc);
690
691   if (!tc->c_is_ip4 && ip6_address_is_link_local_unicast (&tc->c_rmt_ip6))
692     tcp_add_del_adjacency (tc, 1);
693
694   /*  tcp_connection_fib_attach (tc); */
695
696   if (transport_connection_is_tx_paced (&tc->connection)
697       || tcp_cfg.enable_tx_pacing)
698     tcp_enable_pacing (tc);
699
700   if (tc->cfg_flags & TCP_CFG_F_RATE_SAMPLE)
701     tcp_bt_init (tc);
702
703   if (!tcp_cfg.allow_tso)
704     tc->cfg_flags |= TCP_CFG_F_NO_TSO;
705
706   tc->start_ts = tcp_time_now_us (tc->c_thread_index);
707 }
708
709 static int
710 tcp_alloc_custom_local_endpoint (tcp_main_t * tm, ip46_address_t * lcl_addr,
711                                  u16 * lcl_port, u8 is_ip4)
712 {
713   int index, port;
714   if (is_ip4)
715     {
716       index = tm->last_v4_addr_rotor++;
717       if (tm->last_v4_addr_rotor >= vec_len (tcp_cfg.ip4_src_addrs))
718         tm->last_v4_addr_rotor = 0;
719       lcl_addr->ip4.as_u32 = tcp_cfg.ip4_src_addrs[index].as_u32;
720     }
721   else
722     {
723       index = tm->last_v6_addr_rotor++;
724       if (tm->last_v6_addr_rotor >= vec_len (tcp_cfg.ip6_src_addrs))
725         tm->last_v6_addr_rotor = 0;
726       clib_memcpy_fast (&lcl_addr->ip6, &tcp_cfg.ip6_src_addrs[index],
727                         sizeof (ip6_address_t));
728     }
729   port = transport_alloc_local_port (TRANSPORT_PROTO_TCP, lcl_addr);
730   if (port < 1)
731     {
732       clib_warning ("Failed to allocate src port");
733       return -1;
734     }
735   *lcl_port = port;
736   return 0;
737 }
738
739 static int
740 tcp_session_open (transport_endpoint_cfg_t * rmt)
741 {
742   tcp_main_t *tm = vnet_get_tcp_main ();
743   tcp_connection_t *tc;
744   ip46_address_t lcl_addr;
745   u16 lcl_port;
746   int rv;
747
748   /*
749    * Allocate local endpoint
750    */
751   if ((rmt->is_ip4 && vec_len (tcp_cfg.ip4_src_addrs))
752       || (!rmt->is_ip4 && vec_len (tcp_cfg.ip6_src_addrs)))
753     rv = tcp_alloc_custom_local_endpoint (tm, &lcl_addr, &lcl_port,
754                                           rmt->is_ip4);
755   else
756     rv = transport_alloc_local_endpoint (TRANSPORT_PROTO_TCP,
757                                          rmt, &lcl_addr, &lcl_port);
758
759   if (rv)
760     return -1;
761
762   /*
763    * Create connection and send SYN
764    */
765   clib_spinlock_lock_if_init (&tm->half_open_lock);
766   tc = tcp_half_open_connection_new ();
767   ip_copy (&tc->c_rmt_ip, &rmt->ip, rmt->is_ip4);
768   ip_copy (&tc->c_lcl_ip, &lcl_addr, rmt->is_ip4);
769   tc->c_rmt_port = rmt->port;
770   tc->c_lcl_port = clib_host_to_net_u16 (lcl_port);
771   tc->c_is_ip4 = rmt->is_ip4;
772   tc->c_proto = TRANSPORT_PROTO_TCP;
773   tc->c_fib_index = rmt->fib_index;
774   tc->cc_algo = tcp_cc_algo_get (tcp_cfg.cc_algo);
775   /* The other connection vars will be initialized after SYN ACK */
776   tcp_connection_timers_init (tc);
777   tc->mss = rmt->mss;
778
779   TCP_EVT (TCP_EVT_OPEN, tc);
780   tc->state = TCP_STATE_SYN_SENT;
781   tcp_init_snd_vars (tc);
782   tcp_send_syn (tc);
783   clib_spinlock_unlock_if_init (&tm->half_open_lock);
784
785   return tc->c_c_index;
786 }
787
788 static u8 *
789 format_tcp_session (u8 * s, va_list * args)
790 {
791   u32 tci = va_arg (*args, u32);
792   u32 thread_index = va_arg (*args, u32);
793   u32 verbose = va_arg (*args, u32);
794   tcp_connection_t *tc;
795
796   tc = tcp_connection_get (tci, thread_index);
797   if (tc)
798     s = format (s, "%U", format_tcp_connection, tc, verbose);
799   else
800     s = format (s, "empty\n");
801   return s;
802 }
803
804 static u8 *
805 format_tcp_listener_session (u8 * s, va_list * args)
806 {
807   u32 tci = va_arg (*args, u32);
808   u32 __clib_unused thread_index = va_arg (*args, u32);
809   u32 verbose = va_arg (*args, u32);
810   tcp_connection_t *tc = tcp_listener_get (tci);
811   s = format (s, "%-50U", format_tcp_connection_id, tc);
812   if (verbose)
813     s = format (s, "%-15U", format_tcp_state, tc->state);
814   return s;
815 }
816
817 static u8 *
818 format_tcp_half_open_session (u8 * s, va_list * args)
819 {
820   u32 tci = va_arg (*args, u32);
821   u32 __clib_unused thread_index = va_arg (*args, u32);
822   tcp_connection_t *tc = tcp_half_open_connection_get (tci);
823   return format (s, "%U", format_tcp_connection_id, tc);
824 }
825
826 static 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   if (PREDICT_FALSE (!tc))
831     return 0;
832   return &tc->connection;
833 }
834
835 static transport_connection_t *
836 tcp_half_open_session_get_transport (u32 conn_index)
837 {
838   tcp_connection_t *tc = tcp_half_open_connection_get (conn_index);
839   return &tc->connection;
840 }
841
842 static u16
843 tcp_session_cal_goal_size (tcp_connection_t * tc)
844 {
845   u16 goal_size = tc->snd_mss;
846
847   goal_size = TCP_MAX_GSO_SZ - tc->snd_mss % TCP_MAX_GSO_SZ;
848   goal_size = clib_min (goal_size, tc->snd_wnd / 2);
849
850   return goal_size > tc->snd_mss ? goal_size : tc->snd_mss;
851 }
852
853 always_inline u32
854 tcp_round_snd_space (tcp_connection_t * tc, u32 snd_space)
855 {
856   if (PREDICT_FALSE (tc->snd_wnd < tc->snd_mss))
857     {
858       return tc->snd_wnd <= snd_space ? tc->snd_wnd : 0;
859     }
860
861   /* If not snd_wnd constrained and we can't write at least a segment,
862    * don't try at all */
863   if (PREDICT_FALSE (snd_space < tc->snd_mss))
864     return snd_space < tc->cwnd ? 0 : snd_space;
865
866   /* round down to mss multiple */
867   return snd_space - (snd_space % tc->snd_mss);
868 }
869
870 /**
871  * Compute tx window session is allowed to fill.
872  *
873  * Takes into account available send space, snd_mss and the congestion
874  * state of the connection. If possible, the value returned is a multiple
875  * of snd_mss.
876  *
877  * @param tc tcp connection
878  * @return number of bytes session is allowed to write
879  */
880 static inline u32
881 tcp_snd_space_inline (tcp_connection_t * tc)
882 {
883   int snd_space;
884
885   if (PREDICT_FALSE (tcp_in_fastrecovery (tc)
886                      || tc->state == TCP_STATE_CLOSED))
887     return 0;
888
889   snd_space = tcp_available_output_snd_space (tc);
890
891   /* If we got dupacks or sacked bytes but we're not yet in recovery, try
892    * to force the peer to send enough dupacks to start retransmitting as
893    * per Limited Transmit (RFC3042)
894    */
895   if (PREDICT_FALSE (tc->rcv_dupacks != 0 || tc->sack_sb.sacked_bytes))
896     {
897       if (tc->limited_transmit != tc->snd_nxt
898           && (seq_lt (tc->limited_transmit, tc->snd_nxt - 2 * tc->snd_mss)
899               || seq_gt (tc->limited_transmit, tc->snd_nxt)))
900         tc->limited_transmit = tc->snd_nxt;
901
902       ASSERT (seq_leq (tc->limited_transmit, tc->snd_nxt));
903
904       int snt_limited = tc->snd_nxt - tc->limited_transmit;
905       snd_space = clib_max ((int) 2 * tc->snd_mss - snt_limited, 0);
906     }
907   return tcp_round_snd_space (tc, snd_space);
908 }
909
910 u32
911 tcp_snd_space (tcp_connection_t * tc)
912 {
913   return tcp_snd_space_inline (tc);
914 }
915
916 static int
917 tcp_session_send_params (transport_connection_t * trans_conn,
918                          transport_send_params_t * sp)
919 {
920   tcp_connection_t *tc = (tcp_connection_t *) trans_conn;
921
922   /* Ensure snd_mss does accurately reflect the amount of data we can push
923    * in a segment. This also makes sure that options are updated according to
924    * the current state of the connection. */
925   tcp_update_burst_snd_vars (tc);
926
927   if (PREDICT_FALSE (tc->cfg_flags & TCP_CFG_F_TSO))
928     sp->snd_mss = tcp_session_cal_goal_size (tc);
929   else
930     sp->snd_mss = tc->snd_mss;
931
932   sp->snd_space = clib_min (tcp_snd_space_inline (tc),
933                             tc->snd_wnd - (tc->snd_nxt - tc->snd_una));
934
935   ASSERT (seq_geq (tc->snd_nxt, tc->snd_una));
936   /* This still works if fast retransmit is on */
937   sp->tx_offset = tc->snd_nxt - tc->snd_una;
938
939   sp->flags = sp->snd_space ? 0 : TRANSPORT_SND_F_DESCHED;
940
941   return 0;
942 }
943
944 static void
945 tcp_timer_waitclose_handler (tcp_connection_t * tc)
946 {
947   tcp_worker_ctx_t *wrk = tcp_get_worker (tc->c_thread_index);
948
949   switch (tc->state)
950     {
951     case TCP_STATE_CLOSE_WAIT:
952       tcp_connection_timers_reset (tc);
953       /* App never returned with a close */
954       if (!(tc->flags & TCP_CONN_FINPNDG))
955         {
956           tcp_connection_set_state (tc, TCP_STATE_CLOSED);
957           session_transport_closed_notify (&tc->connection);
958           tcp_program_cleanup (wrk, tc);
959           tcp_workerp_stats_inc (wrk, to_closewait, 1);
960           break;
961         }
962
963       /* Send FIN either way and switch to LAST_ACK. */
964       tcp_cong_recovery_off (tc);
965       /* Make sure we don't try to send unsent data */
966       tc->snd_nxt = tc->snd_una;
967       tcp_send_fin (tc);
968       tcp_connection_set_state (tc, TCP_STATE_LAST_ACK);
969       session_transport_closed_notify (&tc->connection);
970
971       /* Make sure we don't wait in LAST ACK forever */
972       tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.lastack_time);
973       tcp_workerp_stats_inc (wrk, to_closewait2, 1);
974
975       /* Don't delete the connection yet */
976       break;
977     case TCP_STATE_FIN_WAIT_1:
978       tcp_connection_timers_reset (tc);
979       if (tc->flags & TCP_CONN_FINPNDG)
980         {
981           /* If FIN pending, we haven't sent everything, but we did try.
982            * Notify session layer that transport is closed. */
983           tcp_connection_set_state (tc, TCP_STATE_CLOSED);
984           tcp_send_reset (tc);
985           tcp_program_cleanup (wrk, tc);
986         }
987       else
988         {
989           /* We've sent the fin but no progress. Close the connection and
990            * to make sure everything is flushed, setup a cleanup timer */
991           tcp_connection_set_state (tc, TCP_STATE_CLOSED);
992           tcp_program_cleanup (wrk, tc);
993         }
994       session_transport_closed_notify (&tc->connection);
995       tcp_workerp_stats_inc (wrk, to_finwait1, 1);
996       break;
997     case TCP_STATE_LAST_ACK:
998       tcp_connection_timers_reset (tc);
999       tcp_connection_set_state (tc, TCP_STATE_CLOSED);
1000       session_transport_closed_notify (&tc->connection);
1001       tcp_program_cleanup (wrk, tc);
1002       tcp_workerp_stats_inc (wrk, to_lastack, 1);
1003       break;
1004     case TCP_STATE_CLOSING:
1005       tcp_connection_timers_reset (tc);
1006       tcp_connection_set_state (tc, TCP_STATE_CLOSED);
1007       session_transport_closed_notify (&tc->connection);
1008       tcp_program_cleanup (wrk, tc);
1009       tcp_workerp_stats_inc (wrk, to_closing, 1);
1010       break;
1011     case TCP_STATE_FIN_WAIT_2:
1012       tcp_send_reset (tc);
1013       tcp_connection_timers_reset (tc);
1014       tcp_connection_set_state (tc, TCP_STATE_CLOSED);
1015       session_transport_closed_notify (&tc->connection);
1016       tcp_program_cleanup (wrk, tc);
1017       tcp_workerp_stats_inc (wrk, to_finwait2, 1);
1018       break;
1019     case TCP_STATE_TIME_WAIT:
1020       tcp_connection_set_state (tc, TCP_STATE_CLOSED);
1021       tcp_program_cleanup (wrk, tc);
1022       break;
1023     default:
1024       clib_warning ("waitclose in state: %U", format_tcp_state, tc->state);
1025       break;
1026     }
1027 }
1028
1029 /* *INDENT-OFF* */
1030 static timer_expiration_handler *timer_expiration_handlers[TCP_N_TIMERS] =
1031 {
1032     tcp_timer_retransmit_handler,
1033     tcp_timer_delack_handler,
1034     tcp_timer_persist_handler,
1035     tcp_timer_waitclose_handler,
1036     tcp_timer_retransmit_syn_handler,
1037 };
1038 /* *INDENT-ON* */
1039
1040 static void
1041 tcp_dispatch_pending_timers (tcp_worker_ctx_t * wrk)
1042 {
1043   u32 n_timers, connection_index, timer_id, thread_index, timer_handle;
1044   tcp_connection_t *tc;
1045   int i;
1046
1047   if (!(n_timers = clib_fifo_elts (wrk->pending_timers)))
1048     return;
1049
1050   thread_index = wrk->vm->thread_index;
1051   for (i = 0; i < clib_min (n_timers, wrk->max_timers_per_loop); i++)
1052     {
1053       clib_fifo_sub1 (wrk->pending_timers, timer_handle);
1054       connection_index = timer_handle & 0x0FFFFFFF;
1055       timer_id = timer_handle >> 28;
1056
1057       if (PREDICT_TRUE (timer_id != TCP_TIMER_RETRANSMIT_SYN))
1058         tc = tcp_connection_get (connection_index, thread_index);
1059       else
1060         tc = tcp_half_open_connection_get (connection_index);
1061
1062       if (PREDICT_FALSE (!tc))
1063         continue;
1064
1065       /* Skip timer if it was rearmed while pending dispatch */
1066       if (PREDICT_FALSE (tc->timers[timer_id] != TCP_TIMER_HANDLE_INVALID))
1067         continue;
1068
1069       (*timer_expiration_handlers[timer_id]) (tc);
1070     }
1071
1072   if (thread_index == 0 && clib_fifo_elts (wrk->pending_timers))
1073     session_queue_run_on_main_thread (wrk->vm);
1074 }
1075
1076 static void
1077 tcp_handle_cleanups (tcp_worker_ctx_t * wrk, clib_time_type_t now)
1078 {
1079   u32 thread_index = wrk->vm->thread_index;
1080   tcp_cleanup_req_t *req;
1081   tcp_connection_t *tc;
1082
1083   while (clib_fifo_elts (wrk->pending_cleanups))
1084     {
1085       req = clib_fifo_head (wrk->pending_cleanups);
1086       if (req->free_time > now)
1087         break;
1088       clib_fifo_sub2 (wrk->pending_cleanups, req);
1089       tc = tcp_connection_get (req->connection_index, thread_index);
1090       if (PREDICT_FALSE (!tc))
1091         continue;
1092       session_transport_delete_notify (&tc->connection);
1093       tcp_connection_cleanup (tc);
1094     }
1095 }
1096
1097 static void
1098 tcp_update_time (f64 now, u8 thread_index)
1099 {
1100   tcp_worker_ctx_t *wrk = tcp_get_worker (thread_index);
1101
1102   tcp_set_time_now (wrk);
1103   tcp_handle_cleanups (wrk, now);
1104   tw_timer_expire_timers_16t_2w_512sl (&wrk->timer_wheel, now);
1105   tcp_dispatch_pending_timers (wrk);
1106 }
1107
1108 static void
1109 tcp_session_flush_data (transport_connection_t * tconn)
1110 {
1111   tcp_connection_t *tc = (tcp_connection_t *) tconn;
1112   if (tc->flags & TCP_CONN_PSH_PENDING)
1113     return;
1114   tc->flags |= TCP_CONN_PSH_PENDING;
1115   tc->psh_seq = tc->snd_una + transport_max_tx_dequeue (tconn) - 1;
1116 }
1117
1118 /* *INDENT-OFF* */
1119 const static transport_proto_vft_t tcp_proto = {
1120   .enable = vnet_tcp_enable_disable,
1121   .start_listen = tcp_session_bind,
1122   .stop_listen = tcp_session_unbind,
1123   .push_header = tcp_session_push_header,
1124   .get_connection = tcp_session_get_transport,
1125   .get_listener = tcp_session_get_listener,
1126   .get_half_open = tcp_half_open_session_get_transport,
1127   .connect = tcp_session_open,
1128   .close = tcp_session_close,
1129   .cleanup = tcp_session_cleanup,
1130   .reset = tcp_session_reset,
1131   .send_params = tcp_session_send_params,
1132   .update_time = tcp_update_time,
1133   .flush_data = tcp_session_flush_data,
1134   .custom_tx = tcp_session_custom_tx,
1135   .format_connection = format_tcp_session,
1136   .format_listener = format_tcp_listener_session,
1137   .format_half_open = format_tcp_half_open_session,
1138   .transport_options = {
1139     .name = "tcp",
1140     .short_name = "T",
1141     .tx_type = TRANSPORT_TX_PEEK,
1142     .service_type = TRANSPORT_SERVICE_VC,
1143   },
1144 };
1145 /* *INDENT-ON* */
1146
1147 void
1148 tcp_connection_tx_pacer_update (tcp_connection_t * tc)
1149 {
1150   if (!transport_connection_is_tx_paced (&tc->connection))
1151     return;
1152
1153   f64 srtt = clib_min ((f64) tc->srtt * TCP_TICK, tc->mrtt_us);
1154
1155   transport_connection_tx_pacer_update (&tc->connection,
1156                                         tcp_cc_get_pacing_rate (tc),
1157                                         srtt * CLIB_US_TIME_FREQ);
1158 }
1159
1160 void
1161 tcp_connection_tx_pacer_reset (tcp_connection_t * tc, u32 window,
1162                                u32 start_bucket)
1163 {
1164   f64 srtt = clib_min ((f64) tc->srtt * TCP_TICK, tc->mrtt_us);
1165   transport_connection_tx_pacer_reset (&tc->connection,
1166                                        tcp_cc_get_pacing_rate (tc),
1167                                        start_bucket,
1168                                        srtt * CLIB_US_TIME_FREQ);
1169 }
1170
1171 void
1172 tcp_reschedule (tcp_connection_t * tc)
1173 {
1174   if (tcp_in_cong_recovery (tc) || tcp_snd_space_inline (tc))
1175     transport_connection_reschedule (&tc->connection);
1176 }
1177
1178 static void
1179 tcp_expired_timers_dispatch (u32 * expired_timers)
1180 {
1181   u32 thread_index = vlib_get_thread_index (), n_left, max_per_loop;
1182   u32 connection_index, timer_id, n_expired, max_loops;
1183   tcp_worker_ctx_t *wrk;
1184   tcp_connection_t *tc;
1185   int i;
1186
1187   wrk = tcp_get_worker (thread_index);
1188   n_expired = vec_len (expired_timers);
1189   tcp_workerp_stats_inc (wrk, timer_expirations, n_expired);
1190   n_left = clib_fifo_elts (wrk->pending_timers);
1191
1192   /*
1193    * Invalidate all timer handles before dispatching. This avoids dangling
1194    * index references to timer wheel pool entries that have been freed.
1195    */
1196   for (i = 0; i < n_expired; i++)
1197     {
1198       connection_index = expired_timers[i] & 0x0FFFFFFF;
1199       timer_id = expired_timers[i] >> 28;
1200
1201       if (timer_id != TCP_TIMER_RETRANSMIT_SYN)
1202         tc = tcp_connection_get (connection_index, thread_index);
1203       else
1204         tc = tcp_half_open_connection_get (connection_index);
1205
1206       TCP_EVT (TCP_EVT_TIMER_POP, connection_index, timer_id);
1207
1208       tc->timers[timer_id] = TCP_TIMER_HANDLE_INVALID;
1209     }
1210
1211   clib_fifo_add (wrk->pending_timers, expired_timers, n_expired);
1212
1213   max_loops = clib_max (1, 0.5 * TCP_TIMER_TICK * wrk->vm->loops_per_second);
1214   max_per_loop = clib_max ((n_left + n_expired) / max_loops, 10);
1215   max_per_loop = clib_min (max_per_loop, VLIB_FRAME_SIZE);
1216   wrk->max_timers_per_loop = clib_max (n_left ? wrk->max_timers_per_loop : 0,
1217                                        max_per_loop);
1218
1219   if (thread_index == 0)
1220     session_queue_run_on_main_thread (wrk->vm);
1221 }
1222
1223 static void
1224 tcp_initialize_timer_wheels (tcp_main_t * tm)
1225 {
1226   tw_timer_wheel_16t_2w_512sl_t *tw;
1227   /* *INDENT-OFF* */
1228   foreach_vlib_main (({
1229     tw = &tm->wrk_ctx[ii].timer_wheel;
1230     tw_timer_wheel_init_16t_2w_512sl (tw, tcp_expired_timers_dispatch,
1231                                       TCP_TIMER_TICK, ~0);
1232     tw->last_run_time = vlib_time_now (this_vlib_main);
1233   }));
1234   /* *INDENT-ON* */
1235 }
1236
1237 static void
1238 tcp_initialize_iss_seed (tcp_main_t * tm)
1239 {
1240   u32 default_seed = random_default_seed ();
1241   u64 time_now = clib_cpu_time_now ();
1242
1243   tm->iss_seed.first = (u64) random_u32 (&default_seed) << 32;
1244   tm->iss_seed.second = random_u64 (&time_now);
1245 }
1246
1247 static clib_error_t *
1248 tcp_main_enable (vlib_main_t * vm)
1249 {
1250   vlib_thread_main_t *vtm = vlib_get_thread_main ();
1251   u32 num_threads, n_workers, prealloc_conn_per_wrk;
1252   tcp_connection_t *tc __attribute__ ((unused));
1253   tcp_main_t *tm = vnet_get_tcp_main ();
1254   tcp_worker_ctx_t *wrk;
1255   clib_error_t *error = 0;
1256   int thread;
1257
1258   if ((error = vlib_call_init_function (vm, ip_main_init)))
1259     return error;
1260   if ((error = vlib_call_init_function (vm, ip4_lookup_init)))
1261     return error;
1262   if ((error = vlib_call_init_function (vm, ip6_lookup_init)))
1263     return error;
1264
1265   /*
1266    * Registrations
1267    */
1268
1269   ip4_register_protocol (IP_PROTOCOL_TCP, tcp4_input_node.index);
1270   ip6_register_protocol (IP_PROTOCOL_TCP, tcp6_input_node.index);
1271
1272   /*
1273    * Initialize data structures
1274    */
1275
1276   num_threads = 1 /* main thread */  + vtm->n_threads;
1277   vec_validate (tm->wrk_ctx, num_threads - 1);
1278   n_workers = num_threads == 1 ? 1 : vtm->n_threads;
1279   prealloc_conn_per_wrk = tcp_cfg.preallocated_connections / n_workers;
1280
1281   wrk = &tm->wrk_ctx[0];
1282   wrk->tco_next_node[0] = vlib_node_get_next (vm, session_queue_node.index,
1283                                               tcp4_output_node.index);
1284   wrk->tco_next_node[1] = vlib_node_get_next (vm, session_queue_node.index,
1285                                               tcp6_output_node.index);
1286
1287   for (thread = 0; thread < num_threads; thread++)
1288     {
1289       wrk = &tm->wrk_ctx[thread];
1290
1291       vec_validate (wrk->pending_deq_acked, 255);
1292       vec_validate (wrk->pending_disconnects, 255);
1293       vec_validate (wrk->pending_resets, 255);
1294       vec_reset_length (wrk->pending_deq_acked);
1295       vec_reset_length (wrk->pending_disconnects);
1296       vec_reset_length (wrk->pending_resets);
1297       wrk->vm = vlib_mains[thread];
1298       wrk->max_timers_per_loop = 10;
1299
1300       if (thread > 0)
1301         {
1302           wrk->tco_next_node[0] = tm->wrk_ctx[0].tco_next_node[0];
1303           wrk->tco_next_node[1] = tm->wrk_ctx[0].tco_next_node[1];
1304         }
1305
1306       /*
1307        * Preallocate connections. Assume that thread 0 won't
1308        * use preallocated threads when running multi-core
1309        */
1310       if ((thread > 0 || num_threads == 1) && prealloc_conn_per_wrk)
1311         pool_init_fixed (wrk->connections, prealloc_conn_per_wrk);
1312     }
1313
1314   /*
1315    * Use a preallocated half-open connection pool?
1316    */
1317   if (tcp_cfg.preallocated_half_open_connections)
1318     pool_init_fixed (tm->half_open_connections,
1319                      tcp_cfg.preallocated_half_open_connections);
1320
1321   /* Initialize clocks per tick for TCP timestamp. Used to compute
1322    * monotonically increasing timestamps. */
1323   tm->tstamp_ticks_per_clock = vm->clib_time.seconds_per_clock
1324     / TCP_TSTAMP_RESOLUTION;
1325
1326   if (num_threads > 1)
1327     {
1328       clib_spinlock_init (&tm->half_open_lock);
1329     }
1330
1331   tcp_initialize_timer_wheels (tm);
1332   tcp_initialize_iss_seed (tm);
1333
1334   tm->bytes_per_buffer = vlib_buffer_get_default_data_size (vm);
1335   tm->cc_last_type = TCP_CC_LAST;
1336
1337   tm->ipl_next_node[0] = vlib_node_get_next (vm, session_queue_node.index,
1338                                              ip4_lookup_node.index);
1339   tm->ipl_next_node[1] = vlib_node_get_next (vm, session_queue_node.index,
1340                                              ip6_lookup_node.index);
1341   return error;
1342 }
1343
1344 clib_error_t *
1345 vnet_tcp_enable_disable (vlib_main_t * vm, u8 is_en)
1346 {
1347   if (is_en)
1348     {
1349       if (tcp_main.is_enabled)
1350         return 0;
1351
1352       return tcp_main_enable (vm);
1353     }
1354   else
1355     {
1356       tcp_main.is_enabled = 0;
1357     }
1358
1359   return 0;
1360 }
1361
1362 void
1363 tcp_punt_unknown (vlib_main_t * vm, u8 is_ip4, u8 is_add)
1364 {
1365   tcp_main_t *tm = &tcp_main;
1366   if (is_ip4)
1367     tm->punt_unknown4 = is_add;
1368   else
1369     tm->punt_unknown6 = is_add;
1370 }
1371
1372 /**
1373  * Initialize default values for tcp parameters
1374  */
1375 static void
1376 tcp_configuration_init (void)
1377 {
1378   /* Initial wnd for SYN. Fifos are not allocated at that point so use some
1379    * predefined value. For SYN-ACK we still want the scale to be computed in
1380    * the same way */
1381   tcp_cfg.max_rx_fifo = 32 << 20;
1382   tcp_cfg.min_rx_fifo = 4 << 10;
1383
1384   tcp_cfg.default_mtu = 1500;
1385   tcp_cfg.initial_cwnd_multiplier = 0;
1386   tcp_cfg.enable_tx_pacing = 1;
1387   tcp_cfg.allow_tso = 0;
1388   tcp_cfg.csum_offload = 1;
1389   tcp_cfg.cc_algo = TCP_CC_NEWRENO;
1390   tcp_cfg.rwnd_min_update_ack = 1;
1391
1392   /* Time constants defined as timer tick (100ms) multiples */
1393   tcp_cfg.delack_time = 1;      /* 0.1s */
1394   tcp_cfg.closewait_time = 20;  /* 2s */
1395   tcp_cfg.timewait_time = 100;  /* 10s */
1396   tcp_cfg.finwait1_time = 600;  /* 60s */
1397   tcp_cfg.lastack_time = 300;   /* 30s */
1398   tcp_cfg.finwait2_time = 300;  /* 30s */
1399   tcp_cfg.closing_time = 300;   /* 30s */
1400   tcp_cfg.cleanup_time = 0.1;   /* 100ms */
1401 }
1402
1403 static clib_error_t *
1404 tcp_init (vlib_main_t * vm)
1405 {
1406   tcp_main_t *tm = vnet_get_tcp_main ();
1407   ip_main_t *im = &ip_main;
1408   ip_protocol_info_t *pi;
1409
1410   /* Session layer, and by implication tcp, are disabled by default */
1411   tm->is_enabled = 0;
1412
1413   /* Register with IP for header parsing */
1414   pi = ip_get_protocol_info (im, IP_PROTOCOL_TCP);
1415   if (pi == 0)
1416     return clib_error_return (0, "TCP protocol info AWOL");
1417   pi->format_header = format_tcp_header;
1418   pi->unformat_pg_edit = unformat_pg_tcp_header;
1419
1420   /* Register as transport with session layer */
1421   transport_register_protocol (TRANSPORT_PROTO_TCP, &tcp_proto,
1422                                FIB_PROTOCOL_IP4, tcp4_output_node.index);
1423   transport_register_protocol (TRANSPORT_PROTO_TCP, &tcp_proto,
1424                                FIB_PROTOCOL_IP6, tcp6_output_node.index);
1425
1426   tcp_configuration_init ();
1427
1428   tm->cc_algo_by_name = hash_create_string (0, sizeof (uword));
1429
1430   return 0;
1431 }
1432
1433 VLIB_INIT_FUNCTION (tcp_init);
1434
1435 /*
1436  * fd.io coding-style-patch-verification: ON
1437  *
1438  * Local Variables:
1439  * eval: (c-set-style "gnu")
1440  * End:
1441  */