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