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