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