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