tcp: move features to separate files
[vpp.git] / src / vnet / tcp / tcp.h
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 #ifndef _vnet_tcp_h_
17 #define _vnet_tcp_h_
18
19 #include <vnet/vnet.h>
20 #include <vnet/ip/ip.h>
21 #include <vnet/session/session.h>
22 #include <vnet/tcp/tcp_types.h>
23 #include <vnet/tcp/tcp_timer.h>
24 #include <vnet/tcp/tcp_debug.h>
25 #include <vnet/tcp/tcp_sack.h>
26 #include <vnet/tcp/tcp_bt.h>
27 #include <vnet/tcp/tcp_cc.h>
28
29 typedef void (timer_expiration_handler) (tcp_connection_t * tc);
30
31 extern timer_expiration_handler tcp_timer_delack_handler;
32 extern timer_expiration_handler tcp_timer_retransmit_handler;
33 extern timer_expiration_handler tcp_timer_persist_handler;
34 extern timer_expiration_handler tcp_timer_retransmit_syn_handler;
35
36 typedef enum _tcp_error
37 {
38 #define tcp_error(n,s) TCP_ERROR_##n,
39 #include <vnet/tcp/tcp_error.def>
40 #undef tcp_error
41   TCP_N_ERROR,
42 } tcp_error_t;
43
44 typedef struct _tcp_lookup_dispatch
45 {
46   u8 next, error;
47 } tcp_lookup_dispatch_t;
48
49 #define foreach_tcp_wrk_stat                                    \
50   _(timer_expirations, u64, "timer expirations")                \
51   _(rxt_segs, u64, "segments retransmitted")                    \
52   _(tr_events, u32, "timer retransmit events")                  \
53   _(to_closewait, u32, "timeout close-wait")                    \
54   _(to_closewait2, u32, "timeout close-wait w/data")            \
55   _(to_finwait1, u32, "timeout fin-wait-1")                     \
56   _(to_finwait2, u32, "timeout fin-wait-2")                     \
57   _(to_lastack, u32, "timeout last-ack")                        \
58   _(to_closing, u32, "timeout closing")                         \
59   _(tr_abort, u32, "timer retransmit abort")                    \
60   _(rst_unread, u32, "reset on close due to unread data")       \
61
62 typedef struct tcp_wrk_stats_
63 {
64 #define _(name, type, str) type name;
65   foreach_tcp_wrk_stat
66 #undef _
67 } tcp_wrk_stats_t;
68
69 typedef struct tcp_free_req_
70 {
71   clib_time_type_t free_time;
72   u32 connection_index;
73 } tcp_cleanup_req_t;
74
75 typedef struct tcp_worker_ctx_
76 {
77   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
78
79   /** worker's pool of connections */
80   tcp_connection_t *connections;
81
82   /** vector of pending ack dequeues */
83   u32 *pending_deq_acked;
84
85   /** vector of pending disconnect notifications */
86   u32 *pending_disconnects;
87
88   /** vector of pending reset notifications */
89   u32 *pending_resets;
90
91   /** convenience pointer to this thread's vlib main */
92   vlib_main_t *vm;
93
94   /** worker time */
95   u32 time_now;
96
97   /* Max timers to be handled per dispatch loop */
98   u32 max_timers_per_loop;
99
100   /** Session layer edge indices to tcp output */
101   u32 tco_next_node[2];
102
103   /* Fifo of pending timer expirations */
104   u32 *pending_timers;
105
106     CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
107
108   /** cached 'on the wire' options for bursts */
109   u8 cached_opts[40];
110
111   /** tx buffer free list */
112   u32 *tx_buffers;
113
114   /* fifo of pending free requests */
115   tcp_cleanup_req_t *pending_cleanups;
116
117   /** worker timer wheel */
118   tw_timer_wheel_16t_2w_512sl_t timer_wheel;
119
120     CLIB_CACHE_LINE_ALIGN_MARK (cacheline2);
121
122   tcp_wrk_stats_t stats;
123 } tcp_worker_ctx_t;
124
125 #define tcp_worker_stats_inc(_ti,_stat,_val)            \
126   tcp_main.wrk_ctx[_ti].stats._stat += _val
127
128 #define tcp_workerp_stats_inc(_wrk,_stat,_val)          \
129   _wrk->stats._stat += _val
130
131 typedef struct tcp_iss_seed_
132 {
133   u64 first;
134   u64 second;
135 } tcp_iss_seed_t;
136
137 typedef struct tcp_configuration_
138 {
139   /** Max rx fifo size for a session (in bytes). It is used in to compute the
140    *  rfc 7323 window scaling factor */
141   u32 max_rx_fifo;
142
143   /** Min rx fifo for a session (in bytes) */
144   u32 min_rx_fifo;
145
146   /** Default MTU to be used when establishing connections */
147   u16 default_mtu;
148
149   /** Initial CWND multiplier, which multiplies MSS to determine initial CWND.
150    *  Set 0 to determine the initial CWND by another way */
151   u16 initial_cwnd_multiplier;
152
153   /** Enable tx pacing for new connections */
154   u8 enable_tx_pacing;
155
156   /** Allow use of TSO whenever available */
157   u8 allow_tso;
158
159   /** Set if csum offloading is enabled */
160   u8 csum_offload;
161
162   /** Default congestion control algorithm type */
163   tcp_cc_algorithm_type_e cc_algo;
164
165   /** Min rwnd, as number of snd_mss segments, for update ack to be sent after
166    * a zero rwnd advertisement */
167   u32 rwnd_min_update_ack;
168
169   /** Delayed ack time (disabled) */
170   u16 delack_time;
171
172   /** Timer ticks to wait for close from app */
173   u16 closewait_time;
174
175   /** Timer ticks to wait in time-wait. Also known as 2MSL */
176   u16 timewait_time;
177
178   /** Timer ticks to wait in fin-wait1 to send fin and rcv fin-ack */
179   u16 finwait1_time;
180
181   /** Timer ticks to wait in last ack for ack */
182   u16 lastack_time;
183
184   /** Timer ticks to wait in fin-wait2 for fin */
185   u16 finwait2_time;
186
187   /** Timer ticks to wait in closing for fin ack */
188   u16 closing_time;
189
190   /** Time to wait (sec) before cleaning up the connection */
191   f32 cleanup_time;
192
193   /** Number of preallocated connections */
194   u32 preallocated_connections;
195
196   /** Number of preallocated half-open connections */
197   u32 preallocated_half_open_connections;
198
199   /** Vectors of src addresses. Optional unless one needs > 63K active-opens */
200   ip4_address_t *ip4_src_addrs;
201   ip6_address_t *ip6_src_addrs;
202
203   /** Fault-injection. Debug only */
204   f64 buffer_fail_fraction;
205 } tcp_configuration_t;
206
207 typedef struct _tcp_main
208 {
209   /** per-worker context */
210   tcp_worker_ctx_t *wrk_ctx;
211
212   /* Pool of listeners. */
213   tcp_connection_t *listener_pool;
214
215   f64 tstamp_ticks_per_clock;
216
217   /** vlib buffer size */
218   u32 bytes_per_buffer;
219
220   /** Session layer edge indices to ip lookup (syns, rst) */
221   u32 ipl_next_node[2];
222
223   /** Dispatch table by state and flags */
224   tcp_lookup_dispatch_t dispatch_table[TCP_N_STATES][64];
225
226   clib_spinlock_t half_open_lock;
227
228   /** Pool of half-open connections on which we've sent a SYN */
229   tcp_connection_t *half_open_connections;
230
231   /** Seed used to generate random iss */
232   tcp_iss_seed_t iss_seed;
233
234   /** Congestion control algorithms registered */
235   tcp_cc_algorithm_t *cc_algos;
236
237   /** Hash table of cc algorithms by name */
238   uword *cc_algo_by_name;
239
240   /** Last cc algo registered */
241   tcp_cc_algorithm_type_e cc_last_type;
242
243   /** Flag that indicates if stack is on or off */
244   u8 is_enabled;
245
246   /** Flag that indicates if v4 punting is enabled */
247   u8 punt_unknown4;
248
249   /** Flag that indicates if v6 punting is enabled */
250   u8 punt_unknown6;
251
252   /** Rotor for v4 source addresses */
253   u32 last_v4_addr_rotor;
254
255   /** Rotor for v6 source addresses */
256   u32 last_v6_addr_rotor;
257
258   /** Protocol configuration */
259   tcp_configuration_t cfg;
260 } tcp_main_t;
261
262 extern tcp_main_t tcp_main;
263 extern vlib_node_registration_t tcp4_input_node;
264 extern vlib_node_registration_t tcp6_input_node;
265 extern vlib_node_registration_t tcp4_output_node;
266 extern vlib_node_registration_t tcp6_output_node;
267 extern vlib_node_registration_t tcp4_established_node;
268 extern vlib_node_registration_t tcp6_established_node;
269 extern vlib_node_registration_t tcp4_syn_sent_node;
270 extern vlib_node_registration_t tcp6_syn_sent_node;
271 extern vlib_node_registration_t tcp4_rcv_process_node;
272 extern vlib_node_registration_t tcp6_rcv_process_node;
273 extern vlib_node_registration_t tcp4_listen_node;
274 extern vlib_node_registration_t tcp6_listen_node;
275
276 #define tcp_cfg tcp_main.cfg
277 #define tcp_node_index(node_id, is_ip4)                                 \
278   ((is_ip4) ? tcp4_##node_id##_node.index : tcp6_##node_id##_node.index)
279
280 always_inline tcp_main_t *
281 vnet_get_tcp_main ()
282 {
283   return &tcp_main;
284 }
285
286 always_inline tcp_worker_ctx_t *
287 tcp_get_worker (u32 thread_index)
288 {
289   ASSERT (thread_index < vec_len (tcp_main.wrk_ctx));
290   return &tcp_main.wrk_ctx[thread_index];
291 }
292
293 #if (VLIB_BUFFER_TRACE_TRAJECTORY)
294 #define tcp_trajectory_add_start(b, start)                      \
295 {                                                               \
296     (*vlib_buffer_trace_trajectory_cb) (b, start);              \
297 }
298 #else
299 #define tcp_trajectory_add_start(b, start)
300 #endif
301
302 tcp_connection_t *tcp_connection_alloc (u8 thread_index);
303 tcp_connection_t *tcp_connection_alloc_w_base (u8 thread_index,
304                                                tcp_connection_t * base);
305 void tcp_connection_free (tcp_connection_t * tc);
306 void tcp_connection_close (tcp_connection_t * tc);
307 void tcp_connection_cleanup (tcp_connection_t * tc);
308 void tcp_connection_del (tcp_connection_t * tc);
309 int tcp_half_open_connection_cleanup (tcp_connection_t * tc);
310
311 void tcp_send_reset_w_pkt (tcp_connection_t * tc, vlib_buffer_t * pkt,
312                            u32 thread_index, u8 is_ip4);
313 void tcp_send_reset (tcp_connection_t * tc);
314 void tcp_send_syn (tcp_connection_t * tc);
315 void tcp_send_synack (tcp_connection_t * tc);
316 void tcp_send_fin (tcp_connection_t * tc);
317 void tcp_send_ack (tcp_connection_t * tc);
318 void tcp_send_window_update_ack (tcp_connection_t * tc);
319
320 void tcp_program_ack (tcp_connection_t * tc);
321 void tcp_program_dupack (tcp_connection_t * tc);
322 void tcp_program_retransmit (tcp_connection_t * tc);
323
324 void tcp_update_burst_snd_vars (tcp_connection_t * tc);
325 u32 tcp_snd_space (tcp_connection_t * tc);
326 int tcp_fastrecovery_prr_snd_space (tcp_connection_t * tc);
327 void tcp_reschedule (tcp_connection_t * tc);
328 fib_node_index_t tcp_lookup_rmt_in_fib (tcp_connection_t * tc);
329 u32 tcp_session_push_header (transport_connection_t * tconn,
330                              vlib_buffer_t * b);
331 int tcp_session_custom_tx (void *conn, u32 max_burst_size);
332
333 void tcp_connection_timers_init (tcp_connection_t * tc);
334 void tcp_connection_timers_reset (tcp_connection_t * tc);
335 void tcp_init_snd_vars (tcp_connection_t * tc);
336 void tcp_connection_init_vars (tcp_connection_t * tc);
337 void tcp_connection_tx_pacer_update (tcp_connection_t * tc);
338 void tcp_connection_tx_pacer_reset (tcp_connection_t * tc, u32 window,
339                                     u32 start_bucket);
340 void tcp_program_cleanup (tcp_worker_ctx_t * wrk, tcp_connection_t * tc);
341
342 void tcp_punt_unknown (vlib_main_t * vm, u8 is_ip4, u8 is_add);
343 int tcp_configure_v4_source_address_range (vlib_main_t * vm,
344                                            ip4_address_t * start,
345                                            ip4_address_t * end, u32 table_id);
346 int tcp_configure_v6_source_address_range (vlib_main_t * vm,
347                                            ip6_address_t * start,
348                                            ip6_address_t * end, u32 table_id);
349
350 clib_error_t *vnet_tcp_enable_disable (vlib_main_t * vm, u8 is_en);
351
352 format_function_t format_tcp_state;
353 format_function_t format_tcp_flags;
354 format_function_t format_tcp_sacks;
355 format_function_t format_tcp_rcv_sacks;
356 format_function_t format_tcp_connection;
357 format_function_t format_tcp_connection_id;
358
359 always_inline void
360 tcp_timer_set (tcp_connection_t * tc, u8 timer_id, u32 interval)
361 {
362   ASSERT (tc->c_thread_index == vlib_get_thread_index ());
363   ASSERT (tc->timers[timer_id] == TCP_TIMER_HANDLE_INVALID);
364   tc->timers[timer_id] =
365     tw_timer_start_16t_2w_512sl (&tcp_main.
366                                  wrk_ctx[tc->c_thread_index].timer_wheel,
367                                  tc->c_c_index, timer_id, interval);
368 }
369
370 always_inline void
371 tcp_timer_reset (tcp_connection_t * tc, u8 timer_id)
372 {
373   ASSERT (tc->c_thread_index == vlib_get_thread_index ());
374   if (tc->timers[timer_id] == TCP_TIMER_HANDLE_INVALID)
375     return;
376
377   tw_timer_stop_16t_2w_512sl (&tcp_main.
378                               wrk_ctx[tc->c_thread_index].timer_wheel,
379                               tc->timers[timer_id]);
380   tc->timers[timer_id] = TCP_TIMER_HANDLE_INVALID;
381 }
382
383 always_inline void
384 tcp_timer_update (tcp_connection_t * tc, u8 timer_id, u32 interval)
385 {
386   ASSERT (tc->c_thread_index == vlib_get_thread_index ());
387   if (tc->timers[timer_id] != TCP_TIMER_HANDLE_INVALID)
388     tw_timer_update_16t_2w_512sl (&tcp_main.
389                                   wrk_ctx[tc->c_thread_index].timer_wheel,
390                                   tc->timers[timer_id], interval);
391   else
392     tc->timers[timer_id] =
393       tw_timer_start_16t_2w_512sl (&tcp_main.
394                                    wrk_ctx[tc->c_thread_index].timer_wheel,
395                                    tc->c_c_index, timer_id, interval);
396 }
397
398 always_inline void
399 tcp_retransmit_timer_set (tcp_connection_t * tc)
400 {
401   ASSERT (tc->snd_una != tc->snd_una_max);
402   tcp_timer_set (tc, TCP_TIMER_RETRANSMIT,
403                  clib_max (tc->rto * TCP_TO_TIMER_TICK, 1));
404 }
405
406 always_inline void
407 tcp_retransmit_timer_reset (tcp_connection_t * tc)
408 {
409   tcp_timer_reset (tc, TCP_TIMER_RETRANSMIT);
410 }
411
412 always_inline void
413 tcp_retransmit_timer_force_update (tcp_connection_t * tc)
414 {
415   tcp_timer_update (tc, TCP_TIMER_RETRANSMIT,
416                     clib_max (tc->rto * TCP_TO_TIMER_TICK, 1));
417 }
418
419 always_inline void
420 tcp_persist_timer_set (tcp_connection_t * tc)
421 {
422   /* Reuse RTO. It's backed off in handler */
423   tcp_timer_set (tc, TCP_TIMER_PERSIST,
424                  clib_max (tc->rto * TCP_TO_TIMER_TICK, 1));
425 }
426
427 always_inline void
428 tcp_persist_timer_update (tcp_connection_t * tc)
429 {
430   u32 interval;
431
432   if (seq_leq (tc->snd_una, tc->snd_congestion + tc->burst_acked))
433     interval = 1;
434   else
435     interval = clib_max (tc->rto * TCP_TO_TIMER_TICK, 1);
436
437   tcp_timer_update (tc, TCP_TIMER_PERSIST, interval);
438 }
439
440 always_inline void
441 tcp_persist_timer_reset (tcp_connection_t * tc)
442 {
443   tcp_timer_reset (tc, TCP_TIMER_PERSIST);
444 }
445
446 always_inline void
447 tcp_retransmit_timer_update (tcp_connection_t * tc)
448 {
449   if (tc->snd_una == tc->snd_nxt)
450     {
451       tcp_retransmit_timer_reset (tc);
452       if (tc->snd_wnd < tc->snd_mss)
453         tcp_persist_timer_update (tc);
454     }
455   else
456     tcp_timer_update (tc, TCP_TIMER_RETRANSMIT,
457                       clib_max (tc->rto * TCP_TO_TIMER_TICK, 1));
458 }
459
460 always_inline u8
461 tcp_timer_is_active (tcp_connection_t * tc, tcp_timers_e timer)
462 {
463   return tc->timers[timer] != TCP_TIMER_HANDLE_INVALID;
464 }
465
466 #define tcp_validate_txf_size(_tc, _a)                                  \
467   ASSERT(_tc->state != TCP_STATE_ESTABLISHED                            \
468          || transport_max_tx_dequeue (&_tc->connection) >= _a)
469
470 #endif /* _vnet_tcp_h_ */
471
472 /*
473  * fd.io coding-style-patch-verification: ON
474  *
475  * Local Variables:
476  * eval: (c-set-style "gnu")
477  * End:
478  */