tcp: improve mss computation
[vpp.git] / src / vnet / tcp / tcp_output.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 #include <vnet/tcp/tcp.h>
17 #include <math.h>
18
19 typedef enum _tcp_output_next
20 {
21   TCP_OUTPUT_NEXT_DROP,
22   TCP_OUTPUT_NEXT_IP_LOOKUP,
23   TCP_OUTPUT_NEXT_IP_REWRITE,
24   TCP_OUTPUT_NEXT_IP_ARP,
25   TCP_OUTPUT_N_NEXT
26 } tcp_output_next_t;
27
28 #define foreach_tcp4_output_next                \
29   _ (DROP, "error-drop")                        \
30   _ (IP_LOOKUP, "ip4-lookup")                   \
31   _ (IP_REWRITE, "ip4-rewrite")                 \
32   _ (IP_ARP, "ip4-arp")
33
34 #define foreach_tcp6_output_next                \
35   _ (DROP, "error-drop")                        \
36   _ (IP_LOOKUP, "ip6-lookup")                   \
37   _ (IP_REWRITE, "ip6-rewrite")                 \
38   _ (IP_ARP, "ip6-discover-neighbor")
39
40 static char *tcp_error_strings[] = {
41 #define tcp_error(n,s) s,
42 #include <vnet/tcp/tcp_error.def>
43 #undef tcp_error
44 };
45
46 typedef struct
47 {
48   tcp_header_t tcp_header;
49   tcp_connection_t tcp_connection;
50 } tcp_tx_trace_t;
51
52 static u8 *
53 format_tcp_tx_trace (u8 * s, va_list * args)
54 {
55   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
56   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
57   tcp_tx_trace_t *t = va_arg (*args, tcp_tx_trace_t *);
58   u32 indent = format_get_indent (s);
59
60   s = format (s, "%U\n%U%U",
61               format_tcp_header, &t->tcp_header, 128,
62               format_white_space, indent,
63               format_tcp_connection, &t->tcp_connection, 1);
64
65   return s;
66 }
67
68 #ifndef CLIB_MARCH_VARIANT
69 static u8
70 tcp_window_compute_scale (u32 window)
71 {
72   u8 wnd_scale = 0;
73   while (wnd_scale < TCP_MAX_WND_SCALE && (window >> wnd_scale) > TCP_WND_MAX)
74     wnd_scale++;
75   return wnd_scale;
76 }
77
78 /**
79  * TCP's initial window
80  */
81 always_inline u32
82 tcp_initial_wnd_unscaled (tcp_connection_t * tc)
83 {
84   /* RFC 6928 recommends the value lower. However at the time our connections
85    * are initialized, fifos may not be allocated. Therefore, advertise the
86    * smallest possible unscaled window size and update once fifos are
87    * assigned to the session.
88    */
89   /*
90      tcp_update_rcv_mss (tc);
91      TCP_IW_N_SEGMENTS * tc->mss;
92    */
93   return tcp_cfg.min_rx_fifo;
94 }
95
96 /**
97  * Compute initial window and scale factor. As per RFC1323, window field in
98  * SYN and SYN-ACK segments is never scaled.
99  */
100 u32
101 tcp_initial_window_to_advertise (tcp_connection_t * tc)
102 {
103   /* Compute rcv wscale only if peer advertised support for it */
104   if (tc->state != TCP_STATE_SYN_RCVD || tcp_opts_wscale (&tc->rcv_opts))
105     tc->rcv_wscale = tcp_window_compute_scale (tcp_cfg.max_rx_fifo);
106
107   tc->rcv_wnd = tcp_initial_wnd_unscaled (tc);
108
109   return clib_min (tc->rcv_wnd, TCP_WND_MAX);
110 }
111
112 static inline void
113 tcp_update_rcv_wnd (tcp_connection_t * tc)
114 {
115   u32 available_space, wnd;
116   i32 observed_wnd;
117
118   ASSERT (tc->rcv_opts.mss < transport_rx_fifo_size (&tc->connection));
119
120   /*
121    * Figure out how much space we have available
122    */
123   available_space = transport_max_rx_enqueue (&tc->connection);
124   if (PREDICT_FALSE (available_space < tc->rcv_opts.mss))
125     available_space = 0;
126
127   /*
128    * Use the above and what we know about what we've previously advertised
129    * to compute the new window
130    */
131   observed_wnd = (i32) tc->rcv_wnd - (tc->rcv_nxt - tc->rcv_las);
132
133   /* Bad. Thou shalt not shrink */
134   if (PREDICT_FALSE ((i32) available_space < observed_wnd))
135     {
136       wnd = clib_max (observed_wnd, 0);
137       TCP_EVT (TCP_EVT_RCV_WND_SHRUNK, tc, observed_wnd, available_space);
138     }
139   else
140     {
141       wnd = available_space;
142     }
143
144   /* Make sure we have a multiple of rcv_wscale */
145   if (wnd && tc->rcv_wscale)
146     {
147       wnd &= ~((1 << tc->rcv_wscale) - 1);
148       if (wnd == 0)
149         wnd = 1 << tc->rcv_wscale;
150     }
151
152   tc->rcv_wnd = clib_min (wnd, TCP_WND_MAX << tc->rcv_wscale);
153 }
154
155 /**
156  * Compute and return window to advertise, scaled as per RFC1323
157  */
158 static inline u32
159 tcp_window_to_advertise (tcp_connection_t * tc, tcp_state_t state)
160 {
161   if (state < TCP_STATE_ESTABLISHED)
162     return tcp_initial_window_to_advertise (tc);
163
164   tcp_update_rcv_wnd (tc);
165   return tc->rcv_wnd >> tc->rcv_wscale;
166 }
167
168 /**
169  * Write TCP options to segment.
170  */
171 static u32
172 tcp_options_write (u8 * data, tcp_options_t * opts)
173 {
174   u32 opts_len = 0;
175   u32 buf, seq_len = 4;
176
177   if (tcp_opts_mss (opts))
178     {
179       *data++ = TCP_OPTION_MSS;
180       *data++ = TCP_OPTION_LEN_MSS;
181       buf = clib_host_to_net_u16 (opts->mss);
182       clib_memcpy_fast (data, &buf, sizeof (opts->mss));
183       data += sizeof (opts->mss);
184       opts_len += TCP_OPTION_LEN_MSS;
185     }
186
187   if (tcp_opts_wscale (opts))
188     {
189       *data++ = TCP_OPTION_WINDOW_SCALE;
190       *data++ = TCP_OPTION_LEN_WINDOW_SCALE;
191       *data++ = opts->wscale;
192       opts_len += TCP_OPTION_LEN_WINDOW_SCALE;
193     }
194
195   if (tcp_opts_sack_permitted (opts))
196     {
197       *data++ = TCP_OPTION_SACK_PERMITTED;
198       *data++ = TCP_OPTION_LEN_SACK_PERMITTED;
199       opts_len += TCP_OPTION_LEN_SACK_PERMITTED;
200     }
201
202   if (tcp_opts_tstamp (opts))
203     {
204       *data++ = TCP_OPTION_TIMESTAMP;
205       *data++ = TCP_OPTION_LEN_TIMESTAMP;
206       buf = clib_host_to_net_u32 (opts->tsval);
207       clib_memcpy_fast (data, &buf, sizeof (opts->tsval));
208       data += sizeof (opts->tsval);
209       buf = clib_host_to_net_u32 (opts->tsecr);
210       clib_memcpy_fast (data, &buf, sizeof (opts->tsecr));
211       data += sizeof (opts->tsecr);
212       opts_len += TCP_OPTION_LEN_TIMESTAMP;
213     }
214
215   if (tcp_opts_sack (opts))
216     {
217       int i;
218
219       if (opts->n_sack_blocks != 0)
220         {
221           *data++ = TCP_OPTION_SACK_BLOCK;
222           *data++ = 2 + opts->n_sack_blocks * TCP_OPTION_LEN_SACK_BLOCK;
223           for (i = 0; i < opts->n_sack_blocks; i++)
224             {
225               buf = clib_host_to_net_u32 (opts->sacks[i].start);
226               clib_memcpy_fast (data, &buf, seq_len);
227               data += seq_len;
228               buf = clib_host_to_net_u32 (opts->sacks[i].end);
229               clib_memcpy_fast (data, &buf, seq_len);
230               data += seq_len;
231             }
232           opts_len += 2 + opts->n_sack_blocks * TCP_OPTION_LEN_SACK_BLOCK;
233         }
234     }
235
236   /* Terminate TCP options */
237   if (opts_len % 4)
238     {
239       *data++ = TCP_OPTION_EOL;
240       opts_len += TCP_OPTION_LEN_EOL;
241     }
242
243   /* Pad with zeroes to a u32 boundary */
244   while (opts_len % 4)
245     {
246       *data++ = TCP_OPTION_NOOP;
247       opts_len += TCP_OPTION_LEN_NOOP;
248     }
249   return opts_len;
250 }
251
252 static int
253 tcp_make_syn_options (tcp_connection_t * tc, tcp_options_t * opts)
254 {
255   u8 len = 0;
256
257   opts->flags |= TCP_OPTS_FLAG_MSS;
258   opts->mss = tc->mss;
259   len += TCP_OPTION_LEN_MSS;
260
261   opts->flags |= TCP_OPTS_FLAG_WSCALE;
262   opts->wscale = tc->rcv_wscale;
263   len += TCP_OPTION_LEN_WINDOW_SCALE;
264
265   opts->flags |= TCP_OPTS_FLAG_TSTAMP;
266   opts->tsval = tcp_time_now ();
267   opts->tsecr = 0;
268   len += TCP_OPTION_LEN_TIMESTAMP;
269
270   if (TCP_USE_SACKS)
271     {
272       opts->flags |= TCP_OPTS_FLAG_SACK_PERMITTED;
273       len += TCP_OPTION_LEN_SACK_PERMITTED;
274     }
275
276   /* Align to needed boundary */
277   len += (TCP_OPTS_ALIGN - len % TCP_OPTS_ALIGN) % TCP_OPTS_ALIGN;
278   return len;
279 }
280
281 static int
282 tcp_make_synack_options (tcp_connection_t * tc, tcp_options_t * opts)
283 {
284   u8 len = 0;
285
286   opts->flags |= TCP_OPTS_FLAG_MSS;
287   opts->mss = tc->mss;
288   len += TCP_OPTION_LEN_MSS;
289
290   if (tcp_opts_wscale (&tc->rcv_opts))
291     {
292       opts->flags |= TCP_OPTS_FLAG_WSCALE;
293       opts->wscale = tc->rcv_wscale;
294       len += TCP_OPTION_LEN_WINDOW_SCALE;
295     }
296
297   if (tcp_opts_tstamp (&tc->rcv_opts))
298     {
299       opts->flags |= TCP_OPTS_FLAG_TSTAMP;
300       opts->tsval = tcp_time_now ();
301       opts->tsecr = tc->tsval_recent;
302       len += TCP_OPTION_LEN_TIMESTAMP;
303     }
304
305   if (tcp_opts_sack_permitted (&tc->rcv_opts))
306     {
307       opts->flags |= TCP_OPTS_FLAG_SACK_PERMITTED;
308       len += TCP_OPTION_LEN_SACK_PERMITTED;
309     }
310
311   /* Align to needed boundary */
312   len += (TCP_OPTS_ALIGN - len % TCP_OPTS_ALIGN) % TCP_OPTS_ALIGN;
313   return len;
314 }
315
316 static int
317 tcp_make_established_options (tcp_connection_t * tc, tcp_options_t * opts)
318 {
319   u8 len = 0;
320
321   opts->flags = 0;
322
323   if (tcp_opts_tstamp (&tc->rcv_opts))
324     {
325       opts->flags |= TCP_OPTS_FLAG_TSTAMP;
326       opts->tsval = tcp_tstamp (tc);
327       opts->tsecr = tc->tsval_recent;
328       len += TCP_OPTION_LEN_TIMESTAMP;
329     }
330   if (tcp_opts_sack_permitted (&tc->rcv_opts))
331     {
332       if (vec_len (tc->snd_sacks))
333         {
334           opts->flags |= TCP_OPTS_FLAG_SACK;
335           if (tc->snd_sack_pos >= vec_len (tc->snd_sacks))
336             tc->snd_sack_pos = 0;
337           opts->sacks = &tc->snd_sacks[tc->snd_sack_pos];
338           opts->n_sack_blocks = vec_len (tc->snd_sacks) - tc->snd_sack_pos;
339           opts->n_sack_blocks = clib_min (opts->n_sack_blocks,
340                                           TCP_OPTS_MAX_SACK_BLOCKS);
341           tc->snd_sack_pos += opts->n_sack_blocks;
342           len += 2 + TCP_OPTION_LEN_SACK_BLOCK * opts->n_sack_blocks;
343         }
344     }
345
346   /* Align to needed boundary */
347   len += (TCP_OPTS_ALIGN - len % TCP_OPTS_ALIGN) % TCP_OPTS_ALIGN;
348   return len;
349 }
350
351 always_inline int
352 tcp_make_options (tcp_connection_t * tc, tcp_options_t * opts,
353                   tcp_state_t state)
354 {
355   switch (state)
356     {
357     case TCP_STATE_ESTABLISHED:
358     case TCP_STATE_CLOSE_WAIT:
359     case TCP_STATE_FIN_WAIT_1:
360     case TCP_STATE_LAST_ACK:
361     case TCP_STATE_CLOSING:
362     case TCP_STATE_FIN_WAIT_2:
363     case TCP_STATE_TIME_WAIT:
364     case TCP_STATE_CLOSED:
365       return tcp_make_established_options (tc, opts);
366     case TCP_STATE_SYN_RCVD:
367       return tcp_make_synack_options (tc, opts);
368     case TCP_STATE_SYN_SENT:
369       return tcp_make_syn_options (tc, opts);
370     default:
371       clib_warning ("State not handled! %d", state);
372       return 0;
373     }
374 }
375
376 /**
377  * Update burst send vars
378  *
379  * - Updates snd_mss to reflect the effective segment size that we can send
380  * by taking into account all TCP options, including SACKs.
381  * - Cache 'on the wire' options for reuse
382  * - Updates receive window which can be reused for a burst.
383  *
384  * This should *only* be called when doing bursts
385  */
386 void
387 tcp_update_burst_snd_vars (tcp_connection_t * tc)
388 {
389   tcp_main_t *tm = &tcp_main;
390
391   /* Compute options to be used for connection. These may be reused when
392    * sending data or to compute the effective mss (snd_mss) */
393   tc->snd_opts_len = tcp_make_options (tc, &tc->snd_opts,
394                                        TCP_STATE_ESTABLISHED);
395
396   /* XXX check if MTU has been updated */
397   tc->snd_mss = clib_min (tc->mss, tc->rcv_opts.mss) - tc->snd_opts_len;
398   ASSERT (tc->snd_mss > 0);
399
400   tcp_options_write (tm->wrk_ctx[tc->c_thread_index].cached_opts,
401                      &tc->snd_opts);
402
403   tcp_update_rcv_wnd (tc);
404
405   if (tc->flags & TCP_CONN_RATE_SAMPLE)
406     tc->flags |= TCP_CONN_TRACK_BURST;
407
408   if (tc->snd_una == tc->snd_nxt)
409     tcp_cc_event (tc, TCP_CC_EVT_START_TX);
410 }
411
412 #endif /* CLIB_MARCH_VARIANT */
413
414 static void *
415 tcp_reuse_buffer (vlib_main_t * vm, vlib_buffer_t * b)
416 {
417   if (b->flags & VLIB_BUFFER_NEXT_PRESENT)
418     vlib_buffer_free_one (vm, b->next_buffer);
419   /* Zero all flags but free list index and trace flag */
420   b->flags &= VLIB_BUFFER_NEXT_PRESENT - 1;
421   b->current_data = 0;
422   b->current_length = 0;
423   b->total_length_not_including_first_buffer = 0;
424   vnet_buffer (b)->tcp.flags = 0;
425
426   /* Leave enough space for headers */
427   return vlib_buffer_make_headroom (b, TRANSPORT_MAX_HDRS_LEN);
428 }
429
430 #ifndef CLIB_MARCH_VARIANT
431 static void *
432 tcp_init_buffer (vlib_main_t * vm, vlib_buffer_t * b)
433 {
434   ASSERT ((b->flags & VLIB_BUFFER_NEXT_PRESENT) == 0);
435   b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
436   b->total_length_not_including_first_buffer = 0;
437   b->current_data = 0;
438   vnet_buffer (b)->tcp.flags = 0;
439   VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b);
440   /* Leave enough space for headers */
441   return vlib_buffer_make_headroom (b, TRANSPORT_MAX_HDRS_LEN);
442 }
443
444 /**
445  * Prepare ACK
446  */
447 static inline void
448 tcp_make_ack_i (tcp_connection_t * tc, vlib_buffer_t * b, tcp_state_t state,
449                 u8 flags)
450 {
451   tcp_options_t _snd_opts, *snd_opts = &_snd_opts;
452   u8 tcp_opts_len, tcp_hdr_opts_len;
453   tcp_header_t *th;
454   u16 wnd;
455
456   wnd = tcp_window_to_advertise (tc, state);
457
458   /* Make and write options */
459   tcp_opts_len = tcp_make_established_options (tc, snd_opts);
460   tcp_hdr_opts_len = tcp_opts_len + sizeof (tcp_header_t);
461
462   th = vlib_buffer_push_tcp (b, tc->c_lcl_port, tc->c_rmt_port, tc->snd_nxt,
463                              tc->rcv_nxt, tcp_hdr_opts_len, flags, wnd);
464
465   tcp_options_write ((u8 *) (th + 1), snd_opts);
466   vnet_buffer (b)->tcp.connection_index = tc->c_c_index;
467
468   if (wnd == 0)
469     tcp_zero_rwnd_sent_on (tc);
470   else
471     tcp_zero_rwnd_sent_off (tc);
472 }
473
474 /**
475  * Convert buffer to ACK
476  */
477 static inline void
478 tcp_make_ack (tcp_connection_t * tc, vlib_buffer_t * b)
479 {
480   tcp_make_ack_i (tc, b, TCP_STATE_ESTABLISHED, TCP_FLAG_ACK);
481   TCP_EVT (TCP_EVT_ACK_SENT, tc);
482   tc->rcv_las = tc->rcv_nxt;
483 }
484
485 /**
486  * Convert buffer to FIN-ACK
487  */
488 void
489 tcp_make_fin (tcp_connection_t * tc, vlib_buffer_t * b)
490 {
491   tcp_make_ack_i (tc, b, TCP_STATE_ESTABLISHED, TCP_FLAG_FIN | TCP_FLAG_ACK);
492 }
493
494 /**
495  * Convert buffer to SYN
496  */
497 void
498 tcp_make_syn (tcp_connection_t * tc, vlib_buffer_t * b)
499 {
500   u8 tcp_hdr_opts_len, tcp_opts_len;
501   tcp_header_t *th;
502   u16 initial_wnd;
503   tcp_options_t snd_opts;
504
505   initial_wnd = tcp_initial_window_to_advertise (tc);
506
507   /* Make and write options */
508   clib_memset (&snd_opts, 0, sizeof (snd_opts));
509   tcp_opts_len = tcp_make_syn_options (tc, &snd_opts);
510   tcp_hdr_opts_len = tcp_opts_len + sizeof (tcp_header_t);
511
512   th = vlib_buffer_push_tcp (b, tc->c_lcl_port, tc->c_rmt_port, tc->iss,
513                              tc->rcv_nxt, tcp_hdr_opts_len, TCP_FLAG_SYN,
514                              initial_wnd);
515   vnet_buffer (b)->tcp.connection_index = tc->c_c_index;
516   tcp_options_write ((u8 *) (th + 1), &snd_opts);
517 }
518
519 /**
520  * Convert buffer to SYN-ACK
521  */
522 void
523 tcp_make_synack (tcp_connection_t * tc, vlib_buffer_t * b)
524 {
525   tcp_options_t _snd_opts, *snd_opts = &_snd_opts;
526   u8 tcp_opts_len, tcp_hdr_opts_len;
527   tcp_header_t *th;
528   u16 initial_wnd;
529
530   clib_memset (snd_opts, 0, sizeof (*snd_opts));
531   initial_wnd = tcp_initial_window_to_advertise (tc);
532   tcp_opts_len = tcp_make_synack_options (tc, snd_opts);
533   tcp_hdr_opts_len = tcp_opts_len + sizeof (tcp_header_t);
534
535   th = vlib_buffer_push_tcp (b, tc->c_lcl_port, tc->c_rmt_port, tc->iss,
536                              tc->rcv_nxt, tcp_hdr_opts_len,
537                              TCP_FLAG_SYN | TCP_FLAG_ACK, initial_wnd);
538   tcp_options_write ((u8 *) (th + 1), snd_opts);
539
540   vnet_buffer (b)->tcp.connection_index = tc->c_c_index;
541 }
542
543 always_inline void
544 tcp_enqueue_to_ip_lookup_i (tcp_worker_ctx_t * wrk, vlib_buffer_t * b, u32 bi,
545                             u8 is_ip4, u32 fib_index, u8 flush)
546 {
547   vlib_main_t *vm = wrk->vm;
548   u32 *to_next, next_index;
549   vlib_frame_t *f;
550
551   b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
552   b->error = 0;
553
554   vnet_buffer (b)->sw_if_index[VLIB_TX] = fib_index;
555   vnet_buffer (b)->sw_if_index[VLIB_RX] = 0;
556
557   /* Send to IP lookup */
558   next_index = is_ip4 ? ip4_lookup_node.index : ip6_lookup_node.index;
559   tcp_trajectory_add_start (b, 1);
560
561   f = wrk->ip_lookup_tx_frames[!is_ip4];
562   if (!f)
563     {
564       f = vlib_get_frame_to_node (vm, next_index);
565       ASSERT (f);
566       wrk->ip_lookup_tx_frames[!is_ip4] = f;
567     }
568
569   to_next = vlib_frame_vector_args (f);
570   to_next[f->n_vectors] = bi;
571   f->n_vectors += 1;
572   if (flush || f->n_vectors == VLIB_FRAME_SIZE)
573     {
574       vlib_put_frame_to_node (vm, next_index, f);
575       wrk->ip_lookup_tx_frames[!is_ip4] = 0;
576     }
577 }
578
579 static void
580 tcp_enqueue_to_ip_lookup_now (tcp_worker_ctx_t * wrk, vlib_buffer_t * b,
581                               u32 bi, u8 is_ip4, u32 fib_index)
582 {
583   tcp_enqueue_to_ip_lookup_i (wrk, b, bi, is_ip4, fib_index, 1);
584 }
585
586 static void
587 tcp_enqueue_to_ip_lookup (tcp_worker_ctx_t * wrk, vlib_buffer_t * b, u32 bi,
588                           u8 is_ip4, u32 fib_index)
589 {
590   tcp_enqueue_to_ip_lookup_i (wrk, b, bi, is_ip4, fib_index, 0);
591   if (wrk->vm->thread_index == 0 && vlib_num_workers ())
592     session_flush_frames_main_thread (wrk->vm);
593 }
594
595 always_inline void
596 tcp_enqueue_to_output_i (tcp_worker_ctx_t * wrk, vlib_buffer_t * b, u32 bi,
597                          u8 is_ip4, u8 flush)
598 {
599   u32 *to_next, next_index;
600   vlib_frame_t *f;
601
602   b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
603   b->error = 0;
604
605   /* Decide where to send the packet */
606   next_index = is_ip4 ? tcp4_output_node.index : tcp6_output_node.index;
607   tcp_trajectory_add_start (b, 2);
608
609   /* Get frame to v4/6 output node */
610   f = wrk->tx_frames[!is_ip4];
611   if (!f)
612     {
613       f = vlib_get_frame_to_node (wrk->vm, next_index);
614       ASSERT (f);
615       wrk->tx_frames[!is_ip4] = f;
616     }
617   to_next = vlib_frame_vector_args (f);
618   to_next[f->n_vectors] = bi;
619   f->n_vectors += 1;
620   if (flush || f->n_vectors == VLIB_FRAME_SIZE)
621     {
622       vlib_put_frame_to_node (wrk->vm, next_index, f);
623       wrk->tx_frames[!is_ip4] = 0;
624     }
625 }
626
627 static void
628 tcp_enqueue_to_output (tcp_worker_ctx_t * wrk, vlib_buffer_t * b, u32 bi,
629                        u8 is_ip4)
630 {
631   tcp_enqueue_to_output_i (wrk, b, bi, is_ip4, 0);
632 }
633
634 static void
635 tcp_enqueue_to_output_now (tcp_worker_ctx_t * wrk, vlib_buffer_t * b, u32 bi,
636                            u8 is_ip4)
637 {
638   tcp_enqueue_to_output_i (wrk, b, bi, is_ip4, 1);
639 }
640 #endif /* CLIB_MARCH_VARIANT */
641
642 static int
643 tcp_make_reset_in_place (vlib_main_t * vm, vlib_buffer_t * b0,
644                          tcp_state_t state, u8 thread_index, u8 is_ip4)
645 {
646   ip4_header_t *ih4;
647   ip6_header_t *ih6;
648   tcp_header_t *th0;
649   ip4_address_t src_ip40, dst_ip40;
650   ip6_address_t src_ip60, dst_ip60;
651   u16 src_port, dst_port;
652   u32 tmp;
653   u32 seq, ack;
654   u8 flags;
655
656   /* Find IP and TCP headers */
657   th0 = tcp_buffer_hdr (b0);
658
659   /* Save src and dst ip */
660   if (is_ip4)
661     {
662       ih4 = vlib_buffer_get_current (b0);
663       ASSERT ((ih4->ip_version_and_header_length & 0xF0) == 0x40);
664       src_ip40.as_u32 = ih4->src_address.as_u32;
665       dst_ip40.as_u32 = ih4->dst_address.as_u32;
666     }
667   else
668     {
669       ih6 = vlib_buffer_get_current (b0);
670       ASSERT ((ih6->ip_version_traffic_class_and_flow_label & 0xF0) == 0x60);
671       clib_memcpy_fast (&src_ip60, &ih6->src_address, sizeof (ip6_address_t));
672       clib_memcpy_fast (&dst_ip60, &ih6->dst_address, sizeof (ip6_address_t));
673     }
674
675   src_port = th0->src_port;
676   dst_port = th0->dst_port;
677
678   /* Try to determine what/why we're actually resetting */
679   if (state == TCP_STATE_CLOSED)
680     {
681       if (!tcp_syn (th0))
682         return -1;
683
684       tmp = clib_net_to_host_u32 (th0->seq_number);
685
686       /* Got a SYN for no listener. */
687       flags = TCP_FLAG_RST | TCP_FLAG_ACK;
688       ack = clib_host_to_net_u32 (tmp + 1);
689       seq = 0;
690     }
691   else
692     {
693       flags = TCP_FLAG_RST;
694       seq = th0->ack_number;
695       ack = 0;
696     }
697
698   tcp_reuse_buffer (vm, b0);
699   tcp_trajectory_add_start (b0, 4);
700   th0 = vlib_buffer_push_tcp_net_order (b0, dst_port, src_port, seq, ack,
701                                         sizeof (tcp_header_t), flags, 0);
702
703   if (is_ip4)
704     {
705       ih4 = vlib_buffer_push_ip4 (vm, b0, &dst_ip40, &src_ip40,
706                                   IP_PROTOCOL_TCP, 1);
707       th0->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ih4);
708     }
709   else
710     {
711       int bogus = ~0;
712       ih6 = vlib_buffer_push_ip6 (vm, b0, &dst_ip60, &src_ip60,
713                                   IP_PROTOCOL_TCP);
714       th0->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b0, ih6, &bogus);
715       ASSERT (!bogus);
716     }
717
718   return 0;
719 }
720
721 #ifndef CLIB_MARCH_VARIANT
722 /**
723  *  Send reset without reusing existing buffer
724  *
725  *  It extracts connection info out of original packet
726  */
727 void
728 tcp_send_reset_w_pkt (tcp_connection_t * tc, vlib_buffer_t * pkt,
729                       u32 thread_index, u8 is_ip4)
730 {
731   tcp_worker_ctx_t *wrk = tcp_get_worker (thread_index);
732   vlib_main_t *vm = wrk->vm;
733   vlib_buffer_t *b;
734   u32 bi, sw_if_index, fib_index;
735   u8 tcp_hdr_len, flags = 0;
736   tcp_header_t *th, *pkt_th;
737   u32 seq, ack;
738   ip4_header_t *ih4, *pkt_ih4;
739   ip6_header_t *ih6, *pkt_ih6;
740   fib_protocol_t fib_proto;
741
742   if (PREDICT_FALSE (!vlib_buffer_alloc (vm, &bi, 1)))
743     return;
744
745   b = vlib_get_buffer (vm, bi);
746   sw_if_index = vnet_buffer (pkt)->sw_if_index[VLIB_RX];
747   fib_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
748   fib_index = fib_table_get_index_for_sw_if_index (fib_proto, sw_if_index);
749   tcp_init_buffer (vm, b);
750
751   /* Make and write options */
752   tcp_hdr_len = sizeof (tcp_header_t);
753
754   if (is_ip4)
755     {
756       pkt_ih4 = vlib_buffer_get_current (pkt);
757       pkt_th = ip4_next_header (pkt_ih4);
758     }
759   else
760     {
761       pkt_ih6 = vlib_buffer_get_current (pkt);
762       pkt_th = ip6_next_header (pkt_ih6);
763     }
764
765   if (tcp_ack (pkt_th))
766     {
767       flags = TCP_FLAG_RST;
768       seq = pkt_th->ack_number;
769       ack = (tc->state >= TCP_STATE_SYN_RCVD) ? tc->rcv_nxt : 0;
770     }
771   else
772     {
773       flags = TCP_FLAG_RST | TCP_FLAG_ACK;
774       seq = 0;
775       ack = clib_host_to_net_u32 (vnet_buffer (pkt)->tcp.seq_end);
776     }
777
778   th = vlib_buffer_push_tcp_net_order (b, pkt_th->dst_port, pkt_th->src_port,
779                                        seq, ack, tcp_hdr_len, flags, 0);
780
781   /* Swap src and dst ip */
782   if (is_ip4)
783     {
784       ASSERT ((pkt_ih4->ip_version_and_header_length & 0xF0) == 0x40);
785       ih4 = vlib_buffer_push_ip4 (vm, b, &pkt_ih4->dst_address,
786                                   &pkt_ih4->src_address, IP_PROTOCOL_TCP, 1);
787       th->checksum = ip4_tcp_udp_compute_checksum (vm, b, ih4);
788     }
789   else
790     {
791       int bogus = ~0;
792       ASSERT ((pkt_ih6->ip_version_traffic_class_and_flow_label & 0xF0) ==
793               0x60);
794       ih6 = vlib_buffer_push_ip6 (vm, b, &pkt_ih6->dst_address,
795                                   &pkt_ih6->src_address, IP_PROTOCOL_TCP);
796       th->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b, ih6, &bogus);
797       ASSERT (!bogus);
798     }
799
800   tcp_enqueue_to_ip_lookup_now (wrk, b, bi, is_ip4, fib_index);
801   TCP_EVT (TCP_EVT_RST_SENT, tc);
802   vlib_node_increment_counter (vm, tcp_node_index (output, tc->c_is_ip4),
803                                TCP_ERROR_RST_SENT, 1);
804 }
805
806 /**
807  * Build and set reset packet for connection
808  */
809 void
810 tcp_send_reset (tcp_connection_t * tc)
811 {
812   tcp_worker_ctx_t *wrk = tcp_get_worker (tc->c_thread_index);
813   vlib_main_t *vm = wrk->vm;
814   vlib_buffer_t *b;
815   u32 bi;
816   tcp_header_t *th;
817   u16 tcp_hdr_opts_len, advertise_wnd, opts_write_len;
818   u8 flags;
819
820   if (PREDICT_FALSE (!vlib_buffer_alloc (vm, &bi, 1)))
821     return;
822   b = vlib_get_buffer (vm, bi);
823   tcp_init_buffer (vm, b);
824
825   tc->snd_opts_len = tcp_make_options (tc, &tc->snd_opts, tc->state);
826   tcp_hdr_opts_len = tc->snd_opts_len + sizeof (tcp_header_t);
827   advertise_wnd = tcp_window_to_advertise (tc, TCP_STATE_ESTABLISHED);
828   flags = TCP_FLAG_RST;
829   th = vlib_buffer_push_tcp (b, tc->c_lcl_port, tc->c_rmt_port, tc->snd_nxt,
830                              tc->rcv_nxt, tcp_hdr_opts_len, flags,
831                              advertise_wnd);
832   opts_write_len = tcp_options_write ((u8 *) (th + 1), &tc->snd_opts);
833   ASSERT (opts_write_len == tc->snd_opts_len);
834   vnet_buffer (b)->tcp.connection_index = tc->c_c_index;
835   tcp_enqueue_to_output (wrk, b, bi, tc->c_is_ip4);
836   TCP_EVT (TCP_EVT_RST_SENT, tc);
837   vlib_node_increment_counter (vm, tcp_node_index (output, tc->c_is_ip4),
838                                TCP_ERROR_RST_SENT, 1);
839 }
840
841 static void
842 tcp_push_ip_hdr (tcp_worker_ctx_t * wrk, tcp_connection_t * tc,
843                  vlib_buffer_t * b)
844 {
845   tcp_header_t *th = vlib_buffer_get_current (b);
846   vlib_main_t *vm = wrk->vm;
847   if (tc->c_is_ip4)
848     {
849       ip4_header_t *ih;
850       ih = vlib_buffer_push_ip4 (vm, b, &tc->c_lcl_ip4,
851                                  &tc->c_rmt_ip4, IP_PROTOCOL_TCP, 1);
852       th->checksum = ip4_tcp_udp_compute_checksum (vm, b, ih);
853     }
854   else
855     {
856       ip6_header_t *ih;
857       int bogus = ~0;
858
859       ih = vlib_buffer_push_ip6 (vm, b, &tc->c_lcl_ip6,
860                                  &tc->c_rmt_ip6, IP_PROTOCOL_TCP);
861       th->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b, ih, &bogus);
862       ASSERT (!bogus);
863     }
864 }
865
866 /**
867  *  Send SYN
868  *
869  *  Builds a SYN packet for a half-open connection and sends it to ipx_lookup.
870  *  The packet is not forwarded through tcpx_output to avoid doing lookups
871  *  in the half_open pool.
872  */
873 void
874 tcp_send_syn (tcp_connection_t * tc)
875 {
876   tcp_worker_ctx_t *wrk = tcp_get_worker (tc->c_thread_index);
877   vlib_main_t *vm = wrk->vm;
878   vlib_buffer_t *b;
879   u32 bi;
880
881   /*
882    * Setup retransmit and establish timers before requesting buffer
883    * such that we can return if we've ran out.
884    */
885   tcp_timer_update (tc, TCP_TIMER_RETRANSMIT_SYN,
886                     tc->rto * TCP_TO_TIMER_TICK);
887
888   if (PREDICT_FALSE (!vlib_buffer_alloc (vm, &bi, 1)))
889     {
890       tcp_timer_update (tc, TCP_TIMER_RETRANSMIT_SYN, 1);
891       return;
892     }
893
894   b = vlib_get_buffer (vm, bi);
895   tcp_init_buffer (vm, b);
896   tcp_make_syn (tc, b);
897
898   /* Measure RTT with this */
899   tc->rtt_ts = tcp_time_now_us (vlib_num_workers ()? 1 : 0);
900   tc->rtt_seq = tc->snd_nxt;
901   tc->rto_boff = 0;
902
903   tcp_push_ip_hdr (wrk, tc, b);
904   tcp_enqueue_to_ip_lookup (wrk, b, bi, tc->c_is_ip4, tc->c_fib_index);
905   TCP_EVT (TCP_EVT_SYN_SENT, tc);
906 }
907
908 void
909 tcp_send_synack (tcp_connection_t * tc)
910 {
911   tcp_worker_ctx_t *wrk = tcp_get_worker (tc->c_thread_index);
912   vlib_main_t *vm = wrk->vm;
913   vlib_buffer_t *b;
914   u32 bi;
915
916   tcp_retransmit_timer_force_update (tc);
917
918   if (PREDICT_FALSE (!vlib_buffer_alloc (vm, &bi, 1)))
919     {
920       tcp_timer_update (tc, TCP_TIMER_RETRANSMIT, 1);
921       return;
922     }
923
924   tc->rtt_ts = tcp_time_now_us (tc->c_thread_index);
925   b = vlib_get_buffer (vm, bi);
926   tcp_init_buffer (vm, b);
927   tcp_make_synack (tc, b);
928   tcp_enqueue_to_output (wrk, b, bi, tc->c_is_ip4);
929   TCP_EVT (TCP_EVT_SYNACK_SENT, tc);
930 }
931
932 /**
933  * Flush tx frame populated by retransmits and timer pops
934  */
935 void
936 tcp_flush_frame_to_output (tcp_worker_ctx_t * wrk, u8 is_ip4)
937 {
938   if (wrk->tx_frames[!is_ip4])
939     {
940       u32 next_index;
941       next_index = is_ip4 ? tcp4_output_node.index : tcp6_output_node.index;
942       vlib_put_frame_to_node (wrk->vm, next_index, wrk->tx_frames[!is_ip4]);
943       wrk->tx_frames[!is_ip4] = 0;
944     }
945 }
946
947 /**
948  * Flush ip lookup tx frames populated by timer pops
949  */
950 static void
951 tcp_flush_frame_to_ip_lookup (tcp_worker_ctx_t * wrk, u8 is_ip4)
952 {
953   if (wrk->ip_lookup_tx_frames[!is_ip4])
954     {
955       u32 next_index;
956       next_index = is_ip4 ? ip4_lookup_node.index : ip6_lookup_node.index;
957       vlib_put_frame_to_node (wrk->vm, next_index,
958                               wrk->ip_lookup_tx_frames[!is_ip4]);
959       wrk->ip_lookup_tx_frames[!is_ip4] = 0;
960     }
961 }
962
963 /**
964  * Flush v4 and v6 tcp and ip-lookup tx frames for thread index
965  */
966 void
967 tcp_flush_frames_to_output (tcp_worker_ctx_t * wrk)
968 {
969   tcp_flush_frame_to_output (wrk, 1);
970   tcp_flush_frame_to_output (wrk, 0);
971   tcp_flush_frame_to_ip_lookup (wrk, 1);
972   tcp_flush_frame_to_ip_lookup (wrk, 0);
973 }
974
975 /**
976  *  Send FIN
977  */
978 void
979 tcp_send_fin (tcp_connection_t * tc)
980 {
981   tcp_worker_ctx_t *wrk = tcp_get_worker (tc->c_thread_index);
982   vlib_main_t *vm = wrk->vm;
983   vlib_buffer_t *b;
984   u32 bi;
985   u8 fin_snt = 0;
986
987   fin_snt = tc->flags & TCP_CONN_FINSNT;
988   if (fin_snt)
989     tc->snd_nxt -= 1;
990
991   if (PREDICT_FALSE (!vlib_buffer_alloc (vm, &bi, 1)))
992     {
993       /* Out of buffers so program fin retransmit ASAP */
994       tcp_timer_update (tc, TCP_TIMER_RETRANSMIT, 1);
995       if (fin_snt)
996         tc->snd_nxt += 1;
997       else
998         /* Make sure retransmit retries a fin not data */
999         tc->flags |= TCP_CONN_FINSNT;
1000       return;
1001     }
1002
1003   tcp_retransmit_timer_force_update (tc);
1004   b = vlib_get_buffer (vm, bi);
1005   tcp_init_buffer (vm, b);
1006   tcp_make_fin (tc, b);
1007   tcp_enqueue_to_output_now (wrk, b, bi, tc->c_is_ip4);
1008   TCP_EVT (TCP_EVT_FIN_SENT, tc);
1009   /* Account for the FIN */
1010   tc->snd_nxt += 1;
1011   if (!fin_snt)
1012     {
1013       tc->flags |= TCP_CONN_FINSNT;
1014       tc->flags &= ~TCP_CONN_FINPNDG;
1015       tc->snd_una_max = seq_max (tc->snd_una_max, tc->snd_nxt);
1016     }
1017 }
1018
1019 /**
1020  * Push TCP header and update connection variables. Should only be called
1021  * for segments with data, not for 'control' packets.
1022  */
1023 always_inline void
1024 tcp_push_hdr_i (tcp_connection_t * tc, vlib_buffer_t * b, u32 snd_nxt,
1025                 u8 compute_opts, u8 maybe_burst, u8 update_snd_nxt)
1026 {
1027   u8 tcp_hdr_opts_len, flags = TCP_FLAG_ACK;
1028   u32 advertise_wnd, data_len;
1029   tcp_main_t *tm = &tcp_main;
1030   tcp_header_t *th;
1031
1032   data_len = b->current_length;
1033   if (PREDICT_FALSE (b->flags & VLIB_BUFFER_NEXT_PRESENT))
1034     data_len += b->total_length_not_including_first_buffer;
1035
1036   vnet_buffer (b)->tcp.flags = 0;
1037   vnet_buffer (b)->tcp.connection_index = tc->c_c_index;
1038
1039   if (compute_opts)
1040     tc->snd_opts_len = tcp_make_options (tc, &tc->snd_opts, tc->state);
1041
1042   tcp_hdr_opts_len = tc->snd_opts_len + sizeof (tcp_header_t);
1043
1044   if (maybe_burst)
1045     advertise_wnd = tc->rcv_wnd >> tc->rcv_wscale;
1046   else
1047     advertise_wnd = tcp_window_to_advertise (tc, TCP_STATE_ESTABLISHED);
1048
1049   if (PREDICT_FALSE (tc->flags & TCP_CONN_PSH_PENDING))
1050     {
1051       if (seq_geq (tc->psh_seq, snd_nxt)
1052           && seq_lt (tc->psh_seq, snd_nxt + data_len))
1053         flags |= TCP_FLAG_PSH;
1054     }
1055   th = vlib_buffer_push_tcp (b, tc->c_lcl_port, tc->c_rmt_port, snd_nxt,
1056                              tc->rcv_nxt, tcp_hdr_opts_len, flags,
1057                              advertise_wnd);
1058
1059   if (maybe_burst)
1060     {
1061       clib_memcpy_fast ((u8 *) (th + 1),
1062                         tm->wrk_ctx[tc->c_thread_index].cached_opts,
1063                         tc->snd_opts_len);
1064     }
1065   else
1066     {
1067       u8 len = tcp_options_write ((u8 *) (th + 1), &tc->snd_opts);
1068       ASSERT (len == tc->snd_opts_len);
1069     }
1070
1071   /*
1072    * Update connection variables
1073    */
1074
1075   if (update_snd_nxt)
1076     tc->snd_nxt += data_len;
1077   tc->rcv_las = tc->rcv_nxt;
1078
1079   tc->bytes_out += data_len;
1080   tc->data_segs_out += 1;
1081
1082   TCP_EVT (TCP_EVT_PKTIZE, tc);
1083 }
1084
1085 u32
1086 tcp_session_push_header (transport_connection_t * tconn, vlib_buffer_t * b)
1087 {
1088   tcp_connection_t *tc = (tcp_connection_t *) tconn;
1089
1090   if (tc->flags & TCP_CONN_TRACK_BURST)
1091     {
1092       tcp_bt_check_app_limited (tc);
1093       tcp_bt_track_tx (tc);
1094       tc->flags &= ~TCP_CONN_TRACK_BURST;
1095     }
1096
1097   tcp_push_hdr_i (tc, b, tc->snd_nxt, /* compute opts */ 0, /* burst */ 1,
1098                   /* update_snd_nxt */ 1);
1099
1100   tc->snd_una_max = seq_max (tc->snd_nxt, tc->snd_una_max);
1101   tcp_validate_txf_size (tc, tc->snd_una_max - tc->snd_una);
1102   /* If not tracking an ACK, start tracking */
1103   if (tc->rtt_ts == 0 && !tcp_in_cong_recovery (tc))
1104     {
1105       tc->rtt_ts = tcp_time_now_us (tc->c_thread_index);
1106       tc->rtt_seq = tc->snd_nxt;
1107     }
1108   if (PREDICT_FALSE (!tcp_timer_is_active (tc, TCP_TIMER_RETRANSMIT)))
1109     {
1110       tcp_retransmit_timer_set (tc);
1111       tc->rto_boff = 0;
1112     }
1113   tcp_trajectory_add_start (b, 3);
1114   return 0;
1115 }
1116
1117 void
1118 tcp_send_ack (tcp_connection_t * tc)
1119 {
1120   tcp_worker_ctx_t *wrk = tcp_get_worker (tc->c_thread_index);
1121   vlib_main_t *vm = wrk->vm;
1122   vlib_buffer_t *b;
1123   u32 bi;
1124
1125   if (PREDICT_FALSE (!vlib_buffer_alloc (vm, &bi, 1)))
1126     {
1127       tcp_update_rcv_wnd (tc);
1128       return;
1129     }
1130   b = vlib_get_buffer (vm, bi);
1131   tcp_init_buffer (vm, b);
1132   tcp_make_ack (tc, b);
1133   tcp_enqueue_to_output (wrk, b, bi, tc->c_is_ip4);
1134 }
1135
1136 void
1137 tcp_program_ack (tcp_connection_t * tc)
1138 {
1139   if (!(tc->flags & TCP_CONN_SNDACK))
1140     {
1141       session_add_self_custom_tx_evt (&tc->connection, 1);
1142       tc->flags |= TCP_CONN_SNDACK;
1143     }
1144 }
1145
1146 void
1147 tcp_program_dupack (tcp_connection_t * tc)
1148 {
1149   if (!(tc->flags & TCP_CONN_SNDACK))
1150     {
1151       session_add_self_custom_tx_evt (&tc->connection, 1);
1152       tc->flags |= TCP_CONN_SNDACK;
1153     }
1154   if (tc->pending_dupacks < 255)
1155     tc->pending_dupacks += 1;
1156 }
1157
1158 void
1159 tcp_program_fastretransmit (tcp_connection_t * tc)
1160 {
1161   if (!(tc->flags & TCP_CONN_FRXT_PENDING))
1162     {
1163       session_add_self_custom_tx_evt (&tc->connection, 0);
1164       tc->flags |= TCP_CONN_FRXT_PENDING;
1165     }
1166 }
1167
1168 /**
1169  * Delayed ack timer handler
1170  *
1171  * Sends delayed ACK when timer expires
1172  */
1173 void
1174 tcp_timer_delack_handler (u32 index)
1175 {
1176   u32 thread_index = vlib_get_thread_index ();
1177   tcp_connection_t *tc;
1178
1179   tc = tcp_connection_get (index, thread_index);
1180   tc->timers[TCP_TIMER_DELACK] = TCP_TIMER_HANDLE_INVALID;
1181   tcp_send_ack (tc);
1182 }
1183
1184 /**
1185  * Send Window Update ACK,
1186  * ensuring that it will be sent once, if RWND became non-zero,
1187  * after zero RWND has been advertised in ACK before
1188  */
1189 void
1190 tcp_send_window_update_ack (tcp_connection_t * tc)
1191 {
1192   u32 win;
1193
1194   if (tcp_zero_rwnd_sent (tc))
1195     {
1196       win = tcp_window_to_advertise (tc, tc->state);
1197       if (win > 0)
1198         {
1199           tcp_zero_rwnd_sent_off (tc);
1200           tcp_program_ack (tc);
1201         }
1202     }
1203 }
1204
1205 /**
1206  * Allocate a new buffer and build a new tcp segment
1207  *
1208  * @param wrk           tcp worker
1209  * @param tc            connection for which the segment will be allocated
1210  * @param offset        offset of the first byte in the tx fifo
1211  * @param max_deq_byte  segment size
1212  * @param[out] b        pointer to buffer allocated
1213  *
1214  * @return      the number of bytes in the segment or 0 if buffer cannot be
1215  *              allocated or no data available
1216  */
1217 static int
1218 tcp_prepare_segment (tcp_worker_ctx_t * wrk, tcp_connection_t * tc,
1219                      u32 offset, u32 max_deq_bytes, vlib_buffer_t ** b)
1220 {
1221   u32 bytes_per_buffer = vnet_get_tcp_main ()->bytes_per_buffer;
1222   vlib_main_t *vm = wrk->vm;
1223   u32 bi, seg_size;
1224   int n_bytes = 0;
1225   u8 *data;
1226
1227   seg_size = max_deq_bytes + TRANSPORT_MAX_HDRS_LEN;
1228
1229   /*
1230    * Prepare options
1231    */
1232   tc->snd_opts_len = tcp_make_options (tc, &tc->snd_opts, tc->state);
1233
1234   /*
1235    * Allocate and fill in buffer(s)
1236    */
1237
1238   /* Easy case, buffer size greater than mss */
1239   if (PREDICT_TRUE (seg_size <= bytes_per_buffer))
1240     {
1241       if (PREDICT_FALSE (!vlib_buffer_alloc (vm, &bi, 1)))
1242         return 0;
1243       *b = vlib_get_buffer (vm, bi);
1244       data = tcp_init_buffer (vm, *b);
1245       n_bytes = session_tx_fifo_peek_bytes (&tc->connection, data, offset,
1246                                             max_deq_bytes);
1247       ASSERT (n_bytes == max_deq_bytes);
1248       b[0]->current_length = n_bytes;
1249       tcp_push_hdr_i (tc, *b, tc->snd_una + offset, /* compute opts */ 0,
1250                       /* burst */ 0, /* update_snd_nxt */ 0);
1251     }
1252   /* Split mss into multiple buffers */
1253   else
1254     {
1255       u32 chain_bi = ~0, n_bufs_per_seg, n_bufs;
1256       u16 n_peeked, len_to_deq;
1257       vlib_buffer_t *chain_b, *prev_b;
1258       int i;
1259
1260       /* Make sure we have enough buffers */
1261       n_bufs_per_seg = ceil ((double) seg_size / bytes_per_buffer);
1262       vec_validate_aligned (wrk->tx_buffers, n_bufs_per_seg - 1,
1263                             CLIB_CACHE_LINE_BYTES);
1264       n_bufs = vlib_buffer_alloc (vm, wrk->tx_buffers, n_bufs_per_seg);
1265       if (PREDICT_FALSE (n_bufs != n_bufs_per_seg))
1266         {
1267           if (n_bufs)
1268             vlib_buffer_free (vm, wrk->tx_buffers, n_bufs);
1269           return 0;
1270         }
1271
1272       *b = vlib_get_buffer (vm, wrk->tx_buffers[--n_bufs]);
1273       data = tcp_init_buffer (vm, *b);
1274       n_bytes = session_tx_fifo_peek_bytes (&tc->connection, data, offset,
1275                                             bytes_per_buffer -
1276                                             TRANSPORT_MAX_HDRS_LEN);
1277       b[0]->current_length = n_bytes;
1278       b[0]->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
1279       b[0]->total_length_not_including_first_buffer = 0;
1280       max_deq_bytes -= n_bytes;
1281
1282       chain_b = *b;
1283       for (i = 1; i < n_bufs_per_seg; i++)
1284         {
1285           prev_b = chain_b;
1286           len_to_deq = clib_min (max_deq_bytes, bytes_per_buffer);
1287           chain_bi = wrk->tx_buffers[--n_bufs];
1288           chain_b = vlib_get_buffer (vm, chain_bi);
1289           chain_b->current_data = 0;
1290           data = vlib_buffer_get_current (chain_b);
1291           n_peeked = session_tx_fifo_peek_bytes (&tc->connection, data,
1292                                                  offset + n_bytes,
1293                                                  len_to_deq);
1294           ASSERT (n_peeked == len_to_deq);
1295           n_bytes += n_peeked;
1296           chain_b->current_length = n_peeked;
1297           chain_b->next_buffer = 0;
1298
1299           /* update previous buffer */
1300           prev_b->next_buffer = chain_bi;
1301           prev_b->flags |= VLIB_BUFFER_NEXT_PRESENT;
1302
1303           max_deq_bytes -= n_peeked;
1304           b[0]->total_length_not_including_first_buffer += n_peeked;
1305         }
1306
1307       tcp_push_hdr_i (tc, *b, tc->snd_una + offset, /* compute opts */ 0,
1308                       /* burst */ 0, /* update_snd_nxt */ 0);
1309
1310       if (PREDICT_FALSE (n_bufs))
1311         {
1312           clib_warning ("not all buffers consumed");
1313           vlib_buffer_free (vm, wrk->tx_buffers, n_bufs);
1314         }
1315     }
1316
1317   ASSERT (n_bytes > 0);
1318   ASSERT (((*b)->current_data + (*b)->current_length) <= bytes_per_buffer);
1319
1320   return n_bytes;
1321 }
1322
1323 /**
1324  * Build a retransmit segment
1325  *
1326  * @return the number of bytes in the segment or 0 if there's nothing to
1327  *         retransmit
1328  */
1329 static u32
1330 tcp_prepare_retransmit_segment (tcp_worker_ctx_t * wrk,
1331                                 tcp_connection_t * tc, u32 offset,
1332                                 u32 max_deq_bytes, vlib_buffer_t ** b)
1333 {
1334   u32 start, available_bytes;
1335   int n_bytes = 0;
1336
1337   ASSERT (tc->state >= TCP_STATE_ESTABLISHED);
1338   ASSERT (max_deq_bytes != 0);
1339
1340   /*
1341    * Make sure we can retransmit something
1342    */
1343   available_bytes = transport_max_tx_dequeue (&tc->connection);
1344   ASSERT (available_bytes >= offset);
1345   available_bytes -= offset;
1346   if (!available_bytes)
1347     return 0;
1348
1349   max_deq_bytes = clib_min (tc->snd_mss, max_deq_bytes);
1350   max_deq_bytes = clib_min (available_bytes, max_deq_bytes);
1351
1352   /* Start is beyond snd_congestion */
1353   start = tc->snd_una + offset;
1354   if (seq_geq (start, tc->snd_congestion))
1355     return 0;
1356
1357   /* Don't overshoot snd_congestion */
1358   if (seq_gt (start + max_deq_bytes, tc->snd_congestion))
1359     {
1360       max_deq_bytes = tc->snd_congestion - start;
1361       if (max_deq_bytes == 0)
1362         return 0;
1363     }
1364
1365   n_bytes = tcp_prepare_segment (wrk, tc, offset, max_deq_bytes, b);
1366   if (!n_bytes)
1367     return 0;
1368
1369   if (tcp_in_fastrecovery (tc))
1370     {
1371       tc->snd_rxt_bytes += n_bytes;
1372       if (tc->flags & TCP_CONN_RATE_SAMPLE)
1373         tcp_bt_track_rxt (tc, start, start + n_bytes);
1374     }
1375
1376   tc->bytes_retrans += n_bytes;
1377   tc->segs_retrans += 1;
1378   TCP_EVT (TCP_EVT_CC_RTX, tc, offset, n_bytes);
1379   return n_bytes;
1380 }
1381
1382 /**
1383  * Reset congestion control, switch cwnd to loss window and try again.
1384  */
1385 static void
1386 tcp_cc_init_rxt_timeout (tcp_connection_t * tc)
1387 {
1388   TCP_EVT (TCP_EVT_CC_EVT, tc, 6);
1389   tc->prev_ssthresh = tc->ssthresh;
1390   tc->prev_cwnd = tc->cwnd;
1391
1392   /* Clear fast recovery state if needed */
1393   if (tcp_in_fastrecovery (tc))
1394     tcp_cc_fastrecovery_clear (tc);
1395
1396   /* Let cc algo decide loss cwnd and ssthresh */
1397   tcp_cc_loss (tc);
1398
1399   /* Start again from the beginning */
1400   tc->snd_congestion = tc->snd_nxt;
1401   tc->rcv_dupacks = 0;
1402   tc->rtt_ts = 0;
1403   tc->cwnd_acc_bytes = 0;
1404   tc->tr_occurences += 1;
1405   tcp_connection_tx_pacer_reset (tc, tc->cwnd, 2 * tc->snd_mss);
1406   tcp_recovery_on (tc);
1407 }
1408
1409 void
1410 tcp_timer_retransmit_handler (u32 tc_index)
1411 {
1412   u32 thread_index = vlib_get_thread_index ();
1413   tcp_worker_ctx_t *wrk = tcp_get_worker (thread_index);
1414   vlib_main_t *vm = wrk->vm;
1415   tcp_connection_t *tc;
1416   vlib_buffer_t *b = 0;
1417   u32 bi, n_bytes;
1418
1419   tc = tcp_connection_get (tc_index, thread_index);
1420
1421   /* Note: the connection may have been closed and pool_put */
1422   if (PREDICT_FALSE (tc == 0 || tc->state == TCP_STATE_SYN_SENT))
1423     return;
1424
1425   tc->timers[TCP_TIMER_RETRANSMIT] = TCP_TIMER_HANDLE_INVALID;
1426
1427   /* Wait-close and retransmit could pop at the same time */
1428   if (tc->state == TCP_STATE_CLOSED)
1429     return;
1430
1431   if (tc->state >= TCP_STATE_ESTABLISHED)
1432     {
1433       TCP_EVT (TCP_EVT_CC_EVT, tc, 2);
1434
1435       /* Lost FIN, retransmit and return */
1436       if (tc->flags & TCP_CONN_FINSNT)
1437         {
1438           tcp_send_fin (tc);
1439           tc->rto_boff += 1;
1440           tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);
1441           return;
1442         }
1443
1444       /* Shouldn't be here. This condition is tricky because it has to take
1445        * into account boff > 0 due to persist timeout. */
1446       if ((tc->rto_boff == 0 && tc->snd_una == tc->snd_nxt)
1447           || (tc->rto_boff > 0 && seq_geq (tc->snd_una, tc->snd_congestion)
1448               && !tcp_flight_size (tc)))
1449         {
1450           ASSERT (!tcp_in_recovery (tc));
1451           tc->rto_boff = 0;
1452           return;
1453         }
1454
1455       /* We're not in recovery so make sure rto_boff is 0. Can be non 0 due
1456        * to persist timer timeout */
1457       if (!tcp_in_recovery (tc) && tc->rto_boff > 0)
1458         {
1459           tc->rto_boff = 0;
1460           tcp_update_rto (tc);
1461         }
1462
1463       /* Peer is dead or network connectivity is lost. Close connection.
1464        * RFC 1122 section 4.2.3.5 recommends a value of at least 100s. For
1465        * a min rto of 0.2s we need to retry about 8 times. */
1466       if (tc->rto_boff >= TCP_RTO_BOFF_MAX)
1467         {
1468           tcp_send_reset (tc);
1469           tcp_connection_set_state (tc, TCP_STATE_CLOSED);
1470           session_transport_closing_notify (&tc->connection);
1471           tcp_connection_timers_reset (tc);
1472           tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.closewait_time);
1473           return;
1474         }
1475
1476       /* Increment RTO backoff (also equal to number of retries) and go back
1477        * to first un-acked byte  */
1478       tc->rto_boff += 1;
1479
1480       /* TODO be less aggressive about clearing scoreboard */
1481       scoreboard_clear (&tc->sack_sb);
1482
1483       /* First retransmit timeout */
1484       if (tc->rto_boff == 1)
1485         {
1486           tcp_cc_init_rxt_timeout (tc);
1487           /* Record timestamp. Eifel detection algorithm RFC3522 */
1488           tc->snd_rxt_ts = tcp_tstamp (tc);
1489         }
1490
1491       if (tc->flags & TCP_CONN_RATE_SAMPLE)
1492         tcp_bt_flush_samples (tc);
1493
1494       /* If we've sent beyond snd_congestion, update it */
1495       tc->snd_congestion = seq_max (tc->snd_nxt, tc->snd_congestion);
1496       tc->snd_nxt = tc->snd_una;
1497
1498       /* Send one segment. n_bytes may be zero due to buffer shortfall */
1499       n_bytes = tcp_prepare_retransmit_segment (wrk, tc, 0, tc->snd_mss, &b);
1500       if (!n_bytes)
1501         {
1502           tcp_timer_update (tc, TCP_TIMER_RETRANSMIT, 1);
1503           return;
1504         }
1505
1506       bi = vlib_get_buffer_index (vm, b);
1507       tcp_enqueue_to_output (wrk, b, bi, tc->c_is_ip4);
1508
1509       tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);
1510       tcp_retransmit_timer_force_update (tc);
1511     }
1512   /* Retransmit SYN-ACK */
1513   else if (tc->state == TCP_STATE_SYN_RCVD)
1514     {
1515       TCP_EVT (TCP_EVT_CC_EVT, tc, 2);
1516
1517       tc->rtt_ts = 0;
1518
1519       /* Passive open establish timeout */
1520       if (tc->rto > TCP_ESTABLISH_TIME >> 1)
1521         {
1522           tcp_connection_set_state (tc, TCP_STATE_CLOSED);
1523           tcp_connection_timers_reset (tc);
1524           tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.cleanup_time);
1525           return;
1526         }
1527
1528       if (PREDICT_FALSE (!vlib_buffer_alloc (vm, &bi, 1)))
1529         {
1530           tcp_timer_update (tc, TCP_TIMER_RETRANSMIT, 1);
1531           return;
1532         }
1533
1534       tc->rto_boff += 1;
1535       if (tc->rto_boff > TCP_RTO_SYN_RETRIES)
1536         tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);
1537
1538       tcp_retransmit_timer_force_update (tc);
1539
1540       b = vlib_get_buffer (vm, bi);
1541       tcp_init_buffer (vm, b);
1542       tcp_make_synack (tc, b);
1543       TCP_EVT (TCP_EVT_SYN_RXT, tc, 1);
1544
1545       /* Retransmit timer already updated, just enqueue to output */
1546       tcp_enqueue_to_output (wrk, b, bi, tc->c_is_ip4);
1547     }
1548   else
1549     {
1550       ASSERT (tc->state == TCP_STATE_CLOSED);
1551       return;
1552     }
1553 }
1554
1555 /**
1556  * SYN retransmit timer handler. Active open only.
1557  */
1558 void
1559 tcp_timer_retransmit_syn_handler (u32 tc_index)
1560 {
1561   u32 thread_index = vlib_get_thread_index ();
1562   tcp_worker_ctx_t *wrk = tcp_get_worker (thread_index);
1563   vlib_main_t *vm = wrk->vm;
1564   tcp_connection_t *tc;
1565   vlib_buffer_t *b = 0;
1566   u32 bi;
1567
1568   tc = tcp_half_open_connection_get (tc_index);
1569
1570   /* Note: the connection may have transitioned to ESTABLISHED... */
1571   if (PREDICT_FALSE (tc == 0 || tc->state != TCP_STATE_SYN_SENT))
1572     return;
1573
1574   tc->timers[TCP_TIMER_RETRANSMIT_SYN] = TCP_TIMER_HANDLE_INVALID;
1575
1576   /* Half-open connection actually moved to established but we were
1577    * waiting for syn retransmit to pop to call cleanup from the right
1578    * thread. */
1579   if (tc->flags & TCP_CONN_HALF_OPEN_DONE)
1580     {
1581       if (tcp_half_open_connection_cleanup (tc))
1582         TCP_DBG ("could not remove half-open connection");
1583       return;
1584     }
1585
1586   TCP_EVT (TCP_EVT_CC_EVT, tc, 2);
1587   tc->rtt_ts = 0;
1588
1589   /* Active open establish timeout */
1590   if (tc->rto >= TCP_ESTABLISH_TIME >> 1)
1591     {
1592       session_stream_connect_notify (&tc->connection, 1 /* fail */ );
1593       tcp_connection_cleanup (tc);
1594       return;
1595     }
1596
1597   if (PREDICT_FALSE (!vlib_buffer_alloc (vm, &bi, 1)))
1598     {
1599       tcp_timer_update (tc, TCP_TIMER_RETRANSMIT_SYN, 1);
1600       return;
1601     }
1602
1603   /* Try without increasing RTO a number of times. If this fails,
1604    * start growing RTO exponentially */
1605   tc->rto_boff += 1;
1606   if (tc->rto_boff > TCP_RTO_SYN_RETRIES)
1607     tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);
1608
1609   b = vlib_get_buffer (vm, bi);
1610   tcp_init_buffer (vm, b);
1611   tcp_make_syn (tc, b);
1612
1613   TCP_EVT (TCP_EVT_SYN_RXT, tc, 0);
1614
1615   /* This goes straight to ipx_lookup */
1616   tcp_push_ip_hdr (wrk, tc, b);
1617   tcp_enqueue_to_ip_lookup (wrk, b, bi, tc->c_is_ip4, tc->c_fib_index);
1618
1619   tcp_timer_update (tc, TCP_TIMER_RETRANSMIT_SYN,
1620                     tc->rto * TCP_TO_TIMER_TICK);
1621 }
1622
1623 /**
1624  * Got 0 snd_wnd from peer, try to do something about it.
1625  *
1626  */
1627 void
1628 tcp_timer_persist_handler (u32 index)
1629 {
1630   u32 thread_index = vlib_get_thread_index ();
1631   tcp_worker_ctx_t *wrk = tcp_get_worker (thread_index);
1632   u32 bi, max_snd_bytes, available_bytes, offset;
1633   tcp_main_t *tm = vnet_get_tcp_main ();
1634   vlib_main_t *vm = wrk->vm;
1635   tcp_connection_t *tc;
1636   vlib_buffer_t *b;
1637   int n_bytes = 0;
1638   u8 *data;
1639
1640   tc = tcp_connection_get_if_valid (index, thread_index);
1641   if (!tc)
1642     return;
1643
1644   /* Make sure timer handle is set to invalid */
1645   tc->timers[TCP_TIMER_PERSIST] = TCP_TIMER_HANDLE_INVALID;
1646
1647   /* Problem already solved or worse */
1648   if (tc->state == TCP_STATE_CLOSED || tc->snd_wnd > tc->snd_mss
1649       || (tc->flags & TCP_CONN_FINSNT))
1650     return;
1651
1652   available_bytes = transport_max_tx_dequeue (&tc->connection);
1653   offset = tc->snd_nxt - tc->snd_una;
1654
1655   /* Reprogram persist if no new bytes available to send. We may have data
1656    * next time */
1657   if (!available_bytes)
1658     {
1659       tcp_persist_timer_set (tc);
1660       return;
1661     }
1662
1663   if (available_bytes <= offset)
1664     {
1665       ASSERT (tcp_timer_is_active (tc, TCP_TIMER_RETRANSMIT));
1666       return;
1667     }
1668
1669   /* Increment RTO backoff */
1670   tc->rto_boff += 1;
1671   tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);
1672
1673   /*
1674    * Try to force the first unsent segment (or buffer)
1675    */
1676   if (PREDICT_FALSE (!vlib_buffer_alloc (vm, &bi, 1)))
1677     {
1678       tcp_persist_timer_set (tc);
1679       return;
1680     }
1681   b = vlib_get_buffer (vm, bi);
1682   data = tcp_init_buffer (vm, b);
1683
1684   tcp_validate_txf_size (tc, offset);
1685   tc->snd_opts_len = tcp_make_options (tc, &tc->snd_opts, tc->state);
1686   max_snd_bytes = clib_min (tc->snd_mss,
1687                             tm->bytes_per_buffer - TRANSPORT_MAX_HDRS_LEN);
1688   n_bytes = session_tx_fifo_peek_bytes (&tc->connection, data, offset,
1689                                         max_snd_bytes);
1690   b->current_length = n_bytes;
1691   ASSERT (n_bytes != 0 && (tcp_timer_is_active (tc, TCP_TIMER_RETRANSMIT)
1692                            || tc->snd_nxt == tc->snd_una_max
1693                            || tc->rto_boff > 1));
1694
1695   tcp_push_hdr_i (tc, b, tc->snd_nxt, /* compute opts */ 0,
1696                   /* burst */ 0, /* update_snd_nxt */ 1);
1697   tc->snd_una_max = seq_max (tc->snd_nxt, tc->snd_una_max);
1698   tcp_validate_txf_size (tc, tc->snd_una_max - tc->snd_una);
1699   tcp_enqueue_to_output (wrk, b, bi, tc->c_is_ip4);
1700
1701   /* Just sent new data, enable retransmit */
1702   tcp_retransmit_timer_update (tc);
1703 }
1704
1705 /**
1706  * Retransmit first unacked segment
1707  */
1708 int
1709 tcp_retransmit_first_unacked (tcp_worker_ctx_t * wrk, tcp_connection_t * tc)
1710 {
1711   vlib_main_t *vm = wrk->vm;
1712   vlib_buffer_t *b;
1713   u32 bi, n_bytes;
1714
1715   TCP_EVT (TCP_EVT_CC_EVT, tc, 1);
1716
1717   n_bytes = tcp_prepare_retransmit_segment (wrk, tc, 0, tc->snd_mss, &b);
1718   if (!n_bytes)
1719     return -1;
1720
1721   bi = vlib_get_buffer_index (vm, b);
1722   tcp_enqueue_to_output (wrk, b, bi, tc->c_is_ip4);
1723
1724   return 0;
1725 }
1726
1727 static int
1728 tcp_fast_retransmit_unsent (tcp_worker_ctx_t * wrk, tcp_connection_t * tc,
1729                             u32 burst_size)
1730 {
1731   u32 offset, n_segs = 0, n_written, bi, available_wnd;
1732   vlib_main_t *vm = wrk->vm;
1733   vlib_buffer_t *b = 0;
1734
1735   offset = tc->snd_nxt - tc->snd_una;
1736   available_wnd = tc->snd_wnd - offset;
1737   burst_size = clib_min (burst_size, available_wnd / tc->snd_mss);
1738
1739   while (n_segs < burst_size)
1740     {
1741       n_written = tcp_prepare_segment (wrk, tc, offset, tc->snd_mss, &b);
1742       if (!n_written)
1743         goto done;
1744
1745       bi = vlib_get_buffer_index (vm, b);
1746       tcp_enqueue_to_output (wrk, b, bi, tc->c_is_ip4);
1747       offset += n_written;
1748       n_segs += 1;
1749
1750       tc->snd_nxt += n_written;
1751       tc->snd_una_max = seq_max (tc->snd_nxt, tc->snd_una_max);
1752     }
1753
1754 done:
1755   return n_segs;
1756 }
1757
1758 #define scoreboard_rescue_rxt_valid(_sb, _tc)                   \
1759     (seq_geq (_sb->rescue_rxt, _tc->snd_una)                    \
1760         && seq_leq (_sb->rescue_rxt, _tc->snd_congestion))
1761
1762 /**
1763  * Do fast retransmit with SACKs
1764  */
1765 int
1766 tcp_fast_retransmit_sack (tcp_worker_ctx_t * wrk, tcp_connection_t * tc,
1767                           u32 burst_size)
1768 {
1769   u32 n_written = 0, offset, max_bytes, n_segs = 0, n_segs_now;
1770   sack_scoreboard_hole_t *hole;
1771   vlib_main_t *vm = wrk->vm;
1772   vlib_buffer_t *b = 0;
1773   sack_scoreboard_t *sb;
1774   u32 bi, max_deq;
1775   int snd_space;
1776   u8 snd_limited = 0, can_rescue = 0;
1777
1778   ASSERT (tcp_in_fastrecovery (tc));
1779
1780   snd_space = tcp_available_cc_snd_space (tc);
1781   if (snd_space < tc->snd_mss)
1782     {
1783       tcp_program_fastretransmit (tc);
1784       return 0;
1785     }
1786
1787   TCP_EVT (TCP_EVT_CC_EVT, tc, 0);
1788   sb = &tc->sack_sb;
1789   hole = scoreboard_get_hole (sb, sb->cur_rxt_hole);
1790
1791   max_deq = transport_max_tx_dequeue (&tc->connection);
1792   max_deq -= tc->snd_nxt - tc->snd_una;
1793
1794   while (snd_space > 0 && n_segs < burst_size)
1795     {
1796       hole = scoreboard_next_rxt_hole (sb, hole, max_deq, &can_rescue,
1797                                        &snd_limited);
1798       if (!hole)
1799         {
1800           if (max_deq)
1801             {
1802               snd_space = clib_min (max_deq, snd_space);
1803               burst_size = clib_min (burst_size - n_segs,
1804                                      snd_space / tc->snd_mss);
1805               n_segs_now = tcp_fast_retransmit_unsent (wrk, tc, burst_size);
1806               if (max_deq > n_segs_now * tc->snd_mss)
1807                 tcp_program_fastretransmit (tc);
1808               n_segs += n_segs_now;
1809               goto done;
1810             }
1811
1812           if (!can_rescue || scoreboard_rescue_rxt_valid (sb, tc))
1813             break;
1814
1815           /* If rescue rxt undefined or less than snd_una then one segment of
1816            * up to SMSS octets that MUST include the highest outstanding
1817            * unSACKed sequence number SHOULD be returned, and RescueRxt set to
1818            * RecoveryPoint. HighRxt MUST NOT be updated.
1819            */
1820           max_bytes = clib_min (tc->snd_mss,
1821                                 tc->snd_congestion - tc->snd_una);
1822           max_bytes = clib_min (max_bytes, snd_space);
1823           offset = tc->snd_congestion - tc->snd_una - max_bytes;
1824           sb->rescue_rxt = tc->snd_congestion;
1825           n_written = tcp_prepare_retransmit_segment (wrk, tc, offset,
1826                                                       max_bytes, &b);
1827           if (!n_written)
1828             goto done;
1829
1830           bi = vlib_get_buffer_index (vm, b);
1831           tcp_enqueue_to_output (wrk, b, bi, tc->c_is_ip4);
1832           n_segs += 1;
1833           break;
1834         }
1835
1836       max_bytes = clib_min (hole->end - sb->high_rxt, snd_space);
1837       max_bytes = snd_limited ? clib_min (max_bytes, tc->snd_mss) : max_bytes;
1838       if (max_bytes == 0)
1839         break;
1840
1841       offset = sb->high_rxt - tc->snd_una;
1842       n_written = tcp_prepare_retransmit_segment (wrk, tc, offset, max_bytes,
1843                                                   &b);
1844       ASSERT (n_written <= snd_space);
1845
1846       /* Nothing left to retransmit */
1847       if (n_written == 0)
1848         break;
1849
1850       bi = vlib_get_buffer_index (vm, b);
1851       tcp_enqueue_to_output (wrk, b, bi, tc->c_is_ip4);
1852
1853       sb->high_rxt += n_written;
1854       snd_space -= n_written;
1855       n_segs += 1;
1856     }
1857
1858   if (hole)
1859     tcp_program_fastretransmit (tc);
1860
1861 done:
1862   return n_segs;
1863 }
1864
1865 /**
1866  * Fast retransmit without SACK info
1867  */
1868 int
1869 tcp_fast_retransmit_no_sack (tcp_worker_ctx_t * wrk, tcp_connection_t * tc,
1870                              u32 burst_size)
1871 {
1872   u32 n_written = 0, offset = 0, bi, max_deq, n_segs_now;
1873   vlib_main_t *vm = wrk->vm;
1874   int snd_space, n_segs = 0;
1875   vlib_buffer_t *b;
1876
1877   ASSERT (tcp_in_fastrecovery (tc));
1878   TCP_EVT (TCP_EVT_CC_EVT, tc, 0);
1879
1880   snd_space = tcp_available_cc_snd_space (tc);
1881
1882   if (!tcp_fastrecovery_first (tc))
1883     goto send_unsent;
1884
1885   /* RFC 6582: [If a partial ack], retransmit the first unacknowledged
1886    * segment. */
1887   while (snd_space > 0 && n_segs < burst_size)
1888     {
1889       n_written = tcp_prepare_retransmit_segment (wrk, tc, offset,
1890                                                   tc->snd_mss, &b);
1891
1892       /* Nothing left to retransmit */
1893       if (n_written == 0)
1894         break;
1895
1896       bi = vlib_get_buffer_index (vm, b);
1897       tcp_enqueue_to_output (wrk, b, bi, tc->c_is_ip4);
1898       snd_space -= n_written;
1899       offset += n_written;
1900       n_segs += 1;
1901     }
1902
1903   if (n_segs == burst_size)
1904     goto done;
1905
1906 send_unsent:
1907
1908   /* RFC 6582: Send a new segment if permitted by the new value of cwnd. */
1909   if (snd_space < tc->snd_mss || tc->snd_mss == 0)
1910     goto done;
1911
1912   max_deq = transport_max_tx_dequeue (&tc->connection);
1913   max_deq -= tc->snd_nxt - tc->snd_una;
1914   if (max_deq)
1915     {
1916       snd_space = clib_min (max_deq, snd_space);
1917       burst_size = clib_min (burst_size - n_segs, snd_space / tc->snd_mss);
1918       n_segs_now = tcp_fast_retransmit_unsent (wrk, tc, burst_size);
1919       if (max_deq > n_segs_now * tc->snd_mss)
1920         tcp_program_fastretransmit (tc);
1921       n_segs += n_segs_now;
1922     }
1923
1924 done:
1925   tcp_fastrecovery_first_off (tc);
1926   return n_segs;
1927 }
1928
1929 /**
1930  * Do fast retransmit
1931  */
1932 int
1933 tcp_fast_retransmit (tcp_worker_ctx_t * wrk, tcp_connection_t * tc,
1934                      u32 burst_size)
1935 {
1936   if (tcp_opts_sack_permitted (&tc->rcv_opts))
1937     return tcp_fast_retransmit_sack (wrk, tc, burst_size);
1938   else
1939     return tcp_fast_retransmit_no_sack (wrk, tc, burst_size);
1940 }
1941
1942 static int
1943 tcp_send_acks (tcp_connection_t * tc, u32 max_burst_size)
1944 {
1945   int j, n_acks;
1946
1947   if (!tc->pending_dupacks)
1948     {
1949       tcp_send_ack (tc);
1950       return 1;
1951     }
1952
1953   /* If we're supposed to send dupacks but have no ooo data
1954    * send only one ack */
1955   if (!vec_len (tc->snd_sacks))
1956     {
1957       tcp_send_ack (tc);
1958       return 1;
1959     }
1960
1961   /* Start with first sack block */
1962   tc->snd_sack_pos = 0;
1963
1964   /* Generate enough dupacks to cover all sack blocks. Do not generate
1965    * more sacks than the number of packets received. But do generate at
1966    * least 3, i.e., the number needed to signal congestion, if needed. */
1967   n_acks = vec_len (tc->snd_sacks) / TCP_OPTS_MAX_SACK_BLOCKS;
1968   n_acks = clib_min (n_acks, tc->pending_dupacks);
1969   n_acks = clib_max (n_acks, clib_min (tc->pending_dupacks, 3));
1970   for (j = 0; j < clib_min (n_acks, max_burst_size); j++)
1971     tcp_send_ack (tc);
1972
1973   if (n_acks < max_burst_size)
1974     {
1975       tc->pending_dupacks = 0;
1976       tc->snd_sack_pos = 0;
1977       tc->dupacks_out += n_acks;
1978       return n_acks;
1979     }
1980   else
1981     {
1982       TCP_DBG ("constrained by burst size");
1983       tc->pending_dupacks = n_acks - max_burst_size;
1984       tc->dupacks_out += max_burst_size;
1985       tcp_program_dupack (tc);
1986       return max_burst_size;
1987     }
1988 }
1989
1990 static int
1991 tcp_do_fastretransmit (tcp_connection_t * tc, u32 max_burst_size)
1992 {
1993   u32 n_segs = 0, burst_size, sent_bytes, burst_bytes;
1994   tcp_worker_ctx_t *wrk;
1995
1996   wrk = tcp_get_worker (tc->c_thread_index);
1997   burst_bytes = transport_connection_tx_pacer_burst (&tc->connection,
1998                                                      wrk->vm->
1999                                                      clib_time.last_cpu_time);
2000   burst_size = clib_min (max_burst_size, burst_bytes / tc->snd_mss);
2001   if (!burst_size)
2002     {
2003       tcp_program_fastretransmit (tc);
2004       return 0;
2005     }
2006
2007   n_segs = tcp_fast_retransmit (wrk, tc, burst_size);
2008   sent_bytes = clib_min (n_segs * tc->snd_mss, burst_bytes);
2009   transport_connection_tx_pacer_update_bytes (&tc->connection, sent_bytes);
2010   return n_segs;
2011 }
2012
2013 int
2014 tcp_session_custom_tx (void *conn, u32 max_burst_size)
2015 {
2016   tcp_connection_t *tc = (tcp_connection_t *) conn;
2017   u32 n_segs = 0;
2018
2019   if (tcp_in_fastrecovery (tc) && (tc->flags & TCP_CONN_FRXT_PENDING))
2020     {
2021       tc->flags &= ~TCP_CONN_FRXT_PENDING;
2022       n_segs = tcp_do_fastretransmit (tc, max_burst_size);
2023       max_burst_size -= n_segs;
2024     }
2025
2026   if (!(tc->flags & TCP_CONN_SNDACK))
2027     return n_segs;
2028
2029   tc->flags &= ~TCP_CONN_SNDACK;
2030
2031   /* We have retransmitted packets and no dupack */
2032   if (n_segs && !tc->pending_dupacks)
2033     return n_segs;
2034
2035   if (!max_burst_size)
2036     {
2037       tcp_program_ack (tc);
2038       return max_burst_size;
2039     }
2040
2041   n_segs += tcp_send_acks (tc, max_burst_size);
2042
2043   return n_segs;
2044 }
2045 #endif /* CLIB_MARCH_VARIANT */
2046
2047 static void
2048 tcp_output_handle_link_local (tcp_connection_t * tc0, vlib_buffer_t * b0,
2049                               u16 * next0, u32 * error0)
2050 {
2051   ip_adjacency_t *adj;
2052   adj_index_t ai;
2053
2054   /* Not thread safe but as long as the connection exists the adj should
2055    * not be removed */
2056   ai = adj_nbr_find (FIB_PROTOCOL_IP6, VNET_LINK_IP6, &tc0->c_rmt_ip,
2057                      tc0->sw_if_index);
2058   if (ai == ADJ_INDEX_INVALID)
2059     {
2060       vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
2061       *next0 = TCP_OUTPUT_NEXT_DROP;
2062       *error0 = TCP_ERROR_LINK_LOCAL_RW;
2063       return;
2064     }
2065
2066   adj = adj_get (ai);
2067   if (PREDICT_TRUE (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE))
2068     *next0 = TCP_OUTPUT_NEXT_IP_REWRITE;
2069   else if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP)
2070     *next0 = TCP_OUTPUT_NEXT_IP_ARP;
2071   else
2072     {
2073       *next0 = TCP_OUTPUT_NEXT_DROP;
2074       *error0 = TCP_ERROR_LINK_LOCAL_RW;
2075     }
2076   vnet_buffer (b0)->ip.adj_index[VLIB_TX] = ai;
2077 }
2078
2079 static void
2080 tcp46_output_trace_frame (vlib_main_t * vm, vlib_node_runtime_t * node,
2081                           u32 * to_next, u32 n_bufs)
2082 {
2083   u32 n_trace = vlib_get_trace_count (vm, node);
2084   tcp_connection_t *tc;
2085   tcp_tx_trace_t *t;
2086   vlib_buffer_t *b;
2087   tcp_header_t *th;
2088   int i;
2089
2090   for (i = 0; i < clib_min (n_trace, n_bufs); i++)
2091     {
2092       b = vlib_get_buffer (vm, to_next[i]);
2093       th = vlib_buffer_get_current (b);
2094       tc = tcp_connection_get (vnet_buffer (b)->tcp.connection_index,
2095                                vm->thread_index);
2096       t = vlib_add_trace (vm, node, b, sizeof (*t));
2097       clib_memcpy_fast (&t->tcp_header, th, sizeof (t->tcp_header));
2098       clib_memcpy_fast (&t->tcp_connection, tc, sizeof (t->tcp_connection));
2099     }
2100 }
2101
2102 always_inline void
2103 tcp_output_push_ip (vlib_main_t * vm, vlib_buffer_t * b0,
2104                     tcp_connection_t * tc0, u8 is_ip4)
2105 {
2106   tcp_header_t *th0 = 0;
2107
2108   th0 = vlib_buffer_get_current (b0);
2109   TCP_EVT (TCP_EVT_OUTPUT, tc0, th0->flags, b0->current_length);
2110   if (is_ip4)
2111     {
2112       vlib_buffer_push_ip4 (vm, b0, &tc0->c_lcl_ip4, &tc0->c_rmt_ip4,
2113                             IP_PROTOCOL_TCP, 1);
2114       b0->flags |= VNET_BUFFER_F_OFFLOAD_TCP_CKSUM;
2115       vnet_buffer (b0)->l4_hdr_offset = (u8 *) th0 - b0->data;
2116       th0->checksum = 0;
2117     }
2118   else
2119     {
2120       ip6_header_t *ih0;
2121       ih0 = vlib_buffer_push_ip6 (vm, b0, &tc0->c_lcl_ip6,
2122                                   &tc0->c_rmt_ip6, IP_PROTOCOL_TCP);
2123       b0->flags |= VNET_BUFFER_F_OFFLOAD_TCP_CKSUM;
2124       vnet_buffer (b0)->l3_hdr_offset = (u8 *) ih0 - b0->data;
2125       vnet_buffer (b0)->l4_hdr_offset = (u8 *) th0 - b0->data;
2126       th0->checksum = 0;
2127     }
2128 }
2129
2130 always_inline void
2131 tcp_output_handle_packet (tcp_connection_t * tc0, vlib_buffer_t * b0,
2132                           vlib_node_runtime_t * error_node, u16 * next0,
2133                           u8 is_ip4)
2134 {
2135   /* If next_index is not drop use it */
2136   if (tc0->next_node_index)
2137     {
2138       *next0 = tc0->next_node_index;
2139       vnet_buffer (b0)->tcp.next_node_opaque = tc0->next_node_opaque;
2140     }
2141
2142   vnet_buffer (b0)->sw_if_index[VLIB_TX] = tc0->c_fib_index;
2143   vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
2144
2145   if (!is_ip4)
2146     {
2147       u32 error0 = 0;
2148
2149       if (PREDICT_FALSE (ip6_address_is_link_local_unicast (&tc0->c_rmt_ip6)))
2150         tcp_output_handle_link_local (tc0, b0, next0, &error0);
2151
2152       if (PREDICT_FALSE (error0))
2153         {
2154           b0->error = error_node->errors[error0];
2155           return;
2156         }
2157     }
2158
2159   if (!TCP_ALWAYS_ACK)
2160     tcp_timer_reset (tc0, TCP_TIMER_DELACK);
2161
2162   tc0->segs_out += 1;
2163 }
2164
2165 always_inline uword
2166 tcp46_output_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
2167                      vlib_frame_t * frame, int is_ip4)
2168 {
2169   u32 n_left_from, *from, thread_index = vm->thread_index;
2170   vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
2171   u16 nexts[VLIB_FRAME_SIZE], *next;
2172   vlib_node_runtime_t *error_node;
2173
2174   error_node = vlib_node_get_runtime (vm, tcp_node_index (output, is_ip4));
2175
2176   from = vlib_frame_vector_args (frame);
2177   n_left_from = frame->n_vectors;
2178   tcp_set_time_now (tcp_get_worker (thread_index));
2179
2180   if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
2181     tcp46_output_trace_frame (vm, node, from, n_left_from);
2182
2183   vlib_get_buffers (vm, from, bufs, n_left_from);
2184   b = bufs;
2185   next = nexts;
2186
2187   while (n_left_from >= 4)
2188     {
2189       tcp_connection_t *tc0, *tc1;
2190
2191       {
2192         vlib_prefetch_buffer_header (b[2], STORE);
2193         CLIB_PREFETCH (b[2]->data, 2 * CLIB_CACHE_LINE_BYTES, STORE);
2194
2195         vlib_prefetch_buffer_header (b[3], STORE);
2196         CLIB_PREFETCH (b[3]->data, 2 * CLIB_CACHE_LINE_BYTES, STORE);
2197       }
2198
2199       next[0] = next[1] = TCP_OUTPUT_NEXT_IP_LOOKUP;
2200
2201       tc0 = tcp_connection_get (vnet_buffer (b[0])->tcp.connection_index,
2202                                 thread_index);
2203       tc1 = tcp_connection_get (vnet_buffer (b[1])->tcp.connection_index,
2204                                 thread_index);
2205
2206       tcp_output_push_ip (vm, b[0], tc0, is_ip4);
2207       tcp_output_push_ip (vm, b[1], tc1, is_ip4);
2208
2209       tcp_output_handle_packet (tc0, b[0], error_node, &next[0], is_ip4);
2210       tcp_output_handle_packet (tc1, b[1], error_node, &next[1], is_ip4);
2211
2212       b += 2;
2213       next += 2;
2214       n_left_from -= 2;
2215     }
2216   while (n_left_from > 0)
2217     {
2218       tcp_connection_t *tc0;
2219
2220       if (n_left_from > 1)
2221         {
2222           vlib_prefetch_buffer_header (b[1], STORE);
2223           CLIB_PREFETCH (b[1]->data, 2 * CLIB_CACHE_LINE_BYTES, STORE);
2224         }
2225
2226       next[0] = TCP_OUTPUT_NEXT_IP_LOOKUP;
2227       tc0 = tcp_connection_get (vnet_buffer (b[0])->tcp.connection_index,
2228                                 thread_index);
2229
2230       tcp_output_push_ip (vm, b[0], tc0, is_ip4);
2231       tcp_output_handle_packet (tc0, b[0], error_node, &next[0], is_ip4);
2232
2233       b += 1;
2234       next += 1;
2235       n_left_from -= 1;
2236     }
2237
2238   vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
2239   vlib_node_increment_counter (vm, tcp_node_index (output, is_ip4),
2240                                TCP_ERROR_PKTS_SENT, frame->n_vectors);
2241   return frame->n_vectors;
2242 }
2243
2244 VLIB_NODE_FN (tcp4_output_node) (vlib_main_t * vm, vlib_node_runtime_t * node,
2245                                  vlib_frame_t * from_frame)
2246 {
2247   return tcp46_output_inline (vm, node, from_frame, 1 /* is_ip4 */ );
2248 }
2249
2250 VLIB_NODE_FN (tcp6_output_node) (vlib_main_t * vm, vlib_node_runtime_t * node,
2251                                  vlib_frame_t * from_frame)
2252 {
2253   return tcp46_output_inline (vm, node, from_frame, 0 /* is_ip4 */ );
2254 }
2255
2256 /* *INDENT-OFF* */
2257 VLIB_REGISTER_NODE (tcp4_output_node) =
2258 {
2259   .name = "tcp4-output",
2260   /* Takes a vector of packets. */
2261   .vector_size = sizeof (u32),
2262   .n_errors = TCP_N_ERROR,
2263   .protocol_hint = VLIB_NODE_PROTO_HINT_TCP,
2264   .error_strings = tcp_error_strings,
2265   .n_next_nodes = TCP_OUTPUT_N_NEXT,
2266   .next_nodes = {
2267 #define _(s,n) [TCP_OUTPUT_NEXT_##s] = n,
2268     foreach_tcp4_output_next
2269 #undef _
2270   },
2271   .format_buffer = format_tcp_header,
2272   .format_trace = format_tcp_tx_trace,
2273 };
2274 /* *INDENT-ON* */
2275
2276 /* *INDENT-OFF* */
2277 VLIB_REGISTER_NODE (tcp6_output_node) =
2278 {
2279   .name = "tcp6-output",
2280     /* Takes a vector of packets. */
2281   .vector_size = sizeof (u32),
2282   .n_errors = TCP_N_ERROR,
2283   .protocol_hint = VLIB_NODE_PROTO_HINT_TCP,
2284   .error_strings = tcp_error_strings,
2285   .n_next_nodes = TCP_OUTPUT_N_NEXT,
2286   .next_nodes = {
2287 #define _(s,n) [TCP_OUTPUT_NEXT_##s] = n,
2288     foreach_tcp6_output_next
2289 #undef _
2290   },
2291   .format_buffer = format_tcp_header,
2292   .format_trace = format_tcp_tx_trace,
2293 };
2294 /* *INDENT-ON* */
2295
2296 typedef enum _tcp_reset_next
2297 {
2298   TCP_RESET_NEXT_DROP,
2299   TCP_RESET_NEXT_IP_LOOKUP,
2300   TCP_RESET_N_NEXT
2301 } tcp_reset_next_t;
2302
2303 #define foreach_tcp4_reset_next         \
2304   _(DROP, "error-drop")                 \
2305   _(IP_LOOKUP, "ip4-lookup")
2306
2307 #define foreach_tcp6_reset_next         \
2308   _(DROP, "error-drop")                 \
2309   _(IP_LOOKUP, "ip6-lookup")
2310
2311 static uword
2312 tcp46_send_reset_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
2313                          vlib_frame_t * from_frame, u8 is_ip4)
2314 {
2315   u32 n_left_from, next_index, *from, *to_next;
2316   u32 my_thread_index = vm->thread_index;
2317
2318   from = vlib_frame_vector_args (from_frame);
2319   n_left_from = from_frame->n_vectors;
2320
2321   next_index = node->cached_next_index;
2322
2323   while (n_left_from > 0)
2324     {
2325       u32 n_left_to_next;
2326
2327       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2328
2329       while (n_left_from > 0 && n_left_to_next > 0)
2330         {
2331           u32 bi0;
2332           vlib_buffer_t *b0;
2333           tcp_tx_trace_t *t0;
2334           tcp_header_t *th0;
2335           u32 error0 = TCP_ERROR_RST_SENT, next0 = TCP_RESET_NEXT_IP_LOOKUP;
2336
2337           bi0 = from[0];
2338           to_next[0] = bi0;
2339           from += 1;
2340           to_next += 1;
2341           n_left_from -= 1;
2342           n_left_to_next -= 1;
2343
2344           b0 = vlib_get_buffer (vm, bi0);
2345
2346           if (tcp_make_reset_in_place (vm, b0, vnet_buffer (b0)->tcp.flags,
2347                                        my_thread_index, is_ip4))
2348             {
2349               error0 = TCP_ERROR_LOOKUP_DROPS;
2350               next0 = TCP_RESET_NEXT_DROP;
2351               goto done;
2352             }
2353
2354           /* Prepare to send to IP lookup */
2355           vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
2356           next0 = TCP_RESET_NEXT_IP_LOOKUP;
2357
2358         done:
2359           b0->error = node->errors[error0];
2360           b0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
2361           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2362             {
2363               th0 = vlib_buffer_get_current (b0);
2364               if (is_ip4)
2365                 th0 = ip4_next_header ((ip4_header_t *) th0);
2366               else
2367                 th0 = ip6_next_header ((ip6_header_t *) th0);
2368               t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
2369               clib_memcpy_fast (&t0->tcp_header, th0,
2370                                 sizeof (t0->tcp_header));
2371             }
2372
2373           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2374                                            n_left_to_next, bi0, next0);
2375         }
2376       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2377     }
2378   return from_frame->n_vectors;
2379 }
2380
2381 VLIB_NODE_FN (tcp4_reset_node) (vlib_main_t * vm, vlib_node_runtime_t * node,
2382                                 vlib_frame_t * from_frame)
2383 {
2384   return tcp46_send_reset_inline (vm, node, from_frame, 1);
2385 }
2386
2387 VLIB_NODE_FN (tcp6_reset_node) (vlib_main_t * vm, vlib_node_runtime_t * node,
2388                                 vlib_frame_t * from_frame)
2389 {
2390   return tcp46_send_reset_inline (vm, node, from_frame, 0);
2391 }
2392
2393 /* *INDENT-OFF* */
2394 VLIB_REGISTER_NODE (tcp4_reset_node) = {
2395   .name = "tcp4-reset",
2396   .vector_size = sizeof (u32),
2397   .n_errors = TCP_N_ERROR,
2398   .error_strings = tcp_error_strings,
2399   .n_next_nodes = TCP_RESET_N_NEXT,
2400   .next_nodes = {
2401 #define _(s,n) [TCP_RESET_NEXT_##s] = n,
2402     foreach_tcp4_reset_next
2403 #undef _
2404   },
2405   .format_trace = format_tcp_tx_trace,
2406 };
2407 /* *INDENT-ON* */
2408
2409 /* *INDENT-OFF* */
2410 VLIB_REGISTER_NODE (tcp6_reset_node) = {
2411   .name = "tcp6-reset",
2412   .vector_size = sizeof (u32),
2413   .n_errors = TCP_N_ERROR,
2414   .error_strings = tcp_error_strings,
2415   .n_next_nodes = TCP_RESET_N_NEXT,
2416   .next_nodes = {
2417 #define _(s,n) [TCP_RESET_NEXT_##s] = n,
2418     foreach_tcp6_reset_next
2419 #undef _
2420   },
2421   .format_trace = format_tcp_tx_trace,
2422 };
2423 /* *INDENT-ON* */
2424
2425 /*
2426  * fd.io coding-style-patch-verification: ON
2427  *
2428  * Local Variables:
2429  * eval: (c-set-style "gnu")
2430  * End:
2431  */