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