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