Fix tcp tx buffer allocation
[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
19 vlib_node_registration_t tcp4_output_node;
20 vlib_node_registration_t tcp6_output_node;
21
22 typedef enum _tcp_output_next
23 {
24   TCP_OUTPUT_NEXT_DROP,
25   TCP_OUTPUT_NEXT_IP_LOOKUP,
26   TCP_OUTPUT_N_NEXT
27 } tcp_output_next_t;
28
29 #define foreach_tcp4_output_next                \
30   _ (DROP, "error-drop")                        \
31   _ (IP_LOOKUP, "ip4-lookup")
32
33 #define foreach_tcp6_output_next                \
34   _ (DROP, "error-drop")                        \
35   _ (IP_LOOKUP, "ip6-lookup")
36
37 static char *tcp_error_strings[] = {
38 #define tcp_error(n,s) s,
39 #include <vnet/tcp/tcp_error.def>
40 #undef tcp_error
41 };
42
43 typedef struct
44 {
45   tcp_header_t tcp_header;
46   tcp_connection_t tcp_connection;
47 } tcp_tx_trace_t;
48
49 u16 dummy_mtu = 1460;
50
51 u8 *
52 format_tcp_tx_trace (u8 * s, va_list * args)
53 {
54   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
55   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
56   tcp_tx_trace_t *t = va_arg (*args, tcp_tx_trace_t *);
57   uword indent = format_get_indent (s);
58
59   s = format (s, "%U\n%U%U",
60               format_tcp_header, &t->tcp_header, 128,
61               format_white_space, indent,
62               format_tcp_connection, &t->tcp_connection, 1);
63
64   return s;
65 }
66
67 static u8
68 tcp_window_compute_scale (u32 available_space)
69 {
70   u8 wnd_scale = 0;
71   while (wnd_scale < TCP_MAX_WND_SCALE
72          && (available_space >> wnd_scale) > TCP_WND_MAX)
73     wnd_scale++;
74   return wnd_scale;
75 }
76
77 /**
78  * Update max segment size we're able to process.
79  *
80  * The value is constrained by our interface's MTU and IP options. It is
81  * also what we advertise to our peer.
82  */
83 void
84 tcp_update_rcv_mss (tcp_connection_t * tc)
85 {
86   /* TODO find our iface MTU */
87   tc->mss = dummy_mtu;
88 }
89
90 /**
91  * TCP's initial window
92  */
93 always_inline u32
94 tcp_initial_wnd_unscaled (tcp_connection_t * tc)
95 {
96   /* RFC 6928 recommends the value lower. However at the time our connections
97    * are initialized, fifos may not be allocated. Therefore, advertise the
98    * smallest possible unscaled window size and update once fifos are
99    * assigned to the session.
100    */
101   /*
102      tcp_update_rcv_mss (tc);
103      TCP_IW_N_SEGMENTS * tc->mss;
104    */
105   return TCP_MIN_RX_FIFO_SIZE;
106 }
107
108 /**
109  * Compute initial window and scale factor. As per RFC1323, window field in
110  * SYN and SYN-ACK segments is never scaled.
111  */
112 u32
113 tcp_initial_window_to_advertise (tcp_connection_t * tc)
114 {
115   u32 max_fifo;
116
117   /* Initial wnd for SYN. Fifos are not allocated yet.
118    * Use some predefined value. For SYN-ACK we still want the
119    * scale to be computed in the same way */
120   max_fifo = TCP_MAX_RX_FIFO_SIZE;
121
122   tc->rcv_wscale = tcp_window_compute_scale (max_fifo);
123   tc->rcv_wnd = tcp_initial_wnd_unscaled (tc);
124
125   return clib_min (tc->rcv_wnd, TCP_WND_MAX);
126 }
127
128 /**
129  * Compute and return window to advertise, scaled as per RFC1323
130  */
131 u32
132 tcp_window_to_advertise (tcp_connection_t * tc, tcp_state_t state)
133 {
134   if (state < TCP_STATE_ESTABLISHED)
135     return tcp_initial_window_to_advertise (tc);
136
137   tcp_update_rcv_wnd (tc);
138
139   if (tc->rcv_wnd == 0)
140     {
141       tc->flags |= TCP_CONN_SENT_RCV_WND0;
142     }
143   else
144     {
145       tc->flags &= ~TCP_CONN_SENT_RCV_WND0;
146     }
147
148   return tc->rcv_wnd >> tc->rcv_wscale;
149 }
150
151 void
152 tcp_update_rcv_wnd (tcp_connection_t * tc)
153 {
154   i32 observed_wnd;
155   u32 available_space, max_fifo, wnd;
156
157   /*
158    * Figure out how much space we have available
159    */
160   available_space = stream_session_max_rx_enqueue (&tc->connection);
161   max_fifo = stream_session_rx_fifo_size (&tc->connection);
162
163   ASSERT (tc->rcv_opts.mss < max_fifo);
164   if (available_space < tc->rcv_opts.mss && available_space < max_fifo >> 3)
165     available_space = 0;
166
167   /*
168    * Use the above and what we know about what we've previously advertised
169    * to compute the new window
170    */
171   observed_wnd = (i32) tc->rcv_wnd - (tc->rcv_nxt - tc->rcv_las);
172   if (observed_wnd < 0)
173     observed_wnd = 0;
174
175   /* Bad. Thou shalt not shrink */
176   if (available_space < observed_wnd)
177     {
178       wnd = observed_wnd;
179       TCP_EVT_DBG (TCP_EVT_RCV_WND_SHRUNK, tc, observed_wnd, available_space);
180     }
181   else
182     {
183       wnd = available_space;
184     }
185
186   /* Make sure we have a multiple of rcv_wscale */
187   if (wnd && tc->rcv_wscale)
188     {
189       wnd &= ~(1 << tc->rcv_wscale);
190       if (wnd == 0)
191         wnd = 1 << tc->rcv_wscale;
192     }
193
194   tc->rcv_wnd = clib_min (wnd, TCP_WND_MAX << tc->rcv_wscale);
195 }
196
197 /**
198  * Write TCP options to segment.
199  */
200 u32
201 tcp_options_write (u8 * data, tcp_options_t * opts)
202 {
203   u32 opts_len = 0;
204   u32 buf, seq_len = 4;
205
206   if (tcp_opts_mss (opts))
207     {
208       *data++ = TCP_OPTION_MSS;
209       *data++ = TCP_OPTION_LEN_MSS;
210       buf = clib_host_to_net_u16 (opts->mss);
211       clib_memcpy (data, &buf, sizeof (opts->mss));
212       data += sizeof (opts->mss);
213       opts_len += TCP_OPTION_LEN_MSS;
214     }
215
216   if (tcp_opts_wscale (opts))
217     {
218       *data++ = TCP_OPTION_WINDOW_SCALE;
219       *data++ = TCP_OPTION_LEN_WINDOW_SCALE;
220       *data++ = opts->wscale;
221       opts_len += TCP_OPTION_LEN_WINDOW_SCALE;
222     }
223
224   if (tcp_opts_sack_permitted (opts))
225     {
226       *data++ = TCP_OPTION_SACK_PERMITTED;
227       *data++ = TCP_OPTION_LEN_SACK_PERMITTED;
228       opts_len += TCP_OPTION_LEN_SACK_PERMITTED;
229     }
230
231   if (tcp_opts_tstamp (opts))
232     {
233       *data++ = TCP_OPTION_TIMESTAMP;
234       *data++ = TCP_OPTION_LEN_TIMESTAMP;
235       buf = clib_host_to_net_u32 (opts->tsval);
236       clib_memcpy (data, &buf, sizeof (opts->tsval));
237       data += sizeof (opts->tsval);
238       buf = clib_host_to_net_u32 (opts->tsecr);
239       clib_memcpy (data, &buf, sizeof (opts->tsecr));
240       data += sizeof (opts->tsecr);
241       opts_len += TCP_OPTION_LEN_TIMESTAMP;
242     }
243
244   if (tcp_opts_sack (opts))
245     {
246       int i;
247       u32 n_sack_blocks = clib_min (vec_len (opts->sacks),
248                                     TCP_OPTS_MAX_SACK_BLOCKS);
249
250       if (n_sack_blocks != 0)
251         {
252           *data++ = TCP_OPTION_SACK_BLOCK;
253           *data++ = 2 + n_sack_blocks * TCP_OPTION_LEN_SACK_BLOCK;
254           for (i = 0; i < n_sack_blocks; i++)
255             {
256               buf = clib_host_to_net_u32 (opts->sacks[i].start);
257               clib_memcpy (data, &buf, seq_len);
258               data += seq_len;
259               buf = clib_host_to_net_u32 (opts->sacks[i].end);
260               clib_memcpy (data, &buf, seq_len);
261               data += seq_len;
262             }
263           opts_len += 2 + n_sack_blocks * TCP_OPTION_LEN_SACK_BLOCK;
264         }
265     }
266
267   /* Terminate TCP options */
268   if (opts_len % 4)
269     {
270       *data++ = TCP_OPTION_EOL;
271       opts_len += TCP_OPTION_LEN_EOL;
272     }
273
274   /* Pad with zeroes to a u32 boundary */
275   while (opts_len % 4)
276     {
277       *data++ = TCP_OPTION_NOOP;
278       opts_len += TCP_OPTION_LEN_NOOP;
279     }
280   return opts_len;
281 }
282
283 always_inline int
284 tcp_make_syn_options (tcp_options_t * opts, u8 wnd_scale)
285 {
286   u8 len = 0;
287
288   opts->flags |= TCP_OPTS_FLAG_MSS;
289   opts->mss = dummy_mtu;        /*XXX discover that */
290   len += TCP_OPTION_LEN_MSS;
291
292   opts->flags |= TCP_OPTS_FLAG_WSCALE;
293   opts->wscale = wnd_scale;
294   len += TCP_OPTION_LEN_WINDOW_SCALE;
295
296   opts->flags |= TCP_OPTS_FLAG_TSTAMP;
297   opts->tsval = tcp_time_now ();
298   opts->tsecr = 0;
299   len += TCP_OPTION_LEN_TIMESTAMP;
300
301   if (TCP_USE_SACKS)
302     {
303       opts->flags |= TCP_OPTS_FLAG_SACK_PERMITTED;
304       len += TCP_OPTION_LEN_SACK_PERMITTED;
305     }
306
307   /* Align to needed boundary */
308   len += (TCP_OPTS_ALIGN - len % TCP_OPTS_ALIGN) % TCP_OPTS_ALIGN;
309   return len;
310 }
311
312 always_inline int
313 tcp_make_synack_options (tcp_connection_t * tc, tcp_options_t * opts)
314 {
315   u8 len = 0;
316
317   opts->flags |= TCP_OPTS_FLAG_MSS;
318   opts->mss = tc->mss;
319   len += TCP_OPTION_LEN_MSS;
320
321   if (tcp_opts_wscale (&tc->rcv_opts))
322     {
323       opts->flags |= TCP_OPTS_FLAG_WSCALE;
324       opts->wscale = tc->rcv_wscale;
325       len += TCP_OPTION_LEN_WINDOW_SCALE;
326     }
327
328   if (tcp_opts_tstamp (&tc->rcv_opts))
329     {
330       opts->flags |= TCP_OPTS_FLAG_TSTAMP;
331       opts->tsval = tcp_time_now ();
332       opts->tsecr = tc->tsval_recent;
333       len += TCP_OPTION_LEN_TIMESTAMP;
334     }
335
336   if (tcp_opts_sack_permitted (&tc->rcv_opts))
337     {
338       opts->flags |= TCP_OPTS_FLAG_SACK_PERMITTED;
339       len += TCP_OPTION_LEN_SACK_PERMITTED;
340     }
341
342   /* Align to needed boundary */
343   len += (TCP_OPTS_ALIGN - len % TCP_OPTS_ALIGN) % TCP_OPTS_ALIGN;
344   return len;
345 }
346
347 always_inline int
348 tcp_make_established_options (tcp_connection_t * tc, tcp_options_t * opts)
349 {
350   u8 len = 0;
351
352   opts->flags = 0;
353
354   if (tcp_opts_tstamp (&tc->rcv_opts))
355     {
356       opts->flags |= TCP_OPTS_FLAG_TSTAMP;
357       opts->tsval = tcp_time_now ();
358       opts->tsecr = tc->tsval_recent;
359       len += TCP_OPTION_LEN_TIMESTAMP;
360     }
361   if (tcp_opts_sack_permitted (&tc->rcv_opts))
362     {
363       if (vec_len (tc->snd_sacks))
364         {
365           opts->flags |= TCP_OPTS_FLAG_SACK;
366           opts->sacks = tc->snd_sacks;
367           opts->n_sack_blocks = clib_min (vec_len (tc->snd_sacks),
368                                           TCP_OPTS_MAX_SACK_BLOCKS);
369           len += 2 + TCP_OPTION_LEN_SACK_BLOCK * opts->n_sack_blocks;
370         }
371     }
372
373   /* Align to needed boundary */
374   len += (TCP_OPTS_ALIGN - len % TCP_OPTS_ALIGN) % TCP_OPTS_ALIGN;
375   return len;
376 }
377
378 always_inline int
379 tcp_make_options (tcp_connection_t * tc, tcp_options_t * opts,
380                   tcp_state_t state)
381 {
382   switch (state)
383     {
384     case TCP_STATE_ESTABLISHED:
385     case TCP_STATE_FIN_WAIT_1:
386       return tcp_make_established_options (tc, opts);
387     case TCP_STATE_SYN_RCVD:
388       return tcp_make_synack_options (tc, opts);
389     case TCP_STATE_SYN_SENT:
390       return tcp_make_syn_options (opts, tc->rcv_wscale);
391     default:
392       clib_warning ("Not handled!");
393       return 0;
394     }
395 }
396
397 /**
398  * Update snd_mss to reflect the effective segment size that we can send
399  * by taking into account all TCP options, including SACKs
400  */
401 void
402 tcp_update_snd_mss (tcp_connection_t * tc)
403 {
404   /* Compute options to be used for connection. These may be reused when
405    * sending data or to compute the effective mss (snd_mss) */
406   tc->snd_opts_len =
407     tcp_make_options (tc, &tc->snd_opts, TCP_STATE_ESTABLISHED);
408
409   /* XXX check if MTU has been updated */
410   tc->snd_mss = clib_min (tc->mss, tc->rcv_opts.mss) - tc->snd_opts_len;
411   ASSERT (tc->snd_mss > 0);
412 }
413
414 void
415 tcp_init_mss (tcp_connection_t * tc)
416 {
417   u16 default_min_mss = 536;
418   tcp_update_rcv_mss (tc);
419
420   /* TODO cache mss and consider PMTU discovery */
421   tc->snd_mss = clib_min (tc->rcv_opts.mss, tc->mss);
422
423   if (tc->snd_mss < 45)
424     {
425       clib_warning ("snd mss is 0");
426       /* Assume that at least the min default mss works */
427       tc->snd_mss = default_min_mss;
428       tc->rcv_opts.mss = default_min_mss;
429     }
430
431   /* We should have enough space for 40 bytes of options */
432   ASSERT (tc->snd_mss > 45);
433
434   /* If we use timestamp option, account for it */
435   if (tcp_opts_tstamp (&tc->rcv_opts))
436     tc->snd_mss -= TCP_OPTION_LEN_TIMESTAMP;
437 }
438
439 always_inline int
440 tcp_get_free_buffer_index (tcp_main_t * tm, u32 * bidx)
441 {
442   u32 *my_tx_buffers, n_free_buffers;
443   u32 thread_index = vlib_get_thread_index ();
444   my_tx_buffers = tm->tx_buffers[thread_index];
445   if (PREDICT_FALSE (vec_len (my_tx_buffers) == 0))
446     {
447       n_free_buffers = VLIB_FRAME_SIZE;
448       vec_validate (my_tx_buffers, n_free_buffers - 1);
449       _vec_len (my_tx_buffers) =
450         vlib_buffer_alloc_from_free_list (vlib_get_main (), my_tx_buffers,
451                                           n_free_buffers,
452                                           VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
453       /* buffer shortage, report failure */
454       if (vec_len (my_tx_buffers) == 0)
455         {
456           clib_warning ("out of buffers");
457           return -1;
458         }
459       tm->tx_buffers[thread_index] = my_tx_buffers;
460     }
461   *bidx = my_tx_buffers[_vec_len (my_tx_buffers) - 1];
462   _vec_len (my_tx_buffers) -= 1;
463   return 0;
464 }
465
466 always_inline void
467 tcp_return_buffer (tcp_main_t * tm)
468 {
469   u32 *my_tx_buffers;
470   u32 thread_index = vlib_get_thread_index ();
471   my_tx_buffers = tm->tx_buffers[thread_index];
472   _vec_len (my_tx_buffers) += 1;
473 }
474
475 always_inline void
476 tcp_reuse_buffer (vlib_main_t * vm, vlib_buffer_t * b)
477 {
478   vlib_buffer_t *it = b;
479   do
480     {
481       it->current_data = 0;
482       it->current_length = 0;
483       it->total_length_not_including_first_buffer = 0;
484     }
485   while ((it->flags & VLIB_BUFFER_NEXT_PRESENT)
486          && (it = vlib_get_buffer (vm, it->next_buffer)));
487
488   /* Leave enough space for headers */
489   vlib_buffer_make_headroom (b, MAX_HDRS_LEN);
490   vnet_buffer (b)->tcp.flags = 0;
491 }
492
493 /**
494  * Prepare ACK
495  */
496 void
497 tcp_make_ack_i (tcp_connection_t * tc, vlib_buffer_t * b, tcp_state_t state,
498                 u8 flags)
499 {
500   tcp_options_t _snd_opts, *snd_opts = &_snd_opts;
501   u8 tcp_opts_len, tcp_hdr_opts_len;
502   tcp_header_t *th;
503   u16 wnd;
504
505   wnd = tcp_window_to_advertise (tc, state);
506
507   /* Make and write options */
508   tcp_opts_len = tcp_make_established_options (tc, snd_opts);
509   tcp_hdr_opts_len = tcp_opts_len + sizeof (tcp_header_t);
510
511   th = vlib_buffer_push_tcp (b, tc->c_lcl_port, tc->c_rmt_port, tc->snd_nxt,
512                              tc->rcv_nxt, tcp_hdr_opts_len, flags, wnd);
513
514   tcp_options_write ((u8 *) (th + 1), snd_opts);
515   vnet_buffer (b)->tcp.connection_index = tc->c_c_index;
516 }
517
518 /**
519  * Convert buffer to ACK
520  */
521 void
522 tcp_make_ack (tcp_connection_t * tc, vlib_buffer_t * b)
523 {
524   vlib_main_t *vm = vlib_get_main ();
525
526   tcp_reuse_buffer (vm, b);
527   tcp_make_ack_i (tc, b, TCP_STATE_ESTABLISHED, TCP_FLAG_ACK);
528   TCP_EVT_DBG (TCP_EVT_ACK_SENT, tc);
529   vnet_buffer (b)->tcp.flags = TCP_BUF_FLAG_ACK;
530   tc->rcv_las = tc->rcv_nxt;
531 }
532
533 /**
534  * Convert buffer to FIN-ACK
535  */
536 void
537 tcp_make_fin (tcp_connection_t * tc, vlib_buffer_t * b)
538 {
539   vlib_main_t *vm = vlib_get_main ();
540   u8 flags = 0;
541
542   tcp_reuse_buffer (vm, b);
543
544   flags = TCP_FLAG_FIN | TCP_FLAG_ACK;
545   tcp_make_ack_i (tc, b, TCP_STATE_ESTABLISHED, flags);
546
547   /* Reset flags, make sure ack is sent */
548   vnet_buffer (b)->tcp.flags &= ~TCP_BUF_FLAG_DUPACK;
549
550   tc->snd_nxt += 1;
551 }
552
553 /**
554  * Convert buffer to SYN-ACK
555  */
556 void
557 tcp_make_synack (tcp_connection_t * tc, vlib_buffer_t * b)
558 {
559   vlib_main_t *vm = vlib_get_main ();
560   tcp_options_t _snd_opts, *snd_opts = &_snd_opts;
561   u8 tcp_opts_len, tcp_hdr_opts_len;
562   tcp_header_t *th;
563   u16 initial_wnd;
564   u32 time_now;
565
566   memset (snd_opts, 0, sizeof (*snd_opts));
567
568   tcp_reuse_buffer (vm, b);
569
570   /* Set random initial sequence */
571   time_now = tcp_time_now ();
572
573   tc->iss = random_u32 (&time_now);
574   tc->snd_una = tc->iss;
575   tc->snd_nxt = tc->iss + 1;
576   tc->snd_una_max = tc->snd_nxt;
577
578   initial_wnd = tcp_initial_window_to_advertise (tc);
579
580   /* Make and write options */
581   tcp_opts_len = tcp_make_synack_options (tc, snd_opts);
582   tcp_hdr_opts_len = tcp_opts_len + sizeof (tcp_header_t);
583
584   th = vlib_buffer_push_tcp (b, tc->c_lcl_port, tc->c_rmt_port, tc->iss,
585                              tc->rcv_nxt, tcp_hdr_opts_len,
586                              TCP_FLAG_SYN | TCP_FLAG_ACK, initial_wnd);
587
588   tcp_options_write ((u8 *) (th + 1), snd_opts);
589
590   vnet_buffer (b)->tcp.connection_index = tc->c_c_index;
591   vnet_buffer (b)->tcp.flags = TCP_BUF_FLAG_ACK;
592
593   /* Init retransmit timer */
594   tcp_retransmit_timer_set (tc);
595   TCP_EVT_DBG (TCP_EVT_SYNACK_SENT, tc);
596 }
597
598 always_inline void
599 tcp_enqueue_to_ip_lookup (vlib_main_t * vm, vlib_buffer_t * b, u32 bi,
600                           u8 is_ip4)
601 {
602   u32 *to_next, next_index;
603   vlib_frame_t *f;
604
605   b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
606   b->error = 0;
607
608   /* Default FIB for now */
609   vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
610
611   /* Send to IP lookup */
612   next_index = is_ip4 ? ip4_lookup_node.index : ip6_lookup_node.index;
613   f = vlib_get_frame_to_node (vm, next_index);
614
615   /* Enqueue the packet */
616   to_next = vlib_frame_vector_args (f);
617   to_next[0] = bi;
618   f->n_vectors = 1;
619   vlib_put_frame_to_node (vm, next_index, f);
620 }
621
622 int
623 tcp_make_reset_in_place (vlib_main_t * vm, vlib_buffer_t * b0,
624                          tcp_state_t state, u8 thread_index, u8 is_ip4)
625 {
626   ip4_header_t *ih4;
627   ip6_header_t *ih6;
628   tcp_header_t *th0;
629   ip4_address_t src_ip40, dst_ip40;
630   ip6_address_t src_ip60, dst_ip60;
631   u16 src_port, dst_port;
632   u32 tmp;
633   u32 seq, ack;
634   u8 flags;
635
636   /* Find IP and TCP headers */
637   th0 = tcp_buffer_hdr (b0);
638
639   /* Save src and dst ip */
640   if (is_ip4)
641     {
642       ih4 = vlib_buffer_get_current (b0);
643       ASSERT ((ih4->ip_version_and_header_length & 0xF0) == 0x40);
644       src_ip40.as_u32 = ih4->src_address.as_u32;
645       dst_ip40.as_u32 = ih4->dst_address.as_u32;
646     }
647   else
648     {
649       ih6 = vlib_buffer_get_current (b0);
650       ASSERT ((ih6->ip_version_traffic_class_and_flow_label & 0xF0) == 0x60);
651       clib_memcpy (&src_ip60, &ih6->src_address, sizeof (ip6_address_t));
652       clib_memcpy (&dst_ip60, &ih6->dst_address, sizeof (ip6_address_t));
653     }
654
655   src_port = th0->src_port;
656   dst_port = th0->dst_port;
657
658   /* Try to determine what/why we're actually resetting */
659   if (state == TCP_STATE_CLOSED)
660     {
661       if (!tcp_syn (th0))
662         return -1;
663
664       tmp = clib_net_to_host_u32 (th0->seq_number);
665
666       /* Got a SYN for no listener. */
667       flags = TCP_FLAG_RST | TCP_FLAG_ACK;
668       ack = clib_host_to_net_u32 (tmp + 1);
669       seq = 0;
670     }
671   else
672     {
673       flags = TCP_FLAG_RST;
674       seq = th0->ack_number;
675       ack = 0;
676     }
677
678   tcp_reuse_buffer (vm, b0);
679   th0 = vlib_buffer_push_tcp_net_order (b0, dst_port, src_port, seq, ack,
680                                         sizeof (tcp_header_t), flags, 0);
681
682   if (is_ip4)
683     {
684       ih4 = vlib_buffer_push_ip4 (vm, b0, &dst_ip40, &src_ip40,
685                                   IP_PROTOCOL_TCP, 1);
686       th0->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ih4);
687     }
688   else
689     {
690       int bogus = ~0;
691       ih6 = vlib_buffer_push_ip6 (vm, b0, &dst_ip60, &src_ip60,
692                                   IP_PROTOCOL_TCP);
693       th0->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b0, ih6, &bogus);
694       ASSERT (!bogus);
695     }
696
697   return 0;
698 }
699
700 /**
701  *  Send reset without reusing existing buffer
702  */
703 void
704 tcp_send_reset (tcp_connection_t * tc, vlib_buffer_t * pkt, u8 is_ip4)
705 {
706   vlib_buffer_t *b;
707   u32 bi;
708   tcp_main_t *tm = vnet_get_tcp_main ();
709   vlib_main_t *vm = vlib_get_main ();
710   u8 tcp_hdr_len, flags = 0;
711   tcp_header_t *th, *pkt_th;
712   u32 seq, ack;
713   ip4_header_t *ih4, *pkt_ih4;
714   ip6_header_t *ih6, *pkt_ih6;
715
716   if (PREDICT_FALSE (tcp_get_free_buffer_index (tm, &bi)))
717     return;
718
719   b = vlib_get_buffer (vm, bi);
720
721   /* Leave enough space for headers */
722   vlib_buffer_make_headroom (b, MAX_HDRS_LEN);
723
724   /* Make and write options */
725   tcp_hdr_len = sizeof (tcp_header_t);
726
727   if (is_ip4)
728     {
729       pkt_ih4 = vlib_buffer_get_current (pkt);
730       pkt_th = ip4_next_header (pkt_ih4);
731     }
732   else
733     {
734       pkt_ih6 = vlib_buffer_get_current (pkt);
735       pkt_th = ip6_next_header (pkt_ih6);
736     }
737
738   if (tcp_ack (pkt_th))
739     {
740       flags = TCP_FLAG_RST;
741       seq = pkt_th->ack_number;
742       ack = (tc && tc->state >= TCP_STATE_SYN_RCVD) ? tc->rcv_nxt : 0;
743     }
744   else
745     {
746       flags = TCP_FLAG_RST | TCP_FLAG_ACK;
747       seq = 0;
748       ack = clib_host_to_net_u32 (vnet_buffer (pkt)->tcp.seq_end);
749     }
750
751   th = vlib_buffer_push_tcp_net_order (b, pkt_th->dst_port, pkt_th->src_port,
752                                        seq, ack, tcp_hdr_len, flags, 0);
753
754   /* Swap src and dst ip */
755   if (is_ip4)
756     {
757       ASSERT ((pkt_ih4->ip_version_and_header_length & 0xF0) == 0x40);
758       ih4 = vlib_buffer_push_ip4 (vm, b, &pkt_ih4->dst_address,
759                                   &pkt_ih4->src_address, IP_PROTOCOL_TCP, 1);
760       th->checksum = ip4_tcp_udp_compute_checksum (vm, b, ih4);
761     }
762   else
763     {
764       int bogus = ~0;
765       pkt_ih6 = (ip6_header_t *) (pkt_th - 1);
766       ASSERT ((pkt_ih6->ip_version_traffic_class_and_flow_label & 0xF0) ==
767               0x60);
768       ih6 =
769         vlib_buffer_push_ip6 (vm, b, &pkt_ih6->dst_address,
770                               &pkt_ih6->src_address, IP_PROTOCOL_TCP);
771       th->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b, ih6, &bogus);
772       ASSERT (!bogus);
773     }
774
775   tcp_enqueue_to_ip_lookup (vm, b, bi, is_ip4);
776   TCP_EVT_DBG (TCP_EVT_RST_SENT, tc);
777 }
778
779 void
780 tcp_push_ip_hdr (tcp_main_t * tm, tcp_connection_t * tc, vlib_buffer_t * b)
781 {
782   tcp_header_t *th = vlib_buffer_get_current (b);
783   vlib_main_t *vm = vlib_get_main ();
784   if (tc->c_is_ip4)
785     {
786       ip4_header_t *ih;
787       ih = vlib_buffer_push_ip4 (vm, b, &tc->c_lcl_ip4,
788                                  &tc->c_rmt_ip4, IP_PROTOCOL_TCP, 1);
789       th->checksum = ip4_tcp_udp_compute_checksum (vm, b, ih);
790     }
791   else
792     {
793       ip6_header_t *ih;
794       int bogus = ~0;
795
796       ih = vlib_buffer_push_ip6 (vm, b, &tc->c_lcl_ip6,
797                                  &tc->c_rmt_ip6, IP_PROTOCOL_TCP);
798       th->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b, ih, &bogus);
799       ASSERT (!bogus);
800     }
801 }
802
803 /**
804  *  Send SYN
805  *
806  *  Builds a SYN packet for a half-open connection and sends it to ipx_lookup.
807  *  The packet is not forwarded through tcpx_output to avoid doing lookups
808  *  in the half_open pool.
809  */
810 void
811 tcp_send_syn (tcp_connection_t * tc)
812 {
813   vlib_buffer_t *b;
814   u32 bi;
815   tcp_main_t *tm = vnet_get_tcp_main ();
816   vlib_main_t *vm = vlib_get_main ();
817   u8 tcp_hdr_opts_len, tcp_opts_len;
818   tcp_header_t *th;
819   u32 time_now;
820   u16 initial_wnd;
821   tcp_options_t snd_opts;
822
823   if (PREDICT_FALSE (tcp_get_free_buffer_index (tm, &bi)))
824     return;
825
826   b = vlib_get_buffer (vm, bi);
827
828   /* Leave enough space for headers */
829   vlib_buffer_make_headroom (b, MAX_HDRS_LEN);
830
831   /* Set random initial sequence */
832   time_now = tcp_time_now ();
833
834   tc->iss = random_u32 (&time_now);
835   tc->snd_una = tc->iss;
836   tc->snd_una_max = tc->snd_nxt = tc->iss + 1;
837
838   initial_wnd = tcp_initial_window_to_advertise (tc);
839
840   /* Make and write options */
841   memset (&snd_opts, 0, sizeof (snd_opts));
842   tcp_opts_len = tcp_make_syn_options (&snd_opts, tc->rcv_wscale);
843   tcp_hdr_opts_len = tcp_opts_len + sizeof (tcp_header_t);
844
845   th = vlib_buffer_push_tcp (b, tc->c_lcl_port, tc->c_rmt_port, tc->iss,
846                              tc->rcv_nxt, tcp_hdr_opts_len, TCP_FLAG_SYN,
847                              initial_wnd);
848
849   tcp_options_write ((u8 *) (th + 1), &snd_opts);
850
851   /* Measure RTT with this */
852   tc->rtt_ts = tcp_time_now ();
853   tc->rtt_seq = tc->snd_nxt;
854
855   /* Start retransmit trimer  */
856   tcp_timer_set (tc, TCP_TIMER_RETRANSMIT_SYN, tc->rto * TCP_TO_TIMER_TICK);
857   tc->rto_boff = 0;
858
859   /* Set the connection establishment timer */
860   tcp_timer_set (tc, TCP_TIMER_ESTABLISH, TCP_ESTABLISH_TIME);
861
862   tcp_push_ip_hdr (tm, tc, b);
863   tcp_enqueue_to_ip_lookup (vm, b, bi, tc->c_is_ip4);
864   TCP_EVT_DBG (TCP_EVT_SYN_SENT, tc);
865 }
866
867 always_inline void
868 tcp_enqueue_to_output_i (vlib_main_t * vm, vlib_buffer_t * b, u32 bi,
869                          u8 is_ip4, u8 flush)
870 {
871   tcp_main_t *tm = vnet_get_tcp_main ();
872   u32 thread_index = vlib_get_thread_index ();
873   u32 *to_next, next_index;
874   vlib_frame_t *f;
875
876   b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
877   b->error = 0;
878
879   /* Decide where to send the packet */
880   next_index = is_ip4 ? tcp4_output_node.index : tcp6_output_node.index;
881
882   /* Initialize the trajectory trace, if configured */
883   if (VLIB_BUFFER_TRACE_TRAJECTORY > 0)
884     {
885       b->pre_data[0] = 1;
886       b->pre_data[1] = next_index;
887     }
888
889   /* Get frame to v4/6 output node */
890   f = tm->tx_frames[!is_ip4][thread_index];
891   if (!f)
892     {
893       f = vlib_get_frame_to_node (vm, next_index);
894       ASSERT (f);
895       tm->tx_frames[!is_ip4][thread_index] = f;
896     }
897   to_next = vlib_frame_vector_args (f);
898   to_next[f->n_vectors] = bi;
899   f->n_vectors += 1;
900   if (flush || f->n_vectors == VLIB_FRAME_SIZE)
901     {
902       vlib_put_frame_to_node (vm, next_index, f);
903       tm->tx_frames[!is_ip4][thread_index] = 0;
904     }
905 }
906
907 always_inline void
908 tcp_enqueue_to_output (vlib_main_t * vm, vlib_buffer_t * b, u32 bi, u8 is_ip4)
909 {
910   tcp_enqueue_to_output_i (vm, b, bi, is_ip4, 0);
911 }
912
913 always_inline void
914 tcp_enqueue_to_output_now (vlib_main_t * vm, vlib_buffer_t * b, u32 bi,
915                            u8 is_ip4)
916 {
917   tcp_enqueue_to_output_i (vm, b, bi, is_ip4, 1);
918 }
919
920 /**
921  * Flush tx frame populated by retransmits and timer pops
922  */
923 void
924 tcp_flush_frame_to_output (vlib_main_t * vm, u8 thread_index, u8 is_ip4)
925 {
926   if (tcp_main.tx_frames[!is_ip4][thread_index])
927     {
928       u32 next_index;
929       next_index = is_ip4 ? tcp4_output_node.index : tcp6_output_node.index;
930       vlib_put_frame_to_node (vm, next_index,
931                               tcp_main.tx_frames[!is_ip4][thread_index]);
932       tcp_main.tx_frames[!is_ip4][thread_index] = 0;
933     }
934 }
935
936 /**
937  * Flush both v4 and v6 tx frames for thread index
938  */
939 void
940 tcp_flush_frames_to_output (u8 thread_index)
941 {
942   vlib_main_t *vm = vlib_get_main ();
943   tcp_flush_frame_to_output (vm, thread_index, 1);
944   tcp_flush_frame_to_output (vm, thread_index, 0);
945 }
946
947 /**
948  *  Send FIN
949  */
950 void
951 tcp_send_fin (tcp_connection_t * tc)
952 {
953   vlib_buffer_t *b;
954   u32 bi;
955   tcp_main_t *tm = vnet_get_tcp_main ();
956   vlib_main_t *vm = vlib_get_main ();
957
958   if (PREDICT_FALSE (tcp_get_free_buffer_index (tm, &bi)))
959     return;
960   b = vlib_get_buffer (vm, bi);
961
962   /* Leave enough space for headers */
963   vlib_buffer_make_headroom (b, MAX_HDRS_LEN);
964
965   tcp_make_fin (tc, b);
966   tcp_enqueue_to_output_now (vm, b, bi, tc->c_is_ip4);
967   tc->flags |= TCP_CONN_FINSNT;
968   tcp_retransmit_timer_force_update (tc);
969   TCP_EVT_DBG (TCP_EVT_FIN_SENT, tc);
970 }
971
972 always_inline u8
973 tcp_make_state_flags (tcp_state_t next_state)
974 {
975   switch (next_state)
976     {
977     case TCP_STATE_ESTABLISHED:
978       return TCP_FLAG_ACK;
979     case TCP_STATE_SYN_RCVD:
980       return TCP_FLAG_SYN | TCP_FLAG_ACK;
981     case TCP_STATE_SYN_SENT:
982       return TCP_FLAG_SYN;
983     case TCP_STATE_LAST_ACK:
984     case TCP_STATE_FIN_WAIT_1:
985       return TCP_FLAG_FIN;
986     default:
987       clib_warning ("Shouldn't be here!");
988     }
989   return 0;
990 }
991
992 /**
993  * Push TCP header and update connection variables
994  */
995 static void
996 tcp_push_hdr_i (tcp_connection_t * tc, vlib_buffer_t * b,
997                 tcp_state_t next_state, u8 compute_opts)
998 {
999   u32 advertise_wnd, data_len;
1000   u8 tcp_hdr_opts_len, opts_write_len, flags;
1001   tcp_header_t *th;
1002
1003   data_len = b->current_length + b->total_length_not_including_first_buffer;
1004   vnet_buffer (b)->tcp.flags = 0;
1005
1006   if (compute_opts)
1007     tc->snd_opts_len = tcp_make_options (tc, &tc->snd_opts, tc->state);
1008
1009   tcp_hdr_opts_len = tc->snd_opts_len + sizeof (tcp_header_t);
1010   advertise_wnd = tcp_window_to_advertise (tc, next_state);
1011   flags = tcp_make_state_flags (next_state);
1012
1013   /* Push header and options */
1014   th = vlib_buffer_push_tcp (b, tc->c_lcl_port, tc->c_rmt_port, tc->snd_nxt,
1015                              tc->rcv_nxt, tcp_hdr_opts_len, flags,
1016                              advertise_wnd);
1017   opts_write_len = tcp_options_write ((u8 *) (th + 1), &tc->snd_opts);
1018
1019   ASSERT (opts_write_len == tc->snd_opts_len);
1020   vnet_buffer (b)->tcp.connection_index = tc->c_c_index;
1021
1022   /*
1023    * Update connection variables
1024    */
1025
1026   tc->snd_nxt += data_len;
1027   tc->rcv_las = tc->rcv_nxt;
1028
1029   /* TODO this is updated in output as well ... */
1030   if (seq_gt (tc->snd_nxt, tc->snd_una_max))
1031     {
1032       tc->snd_una_max = tc->snd_nxt;
1033       tcp_validate_txf_size (tc, tc->snd_una_max - tc->snd_una);
1034     }
1035
1036   TCP_EVT_DBG (TCP_EVT_PKTIZE, tc);
1037 }
1038
1039 void
1040 tcp_send_ack (tcp_connection_t * tc)
1041 {
1042   tcp_main_t *tm = vnet_get_tcp_main ();
1043   vlib_main_t *vm = vlib_get_main ();
1044
1045   vlib_buffer_t *b;
1046   u32 bi;
1047
1048   /* Get buffer */
1049   if (PREDICT_FALSE (tcp_get_free_buffer_index (tm, &bi)))
1050     return;
1051   b = vlib_get_buffer (vm, bi);
1052
1053   /* Fill in the ACK */
1054   tcp_make_ack (tc, b);
1055   tcp_enqueue_to_output (vm, b, bi, tc->c_is_ip4);
1056 }
1057
1058 /* Send delayed ACK when timer expires */
1059 void
1060 tcp_timer_delack_handler (u32 index)
1061 {
1062   u32 thread_index = vlib_get_thread_index ();
1063   tcp_connection_t *tc;
1064
1065   tc = tcp_connection_get (index, thread_index);
1066   tc->timers[TCP_TIMER_DELACK] = TCP_TIMER_HANDLE_INVALID;
1067   tcp_send_ack (tc);
1068 }
1069
1070 /** Build a retransmit segment
1071  *
1072  * @return the number of bytes in the segment or 0 if there's nothing to
1073  *         retransmit
1074  */
1075 u32
1076 tcp_prepare_retransmit_segment (tcp_connection_t * tc, vlib_buffer_t * b,
1077                                 u32 offset, u32 max_bytes)
1078 {
1079   vlib_main_t *vm = vlib_get_main ();
1080   int n_bytes = 0;
1081   u32 start;
1082
1083   tcp_reuse_buffer (vm, b);
1084
1085   ASSERT (tc->state >= TCP_STATE_ESTABLISHED);
1086   ASSERT (max_bytes != 0);
1087
1088   max_bytes = clib_min (tc->snd_mss, max_bytes);
1089   start = tc->snd_una + offset;
1090
1091   /* Start is beyond snd_congestion */
1092   if (seq_geq (start, tc->snd_congestion))
1093     goto done;
1094
1095   /* Don't overshoot snd_congestion */
1096   if (seq_gt (start + max_bytes, tc->snd_congestion))
1097     {
1098       max_bytes = tc->snd_congestion - start;
1099       if (max_bytes == 0)
1100         goto done;
1101     }
1102
1103   tc->snd_opts_len = tcp_make_options (tc, &tc->snd_opts, tc->state);
1104
1105   ASSERT (max_bytes <= tc->snd_mss);
1106
1107   n_bytes = stream_session_peek_bytes (&tc->connection,
1108                                        vlib_buffer_get_current (b), offset,
1109                                        max_bytes);
1110   ASSERT (n_bytes > 0);
1111   b->current_length = n_bytes;
1112   tcp_push_hdr_i (tc, b, tc->state, 0);
1113
1114   if (tcp_in_fastrecovery (tc))
1115     tc->snd_rxt_bytes += n_bytes;
1116
1117 done:
1118   TCP_EVT_DBG (TCP_EVT_CC_RTX, tc, offset, n_bytes);
1119   return n_bytes;
1120 }
1121
1122 /**
1123  * Reset congestion control, switch cwnd to loss window and try again.
1124  */
1125 static void
1126 tcp_rtx_timeout_cc (tcp_connection_t * tc)
1127 {
1128   tc->prev_ssthresh = tc->ssthresh;
1129   tc->prev_cwnd = tc->cwnd;
1130
1131   /* Cleanly recover cc (also clears up fast retransmit) */
1132   if (tcp_in_fastrecovery (tc))
1133     tcp_cc_fastrecovery_exit (tc);
1134
1135   /* Start again from the beginning */
1136   tc->ssthresh = clib_max (tcp_flight_size (tc) / 2, 2 * tc->snd_mss);
1137   tc->cwnd = tcp_loss_wnd (tc);
1138   tc->snd_congestion = tc->snd_una_max;
1139
1140   tcp_recovery_on (tc);
1141 }
1142
1143 static void
1144 tcp_timer_retransmit_handler_i (u32 index, u8 is_syn)
1145 {
1146   tcp_main_t *tm = vnet_get_tcp_main ();
1147   vlib_main_t *vm = vlib_get_main ();
1148   u32 thread_index = vlib_get_thread_index ();
1149   tcp_connection_t *tc;
1150   vlib_buffer_t *b;
1151   u32 bi, n_bytes;
1152
1153   if (is_syn)
1154     {
1155       tc = tcp_half_open_connection_get (index);
1156       tc->timers[TCP_TIMER_RETRANSMIT_SYN] = TCP_TIMER_HANDLE_INVALID;
1157     }
1158   else
1159     {
1160       tc = tcp_connection_get (index, thread_index);
1161       tc->timers[TCP_TIMER_RETRANSMIT] = TCP_TIMER_HANDLE_INVALID;
1162     }
1163
1164   if (!tcp_in_recovery (tc) && tc->rto_boff > 0
1165       && tc->state >= TCP_STATE_ESTABLISHED)
1166     {
1167       tc->rto_boff = 0;
1168       tcp_update_rto (tc);
1169     }
1170
1171   /* Increment RTO backoff (also equal to number of retries) */
1172   tc->rto_boff += 1;
1173
1174   /* Go back to first un-acked byte */
1175   tc->snd_nxt = tc->snd_una;
1176
1177   if (PREDICT_FALSE (tcp_get_free_buffer_index (tm, &bi)))
1178     return;
1179
1180   b = vlib_get_buffer (vm, bi);
1181
1182   if (tc->state >= TCP_STATE_ESTABLISHED)
1183     {
1184       /* Lost FIN, retransmit and return */
1185       if (tc->flags & TCP_CONN_FINSNT)
1186         {
1187           tcp_return_buffer (tm);
1188           tcp_send_fin (tc);
1189           return;
1190         }
1191
1192       /* First retransmit timeout */
1193       if (tc->rto_boff == 1)
1194         tcp_rtx_timeout_cc (tc);
1195
1196       /* Exponential backoff */
1197       tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);
1198
1199       TCP_EVT_DBG (TCP_EVT_CC_EVT, tc, 1);
1200
1201       /* Send one segment */
1202       n_bytes = tcp_prepare_retransmit_segment (tc, b, 0, tc->snd_mss);
1203       /* TODO be less aggressive about this */
1204       scoreboard_clear (&tc->sack_sb);
1205
1206       if (n_bytes == 0)
1207         {
1208           clib_warning ("could not retransmit anything");
1209           clib_warning ("%U", format_tcp_connection, tc, 2);
1210
1211           /* Try again eventually */
1212           tcp_retransmit_timer_set (tc);
1213           ASSERT (0 || (tc->rto_boff > 1
1214                         && tc->snd_una == tc->snd_congestion));
1215           tcp_return_buffer (tm);
1216           return;
1217         }
1218
1219       /* For first retransmit, record timestamp (Eifel detection RFC3522) */
1220       if (tc->rto_boff == 1)
1221         tc->snd_rxt_ts = tcp_time_now ();
1222     }
1223   /* Retransmit for SYN/SYNACK */
1224   else if (tc->state == TCP_STATE_SYN_RCVD || tc->state == TCP_STATE_SYN_SENT)
1225     {
1226       /* Half-open connection actually moved to established but we were
1227        * waiting for syn retransmit to pop to call cleanup from the right
1228        * thread. */
1229       if (tc->flags & TCP_CONN_HALF_OPEN_DONE)
1230         {
1231           ASSERT (tc->state == TCP_STATE_SYN_SENT);
1232           if (tcp_half_open_connection_cleanup (tc))
1233             {
1234               clib_warning ("could not remove half-open connection");
1235               ASSERT (0);
1236             }
1237           tcp_return_buffer (tm);
1238           return;
1239         }
1240
1241       /* Try without increasing RTO a number of times. If this fails,
1242        * start growing RTO exponentially */
1243       if (tc->rto_boff > TCP_RTO_SYN_RETRIES)
1244         tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);
1245
1246       vlib_buffer_make_headroom (b, MAX_HDRS_LEN);
1247       tcp_push_hdr_i (tc, b, tc->state, 1);
1248
1249       /* Account for the SYN */
1250       tc->snd_nxt += 1;
1251       tc->rtt_ts = 0;
1252       TCP_EVT_DBG (TCP_EVT_SYN_RXT, tc,
1253                    (tc->state == TCP_STATE_SYN_SENT ? 0 : 1));
1254     }
1255   else
1256     {
1257       ASSERT (tc->state == TCP_STATE_CLOSED);
1258       clib_warning ("connection closed ...");
1259       tcp_return_buffer (tm);
1260       return;
1261     }
1262
1263   if (!is_syn)
1264     {
1265       tcp_enqueue_to_output (vm, b, bi, tc->c_is_ip4);
1266
1267       /* Re-enable retransmit timer */
1268       tcp_retransmit_timer_set (tc);
1269     }
1270   else
1271     {
1272       ASSERT (tc->state == TCP_STATE_SYN_SENT);
1273
1274       /* This goes straight to ipx_lookup */
1275       tcp_push_ip_hdr (tm, tc, b);
1276       tcp_enqueue_to_ip_lookup (vm, b, bi, tc->c_is_ip4);
1277
1278       /* Re-enable retransmit timer */
1279       tcp_timer_set (tc, TCP_TIMER_RETRANSMIT_SYN,
1280                      tc->rto * TCP_TO_TIMER_TICK);
1281     }
1282 }
1283
1284 void
1285 tcp_timer_retransmit_handler (u32 index)
1286 {
1287   tcp_timer_retransmit_handler_i (index, 0);
1288 }
1289
1290 void
1291 tcp_timer_retransmit_syn_handler (u32 index)
1292 {
1293   tcp_timer_retransmit_handler_i (index, 1);
1294 }
1295
1296 /**
1297  * Got 0 snd_wnd from peer, try to do something about it.
1298  *
1299  */
1300 void
1301 tcp_timer_persist_handler (u32 index)
1302 {
1303   tcp_main_t *tm = vnet_get_tcp_main ();
1304   vlib_main_t *vm = vlib_get_main ();
1305   u32 thread_index = vlib_get_thread_index ();
1306   tcp_connection_t *tc;
1307   vlib_buffer_t *b;
1308   u32 bi, old_snd_nxt;
1309   int n_bytes = 0;
1310
1311   tc = tcp_connection_get_if_valid (index, thread_index);
1312
1313   if (!tc)
1314     return;
1315
1316   /* Make sure timer handle is set to invalid */
1317   tc->timers[TCP_TIMER_PERSIST] = TCP_TIMER_HANDLE_INVALID;
1318
1319   /* Problem already solved or worse */
1320   if (tc->state == TCP_STATE_CLOSED || tc->state > TCP_STATE_ESTABLISHED
1321       || tc->snd_wnd > tc->snd_mss || tcp_in_recovery (tc))
1322     return;
1323
1324   /* Increment RTO backoff */
1325   tc->rto_boff += 1;
1326   tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);
1327
1328   /* Try to force the first unsent segment  */
1329   if (PREDICT_FALSE (tcp_get_free_buffer_index (tm, &bi)))
1330     return;
1331
1332   b = vlib_get_buffer (vm, bi);
1333
1334   tcp_validate_txf_size (tc, tc->snd_una_max - tc->snd_una);
1335   tc->snd_opts_len = tcp_make_options (tc, &tc->snd_opts, tc->state);
1336   n_bytes = stream_session_peek_bytes (&tc->connection,
1337                                        vlib_buffer_get_current (b),
1338                                        tc->snd_una_max - tc->snd_una,
1339                                        tc->snd_mss);
1340   /* Nothing to send */
1341   if (n_bytes <= 0)
1342     {
1343       // clib_warning ("persist found nothing to send");
1344       tcp_return_buffer (tm);
1345       return;
1346     }
1347
1348   b->current_length = n_bytes;
1349   ASSERT (tc->snd_nxt == tc->snd_una_max || tc->rto_boff > 1
1350           || tcp_timer_is_active (tc, TCP_TIMER_RETRANSMIT));
1351
1352   /* Allow updating of snd_una_max but don't update snd_nxt */
1353   old_snd_nxt = tc->snd_nxt;
1354   tcp_push_hdr_i (tc, b, tc->state, 0);
1355   tc->snd_nxt = old_snd_nxt;
1356   tcp_enqueue_to_output (vm, b, bi, tc->c_is_ip4);
1357
1358   /* Re-enable persist timer */
1359   tcp_persist_timer_set (tc);
1360 }
1361
1362 /**
1363  * Retransmit first unacked segment
1364  */
1365 void
1366 tcp_retransmit_first_unacked (tcp_connection_t * tc)
1367 {
1368   tcp_main_t *tm = vnet_get_tcp_main ();
1369   vlib_main_t *vm = vlib_get_main ();
1370   vlib_buffer_t *b;
1371   u32 bi, n_bytes, old_snd_nxt;
1372
1373   old_snd_nxt = tc->snd_nxt;
1374   tc->snd_nxt = tc->snd_una;
1375
1376   /* Get buffer */
1377   if (PREDICT_FALSE (tcp_get_free_buffer_index (tm, &bi)))
1378     return;
1379
1380   b = vlib_get_buffer (vm, bi);
1381
1382   TCP_EVT_DBG (TCP_EVT_CC_EVT, tc, 2);
1383
1384   n_bytes = tcp_prepare_retransmit_segment (tc, b, 0, tc->snd_mss);
1385   if (n_bytes == 0)
1386     {
1387       tcp_return_buffer (tm);
1388       goto done;
1389     }
1390
1391   tcp_enqueue_to_output (vm, b, bi, tc->c_is_ip4);
1392
1393 done:
1394   tc->snd_nxt = old_snd_nxt;
1395 }
1396
1397 /**
1398  * Do fast retransmit with SACKs
1399  */
1400 void
1401 tcp_fast_retransmit_sack (tcp_connection_t * tc)
1402 {
1403   tcp_main_t *tm = vnet_get_tcp_main ();
1404   vlib_main_t *vm = vlib_get_main ();
1405   u32 n_written = 0, offset = 0, max_bytes;
1406   vlib_buffer_t *b;
1407   sack_scoreboard_hole_t *hole;
1408   sack_scoreboard_t *sb;
1409   u32 bi, old_snd_nxt;
1410   int snd_space;
1411   u8 snd_limited = 0, can_rescue = 0;
1412
1413   ASSERT (tcp_in_fastrecovery (tc));
1414   TCP_EVT_DBG (TCP_EVT_CC_EVT, tc, 0);
1415
1416   old_snd_nxt = tc->snd_nxt;
1417   sb = &tc->sack_sb;
1418   snd_space = tcp_available_snd_space (tc);
1419
1420   hole = scoreboard_get_hole (sb, sb->cur_rxt_hole);
1421   while (hole && snd_space > 0)
1422     {
1423       if (PREDICT_FALSE (tcp_get_free_buffer_index (tm, &bi)))
1424         return;
1425
1426       b = vlib_get_buffer (vm, bi);
1427       hole = scoreboard_next_rxt_hole (sb, hole,
1428                                        tcp_fastrecovery_sent_1_smss (tc),
1429                                        &can_rescue, &snd_limited);
1430       if (!hole)
1431         {
1432           if (!can_rescue || !(seq_lt (sb->rescue_rxt, tc->snd_una)
1433                                || seq_gt (sb->rescue_rxt,
1434                                           tc->snd_congestion)))
1435             break;
1436
1437           /* If rescue rxt undefined or less than snd_una then one segment of
1438            * up to SMSS octets that MUST include the highest outstanding
1439            * unSACKed sequence number SHOULD be returned, and RescueRxt set to
1440            * RecoveryPoint. HighRxt MUST NOT be updated.
1441            */
1442           max_bytes = clib_min (tc->snd_mss, snd_space);
1443           offset = tc->snd_congestion - tc->snd_una - max_bytes;
1444           sb->rescue_rxt = tc->snd_congestion;
1445           tc->snd_nxt = tc->snd_una + offset;
1446           tcp_prepare_retransmit_segment (tc, b, offset, max_bytes);
1447           tcp_enqueue_to_output (vm, b, bi, tc->c_is_ip4);
1448           break;
1449         }
1450
1451       max_bytes = snd_limited ? tc->snd_mss : hole->end - sb->high_rxt;
1452       offset = sb->high_rxt - tc->snd_una;
1453       tc->snd_nxt = tc->snd_una + offset;
1454       n_written = tcp_prepare_retransmit_segment (tc, b, offset, max_bytes);
1455
1456       /* Nothing left to retransmit */
1457       if (n_written == 0)
1458         {
1459           tcp_return_buffer (tm);
1460           break;
1461         }
1462
1463       sb->high_rxt += n_written;
1464       tcp_enqueue_to_output (vm, b, bi, tc->c_is_ip4);
1465       snd_space -= n_written;
1466     }
1467
1468   /* If window allows, send 1 SMSS of new data */
1469   tc->snd_nxt = old_snd_nxt;
1470 }
1471
1472 /**
1473  * Fast retransmit without SACK info
1474  */
1475 void
1476 tcp_fast_retransmit_no_sack (tcp_connection_t * tc)
1477 {
1478   tcp_main_t *tm = vnet_get_tcp_main ();
1479   vlib_main_t *vm = vlib_get_main ();
1480   u32 n_written = 0, offset = 0, bi, old_snd_nxt;
1481   int snd_space;
1482   vlib_buffer_t *b;
1483
1484   ASSERT (tcp_in_fastrecovery (tc));
1485   TCP_EVT_DBG (TCP_EVT_CC_EVT, tc, 0);
1486
1487   /* Start resending from first un-acked segment */
1488   old_snd_nxt = tc->snd_nxt;
1489   tc->snd_nxt = tc->snd_una;
1490   snd_space = tcp_available_snd_space (tc);
1491
1492   while (snd_space > 0)
1493     {
1494       if (PREDICT_FALSE (tcp_get_free_buffer_index (tm, &bi)))
1495         return;
1496       b = vlib_get_buffer (vm, bi);
1497       offset += n_written;
1498       n_written = tcp_prepare_retransmit_segment (tc, b, offset, snd_space);
1499
1500       /* Nothing left to retransmit */
1501       if (n_written == 0)
1502         {
1503           tcp_return_buffer (tm);
1504           break;
1505         }
1506
1507       tcp_enqueue_to_output (vm, b, bi, tc->c_is_ip4);
1508       snd_space -= n_written;
1509     }
1510
1511   /* Restore snd_nxt. If window allows, send 1 SMSS of new data */
1512   tc->snd_nxt = old_snd_nxt;
1513 }
1514
1515 /**
1516  * Do fast retransmit
1517  */
1518 void
1519 tcp_fast_retransmit (tcp_connection_t * tc)
1520 {
1521   if (tcp_opts_sack_permitted (&tc->rcv_opts)
1522       && scoreboard_first_hole (&tc->sack_sb))
1523     tcp_fast_retransmit_sack (tc);
1524   else
1525     tcp_fast_retransmit_no_sack (tc);
1526 }
1527
1528 always_inline u32
1529 tcp_session_has_ooo_data (tcp_connection_t * tc)
1530 {
1531   stream_session_t *s =
1532     stream_session_get (tc->c_s_index, tc->c_thread_index);
1533   return svm_fifo_has_ooo_data (s->server_rx_fifo);
1534 }
1535
1536 always_inline uword
1537 tcp46_output_inline (vlib_main_t * vm,
1538                      vlib_node_runtime_t * node,
1539                      vlib_frame_t * from_frame, int is_ip4)
1540 {
1541   u32 n_left_from, next_index, *from, *to_next;
1542   u32 my_thread_index = vm->thread_index;
1543
1544   from = vlib_frame_vector_args (from_frame);
1545   n_left_from = from_frame->n_vectors;
1546
1547   next_index = node->cached_next_index;
1548
1549   while (n_left_from > 0)
1550     {
1551       u32 n_left_to_next;
1552
1553       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1554
1555       while (n_left_from > 0 && n_left_to_next > 0)
1556         {
1557           u32 bi0;
1558           vlib_buffer_t *b0;
1559           tcp_connection_t *tc0;
1560           tcp_tx_trace_t *t0;
1561           tcp_header_t *th0 = 0;
1562           u32 error0 = TCP_ERROR_PKTS_SENT, next0 = TCP_OUTPUT_NEXT_IP_LOOKUP;
1563
1564           bi0 = from[0];
1565           to_next[0] = bi0;
1566           from += 1;
1567           to_next += 1;
1568           n_left_from -= 1;
1569           n_left_to_next -= 1;
1570
1571           b0 = vlib_get_buffer (vm, bi0);
1572           tc0 = tcp_connection_get (vnet_buffer (b0)->tcp.connection_index,
1573                                     my_thread_index);
1574           if (PREDICT_FALSE (tc0 == 0 || tc0->state == TCP_STATE_CLOSED))
1575             {
1576               error0 = TCP_ERROR_INVALID_CONNECTION;
1577               next0 = TCP_OUTPUT_NEXT_DROP;
1578               goto done;
1579             }
1580
1581           th0 = vlib_buffer_get_current (b0);
1582           TCP_EVT_DBG (TCP_EVT_OUTPUT, tc0, th0->flags, b0->current_length);
1583
1584           if (is_ip4)
1585             {
1586               vlib_buffer_push_ip4 (vm, b0, &tc0->c_lcl_ip4, &tc0->c_rmt_ip4,
1587                                     IP_PROTOCOL_TCP, 1);
1588               b0->flags |= VNET_BUFFER_F_OFFLOAD_TCP_CKSUM;
1589               vnet_buffer (b0)->l4_hdr_offset = (u8 *) th0 - b0->data;
1590               th0->checksum = 0;
1591             }
1592           else
1593             {
1594               ip6_header_t *ih0;
1595               ih0 = vlib_buffer_push_ip6 (vm, b0, &tc0->c_lcl_ip6,
1596                                           &tc0->c_rmt_ip6, IP_PROTOCOL_TCP);
1597               b0->flags |= VNET_BUFFER_F_OFFLOAD_TCP_CKSUM;
1598               vnet_buffer (b0)->l3_hdr_offset = (u8 *) ih0 - b0->data;
1599               vnet_buffer (b0)->l4_hdr_offset = (u8 *) th0 - b0->data;
1600               th0->checksum = 0;
1601             }
1602
1603           /* Filter out DUPACKs if there are no OOO segments left */
1604           if (PREDICT_FALSE
1605               (vnet_buffer (b0)->tcp.flags & TCP_BUF_FLAG_DUPACK))
1606             {
1607               if (!tcp_session_has_ooo_data (tc0))
1608                 {
1609                   error0 = TCP_ERROR_FILTERED_DUPACKS;
1610                   next0 = TCP_OUTPUT_NEXT_DROP;
1611                   goto done;
1612                 }
1613             }
1614
1615           /* Stop DELACK timer and fix flags */
1616           tc0->flags &= ~(TCP_CONN_SNDACK);
1617           tcp_timer_reset (tc0, TCP_TIMER_DELACK);
1618
1619           /* If not retransmitting
1620            * 1) update snd_una_max (SYN, SYNACK, FIN)
1621            * 2) If we're not tracking an ACK, start tracking */
1622           if (seq_lt (tc0->snd_una_max, tc0->snd_nxt))
1623             {
1624               tc0->snd_una_max = tc0->snd_nxt;
1625               if (tc0->rtt_ts == 0)
1626                 {
1627                   tc0->rtt_ts = tcp_time_now ();
1628                   tc0->rtt_seq = tc0->snd_nxt;
1629                 }
1630             }
1631
1632           /* Set the retransmit timer if not set already and not
1633            * doing a pure ACK */
1634           if (!tcp_timer_is_active (tc0, TCP_TIMER_RETRANSMIT)
1635               && tc0->snd_nxt != tc0->snd_una)
1636             {
1637               tcp_retransmit_timer_set (tc0);
1638               tc0->rto_boff = 0;
1639             }
1640
1641 #if 0
1642           /* Make sure we haven't lost route to our peer */
1643           if (PREDICT_FALSE (tc0->last_fib_check
1644                              < tc0->snd_opts.tsval + TCP_FIB_RECHECK_PERIOD))
1645             {
1646               if (PREDICT_TRUE
1647                   (tc0->c_rmt_fei == tcp_lookup_rmt_in_fib (tc0)))
1648                 {
1649                   tc0->last_fib_check = tc0->snd_opts.tsval;
1650                 }
1651               else
1652                 {
1653                   clib_warning ("lost connection to peer");
1654                   tcp_connection_reset (tc0);
1655                   goto done;
1656                 }
1657             }
1658
1659           /* Use pre-computed dpo to set next node */
1660           next0 = tc0->c_rmt_dpo.dpoi_next_node;
1661           vnet_buffer (b0)->ip.adj_index[VLIB_TX] = tc0->c_rmt_dpo.dpoi_index;
1662 #endif
1663
1664           vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
1665           vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
1666
1667           b0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
1668         done:
1669           b0->error = node->errors[error0];
1670           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1671             {
1672               t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
1673               if (th0)
1674                 {
1675                   clib_memcpy (&t0->tcp_header, th0, sizeof (t0->tcp_header));
1676                 }
1677               else
1678                 {
1679                   memset (&t0->tcp_header, 0, sizeof (t0->tcp_header));
1680                 }
1681               clib_memcpy (&t0->tcp_connection, tc0,
1682                            sizeof (t0->tcp_connection));
1683             }
1684
1685           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1686                                            n_left_to_next, bi0, next0);
1687         }
1688
1689       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1690     }
1691
1692   return from_frame->n_vectors;
1693 }
1694
1695 static uword
1696 tcp4_output (vlib_main_t * vm, vlib_node_runtime_t * node,
1697              vlib_frame_t * from_frame)
1698 {
1699   return tcp46_output_inline (vm, node, from_frame, 1 /* is_ip4 */ );
1700 }
1701
1702 static uword
1703 tcp6_output (vlib_main_t * vm, vlib_node_runtime_t * node,
1704              vlib_frame_t * from_frame)
1705 {
1706   return tcp46_output_inline (vm, node, from_frame, 0 /* is_ip4 */ );
1707 }
1708
1709 /* *INDENT-OFF* */
1710 VLIB_REGISTER_NODE (tcp4_output_node) =
1711 {
1712   .function = tcp4_output,.name = "tcp4-output",
1713     /* Takes a vector of packets. */
1714     .vector_size = sizeof (u32),
1715     .n_errors = TCP_N_ERROR,
1716     .error_strings = tcp_error_strings,
1717     .n_next_nodes = TCP_OUTPUT_N_NEXT,
1718     .next_nodes = {
1719 #define _(s,n) [TCP_OUTPUT_NEXT_##s] = n,
1720     foreach_tcp4_output_next
1721 #undef _
1722     },
1723     .format_buffer = format_tcp_header,
1724     .format_trace = format_tcp_tx_trace,
1725 };
1726 /* *INDENT-ON* */
1727
1728 VLIB_NODE_FUNCTION_MULTIARCH (tcp4_output_node, tcp4_output);
1729
1730 /* *INDENT-OFF* */
1731 VLIB_REGISTER_NODE (tcp6_output_node) =
1732 {
1733   .function = tcp6_output,
1734   .name = "tcp6-output",
1735     /* Takes a vector of packets. */
1736   .vector_size = sizeof (u32),
1737   .n_errors = TCP_N_ERROR,
1738   .error_strings = tcp_error_strings,
1739   .n_next_nodes = TCP_OUTPUT_N_NEXT,
1740   .next_nodes = {
1741 #define _(s,n) [TCP_OUTPUT_NEXT_##s] = n,
1742     foreach_tcp6_output_next
1743 #undef _
1744   },
1745   .format_buffer = format_tcp_header,
1746   .format_trace = format_tcp_tx_trace,
1747 };
1748 /* *INDENT-ON* */
1749
1750 VLIB_NODE_FUNCTION_MULTIARCH (tcp6_output_node, tcp6_output);
1751
1752 u32
1753 tcp_push_header (transport_connection_t * tconn, vlib_buffer_t * b)
1754 {
1755   tcp_connection_t *tc;
1756
1757   tc = (tcp_connection_t *) tconn;
1758   tcp_push_hdr_i (tc, b, TCP_STATE_ESTABLISHED, 0);
1759
1760   if (tc->rtt_ts == 0 && !tcp_in_cong_recovery (tc))
1761     {
1762       tc->rtt_ts = tcp_time_now ();
1763       tc->rtt_seq = tc->snd_nxt;
1764     }
1765   return 0;
1766 }
1767
1768 typedef enum _tcp_reset_next
1769 {
1770   TCP_RESET_NEXT_DROP,
1771   TCP_RESET_NEXT_IP_LOOKUP,
1772   TCP_RESET_N_NEXT
1773 } tcp_reset_next_t;
1774
1775 #define foreach_tcp4_reset_next         \
1776   _(DROP, "error-drop")                 \
1777   _(IP_LOOKUP, "ip4-lookup")
1778
1779 #define foreach_tcp6_reset_next         \
1780   _(DROP, "error-drop")                 \
1781   _(IP_LOOKUP, "ip6-lookup")
1782
1783 static uword
1784 tcp46_send_reset_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
1785                          vlib_frame_t * from_frame, u8 is_ip4)
1786 {
1787   u32 n_left_from, next_index, *from, *to_next;
1788   u32 my_thread_index = vm->thread_index;
1789
1790   from = vlib_frame_vector_args (from_frame);
1791   n_left_from = from_frame->n_vectors;
1792
1793   next_index = node->cached_next_index;
1794
1795   while (n_left_from > 0)
1796     {
1797       u32 n_left_to_next;
1798
1799       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1800
1801       while (n_left_from > 0 && n_left_to_next > 0)
1802         {
1803           u32 bi0;
1804           vlib_buffer_t *b0;
1805           tcp_tx_trace_t *t0;
1806           tcp_header_t *th0;
1807           u32 error0 = TCP_ERROR_RST_SENT, next0 = TCP_RESET_NEXT_IP_LOOKUP;
1808
1809           bi0 = from[0];
1810           to_next[0] = bi0;
1811           from += 1;
1812           to_next += 1;
1813           n_left_from -= 1;
1814           n_left_to_next -= 1;
1815
1816           b0 = vlib_get_buffer (vm, bi0);
1817
1818           if (tcp_make_reset_in_place (vm, b0, vnet_buffer (b0)->tcp.flags,
1819                                        my_thread_index, is_ip4))
1820             {
1821               error0 = TCP_ERROR_LOOKUP_DROPS;
1822               next0 = TCP_RESET_NEXT_DROP;
1823               goto done;
1824             }
1825
1826           /* Prepare to send to IP lookup */
1827           vnet_buffer (b0)->sw_if_index[VLIB_TX] = 0;
1828           next0 = TCP_RESET_NEXT_IP_LOOKUP;
1829
1830         done:
1831           b0->error = node->errors[error0];
1832           b0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
1833           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1834             {
1835               th0 = vlib_buffer_get_current (b0);
1836               if (is_ip4)
1837                 th0 = ip4_next_header ((ip4_header_t *) th0);
1838               else
1839                 th0 = ip6_next_header ((ip6_header_t *) th0);
1840               t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
1841               clib_memcpy (&t0->tcp_header, th0, sizeof (t0->tcp_header));
1842             }
1843
1844           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1845                                            n_left_to_next, bi0, next0);
1846         }
1847       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1848     }
1849   return from_frame->n_vectors;
1850 }
1851
1852 static uword
1853 tcp4_send_reset (vlib_main_t * vm, vlib_node_runtime_t * node,
1854                  vlib_frame_t * from_frame)
1855 {
1856   return tcp46_send_reset_inline (vm, node, from_frame, 1);
1857 }
1858
1859 static uword
1860 tcp6_send_reset (vlib_main_t * vm, vlib_node_runtime_t * node,
1861                  vlib_frame_t * from_frame)
1862 {
1863   return tcp46_send_reset_inline (vm, node, from_frame, 0);
1864 }
1865
1866 /* *INDENT-OFF* */
1867 VLIB_REGISTER_NODE (tcp4_reset_node) = {
1868   .function = tcp4_send_reset,
1869   .name = "tcp4-reset",
1870   .vector_size = sizeof (u32),
1871   .n_errors = TCP_N_ERROR,
1872   .error_strings = tcp_error_strings,
1873   .n_next_nodes = TCP_RESET_N_NEXT,
1874   .next_nodes = {
1875 #define _(s,n) [TCP_RESET_NEXT_##s] = n,
1876     foreach_tcp4_reset_next
1877 #undef _
1878   },
1879   .format_trace = format_tcp_tx_trace,
1880 };
1881 /* *INDENT-ON* */
1882
1883 VLIB_NODE_FUNCTION_MULTIARCH (tcp4_reset_node, tcp4_send_reset);
1884
1885 /* *INDENT-OFF* */
1886 VLIB_REGISTER_NODE (tcp6_reset_node) = {
1887   .function = tcp6_send_reset,
1888   .name = "tcp6-reset",
1889   .vector_size = sizeof (u32),
1890   .n_errors = TCP_N_ERROR,
1891   .error_strings = tcp_error_strings,
1892   .n_next_nodes = TCP_RESET_N_NEXT,
1893   .next_nodes = {
1894 #define _(s,n) [TCP_RESET_NEXT_##s] = n,
1895     foreach_tcp6_reset_next
1896 #undef _
1897   },
1898   .format_trace = format_tcp_tx_trace,
1899 };
1900 /* *INDENT-ON* */
1901
1902 VLIB_NODE_FUNCTION_MULTIARCH (tcp6_reset_node, tcp6_send_reset);
1903
1904 /*
1905  * fd.io coding-style-patch-verification: ON
1906  *
1907  * Local Variables:
1908  * eval: (c-set-style "gnu")
1909  * End:
1910  */