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