7e431cd0454f5faca26149f9d4166f0b85b9d190
[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_nect
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   u16 src_port;
46   u16 dst_port;
47   u8 state;
48 } tcp_tx_trace_t;
49
50 u16 dummy_mtu = 400;
51
52 u8 *
53 format_tcp_tx_trace (u8 * s, va_list * args)
54 {
55   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
56   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
57
58   s = format (s, "TBD\n");
59
60   return s;
61 }
62
63 void
64 tcp_set_snd_mss (tcp_connection_t * tc)
65 {
66   u16 snd_mss;
67
68   /* TODO find our iface MTU */
69   snd_mss = dummy_mtu;
70
71   /* TODO cache mss and consider PMTU discovery */
72   snd_mss = tc->opt.mss < snd_mss ? tc->opt.mss : snd_mss;
73
74   tc->snd_mss = snd_mss;
75
76   if (tc->snd_mss == 0)
77     {
78       clib_warning ("snd mss is 0");
79       tc->snd_mss = dummy_mtu;
80     }
81 }
82
83 static u8
84 tcp_window_compute_scale (u32 available_space)
85 {
86   u8 wnd_scale = 0;
87   while (wnd_scale < TCP_MAX_WND_SCALE
88          && (available_space >> wnd_scale) > TCP_WND_MAX)
89     wnd_scale++;
90   return wnd_scale;
91 }
92
93 /**
94  * TCP's IW as recommended by RFC6928
95  */
96 always_inline u32
97 tcp_initial_wnd_unscaled (tcp_connection_t * tc)
98 {
99   return TCP_IW_N_SEGMENTS * dummy_mtu;
100 }
101
102 /**
103  * Compute initial window and scale factor. As per RFC1323, window field in
104  * SYN and SYN-ACK segments is never scaled.
105  */
106 u32
107 tcp_initial_window_to_advertise (tcp_connection_t * tc)
108 {
109   u32 max_fifo;
110
111   /* Initial wnd for SYN. Fifos are not allocated yet.
112    * Use some predefined value. For SYN-ACK we still want the
113    * scale to be computed in the same way */
114   max_fifo = TCP_MAX_RX_FIFO_SIZE;
115
116   tc->rcv_wscale = tcp_window_compute_scale (max_fifo);
117   tc->rcv_wnd = tcp_initial_wnd_unscaled (tc);
118
119   return clib_min (tc->rcv_wnd, TCP_WND_MAX);
120 }
121
122 /**
123  * Compute and return window to advertise, scaled as per RFC1323
124  */
125 u32
126 tcp_window_to_advertise (tcp_connection_t * tc, tcp_state_t state)
127 {
128   u32 available_space, max_fifo, observed_wnd;
129
130   if (state < TCP_STATE_ESTABLISHED)
131     return tcp_initial_window_to_advertise (tc);
132
133   /*
134    * Figure out how much space we have available
135    */
136   available_space = stream_session_max_enqueue (&tc->connection);
137   max_fifo = stream_session_fifo_size (&tc->connection);
138
139   ASSERT (tc->opt.mss < max_fifo);
140
141   if (available_space < tc->opt.mss && available_space < max_fifo / 8)
142     available_space = 0;
143
144   /*
145    * Use the above and what we know about what we've previously advertised
146    * to compute the new window
147    */
148   observed_wnd = tc->rcv_wnd - (tc->rcv_nxt - tc->rcv_las);
149
150   /* Bad. Thou shalt not shrink */
151   if (available_space < observed_wnd)
152     {
153       if (available_space == 0)
154         clib_warning ("Didn't shrink rcv window despite not having space");
155     }
156
157   tc->rcv_wnd = clib_min (available_space, TCP_WND_MAX << tc->rcv_wscale);
158
159   if (tc->rcv_wnd == 0)
160     {
161       tc->flags |= TCP_CONN_SENT_RCV_WND0;
162     }
163
164   return tc->rcv_wnd >> tc->rcv_wscale;
165 }
166
167 /**
168  * Write TCP options to segment.
169  */
170 u32
171 tcp_options_write (u8 * data, tcp_options_t * opts)
172 {
173   u32 opts_len = 0;
174   u32 buf, seq_len = 4;
175
176   if (tcp_opts_mss (opts))
177     {
178       *data++ = TCP_OPTION_MSS;
179       *data++ = TCP_OPTION_LEN_MSS;
180       buf = clib_host_to_net_u16 (opts->mss);
181       clib_memcpy (data, &buf, sizeof (opts->mss));
182       data += sizeof (opts->mss);
183       opts_len += TCP_OPTION_LEN_MSS;
184     }
185
186   if (tcp_opts_wscale (opts))
187     {
188       *data++ = TCP_OPTION_WINDOW_SCALE;
189       *data++ = TCP_OPTION_LEN_WINDOW_SCALE;
190       *data++ = opts->wscale;
191       opts_len += TCP_OPTION_LEN_WINDOW_SCALE;
192     }
193
194   if (tcp_opts_sack_permitted (opts))
195     {
196       *data++ = TCP_OPTION_SACK_PERMITTED;
197       *data++ = TCP_OPTION_LEN_SACK_PERMITTED;
198       opts_len += TCP_OPTION_LEN_SACK_PERMITTED;
199     }
200
201   if (tcp_opts_tstamp (opts))
202     {
203       *data++ = TCP_OPTION_TIMESTAMP;
204       *data++ = TCP_OPTION_LEN_TIMESTAMP;
205       buf = clib_host_to_net_u32 (opts->tsval);
206       clib_memcpy (data, &buf, sizeof (opts->tsval));
207       data += sizeof (opts->tsval);
208       buf = clib_host_to_net_u32 (opts->tsecr);
209       clib_memcpy (data, &buf, sizeof (opts->tsecr));
210       data += sizeof (opts->tsecr);
211       opts_len += TCP_OPTION_LEN_TIMESTAMP;
212     }
213
214   if (tcp_opts_sack (opts))
215     {
216       int i;
217       u32 n_sack_blocks = clib_min (vec_len (opts->sacks),
218                                     TCP_OPTS_MAX_SACK_BLOCKS);
219
220       if (n_sack_blocks != 0)
221         {
222           *data++ = TCP_OPTION_SACK_BLOCK;
223           *data++ = 2 + n_sack_blocks * TCP_OPTION_LEN_SACK_BLOCK;
224           for (i = 0; i < n_sack_blocks; i++)
225             {
226               buf = clib_host_to_net_u32 (opts->sacks[i].start);
227               clib_memcpy (data, &buf, seq_len);
228               data += seq_len;
229               buf = clib_host_to_net_u32 (opts->sacks[i].end);
230               clib_memcpy (data, &buf, seq_len);
231               data += seq_len;
232             }
233           opts_len += 2 + n_sack_blocks * TCP_OPTION_LEN_SACK_BLOCK;
234         }
235     }
236
237   /* Terminate TCP options */
238   if (opts_len % 4)
239     {
240       *data++ = TCP_OPTION_EOL;
241       opts_len += TCP_OPTION_LEN_EOL;
242     }
243
244   /* Pad with zeroes to a u32 boundary */
245   while (opts_len % 4)
246     {
247       *data++ = TCP_OPTION_NOOP;
248       opts_len += TCP_OPTION_LEN_NOOP;
249     }
250   return opts_len;
251 }
252
253 always_inline int
254 tcp_make_syn_options (tcp_options_t * opts, u8 wnd_scale)
255 {
256   u8 len = 0;
257
258   opts->flags |= TCP_OPTS_FLAG_MSS;
259   opts->mss = dummy_mtu;        /*XXX discover that */
260   len += TCP_OPTION_LEN_MSS;
261
262   opts->flags |= TCP_OPTS_FLAG_WSCALE;
263   opts->wscale = wnd_scale;
264   len += TCP_OPTION_LEN_WINDOW_SCALE;
265
266   opts->flags |= TCP_OPTS_FLAG_TSTAMP;
267   opts->tsval = tcp_time_now ();
268   opts->tsecr = 0;
269   len += TCP_OPTION_LEN_TIMESTAMP;
270
271   opts->flags |= TCP_OPTS_FLAG_SACK_PERMITTED;
272   len += TCP_OPTION_LEN_SACK_PERMITTED;
273
274   /* Align to needed boundary */
275   len += (TCP_OPTS_ALIGN - len % TCP_OPTS_ALIGN) % TCP_OPTS_ALIGN;
276   return len;
277 }
278
279 always_inline int
280 tcp_make_synack_options (tcp_connection_t * tc, tcp_options_t * opts)
281 {
282   u8 len = 0;
283
284   opts->flags |= TCP_OPTS_FLAG_MSS;
285   opts->mss = dummy_mtu;        /*XXX discover that */
286   len += TCP_OPTION_LEN_MSS;
287
288   if (tcp_opts_wscale (&tc->opt))
289     {
290       opts->flags |= TCP_OPTS_FLAG_WSCALE;
291       opts->wscale = tc->rcv_wscale;
292       len += TCP_OPTION_LEN_WINDOW_SCALE;
293     }
294
295   if (tcp_opts_tstamp (&tc->opt))
296     {
297       opts->flags |= TCP_OPTS_FLAG_TSTAMP;
298       opts->tsval = tcp_time_now ();
299       opts->tsecr = tc->tsval_recent;
300       len += TCP_OPTION_LEN_TIMESTAMP;
301     }
302
303   if (tcp_opts_sack_permitted (&tc->opt))
304     {
305       opts->flags |= TCP_OPTS_FLAG_SACK_PERMITTED;
306       len += TCP_OPTION_LEN_SACK_PERMITTED;
307     }
308
309   /* Align to needed boundary */
310   len += (TCP_OPTS_ALIGN - len % TCP_OPTS_ALIGN) % TCP_OPTS_ALIGN;
311   return len;
312 }
313
314 always_inline int
315 tcp_make_established_options (tcp_connection_t * tc, tcp_options_t * opts)
316 {
317   u8 len = 0;
318
319   opts->flags = 0;
320
321   if (tcp_opts_tstamp (&tc->opt))
322     {
323       opts->flags |= TCP_OPTS_FLAG_TSTAMP;
324       opts->tsval = tcp_time_now ();
325       opts->tsecr = tc->tsval_recent;
326       len += TCP_OPTION_LEN_TIMESTAMP;
327     }
328   if (tcp_opts_sack_permitted (&tc->opt))
329     {
330       if (vec_len (tc->snd_sacks))
331         {
332           opts->flags |= TCP_OPTS_FLAG_SACK;
333           opts->sacks = tc->snd_sacks;
334           opts->n_sack_blocks = vec_len (tc->snd_sacks);
335           len += 2 + TCP_OPTION_LEN_SACK_BLOCK * opts->n_sack_blocks;
336         }
337     }
338
339   /* Align to needed boundary */
340   len += (TCP_OPTS_ALIGN - len % TCP_OPTS_ALIGN) % TCP_OPTS_ALIGN;
341   return len;
342 }
343
344 always_inline int
345 tcp_make_options (tcp_connection_t * tc, tcp_options_t * opts,
346                   tcp_state_t state)
347 {
348   switch (state)
349     {
350     case TCP_STATE_ESTABLISHED:
351     case TCP_STATE_FIN_WAIT_1:
352       return tcp_make_established_options (tc, opts);
353     case TCP_STATE_SYN_RCVD:
354       return tcp_make_synack_options (tc, opts);
355     case TCP_STATE_SYN_SENT:
356       return tcp_make_syn_options (opts, tc->rcv_wscale);
357     default:
358       clib_warning ("Not handled!");
359       return 0;
360     }
361 }
362
363 #define tcp_get_free_buffer_index(tm, bidx)                             \
364 do {                                                                    \
365   u32 *my_tx_buffers, n_free_buffers;                                   \
366   u32 cpu_index = tm->vlib_main->cpu_index;                             \
367   my_tx_buffers = tm->tx_buffers[cpu_index];                            \
368   if (PREDICT_FALSE(vec_len (my_tx_buffers) == 0))                      \
369     {                                                                   \
370       n_free_buffers = 32;      /* TODO config or macro */              \
371       vec_validate (my_tx_buffers, n_free_buffers - 1);                 \
372       _vec_len(my_tx_buffers) = vlib_buffer_alloc_from_free_list (      \
373           tm->vlib_main, my_tx_buffers, n_free_buffers,                 \
374           VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);                         \
375       tm->tx_buffers[cpu_index] = my_tx_buffers;                        \
376     }                                                                   \
377   /* buffer shortage */                                                 \
378   if (PREDICT_FALSE (vec_len (my_tx_buffers) == 0))                     \
379     return;                                                             \
380   *bidx = my_tx_buffers[_vec_len (my_tx_buffers)-1];                    \
381   _vec_len (my_tx_buffers) -= 1;                                        \
382 } while (0)
383
384 always_inline void
385 tcp_reuse_buffer (vlib_main_t * vm, vlib_buffer_t * b)
386 {
387   vlib_buffer_t *it = b;
388   do
389     {
390       it->current_data = 0;
391       it->current_length = 0;
392       it->total_length_not_including_first_buffer = 0;
393     }
394   while ((it->flags & VLIB_BUFFER_NEXT_PRESENT)
395          && (it = vlib_get_buffer (vm, it->next_buffer)));
396
397   /* Leave enough space for headers */
398   vlib_buffer_make_headroom (b, MAX_HDRS_LEN);
399 }
400
401 /**
402  * Prepare ACK
403  */
404 void
405 tcp_make_ack_i (tcp_connection_t * tc, vlib_buffer_t * b, tcp_state_t state,
406                 u8 flags)
407 {
408   tcp_options_t _snd_opts, *snd_opts = &_snd_opts;
409   u8 tcp_opts_len, tcp_hdr_opts_len;
410   tcp_header_t *th;
411   u16 wnd;
412
413   wnd = tcp_window_to_advertise (tc, state);
414
415   /* Make and write options */
416   tcp_opts_len = tcp_make_established_options (tc, snd_opts);
417   tcp_hdr_opts_len = tcp_opts_len + sizeof (tcp_header_t);
418
419   th = vlib_buffer_push_tcp (b, tc->c_lcl_port, tc->c_rmt_port, tc->snd_nxt,
420                              tc->rcv_nxt, tcp_hdr_opts_len, flags, wnd);
421
422   tcp_options_write ((u8 *) (th + 1), snd_opts);
423
424   /* Mark as ACK */
425   vnet_buffer (b)->tcp.connection_index = tc->c_c_index;
426 }
427
428 /**
429  * Convert buffer to ACK
430  */
431 void
432 tcp_make_ack (tcp_connection_t * tc, vlib_buffer_t * b)
433 {
434   tcp_main_t *tm = vnet_get_tcp_main ();
435   vlib_main_t *vm = tm->vlib_main;
436
437   tcp_reuse_buffer (vm, b);
438   tcp_make_ack_i (tc, b, TCP_STATE_ESTABLISHED, TCP_FLAG_ACK);
439   vnet_buffer (b)->tcp.flags = TCP_BUF_FLAG_ACK;
440 }
441
442 /**
443  * Convert buffer to FIN-ACK
444  */
445 void
446 tcp_make_finack (tcp_connection_t * tc, vlib_buffer_t * b)
447 {
448   tcp_main_t *tm = vnet_get_tcp_main ();
449   vlib_main_t *vm = tm->vlib_main;
450
451   tcp_reuse_buffer (vm, b);
452   tcp_make_ack_i (tc, b, TCP_STATE_ESTABLISHED, TCP_FLAG_ACK | TCP_FLAG_FIN);
453
454   /* Reset flags, make sure ack is sent */
455   tc->flags = TCP_CONN_SNDACK;
456   vnet_buffer (b)->tcp.flags &= ~TCP_BUF_FLAG_DUPACK;
457
458   tc->snd_nxt += 1;
459 }
460
461 /**
462  * Convert buffer to SYN-ACK
463  */
464 void
465 tcp_make_synack (tcp_connection_t * tc, vlib_buffer_t * b)
466 {
467   tcp_main_t *tm = vnet_get_tcp_main ();
468   vlib_main_t *vm = tm->vlib_main;
469   tcp_options_t _snd_opts, *snd_opts = &_snd_opts;
470   u8 tcp_opts_len, tcp_hdr_opts_len;
471   tcp_header_t *th;
472   u16 initial_wnd;
473   u32 time_now;
474
475   memset (snd_opts, 0, sizeof (*snd_opts));
476
477   tcp_reuse_buffer (vm, b);
478
479   /* Set random initial sequence */
480   time_now = tcp_time_now ();
481
482   tc->iss = random_u32 (&time_now);
483   tc->snd_una = tc->iss;
484   tc->snd_nxt = tc->iss + 1;
485   tc->snd_una_max = tc->snd_nxt;
486
487   initial_wnd = tcp_initial_window_to_advertise (tc);
488
489   /* Make and write options */
490   tcp_opts_len = tcp_make_synack_options (tc, snd_opts);
491   tcp_hdr_opts_len = tcp_opts_len + sizeof (tcp_header_t);
492
493   th = vlib_buffer_push_tcp (b, tc->c_lcl_port, tc->c_rmt_port, tc->iss,
494                              tc->rcv_nxt, tcp_hdr_opts_len,
495                              TCP_FLAG_SYN | TCP_FLAG_ACK, initial_wnd);
496
497   tcp_options_write ((u8 *) (th + 1), snd_opts);
498
499   vnet_buffer (b)->tcp.connection_index = tc->c_c_index;
500   vnet_buffer (b)->tcp.flags = TCP_BUF_FLAG_ACK;
501
502   /* Init retransmit timer */
503   tcp_retransmit_timer_set (tm, tc);
504 }
505
506 always_inline void
507 tcp_enqueue_to_ip_lookup (vlib_main_t * vm, vlib_buffer_t * b, u32 bi,
508                           u8 is_ip4)
509 {
510   u32 *to_next, next_index;
511   vlib_frame_t *f;
512
513   b->flags |= VNET_BUFFER_LOCALLY_ORIGINATED;
514   b->error = 0;
515
516   /* Default FIB for now */
517   vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
518
519   /* Send to IP lookup */
520   next_index = is_ip4 ? ip4_lookup_node.index : ip6_lookup_node.index;
521   f = vlib_get_frame_to_node (vm, next_index);
522
523   /* Enqueue the packet */
524   to_next = vlib_frame_vector_args (f);
525   to_next[0] = bi;
526   f->n_vectors = 1;
527   vlib_put_frame_to_node (vm, next_index, f);
528 }
529
530 int
531 tcp_make_reset_in_place (vlib_main_t * vm, vlib_buffer_t * b0,
532                          tcp_state_t state, u32 my_thread_index, u8 is_ip4)
533 {
534   u8 tcp_hdr_len = sizeof (tcp_header_t);
535   ip4_header_t *ih4;
536   ip6_header_t *ih6;
537   tcp_header_t *th0;
538   ip4_address_t src_ip40;
539   ip6_address_t src_ip60;
540   u16 src_port0;
541   u32 tmp;
542
543   /* Find IP and TCP headers */
544   if (is_ip4)
545     {
546       ih4 = vlib_buffer_get_current (b0);
547       th0 = ip4_next_header (ih4);
548     }
549   else
550     {
551       ih6 = vlib_buffer_get_current (b0);
552       th0 = ip6_next_header (ih6);
553     }
554
555   /* Swap src and dst ip */
556   if (is_ip4)
557     {
558       ASSERT ((ih4->ip_version_and_header_length & 0xF0) == 0x40);
559       src_ip40.as_u32 = ih4->src_address.as_u32;
560       ih4->src_address.as_u32 = ih4->dst_address.as_u32;
561       ih4->dst_address.as_u32 = src_ip40.as_u32;
562
563       /* Chop the end of the pkt */
564       b0->current_length += ip4_header_bytes (ih4) + tcp_hdr_len;
565     }
566   else
567     {
568       ASSERT ((ih6->ip_version_traffic_class_and_flow_label & 0xF0) == 0x60);
569       clib_memcpy (&src_ip60, &ih6->src_address, sizeof (ip6_address_t));
570       clib_memcpy (&ih6->src_address, &ih6->dst_address,
571                    sizeof (ip6_address_t));
572       clib_memcpy (&ih6->dst_address, &src_ip60, sizeof (ip6_address_t));
573
574       /* Chop the end of the pkt */
575       b0->current_length += sizeof (ip6_header_t) + tcp_hdr_len;
576     }
577
578   /* Try to determine what/why we're actually resetting and swap
579    * src and dst ports */
580   if (state == TCP_STATE_CLOSED)
581     {
582       if (!tcp_syn (th0))
583         return -1;
584
585       tmp = clib_net_to_host_u32 (th0->seq_number);
586
587       /* Got a SYN for no listener. */
588       th0->flags = TCP_FLAG_RST | TCP_FLAG_ACK;
589       th0->ack_number = clib_host_to_net_u32 (tmp + 1);
590       th0->seq_number = 0;
591
592     }
593   else if (state >= TCP_STATE_SYN_SENT)
594     {
595       th0->flags = TCP_FLAG_RST | TCP_FLAG_ACK;
596       th0->seq_number = th0->ack_number;
597       th0->ack_number = 0;
598     }
599
600   src_port0 = th0->src_port;
601   th0->src_port = th0->dst_port;
602   th0->dst_port = src_port0;
603   th0->window = 0;
604   th0->data_offset_and_reserved = (tcp_hdr_len >> 2) << 4;
605   th0->urgent_pointer = 0;
606
607   /* Compute checksum */
608   if (is_ip4)
609     {
610       th0->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ih4);
611     }
612   else
613     {
614       int bogus = ~0;
615       th0->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b0, ih6, &bogus);
616       ASSERT (!bogus);
617     }
618
619   return 0;
620 }
621
622 /**
623  *  Send reset without reusing existing buffer
624  */
625 void
626 tcp_send_reset (vlib_buffer_t * pkt, u8 is_ip4)
627 {
628   vlib_buffer_t *b;
629   u32 bi;
630   tcp_main_t *tm = vnet_get_tcp_main ();
631   vlib_main_t *vm = tm->vlib_main;
632   u8 tcp_hdr_len, flags = 0;
633   tcp_header_t *th, *pkt_th;
634   u32 seq, ack;
635   ip4_header_t *ih4, *pkt_ih4;
636   ip6_header_t *ih6, *pkt_ih6;
637
638   tcp_get_free_buffer_index (tm, &bi);
639   b = vlib_get_buffer (vm, bi);
640
641   /* Leave enough space for headers */
642   vlib_buffer_make_headroom (b, MAX_HDRS_LEN);
643
644   /* Make and write options */
645   tcp_hdr_len = sizeof (tcp_header_t);
646
647   if (is_ip4)
648     {
649       pkt_ih4 = vlib_buffer_get_current (pkt);
650       pkt_th = ip4_next_header (pkt_ih4);
651     }
652   else
653     {
654       pkt_ih6 = vlib_buffer_get_current (pkt);
655       pkt_th = ip6_next_header (pkt_ih6);
656     }
657
658   if (tcp_ack (pkt_th))
659     {
660       flags = TCP_FLAG_RST;
661       seq = pkt_th->ack_number;
662       ack = 0;
663     }
664   else
665     {
666       flags = TCP_FLAG_RST | TCP_FLAG_ACK;
667       seq = 0;
668       ack = clib_host_to_net_u32 (vnet_buffer (pkt)->tcp.seq_end);
669     }
670
671   th = vlib_buffer_push_tcp_net_order (b, pkt_th->dst_port, pkt_th->src_port,
672                                        seq, ack, tcp_hdr_len, flags, 0);
673
674   /* Swap src and dst ip */
675   if (is_ip4)
676     {
677       ASSERT ((pkt_ih4->ip_version_and_header_length & 0xF0) == 0x40);
678       ih4 = vlib_buffer_push_ip4 (vm, b, &pkt_ih4->dst_address,
679                                   &pkt_ih4->src_address, IP_PROTOCOL_TCP);
680       th->checksum = ip4_tcp_udp_compute_checksum (vm, b, ih4);
681     }
682   else
683     {
684       int bogus = ~0;
685       pkt_ih6 = (ip6_header_t *) (pkt_th - 1);
686       ASSERT ((pkt_ih6->ip_version_traffic_class_and_flow_label & 0xF0) ==
687               0x60);
688       ih6 =
689         vlib_buffer_push_ip6 (vm, b, &pkt_ih6->dst_address,
690                               &pkt_ih6->src_address, IP_PROTOCOL_TCP);
691       th->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b, ih6, &bogus);
692       ASSERT (!bogus);
693     }
694
695   tcp_enqueue_to_ip_lookup (vm, b, bi, is_ip4);
696 }
697
698 void
699 tcp_push_ip_hdr (tcp_main_t * tm, tcp_connection_t * tc, vlib_buffer_t * b)
700 {
701   tcp_header_t *th = vlib_buffer_get_current (b);
702
703   if (tc->c_is_ip4)
704     {
705       ip4_header_t *ih;
706       ih = vlib_buffer_push_ip4 (tm->vlib_main, b, &tc->c_lcl_ip4,
707                                  &tc->c_rmt_ip4, IP_PROTOCOL_TCP);
708       th->checksum = ip4_tcp_udp_compute_checksum (tm->vlib_main, b, ih);
709     }
710   else
711     {
712       ip6_header_t *ih;
713       int bogus = ~0;
714
715       ih = vlib_buffer_push_ip6 (tm->vlib_main, b, &tc->c_lcl_ip6,
716                                  &tc->c_rmt_ip6, IP_PROTOCOL_TCP);
717       th->checksum = ip6_tcp_udp_icmp_compute_checksum (tm->vlib_main, b, ih,
718                                                         &bogus);
719       ASSERT (!bogus);
720     }
721 }
722
723 /**
724  *  Send SYN
725  *
726  *  Builds a SYN packet for a half-open connection and sends it to ipx_lookup.
727  *  The packet is not forwarded through tcpx_output to avoid doing lookups
728  *  in the half_open pool.
729  */
730 void
731 tcp_send_syn (tcp_connection_t * tc)
732 {
733   vlib_buffer_t *b;
734   u32 bi;
735   tcp_main_t *tm = vnet_get_tcp_main ();
736   vlib_main_t *vm = tm->vlib_main;
737   u8 tcp_hdr_opts_len, tcp_opts_len;
738   tcp_header_t *th;
739   u32 time_now;
740   u16 initial_wnd;
741   tcp_options_t snd_opts;
742
743   tcp_get_free_buffer_index (tm, &bi);
744   b = vlib_get_buffer (vm, bi);
745
746   /* Leave enough space for headers */
747   vlib_buffer_make_headroom (b, MAX_HDRS_LEN);
748
749   /* Set random initial sequence */
750   time_now = tcp_time_now ();
751
752   tc->iss = random_u32 (&time_now);
753   tc->snd_una = tc->iss;
754   tc->snd_una_max = tc->snd_nxt = tc->iss + 1;
755
756   initial_wnd = tcp_initial_window_to_advertise (tc);
757
758   /* Make and write options */
759   memset (&snd_opts, 0, sizeof (snd_opts));
760   tcp_opts_len = tcp_make_syn_options (&snd_opts, tc->rcv_wscale);
761   tcp_hdr_opts_len = tcp_opts_len + sizeof (tcp_header_t);
762
763   th = vlib_buffer_push_tcp (b, tc->c_lcl_port, tc->c_rmt_port, tc->iss,
764                              tc->rcv_nxt, tcp_hdr_opts_len, TCP_FLAG_SYN,
765                              initial_wnd);
766
767   tcp_options_write ((u8 *) (th + 1), &snd_opts);
768
769   /* Measure RTT with this */
770   tc->rtt_ts = tcp_time_now ();
771   tc->rtt_seq = tc->snd_nxt;
772
773   /* Start retransmit trimer  */
774   tcp_timer_set (tc, TCP_TIMER_RETRANSMIT_SYN, tc->rto * TCP_TO_TIMER_TICK);
775   tc->rto_boff = 0;
776
777   /* Set the connection establishment timer */
778   tcp_timer_set (tc, TCP_TIMER_ESTABLISH, TCP_ESTABLISH_TIME);
779
780   tcp_push_ip_hdr (tm, tc, b);
781   tcp_enqueue_to_ip_lookup (vm, b, bi, tc->c_is_ip4);
782 }
783
784 always_inline void
785 tcp_enqueue_to_output (vlib_main_t * vm, vlib_buffer_t * b, u32 bi, u8 is_ip4)
786 {
787   u32 *to_next, next_index;
788   vlib_frame_t *f;
789
790   b->flags |= VNET_BUFFER_LOCALLY_ORIGINATED;
791   b->error = 0;
792
793   /* Decide where to send the packet */
794   next_index = is_ip4 ? tcp4_output_node.index : tcp6_output_node.index;
795   f = vlib_get_frame_to_node (vm, next_index);
796
797   /* Enqueue the packet */
798   to_next = vlib_frame_vector_args (f);
799   to_next[0] = bi;
800   f->n_vectors = 1;
801   vlib_put_frame_to_node (vm, next_index, f);
802 }
803
804 /**
805  *  Send FIN
806  */
807 void
808 tcp_send_fin (tcp_connection_t * tc)
809 {
810   vlib_buffer_t *b;
811   u32 bi;
812   tcp_main_t *tm = vnet_get_tcp_main ();
813   vlib_main_t *vm = tm->vlib_main;
814
815   tcp_get_free_buffer_index (tm, &bi);
816   b = vlib_get_buffer (vm, bi);
817
818   /* Leave enough space for headers */
819   vlib_buffer_make_headroom (b, MAX_HDRS_LEN);
820
821   tcp_make_finack (tc, b);
822
823   tcp_enqueue_to_output (vm, b, bi, tc->c_is_ip4);
824 }
825
826 always_inline u8
827 tcp_make_state_flags (tcp_state_t next_state)
828 {
829   switch (next_state)
830     {
831     case TCP_STATE_ESTABLISHED:
832       return TCP_FLAG_ACK;
833     case TCP_STATE_SYN_RCVD:
834       return TCP_FLAG_SYN | TCP_FLAG_ACK;
835     case TCP_STATE_SYN_SENT:
836       return TCP_FLAG_SYN;
837     case TCP_STATE_LAST_ACK:
838     case TCP_STATE_FIN_WAIT_1:
839       return TCP_FLAG_FIN;
840     default:
841       clib_warning ("Shouldn't be here!");
842     }
843   return 0;
844 }
845
846 /**
847  * Push TCP header and update connection variables
848  */
849 static void
850 tcp_push_hdr_i (tcp_connection_t * tc, vlib_buffer_t * b,
851                 tcp_state_t next_state)
852 {
853   u32 advertise_wnd, data_len;
854   u8 tcp_opts_len, tcp_hdr_opts_len, opts_write_len, flags;
855   tcp_options_t _snd_opts, *snd_opts = &_snd_opts;
856   tcp_header_t *th;
857
858   data_len = b->current_length;
859   vnet_buffer (b)->tcp.flags = 0;
860
861   /* Make and write options */
862   memset (snd_opts, 0, sizeof (*snd_opts));
863   tcp_opts_len = tcp_make_options (tc, snd_opts, next_state);
864   tcp_hdr_opts_len = tcp_opts_len + sizeof (tcp_header_t);
865
866   /* Get rcv window to advertise */
867   advertise_wnd = tcp_window_to_advertise (tc, next_state);
868   flags = tcp_make_state_flags (next_state);
869
870   /* Push header and options */
871   th = vlib_buffer_push_tcp (b, tc->c_lcl_port, tc->c_rmt_port, tc->snd_nxt,
872                              tc->rcv_nxt, tcp_hdr_opts_len, flags,
873                              advertise_wnd);
874
875   opts_write_len = tcp_options_write ((u8 *) (th + 1), snd_opts);
876
877   ASSERT (opts_write_len == tcp_opts_len);
878
879   /* Tag the buffer with the connection index  */
880   vnet_buffer (b)->tcp.connection_index = tc->c_c_index;
881
882   tc->snd_nxt += data_len;
883 }
884
885 /* Send delayed ACK when timer expires */
886 void
887 tcp_timer_delack_handler (u32 index)
888 {
889   tcp_main_t *tm = vnet_get_tcp_main ();
890   vlib_main_t *vm = tm->vlib_main;
891   u32 thread_index = os_get_cpu_number ();
892   tcp_connection_t *tc;
893   vlib_buffer_t *b;
894   u32 bi;
895
896   tc = tcp_connection_get (index, thread_index);
897
898   /* Get buffer */
899   tcp_get_free_buffer_index (tm, &bi);
900   b = vlib_get_buffer (vm, bi);
901
902   /* Fill in the ACK */
903   tcp_make_ack (tc, b);
904
905   tc->timers[TCP_TIMER_DELACK] = TCP_TIMER_HANDLE_INVALID;
906   tc->flags &= ~TCP_CONN_DELACK;
907
908   tcp_enqueue_to_output (vm, b, bi, tc->c_is_ip4);
909 }
910
911 /** Build a retransmit segment
912  *
913  * @return the number of bytes in the segment or 0 if there's nothing to
914  *         retransmit
915  * */
916 u32
917 tcp_prepare_retransmit_segment (tcp_connection_t * tc, vlib_buffer_t * b,
918                                 u32 max_bytes)
919 {
920   tcp_main_t *tm = vnet_get_tcp_main ();
921   vlib_main_t *vm = tm->vlib_main;
922   u32 n_bytes, offset = 0;
923   sack_scoreboard_hole_t *hole;
924   u32 hole_size;
925
926   tcp_reuse_buffer (vm, b);
927
928   ASSERT (tc->state >= TCP_STATE_ESTABLISHED);
929   ASSERT (max_bytes != 0);
930
931   if (tcp_opts_sack_permitted (&tc->opt))
932     {
933       /* XXX get first hole not retransmitted yet  */
934       hole = scoreboard_first_hole (&tc->sack_sb);
935       if (!hole)
936         return 0;
937
938       offset = hole->start - tc->snd_una;
939       hole_size = hole->end - hole->start;
940
941       ASSERT (hole_size);
942
943       if (hole_size < max_bytes)
944         max_bytes = hole_size;
945     }
946   else
947     {
948       if (seq_geq (tc->snd_nxt, tc->snd_una_max))
949         return 0;
950     }
951
952   n_bytes = stream_session_peek_bytes (&tc->connection,
953                                        vlib_buffer_get_current (b), offset,
954                                        max_bytes);
955   ASSERT (n_bytes != 0);
956
957   tcp_push_hdr_i (tc, b, tc->state);
958
959   return n_bytes;
960 }
961
962 static void
963 tcp_timer_retransmit_handler_i (u32 index, u8 is_syn)
964 {
965   tcp_main_t *tm = vnet_get_tcp_main ();
966   vlib_main_t *vm = tm->vlib_main;
967   u32 thread_index = os_get_cpu_number ();
968   tcp_connection_t *tc;
969   vlib_buffer_t *b;
970   u32 bi, max_bytes, snd_space;
971
972   if (is_syn)
973     {
974       tc = tcp_half_open_connection_get (index);
975     }
976   else
977     {
978       tc = tcp_connection_get (index, thread_index);
979     }
980
981   /* Make sure timer handle is set to invalid */
982   tc->timers[TCP_TIMER_RETRANSMIT] = TCP_TIMER_HANDLE_INVALID;
983
984   /* Increment RTO backoff (also equal to number of retries) */
985   tc->rto_boff += 1;
986
987   /* Go back to first un-acked byte */
988   tc->snd_nxt = tc->snd_una;
989
990   /* Get buffer */
991   tcp_get_free_buffer_index (tm, &bi);
992   b = vlib_get_buffer (vm, bi);
993
994   if (tc->state >= TCP_STATE_ESTABLISHED)
995     {
996       tcp_fastrecovery_off (tc);
997
998       /* Exponential backoff */
999       tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);
1000
1001       /* Figure out what and how many bytes we can send */
1002       snd_space = tcp_available_snd_space (tc);
1003       max_bytes = clib_min (tc->snd_mss, snd_space);
1004
1005       if (max_bytes == 0)
1006         {
1007           clib_warning ("no wnd to retransmit");
1008           return;
1009         }
1010       tcp_prepare_retransmit_segment (tc, b, max_bytes);
1011
1012       tc->rtx_bytes += max_bytes;
1013
1014       /* No fancy recovery for now! */
1015       scoreboard_clear (&tc->sack_sb);
1016     }
1017   else
1018     {
1019       /* Retransmit for SYN/SYNACK */
1020       ASSERT (tc->state == TCP_STATE_SYN_RCVD
1021               || tc->state == TCP_STATE_SYN_SENT);
1022
1023       /* Try without increasing RTO a number of times. If this fails,
1024        * start growing RTO exponentially */
1025       if (tc->rto_boff > TCP_RTO_SYN_RETRIES)
1026         tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);
1027
1028       vlib_buffer_make_headroom (b, MAX_HDRS_LEN);
1029
1030       tcp_push_hdr_i (tc, b, tc->state);
1031
1032       /* Account for the SYN */
1033       tc->snd_nxt += 1;
1034     }
1035
1036   if (!is_syn)
1037     {
1038       tcp_enqueue_to_output (vm, b, bi, tc->c_is_ip4);
1039
1040       /* Re-enable retransmit timer */
1041       tcp_retransmit_timer_set (tm, tc);
1042     }
1043   else
1044     {
1045       ASSERT (tc->state == TCP_STATE_SYN_SENT);
1046
1047       /* This goes straight to ipx_lookup */
1048       tcp_push_ip_hdr (tm, tc, b);
1049       tcp_enqueue_to_ip_lookup (vm, b, bi, tc->c_is_ip4);
1050
1051       /* Re-enable retransmit timer */
1052       tcp_timer_set (tc, TCP_TIMER_RETRANSMIT_SYN,
1053                      tc->rto * TCP_TO_TIMER_TICK);
1054     }
1055 }
1056
1057 void
1058 tcp_timer_retransmit_handler (u32 index)
1059 {
1060   tcp_timer_retransmit_handler_i (index, 0);
1061 }
1062
1063 void
1064 tcp_timer_retransmit_syn_handler (u32 index)
1065 {
1066   tcp_timer_retransmit_handler_i (index, 1);
1067 }
1068
1069 /**
1070  * Retansmit first unacked segment */
1071 void
1072 tcp_retransmit_first_unacked (tcp_connection_t * tc)
1073 {
1074   tcp_main_t *tm = vnet_get_tcp_main ();
1075   u32 snd_nxt = tc->snd_nxt;
1076   vlib_buffer_t *b;
1077   u32 bi;
1078
1079   tc->snd_nxt = tc->snd_una;
1080
1081   /* Get buffer */
1082   tcp_get_free_buffer_index (tm, &bi);
1083   b = vlib_get_buffer (tm->vlib_main, bi);
1084
1085   tcp_prepare_retransmit_segment (tc, b, tc->snd_mss);
1086   tcp_enqueue_to_output (tm->vlib_main, b, bi, tc->c_is_ip4);
1087
1088   tc->snd_nxt = snd_nxt;
1089   tc->rtx_bytes += tc->snd_mss;
1090 }
1091
1092 void
1093 tcp_fast_retransmit (tcp_connection_t * tc)
1094 {
1095   tcp_main_t *tm = vnet_get_tcp_main ();
1096   u32 snd_space, max_bytes, n_bytes, bi;
1097   vlib_buffer_t *b;
1098
1099   ASSERT (tcp_in_fastrecovery (tc));
1100
1101   clib_warning ("fast retransmit!");
1102
1103   /* Start resending from first un-acked segment */
1104   tc->snd_nxt = tc->snd_una;
1105
1106   snd_space = tcp_available_snd_space (tc);
1107
1108   while (snd_space)
1109     {
1110       tcp_get_free_buffer_index (tm, &bi);
1111       b = vlib_get_buffer (tm->vlib_main, bi);
1112
1113       max_bytes = clib_min (tc->snd_mss, snd_space);
1114       n_bytes = tcp_prepare_retransmit_segment (tc, b, max_bytes);
1115
1116       /* Nothing left to retransmit */
1117       if (n_bytes == 0)
1118         return;
1119
1120       tcp_enqueue_to_output (tm->vlib_main, b, bi, tc->c_is_ip4);
1121
1122       snd_space -= n_bytes;
1123     }
1124
1125   /* If window allows, send new data */
1126   tc->snd_nxt = tc->snd_una_max;
1127 }
1128
1129 always_inline u32
1130 tcp_session_has_ooo_data (tcp_connection_t * tc)
1131 {
1132   stream_session_t *s =
1133     stream_session_get (tc->c_s_index, tc->c_thread_index);
1134   return svm_fifo_has_ooo_data (s->server_rx_fifo);
1135 }
1136
1137 always_inline uword
1138 tcp46_output_inline (vlib_main_t * vm,
1139                      vlib_node_runtime_t * node,
1140                      vlib_frame_t * from_frame, int is_ip4)
1141 {
1142   tcp_main_t *tm = vnet_get_tcp_main ();
1143   u32 n_left_from, next_index, *from, *to_next;
1144   u32 my_thread_index = vm->cpu_index;
1145
1146   from = vlib_frame_vector_args (from_frame);
1147   n_left_from = from_frame->n_vectors;
1148
1149   next_index = node->cached_next_index;
1150
1151   while (n_left_from > 0)
1152     {
1153       u32 n_left_to_next;
1154
1155       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1156
1157       while (n_left_from > 0 && n_left_to_next > 0)
1158         {
1159           u32 bi0;
1160           vlib_buffer_t *b0;
1161           tcp_connection_t *tc0;
1162           tcp_header_t *th0;
1163           u32 error0 = TCP_ERROR_PKTS_SENT, next0 = TCP_OUTPUT_NEXT_IP_LOOKUP;
1164
1165           bi0 = from[0];
1166           to_next[0] = bi0;
1167           from += 1;
1168           to_next += 1;
1169           n_left_from -= 1;
1170           n_left_to_next -= 1;
1171
1172           b0 = vlib_get_buffer (vm, bi0);
1173           tc0 = tcp_connection_get (vnet_buffer (b0)->tcp.connection_index,
1174                                     my_thread_index);
1175           th0 = vlib_buffer_get_current (b0);
1176
1177           if (is_ip4)
1178             {
1179               ip4_header_t *ih0;
1180               ih0 = vlib_buffer_push_ip4 (vm, b0, &tc0->c_lcl_ip4,
1181                                           &tc0->c_rmt_ip4, IP_PROTOCOL_TCP);
1182               th0->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ih0);
1183             }
1184           else
1185             {
1186               ip6_header_t *ih0;
1187               int bogus = ~0;
1188
1189               ih0 = vlib_buffer_push_ip6 (vm, b0, &tc0->c_lcl_ip6,
1190                                           &tc0->c_rmt_ip6, IP_PROTOCOL_TCP);
1191               th0->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b0, ih0,
1192                                                                  &bogus);
1193               ASSERT (!bogus);
1194             }
1195
1196           /* Filter out DUPACKs if there are no OOO segments left */
1197           if (PREDICT_FALSE
1198               (vnet_buffer (b0)->tcp.flags & TCP_BUF_FLAG_DUPACK))
1199             {
1200               ASSERT (tc0->snt_dupacks > 0);
1201               tc0->snt_dupacks--;
1202               if (!tcp_session_has_ooo_data (tc0))
1203                 {
1204                   error0 = TCP_ERROR_FILTERED_DUPACKS;
1205                   next0 = TCP_OUTPUT_NEXT_DROP;
1206                   goto done;
1207                 }
1208             }
1209
1210           /* Retransmitted SYNs do reach this but it should be harmless */
1211           tc0->rcv_las = tc0->rcv_nxt;
1212
1213           /* Stop DELACK timer and fix flags */
1214           tc0->flags &=
1215             ~(TCP_CONN_SNDACK | TCP_CONN_DELACK | TCP_CONN_BURSTACK);
1216           if (tcp_timer_is_active (tc0, TCP_TIMER_DELACK))
1217             {
1218               tcp_timer_reset (tc0, TCP_TIMER_DELACK);
1219             }
1220
1221           /* If not retransmitting
1222            * 1) update snd_una_max (SYN, SYNACK, new data, FIN)
1223            * 2) If we're not tracking an ACK, start tracking */
1224           if (seq_lt (tc0->snd_una_max, tc0->snd_nxt))
1225             {
1226               tc0->snd_una_max = tc0->snd_nxt;
1227               if (tc0->rtt_ts == 0)
1228                 {
1229                   tc0->rtt_ts = tcp_time_now ();
1230                   tc0->rtt_seq = tc0->snd_nxt;
1231                 }
1232             }
1233
1234           /* Set the retransmit timer if not set already and not
1235            * doing a pure ACK */
1236           if (!tcp_timer_is_active (tc0, TCP_TIMER_RETRANSMIT)
1237               && tc0->snd_nxt != tc0->snd_una)
1238             {
1239               tcp_retransmit_timer_set (tm, tc0);
1240               tc0->rto_boff = 0;
1241             }
1242
1243           /* set fib index to default and lookup node */
1244           /* XXX network virtualization (vrf/vni) */
1245           vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
1246           vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1247
1248           b0->flags |= VNET_BUFFER_LOCALLY_ORIGINATED;
1249
1250         done:
1251           b0->error = error0 != 0 ? node->errors[error0] : 0;
1252           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1253             {
1254
1255             }
1256
1257           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1258                                            n_left_to_next, bi0, next0);
1259         }
1260
1261       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1262     }
1263
1264   return from_frame->n_vectors;
1265 }
1266
1267 static uword
1268 tcp4_output (vlib_main_t * vm, vlib_node_runtime_t * node,
1269              vlib_frame_t * from_frame)
1270 {
1271   return tcp46_output_inline (vm, node, from_frame, 1 /* is_ip4 */ );
1272 }
1273
1274 static uword
1275 tcp6_output (vlib_main_t * vm, vlib_node_runtime_t * node,
1276              vlib_frame_t * from_frame)
1277 {
1278   return tcp46_output_inline (vm, node, from_frame, 0 /* is_ip4 */ );
1279 }
1280
1281 VLIB_REGISTER_NODE (tcp4_output_node) =
1282 {
1283   .function = tcp4_output,.name = "tcp4-output",
1284     /* Takes a vector of packets. */
1285     .vector_size = sizeof (u32),.n_errors = TCP_N_ERROR,.error_strings =
1286     tcp_error_strings,.n_next_nodes = TCP_OUTPUT_N_NEXT,.next_nodes =
1287   {
1288 #define _(s,n) [TCP_OUTPUT_NEXT_##s] = n,
1289     foreach_tcp4_output_next
1290 #undef _
1291   }
1292 ,.format_buffer = format_tcp_header,.format_trace = format_tcp_tx_trace,};
1293
1294 VLIB_NODE_FUNCTION_MULTIARCH (tcp4_output_node, tcp4_output)
1295 VLIB_REGISTER_NODE (tcp6_output_node) =
1296 {
1297   .function = tcp6_output,.name = "tcp6-output",
1298     /* Takes a vector of packets. */
1299     .vector_size = sizeof (u32),.n_errors = TCP_N_ERROR,.error_strings =
1300     tcp_error_strings,.n_next_nodes = TCP_OUTPUT_N_NEXT,.next_nodes =
1301   {
1302 #define _(s,n) [TCP_OUTPUT_NEXT_##s] = n,
1303     foreach_tcp6_output_next
1304 #undef _
1305   }
1306 ,.format_buffer = format_tcp_header,.format_trace = format_tcp_tx_trace,};
1307
1308 VLIB_NODE_FUNCTION_MULTIARCH (tcp6_output_node, tcp6_output) u32
1309 tcp_push_header (transport_connection_t * tconn, vlib_buffer_t * b)
1310 {
1311   tcp_connection_t *tc;
1312
1313   tc = (tcp_connection_t *) tconn;
1314   tcp_push_hdr_i (tc, b, TCP_STATE_ESTABLISHED);
1315   return 0;
1316 }
1317
1318 typedef enum _tcp_reset_next
1319 {
1320   TCP_RESET_NEXT_DROP,
1321   TCP_RESET_NEXT_IP_LOOKUP,
1322   TCP_RESET_N_NEXT
1323 } tcp_reset_next_t;
1324
1325 #define foreach_tcp4_reset_next         \
1326   _(DROP, "error-drop")                 \
1327   _(IP_LOOKUP, "ip4-lookup")
1328
1329 #define foreach_tcp6_reset_next         \
1330   _(DROP, "error-drop")                 \
1331   _(IP_LOOKUP, "ip6-lookup")
1332
1333 static uword
1334 tcp46_send_reset_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
1335                          vlib_frame_t * from_frame, u8 is_ip4)
1336 {
1337   u32 n_left_from, next_index, *from, *to_next;
1338   u32 my_thread_index = vm->cpu_index;
1339
1340   from = vlib_frame_vector_args (from_frame);
1341   n_left_from = from_frame->n_vectors;
1342
1343   next_index = node->cached_next_index;
1344
1345   while (n_left_from > 0)
1346     {
1347       u32 n_left_to_next;
1348
1349       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1350
1351       while (n_left_from > 0 && n_left_to_next > 0)
1352         {
1353           u32 bi0;
1354           vlib_buffer_t *b0;
1355           u32 error0 = TCP_ERROR_RST_SENT, next0 = TCP_RESET_NEXT_IP_LOOKUP;
1356
1357           bi0 = from[0];
1358           to_next[0] = bi0;
1359           from += 1;
1360           to_next += 1;
1361           n_left_from -= 1;
1362           n_left_to_next -= 1;
1363
1364           b0 = vlib_get_buffer (vm, bi0);
1365
1366           if (tcp_make_reset_in_place (vm, b0, vnet_buffer (b0)->tcp.flags,
1367                                        my_thread_index, is_ip4))
1368             {
1369               error0 = TCP_ERROR_LOOKUP_DROPS;
1370               next0 = TCP_RESET_NEXT_DROP;
1371               goto done;
1372             }
1373
1374           /* Prepare to send to IP lookup */
1375           vnet_buffer (b0)->sw_if_index[VLIB_TX] = 0;
1376           next0 = TCP_RESET_NEXT_IP_LOOKUP;
1377
1378         done:
1379           b0->error = error0 != 0 ? node->errors[error0] : 0;
1380           b0->flags |= VNET_BUFFER_LOCALLY_ORIGINATED;
1381           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1382             {
1383
1384             }
1385
1386           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1387                                            n_left_to_next, bi0, next0);
1388         }
1389       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1390     }
1391   return from_frame->n_vectors;
1392 }
1393
1394 static uword
1395 tcp4_send_reset (vlib_main_t * vm, vlib_node_runtime_t * node,
1396                  vlib_frame_t * from_frame)
1397 {
1398   return tcp46_send_reset_inline (vm, node, from_frame, 1);
1399 }
1400
1401 static uword
1402 tcp6_send_reset (vlib_main_t * vm, vlib_node_runtime_t * node,
1403                  vlib_frame_t * from_frame)
1404 {
1405   return tcp46_send_reset_inline (vm, node, from_frame, 0);
1406 }
1407
1408 /* *INDENT-OFF* */
1409 VLIB_REGISTER_NODE (tcp4_reset_node) = {
1410   .function = tcp4_send_reset,
1411   .name = "tcp4-reset",
1412   .vector_size = sizeof (u32),
1413   .n_errors = TCP_N_ERROR,
1414   .error_strings = tcp_error_strings,
1415   .n_next_nodes = TCP_RESET_N_NEXT,
1416   .next_nodes = {
1417 #define _(s,n) [TCP_RESET_NEXT_##s] = n,
1418     foreach_tcp4_reset_next
1419 #undef _
1420   },
1421 };
1422 /* *INDENT-ON* */
1423
1424 /* *INDENT-OFF* */
1425 VLIB_REGISTER_NODE (tcp6_reset_node) = {
1426   .function = tcp6_send_reset,
1427   .name = "tcp6-reset",
1428   .vector_size = sizeof (u32),
1429   .n_errors = TCP_N_ERROR,
1430   .error_strings = tcp_error_strings,
1431   .n_next_nodes = TCP_RESET_N_NEXT,
1432   .next_nodes = {
1433 #define _(s,n) [TCP_RESET_NEXT_##s] = n,
1434     foreach_tcp6_reset_next
1435 #undef _
1436   },
1437 };
1438 /* *INDENT-ON* */
1439
1440 /*
1441  * fd.io coding-style-patch-verification: ON
1442  *
1443  * Local Variables:
1444  * eval: (c-set-style "gnu")
1445  * End:
1446  */