VPP-659 TCP improvements
[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   vnet_buffer (b)->tcp.flags = 0;
400 }
401
402 /**
403  * Prepare ACK
404  */
405 void
406 tcp_make_ack_i (tcp_connection_t * tc, vlib_buffer_t * b, tcp_state_t state,
407                 u8 flags)
408 {
409   tcp_options_t _snd_opts, *snd_opts = &_snd_opts;
410   u8 tcp_opts_len, tcp_hdr_opts_len;
411   tcp_header_t *th;
412   u16 wnd;
413
414   wnd = tcp_window_to_advertise (tc, state);
415
416   /* Make and write options */
417   tcp_opts_len = tcp_make_established_options (tc, snd_opts);
418   tcp_hdr_opts_len = tcp_opts_len + sizeof (tcp_header_t);
419
420   th = vlib_buffer_push_tcp (b, tc->c_lcl_port, tc->c_rmt_port, tc->snd_nxt,
421                              tc->rcv_nxt, tcp_hdr_opts_len, flags, wnd);
422
423   tcp_options_write ((u8 *) (th + 1), snd_opts);
424
425   /* Mark as ACK */
426   vnet_buffer (b)->tcp.connection_index = tc->c_c_index;
427 }
428
429 /**
430  * Convert buffer to ACK
431  */
432 void
433 tcp_make_ack (tcp_connection_t * tc, vlib_buffer_t * b)
434 {
435   tcp_main_t *tm = vnet_get_tcp_main ();
436   vlib_main_t *vm = tm->vlib_main;
437
438   tcp_reuse_buffer (vm, b);
439   tcp_make_ack_i (tc, b, TCP_STATE_ESTABLISHED, TCP_FLAG_ACK);
440   vnet_buffer (b)->tcp.flags = TCP_BUF_FLAG_ACK;
441 }
442
443 /**
444  * Convert buffer to FIN-ACK
445  */
446 void
447 tcp_make_fin (tcp_connection_t * tc, vlib_buffer_t * b)
448 {
449   tcp_main_t *tm = vnet_get_tcp_main ();
450   vlib_main_t *vm = tm->vlib_main;
451   u8 flags = 0;
452
453   tcp_reuse_buffer (vm, b);
454
455   if (tc->rcv_las == tc->rcv_nxt)
456     flags = TCP_FLAG_FIN;
457   else
458     flags = TCP_FLAG_FIN | TCP_FLAG_ACK;
459
460   tcp_make_ack_i (tc, b, TCP_STATE_ESTABLISHED, flags);
461
462   /* Reset flags, make sure ack is sent */
463   vnet_buffer (b)->tcp.flags &= ~TCP_BUF_FLAG_DUPACK;
464
465   tc->snd_nxt += 1;
466 }
467
468 /**
469  * Convert buffer to SYN-ACK
470  */
471 void
472 tcp_make_synack (tcp_connection_t * tc, vlib_buffer_t * b)
473 {
474   tcp_main_t *tm = vnet_get_tcp_main ();
475   vlib_main_t *vm = tm->vlib_main;
476   tcp_options_t _snd_opts, *snd_opts = &_snd_opts;
477   u8 tcp_opts_len, tcp_hdr_opts_len;
478   tcp_header_t *th;
479   u16 initial_wnd;
480   u32 time_now;
481
482   memset (snd_opts, 0, sizeof (*snd_opts));
483
484   tcp_reuse_buffer (vm, b);
485
486   /* Set random initial sequence */
487   time_now = tcp_time_now ();
488
489   tc->iss = random_u32 (&time_now);
490   tc->snd_una = tc->iss;
491   tc->snd_nxt = tc->iss + 1;
492   tc->snd_una_max = tc->snd_nxt;
493
494   initial_wnd = tcp_initial_window_to_advertise (tc);
495
496   /* Make and write options */
497   tcp_opts_len = tcp_make_synack_options (tc, snd_opts);
498   tcp_hdr_opts_len = tcp_opts_len + sizeof (tcp_header_t);
499
500   th = vlib_buffer_push_tcp (b, tc->c_lcl_port, tc->c_rmt_port, tc->iss,
501                              tc->rcv_nxt, tcp_hdr_opts_len,
502                              TCP_FLAG_SYN | TCP_FLAG_ACK, initial_wnd);
503
504   tcp_options_write ((u8 *) (th + 1), snd_opts);
505
506   vnet_buffer (b)->tcp.connection_index = tc->c_c_index;
507   vnet_buffer (b)->tcp.flags = TCP_BUF_FLAG_ACK;
508
509   /* Init retransmit timer */
510   tcp_retransmit_timer_set (tc);
511 }
512
513 always_inline void
514 tcp_enqueue_to_ip_lookup (vlib_main_t * vm, vlib_buffer_t * b, u32 bi,
515                           u8 is_ip4)
516 {
517   u32 *to_next, next_index;
518   vlib_frame_t *f;
519
520   b->flags |= VNET_BUFFER_LOCALLY_ORIGINATED;
521   b->error = 0;
522
523   /* Default FIB for now */
524   vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
525
526   /* Send to IP lookup */
527   next_index = is_ip4 ? ip4_lookup_node.index : ip6_lookup_node.index;
528   f = vlib_get_frame_to_node (vm, next_index);
529
530   /* Enqueue the packet */
531   to_next = vlib_frame_vector_args (f);
532   to_next[0] = bi;
533   f->n_vectors = 1;
534   vlib_put_frame_to_node (vm, next_index, f);
535 }
536
537 int
538 tcp_make_reset_in_place (vlib_main_t * vm, vlib_buffer_t * b0,
539                          tcp_state_t state, u32 my_thread_index, u8 is_ip4)
540 {
541   u8 tcp_hdr_len = sizeof (tcp_header_t);
542   ip4_header_t *ih4;
543   ip6_header_t *ih6;
544   tcp_header_t *th0;
545   ip4_address_t src_ip40;
546   ip6_address_t src_ip60;
547   u16 src_port0;
548   u32 tmp;
549
550   /* Find IP and TCP headers */
551   if (is_ip4)
552     {
553       ih4 = vlib_buffer_get_current (b0);
554       th0 = ip4_next_header (ih4);
555     }
556   else
557     {
558       ih6 = vlib_buffer_get_current (b0);
559       th0 = ip6_next_header (ih6);
560     }
561
562   /* Swap src and dst ip */
563   if (is_ip4)
564     {
565       ASSERT ((ih4->ip_version_and_header_length & 0xF0) == 0x40);
566       src_ip40.as_u32 = ih4->src_address.as_u32;
567       ih4->src_address.as_u32 = ih4->dst_address.as_u32;
568       ih4->dst_address.as_u32 = src_ip40.as_u32;
569
570       /* Chop the end of the pkt */
571       b0->current_length += ip4_header_bytes (ih4) + tcp_hdr_len;
572     }
573   else
574     {
575       ASSERT ((ih6->ip_version_traffic_class_and_flow_label & 0xF0) == 0x60);
576       clib_memcpy (&src_ip60, &ih6->src_address, sizeof (ip6_address_t));
577       clib_memcpy (&ih6->src_address, &ih6->dst_address,
578                    sizeof (ip6_address_t));
579       clib_memcpy (&ih6->dst_address, &src_ip60, sizeof (ip6_address_t));
580
581       /* Chop the end of the pkt */
582       b0->current_length += sizeof (ip6_header_t) + tcp_hdr_len;
583     }
584
585   /* Try to determine what/why we're actually resetting and swap
586    * src and dst ports */
587   if (state == TCP_STATE_CLOSED)
588     {
589       if (!tcp_syn (th0))
590         return -1;
591
592       tmp = clib_net_to_host_u32 (th0->seq_number);
593
594       /* Got a SYN for no listener. */
595       th0->flags = TCP_FLAG_RST | TCP_FLAG_ACK;
596       th0->ack_number = clib_host_to_net_u32 (tmp + 1);
597       th0->seq_number = 0;
598
599     }
600   else if (state >= TCP_STATE_SYN_SENT)
601     {
602       th0->flags = TCP_FLAG_RST | TCP_FLAG_ACK;
603       th0->seq_number = th0->ack_number;
604       th0->ack_number = 0;
605     }
606
607   src_port0 = th0->src_port;
608   th0->src_port = th0->dst_port;
609   th0->dst_port = src_port0;
610   th0->window = 0;
611   th0->data_offset_and_reserved = (tcp_hdr_len >> 2) << 4;
612   th0->urgent_pointer = 0;
613
614   /* Compute checksum */
615   if (is_ip4)
616     {
617       th0->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ih4);
618     }
619   else
620     {
621       int bogus = ~0;
622       th0->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b0, ih6, &bogus);
623       ASSERT (!bogus);
624     }
625
626   return 0;
627 }
628
629 /**
630  *  Send reset without reusing existing buffer
631  */
632 void
633 tcp_send_reset (vlib_buffer_t * pkt, u8 is_ip4)
634 {
635   vlib_buffer_t *b;
636   u32 bi;
637   tcp_main_t *tm = vnet_get_tcp_main ();
638   vlib_main_t *vm = tm->vlib_main;
639   u8 tcp_hdr_len, flags = 0;
640   tcp_header_t *th, *pkt_th;
641   u32 seq, ack;
642   ip4_header_t *ih4, *pkt_ih4;
643   ip6_header_t *ih6, *pkt_ih6;
644
645   tcp_get_free_buffer_index (tm, &bi);
646   b = vlib_get_buffer (vm, bi);
647
648   /* Leave enough space for headers */
649   vlib_buffer_make_headroom (b, MAX_HDRS_LEN);
650
651   /* Make and write options */
652   tcp_hdr_len = sizeof (tcp_header_t);
653
654   if (is_ip4)
655     {
656       pkt_ih4 = vlib_buffer_get_current (pkt);
657       pkt_th = ip4_next_header (pkt_ih4);
658     }
659   else
660     {
661       pkt_ih6 = vlib_buffer_get_current (pkt);
662       pkt_th = ip6_next_header (pkt_ih6);
663     }
664
665   if (tcp_ack (pkt_th))
666     {
667       flags = TCP_FLAG_RST;
668       seq = pkt_th->ack_number;
669       ack = 0;
670     }
671   else
672     {
673       flags = TCP_FLAG_RST | TCP_FLAG_ACK;
674       seq = 0;
675       ack = clib_host_to_net_u32 (vnet_buffer (pkt)->tcp.seq_end);
676     }
677
678   th = vlib_buffer_push_tcp_net_order (b, pkt_th->dst_port, pkt_th->src_port,
679                                        seq, ack, tcp_hdr_len, flags, 0);
680
681   /* Swap src and dst ip */
682   if (is_ip4)
683     {
684       ASSERT ((pkt_ih4->ip_version_and_header_length & 0xF0) == 0x40);
685       ih4 = vlib_buffer_push_ip4 (vm, b, &pkt_ih4->dst_address,
686                                   &pkt_ih4->src_address, IP_PROTOCOL_TCP);
687       th->checksum = ip4_tcp_udp_compute_checksum (vm, b, ih4);
688     }
689   else
690     {
691       int bogus = ~0;
692       pkt_ih6 = (ip6_header_t *) (pkt_th - 1);
693       ASSERT ((pkt_ih6->ip_version_traffic_class_and_flow_label & 0xF0) ==
694               0x60);
695       ih6 =
696         vlib_buffer_push_ip6 (vm, b, &pkt_ih6->dst_address,
697                               &pkt_ih6->src_address, IP_PROTOCOL_TCP);
698       th->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b, ih6, &bogus);
699       ASSERT (!bogus);
700     }
701
702   tcp_enqueue_to_ip_lookup (vm, b, bi, is_ip4);
703 }
704
705 void
706 tcp_push_ip_hdr (tcp_main_t * tm, tcp_connection_t * tc, vlib_buffer_t * b)
707 {
708   tcp_header_t *th = vlib_buffer_get_current (b);
709
710   if (tc->c_is_ip4)
711     {
712       ip4_header_t *ih;
713       ih = vlib_buffer_push_ip4 (tm->vlib_main, b, &tc->c_lcl_ip4,
714                                  &tc->c_rmt_ip4, IP_PROTOCOL_TCP);
715       th->checksum = ip4_tcp_udp_compute_checksum (tm->vlib_main, b, ih);
716     }
717   else
718     {
719       ip6_header_t *ih;
720       int bogus = ~0;
721
722       ih = vlib_buffer_push_ip6 (tm->vlib_main, b, &tc->c_lcl_ip6,
723                                  &tc->c_rmt_ip6, IP_PROTOCOL_TCP);
724       th->checksum = ip6_tcp_udp_icmp_compute_checksum (tm->vlib_main, b, ih,
725                                                         &bogus);
726       ASSERT (!bogus);
727     }
728 }
729
730 /**
731  *  Send SYN
732  *
733  *  Builds a SYN packet for a half-open connection and sends it to ipx_lookup.
734  *  The packet is not forwarded through tcpx_output to avoid doing lookups
735  *  in the half_open pool.
736  */
737 void
738 tcp_send_syn (tcp_connection_t * tc)
739 {
740   vlib_buffer_t *b;
741   u32 bi;
742   tcp_main_t *tm = vnet_get_tcp_main ();
743   vlib_main_t *vm = tm->vlib_main;
744   u8 tcp_hdr_opts_len, tcp_opts_len;
745   tcp_header_t *th;
746   u32 time_now;
747   u16 initial_wnd;
748   tcp_options_t snd_opts;
749
750   tcp_get_free_buffer_index (tm, &bi);
751   b = vlib_get_buffer (vm, bi);
752
753   /* Leave enough space for headers */
754   vlib_buffer_make_headroom (b, MAX_HDRS_LEN);
755
756   /* Set random initial sequence */
757   time_now = tcp_time_now ();
758
759   tc->iss = random_u32 (&time_now);
760   tc->snd_una = tc->iss;
761   tc->snd_una_max = tc->snd_nxt = tc->iss + 1;
762
763   initial_wnd = tcp_initial_window_to_advertise (tc);
764
765   /* Make and write options */
766   memset (&snd_opts, 0, sizeof (snd_opts));
767   tcp_opts_len = tcp_make_syn_options (&snd_opts, tc->rcv_wscale);
768   tcp_hdr_opts_len = tcp_opts_len + sizeof (tcp_header_t);
769
770   th = vlib_buffer_push_tcp (b, tc->c_lcl_port, tc->c_rmt_port, tc->iss,
771                              tc->rcv_nxt, tcp_hdr_opts_len, TCP_FLAG_SYN,
772                              initial_wnd);
773
774   tcp_options_write ((u8 *) (th + 1), &snd_opts);
775
776   /* Measure RTT with this */
777   tc->rtt_ts = tcp_time_now ();
778   tc->rtt_seq = tc->snd_nxt;
779
780   /* Start retransmit trimer  */
781   tcp_timer_set (tc, TCP_TIMER_RETRANSMIT_SYN, tc->rto * TCP_TO_TIMER_TICK);
782   tc->rto_boff = 0;
783
784   /* Set the connection establishment timer */
785   tcp_timer_set (tc, TCP_TIMER_ESTABLISH, TCP_ESTABLISH_TIME);
786
787   tcp_push_ip_hdr (tm, tc, b);
788   tcp_enqueue_to_ip_lookup (vm, b, bi, tc->c_is_ip4);
789 }
790
791 always_inline void
792 tcp_enqueue_to_output (vlib_main_t * vm, vlib_buffer_t * b, u32 bi, u8 is_ip4)
793 {
794   u32 *to_next, next_index;
795   vlib_frame_t *f;
796
797   b->flags |= VNET_BUFFER_LOCALLY_ORIGINATED;
798   b->error = 0;
799
800   /* Decide where to send the packet */
801   next_index = is_ip4 ? tcp4_output_node.index : tcp6_output_node.index;
802   f = vlib_get_frame_to_node (vm, next_index);
803
804   /* Enqueue the packet */
805   to_next = vlib_frame_vector_args (f);
806   to_next[0] = bi;
807   f->n_vectors = 1;
808   vlib_put_frame_to_node (vm, next_index, f);
809 }
810
811 /**
812  *  Send FIN
813  */
814 void
815 tcp_send_fin (tcp_connection_t * tc)
816 {
817   vlib_buffer_t *b;
818   u32 bi;
819   tcp_main_t *tm = vnet_get_tcp_main ();
820   vlib_main_t *vm = tm->vlib_main;
821
822   tcp_get_free_buffer_index (tm, &bi);
823   b = vlib_get_buffer (vm, bi);
824
825   /* Leave enough space for headers */
826   vlib_buffer_make_headroom (b, MAX_HDRS_LEN);
827
828   tcp_make_fin (tc, b);
829   tcp_enqueue_to_output (vm, b, bi, tc->c_is_ip4);
830   tc->flags |= TCP_CONN_FINSNT;
831 }
832
833 always_inline u8
834 tcp_make_state_flags (tcp_state_t next_state)
835 {
836   switch (next_state)
837     {
838     case TCP_STATE_ESTABLISHED:
839       return TCP_FLAG_ACK;
840     case TCP_STATE_SYN_RCVD:
841       return TCP_FLAG_SYN | TCP_FLAG_ACK;
842     case TCP_STATE_SYN_SENT:
843       return TCP_FLAG_SYN;
844     case TCP_STATE_LAST_ACK:
845     case TCP_STATE_FIN_WAIT_1:
846       return TCP_FLAG_FIN;
847     default:
848       clib_warning ("Shouldn't be here!");
849     }
850   return 0;
851 }
852
853 /**
854  * Push TCP header and update connection variables
855  */
856 static void
857 tcp_push_hdr_i (tcp_connection_t * tc, vlib_buffer_t * b,
858                 tcp_state_t next_state)
859 {
860   u32 advertise_wnd, data_len;
861   u8 tcp_opts_len, tcp_hdr_opts_len, opts_write_len, flags;
862   tcp_options_t _snd_opts, *snd_opts = &_snd_opts;
863   tcp_header_t *th;
864
865   data_len = b->current_length;
866   vnet_buffer (b)->tcp.flags = 0;
867
868   /* Make and write options */
869   memset (snd_opts, 0, sizeof (*snd_opts));
870   tcp_opts_len = tcp_make_options (tc, snd_opts, next_state);
871   tcp_hdr_opts_len = tcp_opts_len + sizeof (tcp_header_t);
872
873   /* Get rcv window to advertise */
874   advertise_wnd = tcp_window_to_advertise (tc, next_state);
875   flags = tcp_make_state_flags (next_state);
876
877   /* Push header and options */
878   th = vlib_buffer_push_tcp (b, tc->c_lcl_port, tc->c_rmt_port, tc->snd_nxt,
879                              tc->rcv_nxt, tcp_hdr_opts_len, flags,
880                              advertise_wnd);
881
882   opts_write_len = tcp_options_write ((u8 *) (th + 1), snd_opts);
883
884   ASSERT (opts_write_len == tcp_opts_len);
885
886   /* Tag the buffer with the connection index  */
887   vnet_buffer (b)->tcp.connection_index = tc->c_c_index;
888
889   tc->snd_nxt += data_len;
890 }
891
892 /* Send delayed ACK when timer expires */
893 void
894 tcp_timer_delack_handler (u32 index)
895 {
896   tcp_main_t *tm = vnet_get_tcp_main ();
897   vlib_main_t *vm = tm->vlib_main;
898   u32 thread_index = os_get_cpu_number ();
899   tcp_connection_t *tc;
900   vlib_buffer_t *b;
901   u32 bi;
902
903   tc = tcp_connection_get (index, thread_index);
904
905   /* Get buffer */
906   tcp_get_free_buffer_index (tm, &bi);
907   b = vlib_get_buffer (vm, bi);
908
909   /* Fill in the ACK */
910   tcp_make_ack (tc, b);
911
912   tc->timers[TCP_TIMER_DELACK] = TCP_TIMER_HANDLE_INVALID;
913   tc->flags &= ~TCP_CONN_DELACK;
914
915   tcp_enqueue_to_output (vm, b, bi, tc->c_is_ip4);
916 }
917
918 /** Build a retransmit segment
919  *
920  * @return the number of bytes in the segment or 0 if there's nothing to
921  *         retransmit
922  * */
923 u32
924 tcp_prepare_retransmit_segment (tcp_connection_t * tc, vlib_buffer_t * b,
925                                 u32 max_bytes)
926 {
927   tcp_main_t *tm = vnet_get_tcp_main ();
928   vlib_main_t *vm = tm->vlib_main;
929   u32 n_bytes, offset = 0;
930   sack_scoreboard_hole_t *hole;
931   u32 hole_size;
932
933   tcp_reuse_buffer (vm, b);
934
935   ASSERT (tc->state >= TCP_STATE_ESTABLISHED);
936   ASSERT (max_bytes != 0);
937
938   if (tcp_opts_sack_permitted (&tc->opt))
939     {
940       /* XXX get first hole not retransmitted yet  */
941       hole = scoreboard_first_hole (&tc->sack_sb);
942       if (!hole)
943         return 0;
944
945       offset = hole->start - tc->snd_una;
946       hole_size = hole->end - hole->start;
947
948       ASSERT (hole_size);
949
950       if (hole_size < max_bytes)
951         max_bytes = hole_size;
952     }
953   else
954     {
955       if (seq_geq (tc->snd_nxt, tc->snd_una_max))
956         return 0;
957     }
958
959   n_bytes = stream_session_peek_bytes (&tc->connection,
960                                        vlib_buffer_get_current (b), offset,
961                                        max_bytes);
962   ASSERT (n_bytes != 0);
963
964   tcp_push_hdr_i (tc, b, tc->state);
965
966   return n_bytes;
967 }
968
969 static void
970 tcp_timer_retransmit_handler_i (u32 index, u8 is_syn)
971 {
972   tcp_main_t *tm = vnet_get_tcp_main ();
973   vlib_main_t *vm = tm->vlib_main;
974   u32 thread_index = os_get_cpu_number ();
975   tcp_connection_t *tc;
976   vlib_buffer_t *b;
977   u32 bi, max_bytes, snd_space;
978
979   if (is_syn)
980     {
981       tc = tcp_half_open_connection_get (index);
982     }
983   else
984     {
985       tc = tcp_connection_get (index, thread_index);
986     }
987
988   /* Make sure timer handle is set to invalid */
989   tc->timers[TCP_TIMER_RETRANSMIT] = TCP_TIMER_HANDLE_INVALID;
990
991   /* Increment RTO backoff (also equal to number of retries) */
992   tc->rto_boff += 1;
993
994   /* Go back to first un-acked byte */
995   tc->snd_nxt = tc->snd_una;
996
997   /* Get buffer */
998   tcp_get_free_buffer_index (tm, &bi);
999   b = vlib_get_buffer (vm, bi);
1000
1001   if (tc->state >= TCP_STATE_ESTABLISHED)
1002     {
1003       tcp_fastrecovery_off (tc);
1004
1005       /* Exponential backoff */
1006       tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);
1007
1008       /* Figure out what and how many bytes we can send */
1009       snd_space = tcp_available_snd_space (tc);
1010       max_bytes = clib_min (tc->snd_mss, snd_space);
1011
1012       if (max_bytes == 0)
1013         {
1014           clib_warning ("no wnd to retransmit");
1015           return;
1016         }
1017       tcp_prepare_retransmit_segment (tc, b, max_bytes);
1018
1019       tc->rtx_bytes += max_bytes;
1020
1021       /* No fancy recovery for now! */
1022       scoreboard_clear (&tc->sack_sb);
1023     }
1024   else
1025     {
1026       /* Retransmit for SYN/SYNACK */
1027       ASSERT (tc->state == TCP_STATE_SYN_RCVD
1028               || tc->state == TCP_STATE_SYN_SENT);
1029
1030       /* Try without increasing RTO a number of times. If this fails,
1031        * start growing RTO exponentially */
1032       if (tc->rto_boff > TCP_RTO_SYN_RETRIES)
1033         tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);
1034
1035       vlib_buffer_make_headroom (b, MAX_HDRS_LEN);
1036
1037       tcp_push_hdr_i (tc, b, tc->state);
1038
1039       /* Account for the SYN */
1040       tc->snd_nxt += 1;
1041     }
1042
1043   if (!is_syn)
1044     {
1045       tcp_enqueue_to_output (vm, b, bi, tc->c_is_ip4);
1046
1047       /* Re-enable retransmit timer */
1048       tcp_retransmit_timer_set (tc);
1049     }
1050   else
1051     {
1052       ASSERT (tc->state == TCP_STATE_SYN_SENT);
1053
1054       /* This goes straight to ipx_lookup */
1055       tcp_push_ip_hdr (tm, tc, b);
1056       tcp_enqueue_to_ip_lookup (vm, b, bi, tc->c_is_ip4);
1057
1058       /* Re-enable retransmit timer */
1059       tcp_timer_set (tc, TCP_TIMER_RETRANSMIT_SYN,
1060                      tc->rto * TCP_TO_TIMER_TICK);
1061     }
1062 }
1063
1064 void
1065 tcp_timer_retransmit_handler (u32 index)
1066 {
1067   tcp_timer_retransmit_handler_i (index, 0);
1068 }
1069
1070 void
1071 tcp_timer_retransmit_syn_handler (u32 index)
1072 {
1073   tcp_timer_retransmit_handler_i (index, 1);
1074 }
1075
1076 /**
1077  * Retansmit first unacked segment */
1078 void
1079 tcp_retransmit_first_unacked (tcp_connection_t * tc)
1080 {
1081   tcp_main_t *tm = vnet_get_tcp_main ();
1082   u32 snd_nxt = tc->snd_nxt;
1083   vlib_buffer_t *b;
1084   u32 bi;
1085
1086   tc->snd_nxt = tc->snd_una;
1087
1088   /* Get buffer */
1089   tcp_get_free_buffer_index (tm, &bi);
1090   b = vlib_get_buffer (tm->vlib_main, bi);
1091
1092   tcp_prepare_retransmit_segment (tc, b, tc->snd_mss);
1093   tcp_enqueue_to_output (tm->vlib_main, b, bi, tc->c_is_ip4);
1094
1095   tc->snd_nxt = snd_nxt;
1096   tc->rtx_bytes += tc->snd_mss;
1097 }
1098
1099 void
1100 tcp_fast_retransmit (tcp_connection_t * tc)
1101 {
1102   tcp_main_t *tm = vnet_get_tcp_main ();
1103   u32 snd_space, max_bytes, n_bytes, bi;
1104   vlib_buffer_t *b;
1105
1106   ASSERT (tcp_in_fastrecovery (tc));
1107
1108   clib_warning ("fast retransmit!");
1109
1110   /* Start resending from first un-acked segment */
1111   tc->snd_nxt = tc->snd_una;
1112
1113   snd_space = tcp_available_snd_space (tc);
1114
1115   while (snd_space)
1116     {
1117       tcp_get_free_buffer_index (tm, &bi);
1118       b = vlib_get_buffer (tm->vlib_main, bi);
1119
1120       max_bytes = clib_min (tc->snd_mss, snd_space);
1121       n_bytes = tcp_prepare_retransmit_segment (tc, b, max_bytes);
1122
1123       /* Nothing left to retransmit */
1124       if (n_bytes == 0)
1125         return;
1126
1127       tcp_enqueue_to_output (tm->vlib_main, b, bi, tc->c_is_ip4);
1128
1129       snd_space -= n_bytes;
1130     }
1131
1132   /* If window allows, send new data */
1133   tc->snd_nxt = tc->snd_una_max;
1134 }
1135
1136 always_inline u32
1137 tcp_session_has_ooo_data (tcp_connection_t * tc)
1138 {
1139   stream_session_t *s =
1140     stream_session_get (tc->c_s_index, tc->c_thread_index);
1141   return svm_fifo_has_ooo_data (s->server_rx_fifo);
1142 }
1143
1144 always_inline uword
1145 tcp46_output_inline (vlib_main_t * vm,
1146                      vlib_node_runtime_t * node,
1147                      vlib_frame_t * from_frame, int is_ip4)
1148 {
1149   u32 n_left_from, next_index, *from, *to_next;
1150   u32 my_thread_index = vm->cpu_index;
1151
1152   from = vlib_frame_vector_args (from_frame);
1153   n_left_from = from_frame->n_vectors;
1154
1155   next_index = node->cached_next_index;
1156
1157   while (n_left_from > 0)
1158     {
1159       u32 n_left_to_next;
1160
1161       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1162
1163       while (n_left_from > 0 && n_left_to_next > 0)
1164         {
1165           u32 bi0;
1166           vlib_buffer_t *b0;
1167           tcp_connection_t *tc0;
1168           tcp_header_t *th0;
1169           u32 error0 = TCP_ERROR_PKTS_SENT, next0 = TCP_OUTPUT_NEXT_IP_LOOKUP;
1170
1171           bi0 = from[0];
1172           to_next[0] = bi0;
1173           from += 1;
1174           to_next += 1;
1175           n_left_from -= 1;
1176           n_left_to_next -= 1;
1177
1178           b0 = vlib_get_buffer (vm, bi0);
1179           tc0 = tcp_connection_get (vnet_buffer (b0)->tcp.connection_index,
1180                                     my_thread_index);
1181           if (PREDICT_FALSE (tc0 == 0 || tc0->state == TCP_STATE_CLOSED))
1182             {
1183               error0 = TCP_ERROR_INVALID_CONNECTION;
1184               next0 = TCP_OUTPUT_NEXT_DROP;
1185               goto done;
1186             }
1187
1188           th0 = vlib_buffer_get_current (b0);
1189
1190           if (is_ip4)
1191             {
1192               ip4_header_t *ih0;
1193               ih0 = vlib_buffer_push_ip4 (vm, b0, &tc0->c_lcl_ip4,
1194                                           &tc0->c_rmt_ip4, IP_PROTOCOL_TCP);
1195               th0->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ih0);
1196             }
1197           else
1198             {
1199               ip6_header_t *ih0;
1200               int bogus = ~0;
1201
1202               ih0 = vlib_buffer_push_ip6 (vm, b0, &tc0->c_lcl_ip6,
1203                                           &tc0->c_rmt_ip6, IP_PROTOCOL_TCP);
1204               th0->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b0, ih0,
1205                                                                  &bogus);
1206               ASSERT (!bogus);
1207             }
1208
1209           /* Filter out DUPACKs if there are no OOO segments left */
1210           if (PREDICT_FALSE
1211               (vnet_buffer (b0)->tcp.flags & TCP_BUF_FLAG_DUPACK))
1212             {
1213               ASSERT (tc0->snt_dupacks > 0);
1214               tc0->snt_dupacks--;
1215               if (!tcp_session_has_ooo_data (tc0))
1216                 {
1217                   error0 = TCP_ERROR_FILTERED_DUPACKS;
1218                   next0 = TCP_OUTPUT_NEXT_DROP;
1219                   goto done;
1220                 }
1221             }
1222
1223           /* Retransmitted SYNs do reach this but it should be harmless */
1224           tc0->rcv_las = tc0->rcv_nxt;
1225
1226           /* Stop DELACK timer and fix flags */
1227           tc0->flags &=
1228             ~(TCP_CONN_SNDACK | TCP_CONN_DELACK | TCP_CONN_BURSTACK);
1229           if (tcp_timer_is_active (tc0, TCP_TIMER_DELACK))
1230             {
1231               tcp_timer_reset (tc0, TCP_TIMER_DELACK);
1232             }
1233
1234           /* If not retransmitting
1235            * 1) update snd_una_max (SYN, SYNACK, new data, FIN)
1236            * 2) If we're not tracking an ACK, start tracking */
1237           if (seq_lt (tc0->snd_una_max, tc0->snd_nxt))
1238             {
1239               tc0->snd_una_max = tc0->snd_nxt;
1240               if (tc0->rtt_ts == 0)
1241                 {
1242                   tc0->rtt_ts = tcp_time_now ();
1243                   tc0->rtt_seq = tc0->snd_nxt;
1244                 }
1245
1246               if (1)
1247                 {
1248                   ELOG_TYPE_DECLARE (e) =
1249                   {
1250                   .format =
1251                       "output: snd_una %u snd_una_max %u",.format_args =
1252                       "i4i4",};
1253                   struct
1254                   {
1255                     u32 data[2];
1256                   } *ed;
1257                   ed = ELOG_DATA (&vm->elog_main, e);
1258                   ed->data[0] = tc0->snd_una - tc0->iss;
1259                   ed->data[1] = tc0->snd_una_max - tc0->iss;
1260                 }
1261             }
1262
1263           /* Set the retransmit timer if not set already and not
1264            * doing a pure ACK */
1265           if (!tcp_timer_is_active (tc0, TCP_TIMER_RETRANSMIT)
1266               && tc0->snd_nxt != tc0->snd_una)
1267             {
1268               tcp_retransmit_timer_set (tc0);
1269               tc0->rto_boff = 0;
1270             }
1271
1272           /* set fib index to default and lookup node */
1273           /* XXX network virtualization (vrf/vni) */
1274           vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
1275           vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1276
1277           b0->flags |= VNET_BUFFER_LOCALLY_ORIGINATED;
1278
1279         done:
1280           b0->error = error0 != 0 ? node->errors[error0] : 0;
1281           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1282             {
1283
1284             }
1285
1286           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1287                                            n_left_to_next, bi0, next0);
1288         }
1289
1290       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1291     }
1292
1293   return from_frame->n_vectors;
1294 }
1295
1296 static uword
1297 tcp4_output (vlib_main_t * vm, vlib_node_runtime_t * node,
1298              vlib_frame_t * from_frame)
1299 {
1300   return tcp46_output_inline (vm, node, from_frame, 1 /* is_ip4 */ );
1301 }
1302
1303 static uword
1304 tcp6_output (vlib_main_t * vm, vlib_node_runtime_t * node,
1305              vlib_frame_t * from_frame)
1306 {
1307   return tcp46_output_inline (vm, node, from_frame, 0 /* is_ip4 */ );
1308 }
1309
1310 VLIB_REGISTER_NODE (tcp4_output_node) =
1311 {
1312   .function = tcp4_output,.name = "tcp4-output",
1313     /* Takes a vector of packets. */
1314     .vector_size = sizeof (u32),.n_errors = TCP_N_ERROR,.error_strings =
1315     tcp_error_strings,.n_next_nodes = TCP_OUTPUT_N_NEXT,.next_nodes =
1316   {
1317 #define _(s,n) [TCP_OUTPUT_NEXT_##s] = n,
1318     foreach_tcp4_output_next
1319 #undef _
1320   }
1321 ,.format_buffer = format_tcp_header,.format_trace = format_tcp_tx_trace,};
1322
1323 VLIB_NODE_FUNCTION_MULTIARCH (tcp4_output_node, tcp4_output)
1324 VLIB_REGISTER_NODE (tcp6_output_node) =
1325 {
1326   .function = tcp6_output,.name = "tcp6-output",
1327     /* Takes a vector of packets. */
1328     .vector_size = sizeof (u32),.n_errors = TCP_N_ERROR,.error_strings =
1329     tcp_error_strings,.n_next_nodes = TCP_OUTPUT_N_NEXT,.next_nodes =
1330   {
1331 #define _(s,n) [TCP_OUTPUT_NEXT_##s] = n,
1332     foreach_tcp6_output_next
1333 #undef _
1334   }
1335 ,.format_buffer = format_tcp_header,.format_trace = format_tcp_tx_trace,};
1336
1337 VLIB_NODE_FUNCTION_MULTIARCH (tcp6_output_node, tcp6_output) u32
1338 tcp_push_header (transport_connection_t * tconn, vlib_buffer_t * b)
1339 {
1340   tcp_connection_t *tc;
1341
1342   tc = (tcp_connection_t *) tconn;
1343   tcp_push_hdr_i (tc, b, TCP_STATE_ESTABLISHED);
1344   return 0;
1345 }
1346
1347 typedef enum _tcp_reset_next
1348 {
1349   TCP_RESET_NEXT_DROP,
1350   TCP_RESET_NEXT_IP_LOOKUP,
1351   TCP_RESET_N_NEXT
1352 } tcp_reset_next_t;
1353
1354 #define foreach_tcp4_reset_next         \
1355   _(DROP, "error-drop")                 \
1356   _(IP_LOOKUP, "ip4-lookup")
1357
1358 #define foreach_tcp6_reset_next         \
1359   _(DROP, "error-drop")                 \
1360   _(IP_LOOKUP, "ip6-lookup")
1361
1362 static uword
1363 tcp46_send_reset_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
1364                          vlib_frame_t * from_frame, u8 is_ip4)
1365 {
1366   u32 n_left_from, next_index, *from, *to_next;
1367   u32 my_thread_index = vm->cpu_index;
1368
1369   from = vlib_frame_vector_args (from_frame);
1370   n_left_from = from_frame->n_vectors;
1371
1372   next_index = node->cached_next_index;
1373
1374   while (n_left_from > 0)
1375     {
1376       u32 n_left_to_next;
1377
1378       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1379
1380       while (n_left_from > 0 && n_left_to_next > 0)
1381         {
1382           u32 bi0;
1383           vlib_buffer_t *b0;
1384           u32 error0 = TCP_ERROR_RST_SENT, next0 = TCP_RESET_NEXT_IP_LOOKUP;
1385
1386           bi0 = from[0];
1387           to_next[0] = bi0;
1388           from += 1;
1389           to_next += 1;
1390           n_left_from -= 1;
1391           n_left_to_next -= 1;
1392
1393           b0 = vlib_get_buffer (vm, bi0);
1394
1395           if (tcp_make_reset_in_place (vm, b0, vnet_buffer (b0)->tcp.flags,
1396                                        my_thread_index, is_ip4))
1397             {
1398               error0 = TCP_ERROR_LOOKUP_DROPS;
1399               next0 = TCP_RESET_NEXT_DROP;
1400               goto done;
1401             }
1402
1403           /* Prepare to send to IP lookup */
1404           vnet_buffer (b0)->sw_if_index[VLIB_TX] = 0;
1405           next0 = TCP_RESET_NEXT_IP_LOOKUP;
1406
1407         done:
1408           b0->error = error0 != 0 ? node->errors[error0] : 0;
1409           b0->flags |= VNET_BUFFER_LOCALLY_ORIGINATED;
1410           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1411             {
1412
1413             }
1414
1415           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1416                                            n_left_to_next, bi0, next0);
1417         }
1418       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1419     }
1420   return from_frame->n_vectors;
1421 }
1422
1423 static uword
1424 tcp4_send_reset (vlib_main_t * vm, vlib_node_runtime_t * node,
1425                  vlib_frame_t * from_frame)
1426 {
1427   return tcp46_send_reset_inline (vm, node, from_frame, 1);
1428 }
1429
1430 static uword
1431 tcp6_send_reset (vlib_main_t * vm, vlib_node_runtime_t * node,
1432                  vlib_frame_t * from_frame)
1433 {
1434   return tcp46_send_reset_inline (vm, node, from_frame, 0);
1435 }
1436
1437 /* *INDENT-OFF* */
1438 VLIB_REGISTER_NODE (tcp4_reset_node) = {
1439   .function = tcp4_send_reset,
1440   .name = "tcp4-reset",
1441   .vector_size = sizeof (u32),
1442   .n_errors = TCP_N_ERROR,
1443   .error_strings = tcp_error_strings,
1444   .n_next_nodes = TCP_RESET_N_NEXT,
1445   .next_nodes = {
1446 #define _(s,n) [TCP_RESET_NEXT_##s] = n,
1447     foreach_tcp4_reset_next
1448 #undef _
1449   },
1450 };
1451 /* *INDENT-ON* */
1452
1453 /* *INDENT-OFF* */
1454 VLIB_REGISTER_NODE (tcp6_reset_node) = {
1455   .function = tcp6_send_reset,
1456   .name = "tcp6-reset",
1457   .vector_size = sizeof (u32),
1458   .n_errors = TCP_N_ERROR,
1459   .error_strings = tcp_error_strings,
1460   .n_next_nodes = TCP_RESET_N_NEXT,
1461   .next_nodes = {
1462 #define _(s,n) [TCP_RESET_NEXT_##s] = n,
1463     foreach_tcp6_reset_next
1464 #undef _
1465   },
1466 };
1467 /* *INDENT-ON* */
1468
1469 /*
1470  * fd.io coding-style-patch-verification: ON
1471  *
1472  * Local Variables:
1473  * eval: (c-set-style "gnu")
1474  * End:
1475  */