Optimize xxx_zero_byte_mask NEON function
[vpp.git] / src / vnet / tcp / tcp_input.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 <vppinfra/sparse_vec.h>
17 #include <vnet/tcp/tcp_packet.h>
18 #include <vnet/tcp/tcp.h>
19 #include <vnet/session/session.h>
20 #include <math.h>
21
22 static char *tcp_error_strings[] = {
23 #define tcp_error(n,s) s,
24 #include <vnet/tcp/tcp_error.def>
25 #undef tcp_error
26 };
27
28 /* All TCP nodes have the same outgoing arcs */
29 #define foreach_tcp_state_next                  \
30   _ (DROP4, "ip4-drop")                         \
31   _ (DROP6, "ip6-drop")                         \
32   _ (TCP4_OUTPUT, "tcp4-output")                \
33   _ (TCP6_OUTPUT, "tcp6-output")
34
35 typedef enum _tcp_established_next
36 {
37 #define _(s,n) TCP_ESTABLISHED_NEXT_##s,
38   foreach_tcp_state_next
39 #undef _
40     TCP_ESTABLISHED_N_NEXT,
41 } tcp_established_next_t;
42
43 typedef enum _tcp_rcv_process_next
44 {
45 #define _(s,n) TCP_RCV_PROCESS_NEXT_##s,
46   foreach_tcp_state_next
47 #undef _
48     TCP_RCV_PROCESS_N_NEXT,
49 } tcp_rcv_process_next_t;
50
51 typedef enum _tcp_syn_sent_next
52 {
53 #define _(s,n) TCP_SYN_SENT_NEXT_##s,
54   foreach_tcp_state_next
55 #undef _
56     TCP_SYN_SENT_N_NEXT,
57 } tcp_syn_sent_next_t;
58
59 typedef enum _tcp_listen_next
60 {
61 #define _(s,n) TCP_LISTEN_NEXT_##s,
62   foreach_tcp_state_next
63 #undef _
64     TCP_LISTEN_N_NEXT,
65 } tcp_listen_next_t;
66
67 /* Generic, state independent indices */
68 typedef enum _tcp_state_next
69 {
70 #define _(s,n) TCP_NEXT_##s,
71   foreach_tcp_state_next
72 #undef _
73     TCP_STATE_N_NEXT,
74 } tcp_state_next_t;
75
76 #define tcp_next_output(is_ip4) (is_ip4 ? TCP_NEXT_TCP4_OUTPUT          \
77                                         : TCP_NEXT_TCP6_OUTPUT)
78
79 #define tcp_next_drop(is_ip4) (is_ip4 ? TCP_NEXT_DROP4                  \
80                                       : TCP_NEXT_DROP6)
81
82 vlib_node_registration_t tcp4_established_node;
83 vlib_node_registration_t tcp6_established_node;
84
85 /**
86  * Validate segment sequence number. As per RFC793:
87  *
88  * Segment Receive Test
89  *      Length  Window
90  *      ------- -------  -------------------------------------------
91  *      0       0       SEG.SEQ = RCV.NXT
92  *      0       >0      RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
93  *      >0      0       not acceptable
94  *      >0      >0      RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
95  *                      or RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND
96  *
97  * This ultimately consists in checking if segment falls within the window.
98  * The one important difference compared to RFC793 is that we use rcv_las,
99  * or the rcv_nxt at last ack sent instead of rcv_nxt since that's the
100  * peer's reference when computing our receive window.
101  *
102  * This:
103  *  seq_leq (end_seq, tc->rcv_las + tc->rcv_wnd) && seq_geq (seq, tc->rcv_las)
104  * however, is too strict when we have retransmits. Instead we just check that
105  * the seq is not beyond the right edge and that the end of the segment is not
106  * less than the left edge.
107  *
108  * N.B. rcv_nxt and rcv_wnd are both updated in this node if acks are sent, so
109  * use rcv_nxt in the right edge window test instead of rcv_las.
110  *
111  */
112 always_inline u8
113 tcp_segment_in_rcv_wnd (tcp_connection_t * tc, u32 seq, u32 end_seq)
114 {
115   return (seq_geq (end_seq, tc->rcv_las)
116           && seq_leq (seq, tc->rcv_nxt + tc->rcv_wnd));
117 }
118
119 /**
120  * Parse TCP header options.
121  *
122  * @param th TCP header
123  * @param to TCP options data structure to be populated
124  * @return -1 if parsing failed
125  */
126 static int
127 tcp_options_parse (tcp_header_t * th, tcp_options_t * to)
128 {
129   const u8 *data;
130   u8 opt_len, opts_len, kind;
131   int j;
132   sack_block_t b;
133
134   opts_len = (tcp_doff (th) << 2) - sizeof (tcp_header_t);
135   data = (const u8 *) (th + 1);
136
137   /* Zero out all flags but those set in SYN */
138   to->flags &= (TCP_OPTS_FLAG_SACK_PERMITTED | TCP_OPTS_FLAG_WSCALE
139                 | TCP_OPTS_FLAG_SACK);
140
141   for (; opts_len > 0; opts_len -= opt_len, data += opt_len)
142     {
143       kind = data[0];
144
145       /* Get options length */
146       if (kind == TCP_OPTION_EOL)
147         break;
148       else if (kind == TCP_OPTION_NOOP)
149         {
150           opt_len = 1;
151           continue;
152         }
153       else
154         {
155           /* broken options */
156           if (opts_len < 2)
157             return -1;
158           opt_len = data[1];
159
160           /* weird option length */
161           if (opt_len < 2 || opt_len > opts_len)
162             return -1;
163         }
164
165       /* Parse options */
166       switch (kind)
167         {
168         case TCP_OPTION_MSS:
169           if ((opt_len == TCP_OPTION_LEN_MSS) && tcp_syn (th))
170             {
171               to->flags |= TCP_OPTS_FLAG_MSS;
172               to->mss = clib_net_to_host_u16 (*(u16 *) (data + 2));
173             }
174           break;
175         case TCP_OPTION_WINDOW_SCALE:
176           if ((opt_len == TCP_OPTION_LEN_WINDOW_SCALE) && tcp_syn (th))
177             {
178               to->flags |= TCP_OPTS_FLAG_WSCALE;
179               to->wscale = data[2];
180               if (to->wscale > TCP_MAX_WND_SCALE)
181                 {
182                   clib_warning ("Illegal window scaling value: %d",
183                                 to->wscale);
184                   to->wscale = TCP_MAX_WND_SCALE;
185                 }
186             }
187           break;
188         case TCP_OPTION_TIMESTAMP:
189           if (opt_len == TCP_OPTION_LEN_TIMESTAMP)
190             {
191               to->flags |= TCP_OPTS_FLAG_TSTAMP;
192               to->tsval = clib_net_to_host_u32 (*(u32 *) (data + 2));
193               to->tsecr = clib_net_to_host_u32 (*(u32 *) (data + 6));
194             }
195           break;
196         case TCP_OPTION_SACK_PERMITTED:
197           if (opt_len == TCP_OPTION_LEN_SACK_PERMITTED && tcp_syn (th))
198             to->flags |= TCP_OPTS_FLAG_SACK_PERMITTED;
199           break;
200         case TCP_OPTION_SACK_BLOCK:
201           /* If SACK permitted was not advertised or a SYN, break */
202           if ((to->flags & TCP_OPTS_FLAG_SACK_PERMITTED) == 0 || tcp_syn (th))
203             break;
204
205           /* If too short or not correctly formatted, break */
206           if (opt_len < 10 || ((opt_len - 2) % TCP_OPTION_LEN_SACK_BLOCK))
207             break;
208
209           to->flags |= TCP_OPTS_FLAG_SACK;
210           to->n_sack_blocks = (opt_len - 2) / TCP_OPTION_LEN_SACK_BLOCK;
211           vec_reset_length (to->sacks);
212           for (j = 0; j < to->n_sack_blocks; j++)
213             {
214               b.start = clib_net_to_host_u32 (*(u32 *) (data + 2 + 8 * j));
215               b.end = clib_net_to_host_u32 (*(u32 *) (data + 6 + 8 * j));
216               vec_add1 (to->sacks, b);
217             }
218           break;
219         default:
220           /* Nothing to see here */
221           continue;
222         }
223     }
224   return 0;
225 }
226
227 /**
228  * RFC1323: Check against wrapped sequence numbers (PAWS). If we have
229  * timestamp to echo and it's less than tsval_recent, drop segment
230  * but still send an ACK in order to retain TCP's mechanism for detecting
231  * and recovering from half-open connections
232  *
233  * Or at least that's what the theory says. It seems that this might not work
234  * very well with packet reordering and fast retransmit. XXX
235  */
236 always_inline int
237 tcp_segment_check_paws (tcp_connection_t * tc)
238 {
239   return tcp_opts_tstamp (&tc->rcv_opts) && tc->tsval_recent
240     && timestamp_lt (tc->rcv_opts.tsval, tc->tsval_recent);
241 }
242
243 /**
244  * Update tsval recent
245  */
246 always_inline void
247 tcp_update_timestamp (tcp_connection_t * tc, u32 seq, u32 seq_end)
248 {
249   /*
250    * RFC1323: If Last.ACK.sent falls within the range of sequence numbers
251    * of an incoming segment:
252    *    SEG.SEQ <= Last.ACK.sent < SEG.SEQ + SEG.LEN
253    * then the TSval from the segment is copied to TS.Recent;
254    * otherwise, the TSval is ignored.
255    */
256   if (tcp_opts_tstamp (&tc->rcv_opts) && seq_leq (seq, tc->rcv_las)
257       && seq_leq (tc->rcv_las, seq_end))
258     {
259       ASSERT (timestamp_leq (tc->tsval_recent, tc->rcv_opts.tsval));
260       tc->tsval_recent = tc->rcv_opts.tsval;
261       tc->tsval_recent_age = tcp_time_now_w_thread (tc->c_thread_index);
262     }
263 }
264
265 /**
266  * Validate incoming segment as per RFC793 p. 69 and RFC1323 p. 19
267  *
268  * It first verifies if segment has a wrapped sequence number (PAWS) and then
269  * does the processing associated to the first four steps (ignoring security
270  * and precedence): sequence number, rst bit and syn bit checks.
271  *
272  * @return 0 if segments passes validation.
273  */
274 static int
275 tcp_segment_validate (vlib_main_t * vm, tcp_connection_t * tc0,
276                       vlib_buffer_t * b0, tcp_header_t * th0,
277                       u32 * next0, u32 * error0)
278 {
279   /* We could get a burst of RSTs interleaved with acks */
280   if (PREDICT_FALSE (tc0->state == TCP_STATE_CLOSED))
281     {
282       tcp_send_reset (tc0);
283       *error0 = TCP_ERROR_CONNECTION_CLOSED;
284       goto drop;
285     }
286
287   if (PREDICT_FALSE (!tcp_ack (th0) && !tcp_rst (th0) && !tcp_syn (th0)))
288     {
289       *error0 = TCP_ERROR_SEGMENT_INVALID;
290       goto drop;
291     }
292
293   if (PREDICT_FALSE (tcp_options_parse (th0, &tc0->rcv_opts)))
294     {
295       clib_warning ("options parse error");
296       *error0 = TCP_ERROR_OPTIONS;
297       goto drop;
298     }
299
300   if (PREDICT_FALSE (tcp_segment_check_paws (tc0)))
301     {
302       *error0 = TCP_ERROR_PAWS;
303       if (CLIB_DEBUG > 2)
304         clib_warning ("paws failed\n%U", format_tcp_connection, tc0, 2);
305       TCP_EVT_DBG (TCP_EVT_PAWS_FAIL, tc0, vnet_buffer (b0)->tcp.seq_number,
306                    vnet_buffer (b0)->tcp.seq_end);
307
308       /* If it just so happens that a segment updates tsval_recent for a
309        * segment over 24 days old, invalidate tsval_recent. */
310       if (timestamp_lt (tc0->tsval_recent_age + TCP_PAWS_IDLE,
311                         tcp_time_now_w_thread (tc0->c_thread_index)))
312         {
313           /* Age isn't reset until we get a valid tsval (bsd inspired) */
314           tc0->tsval_recent = 0;
315           clib_warning ("paws failed - really old segment. REALLY?");
316         }
317       else
318         {
319           /* Drop after ack if not rst */
320           if (!tcp_rst (th0))
321             {
322               tcp_make_ack (tc0, b0);
323               TCP_EVT_DBG (TCP_EVT_DUPACK_SENT, tc0, vnet_buffer (b0)->tcp);
324               goto error;
325             }
326         }
327       goto drop;
328     }
329
330   /* 1st: check sequence number */
331   if (!tcp_segment_in_rcv_wnd (tc0, vnet_buffer (b0)->tcp.seq_number,
332                                vnet_buffer (b0)->tcp.seq_end))
333     {
334       *error0 = TCP_ERROR_RCV_WND;
335       /* If our window is 0 and the packet is in sequence, let it pass
336        * through for ack processing. It should be dropped later. */
337       if (!(tc0->rcv_wnd == 0
338             && tc0->rcv_nxt == vnet_buffer (b0)->tcp.seq_number))
339         {
340           /* If not RST, send dup ack */
341           if (!tcp_rst (th0))
342             {
343               tcp_make_ack (tc0, b0);
344               TCP_EVT_DBG (TCP_EVT_DUPACK_SENT, tc0, vnet_buffer (b0)->tcp);
345               goto error;
346             }
347           goto drop;
348         }
349     }
350
351   /* 2nd: check the RST bit */
352   if (PREDICT_FALSE (tcp_rst (th0)))
353     {
354       tcp_connection_reset (tc0);
355       *error0 = TCP_ERROR_RST_RCVD;
356       goto drop;
357     }
358
359   /* 3rd: check security and precedence (skip) */
360
361   /* 4th: check the SYN bit */
362   if (PREDICT_FALSE (tcp_syn (th0)))
363     {
364       /* TODO implement RFC 5961 */
365       if (tc0->state == TCP_STATE_SYN_RCVD)
366         {
367           tcp_make_synack (tc0, b0);
368           TCP_EVT_DBG (TCP_EVT_SYN_RCVD, tc0, 0);
369         }
370       else
371         {
372           tcp_make_ack (tc0, b0);
373           TCP_EVT_DBG (TCP_EVT_SYNACK_RCVD, tc0);
374         }
375       goto error;
376     }
377
378   /* If segment in window, save timestamp */
379   tcp_update_timestamp (tc0, vnet_buffer (b0)->tcp.seq_number,
380                         vnet_buffer (b0)->tcp.seq_end);
381   return 0;
382
383 drop:
384   *next0 = tcp_next_drop (tc0->c_is_ip4);
385   return -1;
386 error:
387   *next0 = tcp_next_output (tc0->c_is_ip4);
388   return -1;
389 }
390
391 always_inline int
392 tcp_rcv_ack_is_acceptable (tcp_connection_t * tc0, vlib_buffer_t * tb0)
393 {
394   /* SND.UNA =< SEG.ACK =< SND.NXT */
395   return (seq_leq (tc0->snd_una, vnet_buffer (tb0)->tcp.ack_number)
396           && seq_leq (vnet_buffer (tb0)->tcp.ack_number, tc0->snd_nxt));
397 }
398
399 /**
400  * Compute smoothed RTT as per VJ's '88 SIGCOMM and RFC6298
401  *
402  * Note that although the original article, srtt and rttvar are scaled
403  * to minimize round-off errors, here we don't. Instead, we rely on
404  * better precision time measurements.
405  *
406  * TODO support us rtt resolution
407  */
408 static void
409 tcp_estimate_rtt (tcp_connection_t * tc, u32 mrtt)
410 {
411   int err, diff;
412
413   if (tc->srtt != 0)
414     {
415       err = mrtt - tc->srtt;
416
417       /* XXX Drop in RTT results in RTTVAR increase and bigger RTO.
418        * The increase should be bound */
419       tc->srtt = clib_max ((int) tc->srtt + (err >> 3), 1);
420       diff = (clib_abs (err) - (int) tc->rttvar) >> 2;
421       tc->rttvar = clib_max ((int) tc->rttvar + diff, 1);
422     }
423   else
424     {
425       /* First measurement. */
426       tc->srtt = mrtt;
427       tc->rttvar = mrtt >> 1;
428     }
429 }
430
431 void
432 tcp_update_rto (tcp_connection_t * tc)
433 {
434   tc->rto = clib_min (tc->srtt + (tc->rttvar << 2), TCP_RTO_MAX);
435   tc->rto = clib_max (tc->rto, TCP_RTO_MIN);
436 }
437
438 /**
439  * Update RTT estimate and RTO timer
440  *
441  * Measure RTT: We have two sources of RTT measurements: TSOPT and ACK
442  * timing. Middle boxes are known to fiddle with TCP options so we
443  * should give higher priority to ACK timing.
444  *
445  * This should be called only if previously sent bytes have been acked.
446  *
447  * return 1 if valid rtt 0 otherwise
448  */
449 static int
450 tcp_update_rtt (tcp_connection_t * tc, u32 ack)
451 {
452   u32 mrtt = 0;
453
454   /* Karn's rule, part 1. Don't use retransmitted segments to estimate
455    * RTT because they're ambiguous. */
456   if (tcp_in_cong_recovery (tc) || tc->sack_sb.sacked_bytes)
457     {
458       if (tcp_in_recovery (tc))
459         return 0;
460       goto done;
461     }
462
463   if (tc->rtt_ts && seq_geq (ack, tc->rtt_seq))
464     {
465       tc->mrtt_us = tcp_time_now_us (tc->c_thread_index) - tc->rtt_ts;
466       mrtt = clib_max ((u32) (tc->mrtt_us * THZ), 1);
467     }
468   /* As per RFC7323 TSecr can be used for RTTM only if the segment advances
469    * snd_una, i.e., the left side of the send window:
470    * seq_lt (tc->snd_una, ack). This is a condition for calling update_rtt */
471   else if (tcp_opts_tstamp (&tc->rcv_opts) && tc->rcv_opts.tsecr)
472     {
473       u32 now = tcp_time_now_w_thread (tc->c_thread_index);
474       mrtt = clib_max (now - tc->rcv_opts.tsecr, 1);
475     }
476
477   /* Ignore dubious measurements */
478   if (mrtt == 0 || mrtt > TCP_RTT_MAX)
479     goto done;
480
481   tcp_estimate_rtt (tc, mrtt);
482
483 done:
484
485   /* Allow measuring of a new RTT */
486   tc->rtt_ts = 0;
487
488   /* If we got here something must've been ACKed so make sure boff is 0,
489    * even if mrtt is not valid since we update the rto lower */
490   tc->rto_boff = 0;
491   tcp_update_rto (tc);
492
493   return 0;
494 }
495
496 /**
497  * Dequeue bytes for connections that have received acks in last burst
498  */
499 static void
500 tcp_handle_postponed_dequeues (tcp_worker_ctx_t * wrk)
501 {
502   u32 thread_index = wrk->vm->thread_index;
503   u32 *pending_deq_acked;
504   tcp_connection_t *tc;
505   int i;
506
507   if (!vec_len (wrk->pending_deq_acked))
508     return;
509
510   pending_deq_acked = wrk->pending_deq_acked;
511   for (i = 0; i < vec_len (pending_deq_acked); i++)
512     {
513       tc = tcp_connection_get (pending_deq_acked[i], thread_index);
514       tc->flags &= ~TCP_CONN_DEQ_PENDING;
515
516       /* Dequeue the newly ACKed bytes */
517       stream_session_dequeue_drop (&tc->connection, tc->burst_acked);
518       tc->burst_acked = 0;
519       tcp_validate_txf_size (tc, tc->snd_una_max - tc->snd_una);
520
521       /* If everything has been acked, stop retransmit timer
522        * otherwise update. */
523       tcp_retransmit_timer_update (tc);
524     }
525   _vec_len (wrk->pending_deq_acked) = 0;
526 }
527
528 static void
529 tcp_program_dequeue (tcp_worker_ctx_t * wrk, tcp_connection_t * tc)
530 {
531   if (!(tc->flags & TCP_CONN_DEQ_PENDING))
532     {
533       vec_add1 (wrk->pending_deq_acked, tc->c_c_index);
534       tc->flags |= TCP_CONN_DEQ_PENDING;
535     }
536   tc->burst_acked += tc->bytes_acked + tc->sack_sb.snd_una_adv;
537 }
538
539 /**
540  * Check if duplicate ack as per RFC5681 Sec. 2
541  */
542 static u8
543 tcp_ack_is_dupack (tcp_connection_t * tc, vlib_buffer_t * b, u32 prev_snd_wnd,
544                    u32 prev_snd_una)
545 {
546   return ((vnet_buffer (b)->tcp.ack_number == prev_snd_una)
547           && seq_gt (tc->snd_una_max, tc->snd_una)
548           && (vnet_buffer (b)->tcp.seq_end == vnet_buffer (b)->tcp.seq_number)
549           && (prev_snd_wnd == tc->snd_wnd));
550 }
551
552 /**
553  * Checks if ack is a congestion control event.
554  */
555 static u8
556 tcp_ack_is_cc_event (tcp_connection_t * tc, vlib_buffer_t * b,
557                      u32 prev_snd_wnd, u32 prev_snd_una, u8 * is_dack)
558 {
559   /* Check if ack is duplicate. Per RFC 6675, ACKs that SACK new data are
560    * defined to be 'duplicate' */
561   *is_dack = tc->sack_sb.last_sacked_bytes
562     || tcp_ack_is_dupack (tc, b, prev_snd_wnd, prev_snd_una);
563
564   return ((*is_dack || tcp_in_cong_recovery (tc)) && !tcp_is_lost_fin (tc));
565 }
566
567 static u32
568 scoreboard_hole_index (sack_scoreboard_t * sb, sack_scoreboard_hole_t * hole)
569 {
570   ASSERT (!pool_is_free_index (sb->holes, hole - sb->holes));
571   return hole - sb->holes;
572 }
573
574 static u32
575 scoreboard_hole_bytes (sack_scoreboard_hole_t * hole)
576 {
577   return hole->end - hole->start;
578 }
579
580 sack_scoreboard_hole_t *
581 scoreboard_get_hole (sack_scoreboard_t * sb, u32 index)
582 {
583   if (index != TCP_INVALID_SACK_HOLE_INDEX)
584     return pool_elt_at_index (sb->holes, index);
585   return 0;
586 }
587
588 sack_scoreboard_hole_t *
589 scoreboard_next_hole (sack_scoreboard_t * sb, sack_scoreboard_hole_t * hole)
590 {
591   if (hole->next != TCP_INVALID_SACK_HOLE_INDEX)
592     return pool_elt_at_index (sb->holes, hole->next);
593   return 0;
594 }
595
596 sack_scoreboard_hole_t *
597 scoreboard_prev_hole (sack_scoreboard_t * sb, sack_scoreboard_hole_t * hole)
598 {
599   if (hole->prev != TCP_INVALID_SACK_HOLE_INDEX)
600     return pool_elt_at_index (sb->holes, hole->prev);
601   return 0;
602 }
603
604 sack_scoreboard_hole_t *
605 scoreboard_first_hole (sack_scoreboard_t * sb)
606 {
607   if (sb->head != TCP_INVALID_SACK_HOLE_INDEX)
608     return pool_elt_at_index (sb->holes, sb->head);
609   return 0;
610 }
611
612 sack_scoreboard_hole_t *
613 scoreboard_last_hole (sack_scoreboard_t * sb)
614 {
615   if (sb->tail != TCP_INVALID_SACK_HOLE_INDEX)
616     return pool_elt_at_index (sb->holes, sb->tail);
617   return 0;
618 }
619
620 static void
621 scoreboard_remove_hole (sack_scoreboard_t * sb, sack_scoreboard_hole_t * hole)
622 {
623   sack_scoreboard_hole_t *next, *prev;
624
625   if (hole->next != TCP_INVALID_SACK_HOLE_INDEX)
626     {
627       next = pool_elt_at_index (sb->holes, hole->next);
628       next->prev = hole->prev;
629     }
630   else
631     {
632       sb->tail = hole->prev;
633     }
634
635   if (hole->prev != TCP_INVALID_SACK_HOLE_INDEX)
636     {
637       prev = pool_elt_at_index (sb->holes, hole->prev);
638       prev->next = hole->next;
639     }
640   else
641     {
642       sb->head = hole->next;
643     }
644
645   if (scoreboard_hole_index (sb, hole) == sb->cur_rxt_hole)
646     sb->cur_rxt_hole = TCP_INVALID_SACK_HOLE_INDEX;
647
648   /* Poison the entry */
649   if (CLIB_DEBUG > 0)
650     clib_memset (hole, 0xfe, sizeof (*hole));
651
652   pool_put (sb->holes, hole);
653 }
654
655 static sack_scoreboard_hole_t *
656 scoreboard_insert_hole (sack_scoreboard_t * sb, u32 prev_index,
657                         u32 start, u32 end)
658 {
659   sack_scoreboard_hole_t *hole, *next, *prev;
660   u32 hole_index;
661
662   pool_get (sb->holes, hole);
663   clib_memset (hole, 0, sizeof (*hole));
664
665   hole->start = start;
666   hole->end = end;
667   hole_index = scoreboard_hole_index (sb, hole);
668
669   prev = scoreboard_get_hole (sb, prev_index);
670   if (prev)
671     {
672       hole->prev = prev_index;
673       hole->next = prev->next;
674
675       if ((next = scoreboard_next_hole (sb, hole)))
676         next->prev = hole_index;
677       else
678         sb->tail = hole_index;
679
680       prev->next = hole_index;
681     }
682   else
683     {
684       sb->head = hole_index;
685       hole->prev = TCP_INVALID_SACK_HOLE_INDEX;
686       hole->next = TCP_INVALID_SACK_HOLE_INDEX;
687     }
688
689   return hole;
690 }
691
692 static void
693 scoreboard_update_bytes (tcp_connection_t * tc, sack_scoreboard_t * sb)
694 {
695   sack_scoreboard_hole_t *left, *right;
696   u32 bytes = 0, blks = 0;
697
698   sb->lost_bytes = 0;
699   sb->sacked_bytes = 0;
700   left = scoreboard_last_hole (sb);
701   if (!left)
702     return;
703
704   if (seq_gt (sb->high_sacked, left->end))
705     {
706       bytes = sb->high_sacked - left->end;
707       blks = 1;
708     }
709
710   while ((right = left)
711          && bytes < (TCP_DUPACK_THRESHOLD - 1) * tc->snd_mss
712          && blks < TCP_DUPACK_THRESHOLD
713          /* left not updated if above conditions fail */
714          && (left = scoreboard_prev_hole (sb, right)))
715     {
716       bytes += right->start - left->end;
717       blks++;
718     }
719
720   /* left is first lost */
721   if (left)
722     {
723       do
724         {
725           sb->lost_bytes += scoreboard_hole_bytes (right);
726           left->is_lost = 1;
727           left = scoreboard_prev_hole (sb, right);
728           if (left)
729             bytes += right->start - left->end;
730         }
731       while ((right = left));
732     }
733
734   sb->sacked_bytes = bytes;
735 }
736
737 /**
738  * Figure out the next hole to retransmit
739  *
740  * Follows logic proposed in RFC6675 Sec. 4, NextSeg()
741  */
742 sack_scoreboard_hole_t *
743 scoreboard_next_rxt_hole (sack_scoreboard_t * sb,
744                           sack_scoreboard_hole_t * start,
745                           u8 have_unsent, u8 * can_rescue, u8 * snd_limited)
746 {
747   sack_scoreboard_hole_t *hole = 0;
748
749   hole = start ? start : scoreboard_first_hole (sb);
750   while (hole && seq_leq (hole->end, sb->high_rxt) && hole->is_lost)
751     hole = scoreboard_next_hole (sb, hole);
752
753   /* Nothing, return */
754   if (!hole)
755     {
756       sb->cur_rxt_hole = TCP_INVALID_SACK_HOLE_INDEX;
757       return 0;
758     }
759
760   /* Rule (1): if higher than rxt, less than high_sacked and lost */
761   if (hole->is_lost && seq_lt (hole->start, sb->high_sacked))
762     {
763       sb->cur_rxt_hole = scoreboard_hole_index (sb, hole);
764     }
765   else
766     {
767       /* Rule (2): available unsent data */
768       if (have_unsent)
769         {
770           sb->cur_rxt_hole = TCP_INVALID_SACK_HOLE_INDEX;
771           return 0;
772         }
773       /* Rule (3): if hole not lost */
774       else if (seq_lt (hole->start, sb->high_sacked))
775         {
776           *snd_limited = 0;
777           sb->cur_rxt_hole = scoreboard_hole_index (sb, hole);
778         }
779       /* Rule (4): if hole beyond high_sacked */
780       else
781         {
782           ASSERT (seq_geq (hole->start, sb->high_sacked));
783           *snd_limited = 1;
784           *can_rescue = 1;
785           /* HighRxt MUST NOT be updated */
786           return 0;
787         }
788     }
789
790   if (hole && seq_lt (sb->high_rxt, hole->start))
791     sb->high_rxt = hole->start;
792
793   return hole;
794 }
795
796 static void
797 scoreboard_init_high_rxt (sack_scoreboard_t * sb, u32 snd_una)
798 {
799   sack_scoreboard_hole_t *hole;
800   hole = scoreboard_first_hole (sb);
801   if (hole)
802     {
803       snd_una = seq_gt (snd_una, hole->start) ? snd_una : hole->start;
804       sb->cur_rxt_hole = sb->head;
805     }
806   sb->high_rxt = snd_una;
807   sb->rescue_rxt = snd_una - 1;
808 }
809
810 void
811 scoreboard_init (sack_scoreboard_t * sb)
812 {
813   sb->head = TCP_INVALID_SACK_HOLE_INDEX;
814   sb->tail = TCP_INVALID_SACK_HOLE_INDEX;
815   sb->cur_rxt_hole = TCP_INVALID_SACK_HOLE_INDEX;
816 }
817
818 void
819 scoreboard_clear (sack_scoreboard_t * sb)
820 {
821   sack_scoreboard_hole_t *hole;
822   while ((hole = scoreboard_first_hole (sb)))
823     {
824       scoreboard_remove_hole (sb, hole);
825     }
826   ASSERT (sb->head == sb->tail && sb->head == TCP_INVALID_SACK_HOLE_INDEX);
827   ASSERT (pool_elts (sb->holes) == 0);
828   sb->sacked_bytes = 0;
829   sb->last_sacked_bytes = 0;
830   sb->last_bytes_delivered = 0;
831   sb->snd_una_adv = 0;
832   sb->high_sacked = 0;
833   sb->high_rxt = 0;
834   sb->lost_bytes = 0;
835   sb->cur_rxt_hole = TCP_INVALID_SACK_HOLE_INDEX;
836 }
837
838 /**
839  * Test that scoreboard is sane after recovery
840  *
841  * Returns 1 if scoreboard is empty or if first hole beyond
842  * snd_una.
843  */
844 static u8
845 tcp_scoreboard_is_sane_post_recovery (tcp_connection_t * tc)
846 {
847   sack_scoreboard_hole_t *hole;
848   hole = scoreboard_first_hole (&tc->sack_sb);
849   return (!hole || (seq_geq (hole->start, tc->snd_una)
850                     && seq_lt (hole->end, tc->snd_una_max)));
851 }
852
853 void
854 tcp_rcv_sacks (tcp_connection_t * tc, u32 ack)
855 {
856   sack_scoreboard_t *sb = &tc->sack_sb;
857   sack_block_t *blk, tmp;
858   sack_scoreboard_hole_t *hole, *next_hole, *last_hole;
859   u32 blk_index = 0, old_sacked_bytes, hole_index;
860   int i, j;
861
862   sb->last_sacked_bytes = 0;
863   sb->last_bytes_delivered = 0;
864   sb->snd_una_adv = 0;
865
866   if (!tcp_opts_sack (&tc->rcv_opts)
867       && sb->head == TCP_INVALID_SACK_HOLE_INDEX)
868     return;
869
870   old_sacked_bytes = sb->sacked_bytes;
871
872   /* Remove invalid blocks */
873   blk = tc->rcv_opts.sacks;
874   while (blk < vec_end (tc->rcv_opts.sacks))
875     {
876       if (seq_lt (blk->start, blk->end)
877           && seq_gt (blk->start, tc->snd_una)
878           && seq_gt (blk->start, ack) && seq_leq (blk->end, tc->snd_una_max))
879         {
880           blk++;
881           continue;
882         }
883       vec_del1 (tc->rcv_opts.sacks, blk - tc->rcv_opts.sacks);
884     }
885
886   /* Add block for cumulative ack */
887   if (seq_gt (ack, tc->snd_una))
888     {
889       tmp.start = tc->snd_una;
890       tmp.end = ack;
891       vec_add1 (tc->rcv_opts.sacks, tmp);
892     }
893
894   if (vec_len (tc->rcv_opts.sacks) == 0)
895     return;
896
897   tcp_scoreboard_trace_add (tc, ack);
898
899   /* Make sure blocks are ordered */
900   for (i = 0; i < vec_len (tc->rcv_opts.sacks); i++)
901     for (j = i + 1; j < vec_len (tc->rcv_opts.sacks); j++)
902       if (seq_lt (tc->rcv_opts.sacks[j].start, tc->rcv_opts.sacks[i].start))
903         {
904           tmp = tc->rcv_opts.sacks[i];
905           tc->rcv_opts.sacks[i] = tc->rcv_opts.sacks[j];
906           tc->rcv_opts.sacks[j] = tmp;
907         }
908
909   if (sb->head == TCP_INVALID_SACK_HOLE_INDEX)
910     {
911       /* If no holes, insert the first that covers all outstanding bytes */
912       last_hole = scoreboard_insert_hole (sb, TCP_INVALID_SACK_HOLE_INDEX,
913                                           tc->snd_una, tc->snd_una_max);
914       sb->tail = scoreboard_hole_index (sb, last_hole);
915       tmp = tc->rcv_opts.sacks[vec_len (tc->rcv_opts.sacks) - 1];
916       sb->high_sacked = tmp.end;
917     }
918   else
919     {
920       /* If we have holes but snd_una_max is beyond the last hole, update
921        * last hole end */
922       tmp = tc->rcv_opts.sacks[vec_len (tc->rcv_opts.sacks) - 1];
923       last_hole = scoreboard_last_hole (sb);
924       if (seq_gt (tc->snd_una_max, last_hole->end))
925         {
926           if (seq_geq (last_hole->start, sb->high_sacked))
927             {
928               last_hole->end = tc->snd_una_max;
929             }
930           /* New hole after high sacked block */
931           else if (seq_lt (sb->high_sacked, tc->snd_una_max))
932             {
933               scoreboard_insert_hole (sb, sb->tail, sb->high_sacked,
934                                       tc->snd_una_max);
935             }
936         }
937       /* Keep track of max byte sacked for when the last hole
938        * is acked */
939       if (seq_gt (tmp.end, sb->high_sacked))
940         sb->high_sacked = tmp.end;
941     }
942
943   /* Walk the holes with the SACK blocks */
944   hole = pool_elt_at_index (sb->holes, sb->head);
945   while (hole && blk_index < vec_len (tc->rcv_opts.sacks))
946     {
947       blk = &tc->rcv_opts.sacks[blk_index];
948       if (seq_leq (blk->start, hole->start))
949         {
950           /* Block covers hole. Remove hole */
951           if (seq_geq (blk->end, hole->end))
952             {
953               next_hole = scoreboard_next_hole (sb, hole);
954
955               /* Byte accounting: snd_una needs to be advanced */
956               if (blk->end == ack)
957                 {
958                   if (next_hole)
959                     {
960                       if (seq_lt (ack, next_hole->start))
961                         sb->snd_una_adv = next_hole->start - ack;
962                       sb->last_bytes_delivered +=
963                         next_hole->start - hole->end;
964                     }
965                   else
966                     {
967                       ASSERT (seq_geq (sb->high_sacked, ack));
968                       sb->snd_una_adv = sb->high_sacked - ack;
969                       sb->last_bytes_delivered += sb->high_sacked - hole->end;
970                     }
971                 }
972
973               scoreboard_remove_hole (sb, hole);
974               hole = next_hole;
975             }
976           /* Partial 'head' overlap */
977           else
978             {
979               if (seq_gt (blk->end, hole->start))
980                 {
981                   hole->start = blk->end;
982                 }
983               blk_index++;
984             }
985         }
986       else
987         {
988           /* Hole must be split */
989           if (seq_lt (blk->end, hole->end))
990             {
991               hole_index = scoreboard_hole_index (sb, hole);
992               next_hole = scoreboard_insert_hole (sb, hole_index, blk->end,
993                                                   hole->end);
994
995               /* Pool might've moved */
996               hole = scoreboard_get_hole (sb, hole_index);
997               hole->end = blk->start;
998               blk_index++;
999               ASSERT (hole->next == scoreboard_hole_index (sb, next_hole));
1000             }
1001           else if (seq_lt (blk->start, hole->end))
1002             {
1003               hole->end = blk->start;
1004             }
1005           hole = scoreboard_next_hole (sb, hole);
1006         }
1007     }
1008
1009   if (pool_elts (sb->holes) == 1)
1010     {
1011       hole = scoreboard_first_hole (sb);
1012       if (hole->start == ack + sb->snd_una_adv
1013           && hole->end == tc->snd_una_max)
1014         scoreboard_remove_hole (sb, hole);
1015     }
1016
1017   scoreboard_update_bytes (tc, sb);
1018   sb->last_sacked_bytes = sb->sacked_bytes
1019     - (old_sacked_bytes - sb->last_bytes_delivered);
1020   ASSERT (sb->last_sacked_bytes <= sb->sacked_bytes || tcp_in_recovery (tc));
1021   ASSERT (sb->sacked_bytes == 0 || tcp_in_recovery (tc)
1022           || sb->sacked_bytes < tc->snd_una_max - seq_max (tc->snd_una, ack));
1023   ASSERT (sb->last_sacked_bytes + sb->lost_bytes <= tc->snd_una_max
1024           - seq_max (tc->snd_una, ack) || tcp_in_recovery (tc));
1025   ASSERT (sb->head == TCP_INVALID_SACK_HOLE_INDEX || tcp_in_recovery (tc)
1026           || sb->holes[sb->head].start == ack + sb->snd_una_adv);
1027   TCP_EVT_DBG (TCP_EVT_CC_SCOREBOARD, tc);
1028 }
1029
1030 /**
1031  * Try to update snd_wnd based on feedback received from peer.
1032  *
1033  * If successful, and new window is 'effectively' 0, activate persist
1034  * timer.
1035  */
1036 static void
1037 tcp_update_snd_wnd (tcp_connection_t * tc, u32 seq, u32 ack, u32 snd_wnd)
1038 {
1039   /* If (SND.WL1 < SEG.SEQ or (SND.WL1 = SEG.SEQ and SND.WL2 =< SEG.ACK)), set
1040    * SND.WND <- SEG.WND, set SND.WL1 <- SEG.SEQ, and set SND.WL2 <- SEG.ACK */
1041   if (seq_lt (tc->snd_wl1, seq)
1042       || (tc->snd_wl1 == seq && seq_leq (tc->snd_wl2, ack)))
1043     {
1044       tc->snd_wnd = snd_wnd;
1045       tc->snd_wl1 = seq;
1046       tc->snd_wl2 = ack;
1047       TCP_EVT_DBG (TCP_EVT_SND_WND, tc);
1048
1049       if (PREDICT_FALSE (tc->snd_wnd < tc->snd_mss))
1050         {
1051           /* Set persist timer if not set and we just got 0 wnd */
1052           if (!tcp_timer_is_active (tc, TCP_TIMER_PERSIST)
1053               && !tcp_timer_is_active (tc, TCP_TIMER_RETRANSMIT))
1054             tcp_persist_timer_set (tc);
1055         }
1056       else
1057         {
1058           tcp_persist_timer_reset (tc);
1059           if (PREDICT_FALSE (!tcp_in_recovery (tc) && tc->rto_boff > 0))
1060             {
1061               tc->rto_boff = 0;
1062               tcp_update_rto (tc);
1063             }
1064         }
1065     }
1066 }
1067
1068 /**
1069  * Init loss recovery/fast recovery.
1070  *
1071  * Triggered by dup acks as opposed to timer timeout. Note that cwnd is
1072  * updated in @ref tcp_cc_handle_event after fast retransmit
1073  */
1074 void
1075 tcp_cc_init_congestion (tcp_connection_t * tc)
1076 {
1077   tcp_fastrecovery_on (tc);
1078   tc->snd_congestion = tc->snd_una_max;
1079   tc->cwnd_acc_bytes = 0;
1080   tc->snd_rxt_bytes = 0;
1081   tc->prev_ssthresh = tc->ssthresh;
1082   tc->prev_cwnd = tc->cwnd;
1083   tc->cc_algo->congestion (tc);
1084   TCP_EVT_DBG (TCP_EVT_CC_EVT, tc, 4);
1085 }
1086
1087 static void
1088 tcp_cc_recovery_exit (tcp_connection_t * tc)
1089 {
1090   tc->rto_boff = 0;
1091   tcp_update_rto (tc);
1092   tc->snd_rxt_ts = 0;
1093   tc->snd_nxt = tc->snd_una_max;
1094   tcp_recovery_off (tc);
1095   TCP_EVT_DBG (TCP_EVT_CC_EVT, tc, 3);
1096 }
1097
1098 void
1099 tcp_cc_fastrecovery_exit (tcp_connection_t * tc)
1100 {
1101   tc->cc_algo->recovered (tc);
1102   tc->snd_rxt_bytes = 0;
1103   tc->rcv_dupacks = 0;
1104   tc->snd_nxt = tc->snd_una_max;
1105   tc->snd_rxt_bytes = 0;
1106
1107   tcp_fastrecovery_off (tc);
1108   tcp_fastrecovery_1_smss_off (tc);
1109   tcp_fastrecovery_first_off (tc);
1110
1111   TCP_EVT_DBG (TCP_EVT_CC_EVT, tc, 3);
1112 }
1113
1114 static void
1115 tcp_cc_congestion_undo (tcp_connection_t * tc)
1116 {
1117   tc->cwnd = tc->prev_cwnd;
1118   tc->ssthresh = tc->prev_ssthresh;
1119   tc->snd_nxt = tc->snd_una_max;
1120   tc->rcv_dupacks = 0;
1121   if (tcp_in_recovery (tc))
1122     tcp_cc_recovery_exit (tc);
1123   else if (tcp_in_fastrecovery (tc))
1124     tcp_cc_fastrecovery_exit (tc);
1125   ASSERT (tc->rto_boff == 0);
1126   TCP_EVT_DBG (TCP_EVT_CC_EVT, tc, 5);
1127 }
1128
1129 static inline u8
1130 tcp_cc_is_spurious_timeout_rxt (tcp_connection_t * tc)
1131 {
1132   return (tcp_in_recovery (tc) && tc->rto_boff == 1
1133           && tc->snd_rxt_ts
1134           && tcp_opts_tstamp (&tc->rcv_opts)
1135           && timestamp_lt (tc->rcv_opts.tsecr, tc->snd_rxt_ts));
1136 }
1137
1138 static inline u8
1139 tcp_cc_is_spurious_fast_rxt (tcp_connection_t * tc)
1140 {
1141   return (tcp_in_fastrecovery (tc)
1142           && tc->cwnd > tc->ssthresh + 3 * tc->snd_mss);
1143 }
1144
1145 static u8
1146 tcp_cc_is_spurious_retransmit (tcp_connection_t * tc)
1147 {
1148   return (tcp_cc_is_spurious_timeout_rxt (tc)
1149           || tcp_cc_is_spurious_fast_rxt (tc));
1150 }
1151
1152 static int
1153 tcp_cc_recover (tcp_connection_t * tc)
1154 {
1155   ASSERT (tcp_in_cong_recovery (tc));
1156   if (tcp_cc_is_spurious_retransmit (tc))
1157     {
1158       tcp_cc_congestion_undo (tc);
1159       return 1;
1160     }
1161
1162   if (tcp_in_recovery (tc))
1163     tcp_cc_recovery_exit (tc);
1164   else if (tcp_in_fastrecovery (tc))
1165     tcp_cc_fastrecovery_exit (tc);
1166
1167   ASSERT (tc->rto_boff == 0);
1168   ASSERT (!tcp_in_cong_recovery (tc));
1169   ASSERT (tcp_scoreboard_is_sane_post_recovery (tc));
1170   return 0;
1171 }
1172
1173 static void
1174 tcp_cc_update (tcp_connection_t * tc, vlib_buffer_t * b)
1175 {
1176   ASSERT (!tcp_in_cong_recovery (tc) || tcp_is_lost_fin (tc));
1177
1178   /* Congestion avoidance */
1179   tcp_cc_rcv_ack (tc);
1180
1181   /* If a cumulative ack, make sure dupacks is 0 */
1182   tc->rcv_dupacks = 0;
1183
1184   /* When dupacks hits the threshold we only enter fast retransmit if
1185    * cumulative ack covers more than snd_congestion. Should snd_una
1186    * wrap this test may fail under otherwise valid circumstances.
1187    * Therefore, proactively update snd_congestion when wrap detected. */
1188   if (PREDICT_FALSE
1189       (seq_leq (tc->snd_congestion, tc->snd_una - tc->bytes_acked)
1190        && seq_gt (tc->snd_congestion, tc->snd_una)))
1191     tc->snd_congestion = tc->snd_una - 1;
1192 }
1193
1194 static u8
1195 tcp_should_fastrecover_sack (tcp_connection_t * tc)
1196 {
1197   return (TCP_DUPACK_THRESHOLD - 1) * tc->snd_mss < tc->sack_sb.sacked_bytes;
1198 }
1199
1200 static u8
1201 tcp_should_fastrecover (tcp_connection_t * tc)
1202 {
1203   return (tc->rcv_dupacks == TCP_DUPACK_THRESHOLD
1204           || tcp_should_fastrecover_sack (tc));
1205 }
1206
1207 void
1208 tcp_program_fastretransmit (tcp_worker_ctx_t * wrk, tcp_connection_t * tc)
1209 {
1210   if (!(tc->flags & TCP_CONN_FRXT_PENDING))
1211     {
1212       vec_add1 (wrk->pending_fast_rxt, tc->c_c_index);
1213       tc->flags |= TCP_CONN_FRXT_PENDING;
1214     }
1215 }
1216
1217 void
1218 tcp_do_fastretransmits (tcp_worker_ctx_t * wrk)
1219 {
1220   u32 *ongoing_fast_rxt, burst_bytes, sent_bytes, thread_index;
1221   u32 max_burst_size, burst_size, n_segs = 0, n_segs_now;
1222   tcp_connection_t *tc;
1223   u64 last_cpu_time;
1224   int i;
1225
1226   if (vec_len (wrk->pending_fast_rxt) == 0
1227       && vec_len (wrk->postponed_fast_rxt) == 0)
1228     return;
1229
1230   thread_index = wrk->vm->thread_index;
1231   last_cpu_time = wrk->vm->clib_time.last_cpu_time;
1232   ongoing_fast_rxt = wrk->ongoing_fast_rxt;
1233   vec_append (ongoing_fast_rxt, wrk->postponed_fast_rxt);
1234   vec_append (ongoing_fast_rxt, wrk->pending_fast_rxt);
1235
1236   _vec_len (wrk->postponed_fast_rxt) = 0;
1237   _vec_len (wrk->pending_fast_rxt) = 0;
1238
1239   max_burst_size = VLIB_FRAME_SIZE / vec_len (ongoing_fast_rxt);
1240   max_burst_size = clib_max (max_burst_size, 1);
1241
1242   for (i = 0; i < vec_len (ongoing_fast_rxt); i++)
1243     {
1244       if (n_segs >= VLIB_FRAME_SIZE)
1245         {
1246           vec_add1 (wrk->postponed_fast_rxt, ongoing_fast_rxt[i]);
1247           continue;
1248         }
1249
1250       tc = tcp_connection_get (ongoing_fast_rxt[i], thread_index);
1251       tc->flags &= ~TCP_CONN_FRXT_PENDING;
1252
1253       if (!tcp_in_fastrecovery (tc))
1254         continue;
1255
1256       burst_size = clib_min (max_burst_size, VLIB_FRAME_SIZE - n_segs);
1257       burst_bytes = transport_connection_tx_pacer_burst (&tc->connection,
1258                                                          last_cpu_time);
1259       burst_size = clib_min (burst_size, burst_bytes / tc->snd_mss);
1260       if (!burst_size)
1261         {
1262           tcp_program_fastretransmit (wrk, tc);
1263           continue;
1264         }
1265
1266       n_segs_now = tcp_fast_retransmit (wrk, tc, burst_size);
1267       sent_bytes = clib_min (n_segs_now * tc->snd_mss, burst_bytes);
1268       transport_connection_tx_pacer_update_bytes (&tc->connection,
1269                                                   sent_bytes);
1270       n_segs += n_segs_now;
1271     }
1272   _vec_len (ongoing_fast_rxt) = 0;
1273   wrk->ongoing_fast_rxt = ongoing_fast_rxt;
1274 }
1275
1276 /**
1277  * One function to rule them all ... and in the darkness bind them
1278  */
1279 static void
1280 tcp_cc_handle_event (tcp_connection_t * tc, u32 is_dack)
1281 {
1282   u32 rxt_delivered;
1283
1284   if (tcp_in_fastrecovery (tc) && tcp_opts_sack_permitted (&tc->rcv_opts))
1285     {
1286       if (tc->bytes_acked)
1287         goto partial_ack;
1288       tcp_program_fastretransmit (tcp_get_worker (tc->c_thread_index), tc);
1289       return;
1290     }
1291   /*
1292    * Duplicate ACK. Check if we should enter fast recovery, or if already in
1293    * it account for the bytes that left the network.
1294    */
1295   else if (is_dack && !tcp_in_recovery (tc))
1296     {
1297       TCP_EVT_DBG (TCP_EVT_DUPACK_RCVD, tc, 1);
1298       ASSERT (tc->snd_una != tc->snd_una_max
1299               || tc->sack_sb.last_sacked_bytes);
1300
1301       tc->rcv_dupacks++;
1302
1303       /* Pure duplicate ack. If some data got acked, it's handled lower */
1304       if (tc->rcv_dupacks > TCP_DUPACK_THRESHOLD && !tc->bytes_acked)
1305         {
1306           ASSERT (tcp_in_fastrecovery (tc));
1307           tc->cc_algo->rcv_cong_ack (tc, TCP_CC_DUPACK);
1308           return;
1309         }
1310       else if (tcp_should_fastrecover (tc))
1311         {
1312           u32 pacer_wnd;
1313
1314           ASSERT (!tcp_in_fastrecovery (tc));
1315
1316           /* Heuristic to catch potential late dupacks
1317            * after fast retransmit exits */
1318           if (is_dack && tc->snd_una == tc->snd_congestion
1319               && timestamp_leq (tc->rcv_opts.tsecr, tc->tsecr_last_ack))
1320             {
1321               tc->rcv_dupacks = 0;
1322               return;
1323             }
1324
1325           tcp_cc_init_congestion (tc);
1326           tc->cc_algo->rcv_cong_ack (tc, TCP_CC_DUPACK);
1327
1328           if (tcp_opts_sack_permitted (&tc->rcv_opts))
1329             {
1330               tc->cwnd = tc->ssthresh;
1331               scoreboard_init_high_rxt (&tc->sack_sb, tc->snd_una);
1332             }
1333           else
1334             {
1335               /* Post retransmit update cwnd to ssthresh and account for the
1336                * three segments that have left the network and should've been
1337                * buffered at the receiver XXX */
1338               tc->cwnd = tc->ssthresh + 3 * tc->snd_mss;
1339             }
1340
1341           /* Constrain rate until we get a partial ack */
1342           pacer_wnd = clib_max (0.1 * tc->cwnd, 2 * tc->snd_mss);
1343           tcp_connection_tx_pacer_reset (tc, pacer_wnd,
1344                                          0 /* start bucket */ );
1345           tcp_program_fastretransmit (tcp_get_worker (tc->c_thread_index),
1346                                       tc);
1347           return;
1348         }
1349       else if (!tc->bytes_acked
1350                || (tc->bytes_acked && !tcp_in_cong_recovery (tc)))
1351         {
1352           tc->cc_algo->rcv_cong_ack (tc, TCP_CC_DUPACK);
1353           return;
1354         }
1355       else
1356         goto partial_ack;
1357     }
1358   /* Don't allow entry in fast recovery if still in recovery, for now */
1359   else if (0 && is_dack && tcp_in_recovery (tc))
1360     {
1361       /* If of of the two conditions lower hold, reset dupacks because
1362        * we're probably after timeout (RFC6582 heuristics).
1363        * If Cumulative ack does not cover more than congestion threshold,
1364        * and:
1365        * 1) The following doesn't hold: The congestion window is greater
1366        *    than SMSS bytes and the difference between highest_ack
1367        *    and prev_highest_ack is at most 4*SMSS bytes
1368        * 2) Echoed timestamp in the last non-dup ack does not equal the
1369        *    stored timestamp
1370        */
1371       if (seq_leq (tc->snd_una, tc->snd_congestion)
1372           && ((!(tc->cwnd > tc->snd_mss
1373                  && tc->bytes_acked <= 4 * tc->snd_mss))
1374               || (tc->rcv_opts.tsecr != tc->tsecr_last_ack)))
1375         {
1376           tc->rcv_dupacks = 0;
1377           return;
1378         }
1379     }
1380
1381   if (!tc->bytes_acked)
1382     return;
1383
1384 partial_ack:
1385   TCP_EVT_DBG (TCP_EVT_CC_PACK, tc);
1386
1387   /*
1388    * Legitimate ACK. 1) See if we can exit recovery
1389    */
1390
1391   if (seq_geq (tc->snd_una, tc->snd_congestion))
1392     {
1393       tcp_retransmit_timer_update (tc);
1394
1395       /* If spurious return, we've already updated everything */
1396       if (tcp_cc_recover (tc))
1397         {
1398           tc->tsecr_last_ack = tc->rcv_opts.tsecr;
1399           return;
1400         }
1401
1402       tc->snd_nxt = tc->snd_una_max;
1403
1404       /* Treat as congestion avoidance ack */
1405       tcp_cc_rcv_ack (tc);
1406       return;
1407     }
1408
1409   /*
1410    * Legitimate ACK. 2) If PARTIAL ACK try to retransmit
1411    */
1412
1413   /* Update the pacing rate. For the first partial ack we move from
1414    * the artificially constrained rate to the one after congestion */
1415   tcp_connection_tx_pacer_update (tc);
1416
1417   /* XXX limit this only to first partial ack? */
1418   tcp_retransmit_timer_force_update (tc);
1419
1420   /* RFC6675: If the incoming ACK is a cumulative acknowledgment,
1421    * reset dupacks to 0. Also needed if in congestion recovery */
1422   tc->rcv_dupacks = 0;
1423
1424   /* Post RTO timeout don't try anything fancy */
1425   if (tcp_in_recovery (tc))
1426     {
1427       tcp_cc_rcv_ack (tc);
1428       transport_add_tx_event (&tc->connection);
1429       return;
1430     }
1431
1432   /* Remove retransmitted bytes that have been delivered */
1433   if (tcp_opts_sack_permitted (&tc->rcv_opts))
1434     {
1435       ASSERT (tc->bytes_acked + tc->sack_sb.snd_una_adv
1436               >= tc->sack_sb.last_bytes_delivered
1437               || (tc->flags & TCP_CONN_FINSNT));
1438
1439       /* If we have sacks and we haven't gotten an ack beyond high_rxt,
1440        * remove sacked bytes delivered */
1441       if (seq_lt (tc->snd_una, tc->sack_sb.high_rxt))
1442         {
1443           rxt_delivered = tc->bytes_acked + tc->sack_sb.snd_una_adv
1444             - tc->sack_sb.last_bytes_delivered;
1445           ASSERT (tc->snd_rxt_bytes >= rxt_delivered);
1446           tc->snd_rxt_bytes -= rxt_delivered;
1447         }
1448       else
1449         {
1450           /* Apparently all retransmitted holes have been acked */
1451           tc->snd_rxt_bytes = 0;
1452           tc->sack_sb.high_rxt = tc->snd_una;
1453         }
1454     }
1455   else
1456     {
1457       tcp_fastrecovery_first_on (tc);
1458       /* Reuse last bytes delivered to track total bytes acked */
1459       tc->sack_sb.last_bytes_delivered += tc->bytes_acked;
1460       if (tc->snd_rxt_bytes > tc->bytes_acked)
1461         tc->snd_rxt_bytes -= tc->bytes_acked;
1462       else
1463         tc->snd_rxt_bytes = 0;
1464     }
1465
1466   tc->cc_algo->rcv_cong_ack (tc, TCP_CC_PARTIALACK);
1467
1468   /*
1469    * Since this was a partial ack, try to retransmit some more data
1470    */
1471   tcp_program_fastretransmit (tcp_get_worker (tc->c_thread_index), tc);
1472 }
1473
1474 /**
1475  * Process incoming ACK
1476  */
1477 static int
1478 tcp_rcv_ack (tcp_worker_ctx_t * wrk, tcp_connection_t * tc, vlib_buffer_t * b,
1479              tcp_header_t * th, u32 * next, u32 * error)
1480 {
1481   u32 prev_snd_wnd, prev_snd_una;
1482   u8 is_dack;
1483
1484   TCP_EVT_DBG (TCP_EVT_CC_STAT, tc);
1485
1486   /* If the ACK acks something not yet sent (SEG.ACK > SND.NXT) */
1487   if (PREDICT_FALSE (seq_gt (vnet_buffer (b)->tcp.ack_number, tc->snd_nxt)))
1488     {
1489       /* When we entered recovery, we reset snd_nxt to snd_una. Seems peer
1490        * still has the data so accept the ack */
1491       if (tcp_in_recovery (tc)
1492           && seq_leq (vnet_buffer (b)->tcp.ack_number, tc->snd_congestion))
1493         {
1494           tc->snd_nxt = vnet_buffer (b)->tcp.ack_number;
1495           if (seq_gt (tc->snd_nxt, tc->snd_una_max))
1496             tc->snd_una_max = tc->snd_nxt;
1497           goto process_ack;
1498         }
1499
1500       /* If we have outstanding data and this is within the window, accept it,
1501        * probably retransmit has timed out. Otherwise ACK segment and then
1502        * drop it */
1503       if (seq_gt (vnet_buffer (b)->tcp.ack_number, tc->snd_una_max))
1504         {
1505           tcp_make_ack (tc, b);
1506           *next = tcp_next_output (tc->c_is_ip4);
1507           *error = TCP_ERROR_ACK_FUTURE;
1508           TCP_EVT_DBG (TCP_EVT_ACK_RCV_ERR, tc, 0,
1509                        vnet_buffer (b)->tcp.ack_number);
1510           return -1;
1511         }
1512
1513       TCP_EVT_DBG (TCP_EVT_ACK_RCV_ERR, tc, 2,
1514                    vnet_buffer (b)->tcp.ack_number);
1515
1516       tc->snd_nxt = vnet_buffer (b)->tcp.ack_number;
1517     }
1518
1519   /* If old ACK, probably it's an old dupack */
1520   if (PREDICT_FALSE (seq_lt (vnet_buffer (b)->tcp.ack_number, tc->snd_una)))
1521     {
1522       *error = TCP_ERROR_ACK_OLD;
1523       TCP_EVT_DBG (TCP_EVT_ACK_RCV_ERR, tc, 1,
1524                    vnet_buffer (b)->tcp.ack_number);
1525       if (tcp_in_fastrecovery (tc) && tc->rcv_dupacks == TCP_DUPACK_THRESHOLD)
1526         tcp_cc_handle_event (tc, 1);
1527       /* Don't drop yet */
1528       return 0;
1529     }
1530
1531   /*
1532    * Looks okay, process feedback
1533    */
1534 process_ack:
1535   if (tcp_opts_sack_permitted (&tc->rcv_opts))
1536     tcp_rcv_sacks (tc, vnet_buffer (b)->tcp.ack_number);
1537
1538   prev_snd_wnd = tc->snd_wnd;
1539   prev_snd_una = tc->snd_una;
1540   tcp_update_snd_wnd (tc, vnet_buffer (b)->tcp.seq_number,
1541                       vnet_buffer (b)->tcp.ack_number,
1542                       clib_net_to_host_u16 (th->window) << tc->snd_wscale);
1543   tc->bytes_acked = vnet_buffer (b)->tcp.ack_number - tc->snd_una;
1544   tc->snd_una = vnet_buffer (b)->tcp.ack_number + tc->sack_sb.snd_una_adv;
1545   tcp_validate_txf_size (tc, tc->bytes_acked);
1546
1547   if (tc->bytes_acked)
1548     {
1549       tcp_program_dequeue (wrk, tc);
1550       tcp_update_rtt (tc, vnet_buffer (b)->tcp.ack_number);
1551     }
1552
1553   TCP_EVT_DBG (TCP_EVT_ACK_RCVD, tc);
1554
1555   /*
1556    * Check if we have congestion event
1557    */
1558
1559   if (tcp_ack_is_cc_event (tc, b, prev_snd_wnd, prev_snd_una, &is_dack))
1560     {
1561       tcp_cc_handle_event (tc, is_dack);
1562       if (!tcp_in_cong_recovery (tc))
1563         return 0;
1564       *error = TCP_ERROR_ACK_DUP;
1565       if (vnet_buffer (b)->tcp.data_len || tcp_is_fin (th))
1566         return 0;
1567       return -1;
1568     }
1569
1570   /*
1571    * Update congestion control (slow start/congestion avoidance)
1572    */
1573   tcp_cc_update (tc, b);
1574   *error = TCP_ERROR_ACK_OK;
1575   return 0;
1576 }
1577
1578 static u8
1579 tcp_sack_vector_is_sane (sack_block_t * sacks)
1580 {
1581   int i;
1582   for (i = 1; i < vec_len (sacks); i++)
1583     {
1584       if (sacks[i - 1].end == sacks[i].start)
1585         return 0;
1586     }
1587   return 1;
1588 }
1589
1590 /**
1591  * Build SACK list as per RFC2018.
1592  *
1593  * Makes sure the first block contains the segment that generated the current
1594  * ACK and the following ones are the ones most recently reported in SACK
1595  * blocks.
1596  *
1597  * @param tc TCP connection for which the SACK list is updated
1598  * @param start Start sequence number of the newest SACK block
1599  * @param end End sequence of the newest SACK block
1600  */
1601 void
1602 tcp_update_sack_list (tcp_connection_t * tc, u32 start, u32 end)
1603 {
1604   sack_block_t *new_list = 0, *block = 0;
1605   int i;
1606
1607   /* If the first segment is ooo add it to the list. Last write might've moved
1608    * rcv_nxt over the first segment. */
1609   if (seq_lt (tc->rcv_nxt, start))
1610     {
1611       vec_add2 (new_list, block, 1);
1612       block->start = start;
1613       block->end = end;
1614     }
1615
1616   /* Find the blocks still worth keeping. */
1617   for (i = 0; i < vec_len (tc->snd_sacks); i++)
1618     {
1619       /* Discard if rcv_nxt advanced beyond current block */
1620       if (seq_leq (tc->snd_sacks[i].start, tc->rcv_nxt))
1621         continue;
1622
1623       /* Merge or drop if segment overlapped by the new segment */
1624       if (block && (seq_geq (tc->snd_sacks[i].end, new_list[0].start)
1625                     && seq_leq (tc->snd_sacks[i].start, new_list[0].end)))
1626         {
1627           if (seq_lt (tc->snd_sacks[i].start, new_list[0].start))
1628             new_list[0].start = tc->snd_sacks[i].start;
1629           if (seq_lt (new_list[0].end, tc->snd_sacks[i].end))
1630             new_list[0].end = tc->snd_sacks[i].end;
1631           continue;
1632         }
1633
1634       /* Save to new SACK list if we have space. */
1635       if (vec_len (new_list) < TCP_MAX_SACK_BLOCKS)
1636         {
1637           vec_add1 (new_list, tc->snd_sacks[i]);
1638         }
1639       else
1640         {
1641           clib_warning ("sack discarded");
1642         }
1643     }
1644
1645   ASSERT (vec_len (new_list) <= TCP_MAX_SACK_BLOCKS);
1646
1647   /* Replace old vector with new one */
1648   vec_free (tc->snd_sacks);
1649   tc->snd_sacks = new_list;
1650
1651   /* Segments should not 'touch' */
1652   ASSERT (tcp_sack_vector_is_sane (tc->snd_sacks));
1653 }
1654
1655 u32
1656 tcp_sack_list_bytes (tcp_connection_t * tc)
1657 {
1658   u32 bytes = 0, i;
1659   for (i = 0; i < vec_len (tc->snd_sacks); i++)
1660     bytes += tc->snd_sacks[i].end - tc->snd_sacks[i].start;
1661   return bytes;
1662 }
1663
1664 /** Enqueue data for delivery to application */
1665 static int
1666 tcp_session_enqueue_data (tcp_connection_t * tc, vlib_buffer_t * b,
1667                           u16 data_len)
1668 {
1669   int written, error = TCP_ERROR_ENQUEUED;
1670
1671   ASSERT (seq_geq (vnet_buffer (b)->tcp.seq_number, tc->rcv_nxt));
1672   ASSERT (data_len);
1673   written = session_enqueue_stream_connection (&tc->connection, b, 0,
1674                                                1 /* queue event */ , 1);
1675
1676   TCP_EVT_DBG (TCP_EVT_INPUT, tc, 0, data_len, written);
1677
1678   /* Update rcv_nxt */
1679   if (PREDICT_TRUE (written == data_len))
1680     {
1681       tc->rcv_nxt += written;
1682     }
1683   /* If more data written than expected, account for out-of-order bytes. */
1684   else if (written > data_len)
1685     {
1686       tc->rcv_nxt += written;
1687
1688       /* Send ACK confirming the update */
1689       tc->flags |= TCP_CONN_SNDACK;
1690       TCP_EVT_DBG (TCP_EVT_CC_INPUT, tc, data_len, written);
1691     }
1692   else if (written > 0)
1693     {
1694       /* We've written something but FIFO is probably full now */
1695       tc->rcv_nxt += written;
1696
1697       /* Depending on how fast the app is, all remaining buffers in burst will
1698        * not be enqueued. Inform peer */
1699       tc->flags |= TCP_CONN_SNDACK;
1700
1701       error = TCP_ERROR_PARTIALLY_ENQUEUED;
1702     }
1703   else
1704     {
1705       tc->flags |= TCP_CONN_SNDACK;
1706       return TCP_ERROR_FIFO_FULL;
1707     }
1708
1709   /* Update SACK list if need be */
1710   if (tcp_opts_sack_permitted (&tc->rcv_opts))
1711     {
1712       /* Remove SACK blocks that have been delivered */
1713       tcp_update_sack_list (tc, tc->rcv_nxt, tc->rcv_nxt);
1714     }
1715
1716   return error;
1717 }
1718
1719 /** Enqueue out-of-order data */
1720 static int
1721 tcp_session_enqueue_ooo (tcp_connection_t * tc, vlib_buffer_t * b,
1722                          u16 data_len)
1723 {
1724   stream_session_t *s0;
1725   int rv, offset;
1726
1727   ASSERT (seq_gt (vnet_buffer (b)->tcp.seq_number, tc->rcv_nxt));
1728   ASSERT (data_len);
1729
1730   /* Enqueue out-of-order data with relative offset */
1731   rv = session_enqueue_stream_connection (&tc->connection, b,
1732                                           vnet_buffer (b)->tcp.seq_number -
1733                                           tc->rcv_nxt, 0 /* queue event */ ,
1734                                           0);
1735
1736   /* Nothing written */
1737   if (rv)
1738     {
1739       TCP_EVT_DBG (TCP_EVT_INPUT, tc, 1, data_len, 0);
1740       return TCP_ERROR_FIFO_FULL;
1741     }
1742
1743   TCP_EVT_DBG (TCP_EVT_INPUT, tc, 1, data_len, data_len);
1744
1745   /* Update SACK list if in use */
1746   if (tcp_opts_sack_permitted (&tc->rcv_opts))
1747     {
1748       ooo_segment_t *newest;
1749       u32 start, end;
1750
1751       s0 = session_get (tc->c_s_index, tc->c_thread_index);
1752
1753       /* Get the newest segment from the fifo */
1754       newest = svm_fifo_newest_ooo_segment (s0->server_rx_fifo);
1755       if (newest)
1756         {
1757           offset = ooo_segment_offset (s0->server_rx_fifo, newest);
1758           ASSERT (offset <= vnet_buffer (b)->tcp.seq_number - tc->rcv_nxt);
1759           start = tc->rcv_nxt + offset;
1760           end = start + ooo_segment_length (s0->server_rx_fifo, newest);
1761           tcp_update_sack_list (tc, start, end);
1762           svm_fifo_newest_ooo_segment_reset (s0->server_rx_fifo);
1763           TCP_EVT_DBG (TCP_EVT_CC_SACKS, tc);
1764         }
1765     }
1766
1767   return TCP_ERROR_ENQUEUED_OOO;
1768 }
1769
1770 /**
1771  * Check if ACK could be delayed. If ack can be delayed, it should return
1772  * true for a full frame. If we're always acking return 0.
1773  */
1774 always_inline int
1775 tcp_can_delack (tcp_connection_t * tc)
1776 {
1777   /* Send ack if ... */
1778   if (TCP_ALWAYS_ACK
1779       /* just sent a rcv wnd 0 */
1780       || (tc->flags & TCP_CONN_SENT_RCV_WND0) != 0
1781       /* constrained to send ack */
1782       || (tc->flags & TCP_CONN_SNDACK) != 0
1783       /* we're almost out of tx wnd */
1784       || tcp_available_cc_snd_space (tc) < 4 * tc->snd_mss)
1785     return 0;
1786
1787   return 1;
1788 }
1789
1790 static int
1791 tcp_buffer_discard_bytes (vlib_buffer_t * b, u32 n_bytes_to_drop)
1792 {
1793   u32 discard, first = b->current_length;
1794   vlib_main_t *vm = vlib_get_main ();
1795
1796   /* Handle multi-buffer segments */
1797   if (n_bytes_to_drop > b->current_length)
1798     {
1799       if (!(b->flags & VLIB_BUFFER_NEXT_PRESENT))
1800         return -1;
1801       do
1802         {
1803           discard = clib_min (n_bytes_to_drop, b->current_length);
1804           vlib_buffer_advance (b, discard);
1805           b = vlib_get_buffer (vm, b->next_buffer);
1806           n_bytes_to_drop -= discard;
1807         }
1808       while (n_bytes_to_drop);
1809       if (n_bytes_to_drop > first)
1810         b->total_length_not_including_first_buffer -= n_bytes_to_drop - first;
1811     }
1812   else
1813     vlib_buffer_advance (b, n_bytes_to_drop);
1814   vnet_buffer (b)->tcp.data_len -= n_bytes_to_drop;
1815   return 0;
1816 }
1817
1818 /**
1819  * Receive buffer for connection and handle acks
1820  *
1821  * It handles both in order or out-of-order data.
1822  */
1823 static int
1824 tcp_segment_rcv (tcp_connection_t * tc, vlib_buffer_t * b, u32 * next0)
1825 {
1826   u32 error, n_bytes_to_drop, n_data_bytes;
1827
1828   vlib_buffer_advance (b, vnet_buffer (b)->tcp.data_offset);
1829   n_data_bytes = vnet_buffer (b)->tcp.data_len;
1830   ASSERT (n_data_bytes);
1831
1832   /* Handle out-of-order data */
1833   if (PREDICT_FALSE (vnet_buffer (b)->tcp.seq_number != tc->rcv_nxt))
1834     {
1835       /* Old sequence numbers allowed through because they overlapped
1836        * the rx window */
1837       if (seq_lt (vnet_buffer (b)->tcp.seq_number, tc->rcv_nxt))
1838         {
1839           /* Completely in the past (possible retransmit). Ack
1840            * retransmissions since we may not have any data to send */
1841           if (seq_leq (vnet_buffer (b)->tcp.seq_end, tc->rcv_nxt))
1842             {
1843               tcp_make_ack (tc, b);
1844               error = TCP_ERROR_SEGMENT_OLD;
1845               *next0 = tcp_next_output (tc->c_is_ip4);
1846               goto done;
1847             }
1848
1849           /* Chop off the bytes in the past and see if what is left
1850            * can be enqueued in order */
1851           n_bytes_to_drop = tc->rcv_nxt - vnet_buffer (b)->tcp.seq_number;
1852           n_data_bytes -= n_bytes_to_drop;
1853           vnet_buffer (b)->tcp.seq_number = tc->rcv_nxt;
1854           if (tcp_buffer_discard_bytes (b, n_bytes_to_drop))
1855             {
1856               error = TCP_ERROR_SEGMENT_OLD;
1857               *next0 = tcp_next_drop (tc->c_is_ip4);
1858               goto done;
1859             }
1860           goto in_order;
1861         }
1862
1863       /* RFC2581: Enqueue and send DUPACK for fast retransmit */
1864       error = tcp_session_enqueue_ooo (tc, b, n_data_bytes);
1865       *next0 = tcp_next_output (tc->c_is_ip4);
1866       tcp_make_ack (tc, b);
1867       vnet_buffer (b)->tcp.flags = TCP_BUF_FLAG_DUPACK;
1868       TCP_EVT_DBG (TCP_EVT_DUPACK_SENT, tc, vnet_buffer (b)->tcp);
1869       goto done;
1870     }
1871
1872 in_order:
1873
1874   /* In order data, enqueue. Fifo figures out by itself if any out-of-order
1875    * segments can be enqueued after fifo tail offset changes. */
1876   error = tcp_session_enqueue_data (tc, b, n_data_bytes);
1877   if (tcp_can_delack (tc))
1878     {
1879       *next0 = tcp_next_drop (tc->c_is_ip4);
1880       if (!tcp_timer_is_active (tc, TCP_TIMER_DELACK))
1881         tcp_timer_set (tc, TCP_TIMER_DELACK, TCP_DELACK_TIME);
1882       goto done;
1883     }
1884
1885   *next0 = tcp_next_output (tc->c_is_ip4);
1886   tcp_make_ack (tc, b);
1887
1888 done:
1889   return error;
1890 }
1891
1892 typedef struct
1893 {
1894   tcp_header_t tcp_header;
1895   tcp_connection_t tcp_connection;
1896 } tcp_rx_trace_t;
1897
1898 static u8 *
1899 format_tcp_rx_trace (u8 * s, va_list * args)
1900 {
1901   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1902   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1903   tcp_rx_trace_t *t = va_arg (*args, tcp_rx_trace_t *);
1904   u32 indent = format_get_indent (s);
1905
1906   s = format (s, "%U\n%U%U",
1907               format_tcp_header, &t->tcp_header, 128,
1908               format_white_space, indent,
1909               format_tcp_connection, &t->tcp_connection, 1);
1910
1911   return s;
1912 }
1913
1914 static u8 *
1915 format_tcp_rx_trace_short (u8 * s, va_list * args)
1916 {
1917   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1918   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1919   tcp_rx_trace_t *t = va_arg (*args, tcp_rx_trace_t *);
1920
1921   s = format (s, "%d -> %d (%U)",
1922               clib_net_to_host_u16 (t->tcp_header.dst_port),
1923               clib_net_to_host_u16 (t->tcp_header.src_port), format_tcp_state,
1924               t->tcp_connection.state);
1925
1926   return s;
1927 }
1928
1929 static void
1930 tcp_set_rx_trace_data (tcp_rx_trace_t * t0, tcp_connection_t * tc0,
1931                        tcp_header_t * th0, vlib_buffer_t * b0, u8 is_ip4)
1932 {
1933   if (tc0)
1934     {
1935       clib_memcpy (&t0->tcp_connection, tc0, sizeof (t0->tcp_connection));
1936     }
1937   else
1938     {
1939       th0 = tcp_buffer_hdr (b0);
1940     }
1941   clib_memcpy (&t0->tcp_header, th0, sizeof (t0->tcp_header));
1942 }
1943
1944 static void
1945 tcp_established_trace_frame (vlib_main_t * vm, vlib_node_runtime_t * node,
1946                              vlib_frame_t * frame, u8 is_ip4)
1947 {
1948   u32 *from, n_left;
1949
1950   n_left = frame->n_vectors;
1951   from = vlib_frame_vector_args (frame);
1952
1953   while (n_left >= 1)
1954     {
1955       tcp_connection_t *tc0;
1956       tcp_rx_trace_t *t0;
1957       tcp_header_t *th0;
1958       vlib_buffer_t *b0;
1959       u32 bi0;
1960
1961       bi0 = from[0];
1962       b0 = vlib_get_buffer (vm, bi0);
1963
1964       if (b0->flags & VLIB_BUFFER_IS_TRACED)
1965         {
1966           t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
1967           tc0 = tcp_connection_get (vnet_buffer (b0)->tcp.connection_index,
1968                                     vm->thread_index);
1969           th0 = tcp_buffer_hdr (b0);
1970           tcp_set_rx_trace_data (t0, tc0, th0, b0, is_ip4);
1971         }
1972
1973       from += 1;
1974       n_left -= 1;
1975     }
1976 }
1977
1978 always_inline void
1979 tcp_node_inc_counter_i (vlib_main_t * vm, u32 tcp4_node, u32 tcp6_node,
1980                         u8 is_ip4, u32 evt, u32 val)
1981 {
1982   if (is_ip4)
1983     vlib_node_increment_counter (vm, tcp4_node, evt, val);
1984   else
1985     vlib_node_increment_counter (vm, tcp6_node, evt, val);
1986 }
1987
1988 #define tcp_maybe_inc_counter(node_id, err, count)                      \
1989 {                                                                       \
1990   if (next0 != tcp_next_drop (is_ip4))                                  \
1991     tcp_node_inc_counter_i (vm, tcp4_##node_id##_node.index,            \
1992                             tcp6_##node_id##_node.index, is_ip4, err,   \
1993                             1);                                         \
1994 }
1995 #define tcp_inc_counter(node_id, err, count)                            \
1996   tcp_node_inc_counter_i (vm, tcp4_##node_id##_node.index,              \
1997                            tcp6_##node_id##_node.index, is_ip4,         \
1998                            err, count)
1999 #define tcp_maybe_inc_err_counter(cnts, err)                            \
2000 {                                                                       \
2001   cnts[err] += (next0 != tcp_next_drop (is_ip4));                       \
2002 }
2003 #define tcp_inc_err_counter(cnts, err, val)                             \
2004 {                                                                       \
2005   cnts[err] += val;                                                     \
2006 }
2007 #define tcp_store_err_counters(node_id, cnts)                           \
2008 {                                                                       \
2009   int i;                                                                \
2010   for (i = 0; i < TCP_N_ERROR; i++)                                     \
2011     if (cnts[i])                                                        \
2012       tcp_inc_counter(node_id, i, cnts[i]);                             \
2013 }
2014
2015
2016 always_inline uword
2017 tcp46_established_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
2018                           vlib_frame_t * frame, int is_ip4)
2019 {
2020   u32 thread_index = vm->thread_index, errors = 0;
2021   tcp_worker_ctx_t *wrk = tcp_get_worker (thread_index);
2022   u32 n_left_from, next_index, *from, *to_next;
2023   u16 err_counters[TCP_N_ERROR] = { 0 };
2024   u8 is_fin = 0;
2025
2026   if (node->flags & VLIB_NODE_FLAG_TRACE)
2027     tcp_established_trace_frame (vm, node, frame, is_ip4);
2028
2029   from = vlib_frame_vector_args (frame);
2030   n_left_from = frame->n_vectors;
2031   next_index = node->cached_next_index;
2032
2033   while (n_left_from > 0)
2034     {
2035       u32 n_left_to_next;
2036
2037       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2038       while (n_left_from > 0 && n_left_to_next > 0)
2039         {
2040           u32 bi0;
2041           vlib_buffer_t *b0;
2042           tcp_header_t *th0 = 0;
2043           tcp_connection_t *tc0;
2044           u32 next0 = tcp_next_drop (is_ip4), error0 = TCP_ERROR_ACK_OK;
2045
2046           if (n_left_from > 1)
2047             {
2048               vlib_buffer_t *pb;
2049               pb = vlib_get_buffer (vm, from[1]);
2050               vlib_prefetch_buffer_header (pb, LOAD);
2051               CLIB_PREFETCH (pb->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
2052             }
2053
2054           bi0 = from[0];
2055           to_next[0] = bi0;
2056           from += 1;
2057           to_next += 1;
2058           n_left_from -= 1;
2059           n_left_to_next -= 1;
2060
2061           b0 = vlib_get_buffer (vm, bi0);
2062           tc0 = tcp_connection_get (vnet_buffer (b0)->tcp.connection_index,
2063                                     thread_index);
2064
2065           if (PREDICT_FALSE (tc0 == 0))
2066             {
2067               error0 = TCP_ERROR_INVALID_CONNECTION;
2068               goto done;
2069             }
2070
2071           th0 = tcp_buffer_hdr (b0);
2072           /* N.B. buffer is rewritten if segment is ooo. Thus, th0 becomes a
2073            * dangling reference. */
2074           is_fin = tcp_is_fin (th0);
2075
2076           /* SYNs, FINs and data consume sequence numbers */
2077           vnet_buffer (b0)->tcp.seq_end = vnet_buffer (b0)->tcp.seq_number
2078             + tcp_is_syn (th0) + is_fin + vnet_buffer (b0)->tcp.data_len;
2079
2080           /* TODO header prediction fast path */
2081
2082           /* 1-4: check SEQ, RST, SYN */
2083           if (PREDICT_FALSE (tcp_segment_validate (vm, tc0, b0, th0, &next0,
2084                                                    &error0)))
2085             {
2086               tcp_maybe_inc_err_counter (err_counters, error0);
2087               TCP_EVT_DBG (TCP_EVT_SEG_INVALID, tc0, vnet_buffer (b0)->tcp);
2088               goto done;
2089             }
2090
2091           /* 5: check the ACK field  */
2092           if (PREDICT_FALSE (tcp_rcv_ack (wrk, tc0, b0, th0, &next0,
2093                                           &error0)))
2094             {
2095               tcp_maybe_inc_err_counter (err_counters, error0);
2096               goto done;
2097             }
2098
2099           /* 6: check the URG bit TODO */
2100
2101           /* 7: process the segment text */
2102           if (vnet_buffer (b0)->tcp.data_len)
2103             {
2104               error0 = tcp_segment_rcv (tc0, b0, &next0);
2105               tcp_maybe_inc_err_counter (err_counters, error0);
2106             }
2107
2108           /* 8: check the FIN bit */
2109           if (PREDICT_FALSE (is_fin))
2110             {
2111               /* Enter CLOSE-WAIT and notify session. To avoid lingering
2112                * in CLOSE-WAIT, set timer (reuse WAITCLOSE). */
2113               /* Account for the FIN if nothing else was received */
2114               if (vnet_buffer (b0)->tcp.data_len == 0)
2115                 tc0->rcv_nxt += 1;
2116               tcp_make_ack (tc0, b0);
2117               next0 = tcp_next_output (tc0->c_is_ip4);
2118               tc0->state = TCP_STATE_CLOSE_WAIT;
2119               stream_session_disconnect_notify (&tc0->connection);
2120               tcp_timer_update (tc0, TCP_TIMER_WAITCLOSE, TCP_CLOSEWAIT_TIME);
2121               TCP_EVT_DBG (TCP_EVT_FIN_RCVD, tc0);
2122               tcp_inc_err_counter (err_counters, TCP_ERROR_FIN_RCVD, 1);
2123             }
2124
2125         done:
2126           b0->error = node->errors[error0];
2127           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2128                                            n_left_to_next, bi0, next0);
2129         }
2130
2131       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2132     }
2133
2134   errors = session_manager_flush_enqueue_events (TRANSPORT_PROTO_TCP,
2135                                                  thread_index);
2136   err_counters[TCP_ERROR_EVENT_FIFO_FULL] = errors;
2137   tcp_store_err_counters (established, err_counters);
2138   tcp_handle_postponed_dequeues (wrk);
2139   tcp_flush_frame_to_output (wrk, is_ip4);
2140
2141   return frame->n_vectors;
2142 }
2143
2144 static uword
2145 tcp4_established (vlib_main_t * vm, vlib_node_runtime_t * node,
2146                   vlib_frame_t * from_frame)
2147 {
2148   return tcp46_established_inline (vm, node, from_frame, 1 /* is_ip4 */ );
2149 }
2150
2151 static uword
2152 tcp6_established (vlib_main_t * vm, vlib_node_runtime_t * node,
2153                   vlib_frame_t * from_frame)
2154 {
2155   return tcp46_established_inline (vm, node, from_frame, 0 /* is_ip4 */ );
2156 }
2157
2158 /* *INDENT-OFF* */
2159 VLIB_REGISTER_NODE (tcp4_established_node) =
2160 {
2161   .function = tcp4_established,
2162   .name = "tcp4-established",
2163   /* Takes a vector of packets. */
2164   .vector_size = sizeof (u32),
2165   .n_errors = TCP_N_ERROR,
2166   .error_strings = tcp_error_strings,
2167   .n_next_nodes = TCP_ESTABLISHED_N_NEXT,
2168   .next_nodes =
2169   {
2170 #define _(s,n) [TCP_ESTABLISHED_NEXT_##s] = n,
2171     foreach_tcp_state_next
2172 #undef _
2173   },
2174   .format_trace = format_tcp_rx_trace_short,
2175 };
2176 /* *INDENT-ON* */
2177
2178 VLIB_NODE_FUNCTION_MULTIARCH (tcp4_established_node, tcp4_established);
2179
2180 /* *INDENT-OFF* */
2181 VLIB_REGISTER_NODE (tcp6_established_node) =
2182 {
2183   .function = tcp6_established,
2184   .name = "tcp6-established",
2185   /* Takes a vector of packets. */
2186   .vector_size = sizeof (u32),
2187   .n_errors = TCP_N_ERROR,
2188   .error_strings = tcp_error_strings,
2189   .n_next_nodes = TCP_ESTABLISHED_N_NEXT,
2190   .next_nodes =
2191   {
2192 #define _(s,n) [TCP_ESTABLISHED_NEXT_##s] = n,
2193     foreach_tcp_state_next
2194 #undef _
2195   },
2196   .format_trace = format_tcp_rx_trace_short,
2197 };
2198 /* *INDENT-ON* */
2199
2200
2201 VLIB_NODE_FUNCTION_MULTIARCH (tcp6_established_node, tcp6_established);
2202
2203 vlib_node_registration_t tcp4_syn_sent_node;
2204 vlib_node_registration_t tcp6_syn_sent_node;
2205
2206 static u8
2207 tcp_lookup_is_valid (tcp_connection_t * tc, tcp_header_t * hdr)
2208 {
2209   transport_connection_t *tmp = 0;
2210   u64 handle;
2211
2212   if (!tc)
2213     return 1;
2214
2215   /* Proxy case */
2216   if (tc->c_lcl_port == 0 && tc->state == TCP_STATE_LISTEN)
2217     return 1;
2218
2219   u8 is_valid = (tc->c_lcl_port == hdr->dst_port
2220                  && (tc->state == TCP_STATE_LISTEN
2221                      || tc->c_rmt_port == hdr->src_port));
2222
2223   if (!is_valid)
2224     {
2225       handle = session_lookup_half_open_handle (&tc->connection);
2226       tmp = session_lookup_half_open_connection (handle & 0xFFFFFFFF,
2227                                                  tc->c_proto, tc->c_is_ip4);
2228
2229       if (tmp)
2230         {
2231           if (tmp->lcl_port == hdr->dst_port
2232               && tmp->rmt_port == hdr->src_port)
2233             {
2234               TCP_DBG ("half-open is valid!");
2235             }
2236         }
2237     }
2238   return is_valid;
2239 }
2240
2241 /**
2242  * Lookup transport connection
2243  */
2244 static tcp_connection_t *
2245 tcp_lookup_connection (u32 fib_index, vlib_buffer_t * b, u8 thread_index,
2246                        u8 is_ip4)
2247 {
2248   tcp_header_t *tcp;
2249   transport_connection_t *tconn;
2250   tcp_connection_t *tc;
2251   u8 is_filtered = 0;
2252   if (is_ip4)
2253     {
2254       ip4_header_t *ip4;
2255       ip4 = vlib_buffer_get_current (b);
2256       tcp = ip4_next_header (ip4);
2257       tconn = session_lookup_connection_wt4 (fib_index,
2258                                              &ip4->dst_address,
2259                                              &ip4->src_address,
2260                                              tcp->dst_port,
2261                                              tcp->src_port,
2262                                              TRANSPORT_PROTO_TCP,
2263                                              thread_index, &is_filtered);
2264       tc = tcp_get_connection_from_transport (tconn);
2265       ASSERT (tcp_lookup_is_valid (tc, tcp));
2266     }
2267   else
2268     {
2269       ip6_header_t *ip6;
2270       ip6 = vlib_buffer_get_current (b);
2271       tcp = ip6_next_header (ip6);
2272       tconn = session_lookup_connection_wt6 (fib_index,
2273                                              &ip6->dst_address,
2274                                              &ip6->src_address,
2275                                              tcp->dst_port,
2276                                              tcp->src_port,
2277                                              TRANSPORT_PROTO_TCP,
2278                                              thread_index, &is_filtered);
2279       tc = tcp_get_connection_from_transport (tconn);
2280       ASSERT (tcp_lookup_is_valid (tc, tcp));
2281     }
2282   return tc;
2283 }
2284
2285 always_inline uword
2286 tcp46_syn_sent_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
2287                        vlib_frame_t * from_frame, int is_ip4)
2288 {
2289   tcp_main_t *tm = vnet_get_tcp_main ();
2290   u32 n_left_from, next_index, *from, *to_next;
2291   u32 my_thread_index = vm->thread_index, errors = 0;
2292
2293   from = vlib_frame_vector_args (from_frame);
2294   n_left_from = from_frame->n_vectors;
2295
2296   next_index = node->cached_next_index;
2297
2298   while (n_left_from > 0)
2299     {
2300       u32 n_left_to_next;
2301
2302       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2303
2304       while (n_left_from > 0 && n_left_to_next > 0)
2305         {
2306           u32 bi0, ack0, seq0;
2307           vlib_buffer_t *b0;
2308           tcp_rx_trace_t *t0;
2309           tcp_header_t *tcp0 = 0;
2310           tcp_connection_t *tc0;
2311           tcp_connection_t *new_tc0;
2312           u32 next0 = tcp_next_drop (is_ip4), error0 = TCP_ERROR_ENQUEUED;
2313
2314           bi0 = from[0];
2315           to_next[0] = bi0;
2316           from += 1;
2317           to_next += 1;
2318           n_left_from -= 1;
2319           n_left_to_next -= 1;
2320
2321           b0 = vlib_get_buffer (vm, bi0);
2322           tc0 =
2323             tcp_half_open_connection_get (vnet_buffer (b0)->
2324                                           tcp.connection_index);
2325           if (PREDICT_FALSE (tc0 == 0))
2326             {
2327               error0 = TCP_ERROR_INVALID_CONNECTION;
2328               goto drop;
2329             }
2330
2331           /* Half-open completed recently but the connection was't removed
2332            * yet by the owning thread */
2333           if (PREDICT_FALSE (tc0->flags & TCP_CONN_HALF_OPEN_DONE))
2334             {
2335               /* Make sure the connection actually exists */
2336               ASSERT (tcp_lookup_connection (tc0->c_fib_index, b0,
2337                                              my_thread_index, is_ip4));
2338               goto drop;
2339             }
2340
2341           ack0 = vnet_buffer (b0)->tcp.ack_number;
2342           seq0 = vnet_buffer (b0)->tcp.seq_number;
2343           tcp0 = tcp_buffer_hdr (b0);
2344
2345           /* Crude check to see if the connection handle does not match
2346            * the packet. Probably connection just switched to established */
2347           if (PREDICT_FALSE (tcp0->dst_port != tc0->c_lcl_port
2348                              || tcp0->src_port != tc0->c_rmt_port))
2349             goto drop;
2350
2351           if (PREDICT_FALSE
2352               (!tcp_ack (tcp0) && !tcp_rst (tcp0) && !tcp_syn (tcp0)))
2353             goto drop;
2354
2355           /* SYNs, FINs and data consume sequence numbers */
2356           vnet_buffer (b0)->tcp.seq_end = seq0 + tcp_is_syn (tcp0)
2357             + tcp_is_fin (tcp0) + vnet_buffer (b0)->tcp.data_len;
2358
2359           /*
2360            *  1. check the ACK bit
2361            */
2362
2363           /*
2364            *   If the ACK bit is set
2365            *     If SEG.ACK =< ISS, or SEG.ACK > SND.NXT, send a reset (unless
2366            *     the RST bit is set, if so drop the segment and return)
2367            *       <SEQ=SEG.ACK><CTL=RST>
2368            *     and discard the segment.  Return.
2369            *     If SND.UNA =< SEG.ACK =< SND.NXT then the ACK is acceptable.
2370            */
2371           if (tcp_ack (tcp0))
2372             {
2373               if (seq_leq (ack0, tc0->iss) || seq_gt (ack0, tc0->snd_nxt))
2374                 {
2375                   clib_warning ("ack not in rcv wnd");
2376                   if (!tcp_rst (tcp0))
2377                     tcp_send_reset_w_pkt (tc0, b0, is_ip4);
2378                   goto drop;
2379                 }
2380
2381               /* Make sure ACK is valid */
2382               if (seq_gt (tc0->snd_una, ack0))
2383                 {
2384                   clib_warning ("ack invalid");
2385                   goto drop;
2386                 }
2387             }
2388
2389           /*
2390            * 2. check the RST bit
2391            */
2392
2393           if (tcp_rst (tcp0))
2394             {
2395               /* If ACK is acceptable, signal client that peer is not
2396                * willing to accept connection and drop connection*/
2397               if (tcp_ack (tcp0))
2398                 tcp_connection_reset (tc0);
2399               goto drop;
2400             }
2401
2402           /*
2403            * 3. check the security and precedence (skipped)
2404            */
2405
2406           /*
2407            * 4. check the SYN bit
2408            */
2409
2410           /* No SYN flag. Drop. */
2411           if (!tcp_syn (tcp0))
2412             {
2413               clib_warning ("not synack");
2414               goto drop;
2415             }
2416
2417           /* Parse options */
2418           if (tcp_options_parse (tcp0, &tc0->rcv_opts))
2419             {
2420               clib_warning ("options parse fail");
2421               goto drop;
2422             }
2423
2424           /* Valid SYN or SYN-ACK. Move connection from half-open pool to
2425            * current thread pool. */
2426           pool_get (tm->connections[my_thread_index], new_tc0);
2427           clib_memcpy (new_tc0, tc0, sizeof (*new_tc0));
2428           new_tc0->c_c_index = new_tc0 - tm->connections[my_thread_index];
2429           new_tc0->c_thread_index = my_thread_index;
2430           new_tc0->rcv_nxt = vnet_buffer (b0)->tcp.seq_end;
2431           new_tc0->irs = seq0;
2432           new_tc0->timers[TCP_TIMER_ESTABLISH] = TCP_TIMER_HANDLE_INVALID;
2433           new_tc0->timers[TCP_TIMER_RETRANSMIT_SYN] =
2434             TCP_TIMER_HANDLE_INVALID;
2435           new_tc0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
2436
2437           /* If this is not the owning thread, wait for syn retransmit to
2438            * expire and cleanup then */
2439           if (tcp_half_open_connection_cleanup (tc0))
2440             tc0->flags |= TCP_CONN_HALF_OPEN_DONE;
2441
2442           if (tcp_opts_tstamp (&new_tc0->rcv_opts))
2443             {
2444               new_tc0->tsval_recent = new_tc0->rcv_opts.tsval;
2445               new_tc0->tsval_recent_age = tcp_time_now ();
2446             }
2447
2448           if (tcp_opts_wscale (&new_tc0->rcv_opts))
2449             new_tc0->snd_wscale = new_tc0->rcv_opts.wscale;
2450
2451           new_tc0->snd_wnd = clib_net_to_host_u16 (tcp0->window)
2452             << new_tc0->snd_wscale;
2453           new_tc0->snd_wl1 = seq0;
2454           new_tc0->snd_wl2 = ack0;
2455
2456           tcp_connection_init_vars (new_tc0);
2457
2458           /* SYN-ACK: See if we can switch to ESTABLISHED state */
2459           if (PREDICT_TRUE (tcp_ack (tcp0)))
2460             {
2461               /* Our SYN is ACKed: we have iss < ack = snd_una */
2462
2463               /* TODO Dequeue acknowledged segments if we support Fast Open */
2464               new_tc0->snd_una = ack0;
2465               new_tc0->state = TCP_STATE_ESTABLISHED;
2466
2467               /* Make sure las is initialized for the wnd computation */
2468               new_tc0->rcv_las = new_tc0->rcv_nxt;
2469
2470               /* Notify app that we have connection. If session layer can't
2471                * allocate session send reset */
2472               if (session_stream_connect_notify (&new_tc0->connection, 0))
2473                 {
2474                   clib_warning ("connect notify fail");
2475                   tcp_send_reset_w_pkt (new_tc0, b0, is_ip4);
2476                   tcp_connection_cleanup (new_tc0);
2477                   goto drop;
2478                 }
2479
2480               /* Make sure after data segment processing ACK is sent */
2481               new_tc0->flags |= TCP_CONN_SNDACK;
2482
2483               /* Update rtt with the syn-ack sample */
2484               tcp_update_rtt (new_tc0, vnet_buffer (b0)->tcp.ack_number);
2485               TCP_EVT_DBG (TCP_EVT_SYNACK_RCVD, new_tc0);
2486             }
2487           /* SYN: Simultaneous open. Change state to SYN-RCVD and send SYN-ACK */
2488           else
2489             {
2490               new_tc0->state = TCP_STATE_SYN_RCVD;
2491
2492               /* Notify app that we have connection */
2493               if (session_stream_connect_notify (&new_tc0->connection, 0))
2494                 {
2495                   tcp_connection_cleanup (new_tc0);
2496                   tcp_send_reset_w_pkt (tc0, b0, is_ip4);
2497                   TCP_EVT_DBG (TCP_EVT_RST_SENT, tc0);
2498                   goto drop;
2499                 }
2500
2501               tc0->rtt_ts = 0;
2502               tcp_init_snd_vars (tc0);
2503               tcp_make_synack (new_tc0, b0);
2504               next0 = tcp_next_output (is_ip4);
2505
2506               goto drop;
2507             }
2508
2509           /* Read data, if any */
2510           if (PREDICT_FALSE (vnet_buffer (b0)->tcp.data_len))
2511             {
2512               clib_warning ("rcvd data in syn-sent");
2513               error0 = tcp_segment_rcv (new_tc0, b0, &next0);
2514               if (error0 == TCP_ERROR_ACK_OK)
2515                 error0 = TCP_ERROR_SYN_ACKS_RCVD;
2516               tcp_maybe_inc_counter (syn_sent, error0, 1);
2517             }
2518           else
2519             {
2520               tcp_make_ack (new_tc0, b0);
2521               next0 = tcp_next_output (new_tc0->c_is_ip4);
2522             }
2523
2524         drop:
2525
2526           b0->error = error0 ? node->errors[error0] : 0;
2527           if (PREDICT_FALSE
2528               ((b0->flags & VLIB_BUFFER_IS_TRACED) && tcp0 != 0))
2529             {
2530               t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
2531               clib_memcpy (&t0->tcp_header, tcp0, sizeof (t0->tcp_header));
2532               clib_memcpy (&t0->tcp_connection, tc0,
2533                            sizeof (t0->tcp_connection));
2534             }
2535
2536           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2537                                            n_left_to_next, bi0, next0);
2538         }
2539
2540       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2541     }
2542
2543   errors = session_manager_flush_enqueue_events (TRANSPORT_PROTO_TCP,
2544                                                  my_thread_index);
2545   tcp_inc_counter (syn_sent, TCP_ERROR_EVENT_FIFO_FULL, errors);
2546   return from_frame->n_vectors;
2547 }
2548
2549 static uword
2550 tcp4_syn_sent (vlib_main_t * vm, vlib_node_runtime_t * node,
2551                vlib_frame_t * from_frame)
2552 {
2553   return tcp46_syn_sent_inline (vm, node, from_frame, 1 /* is_ip4 */ );
2554 }
2555
2556 static uword
2557 tcp6_syn_sent_rcv (vlib_main_t * vm, vlib_node_runtime_t * node,
2558                    vlib_frame_t * from_frame)
2559 {
2560   return tcp46_syn_sent_inline (vm, node, from_frame, 0 /* is_ip4 */ );
2561 }
2562
2563 /* *INDENT-OFF* */
2564 VLIB_REGISTER_NODE (tcp4_syn_sent_node) =
2565 {
2566   .function = tcp4_syn_sent,
2567   .name = "tcp4-syn-sent",
2568   /* Takes a vector of packets. */
2569   .vector_size = sizeof (u32),
2570   .n_errors = TCP_N_ERROR,
2571   .error_strings = tcp_error_strings,
2572   .n_next_nodes = TCP_SYN_SENT_N_NEXT,
2573   .next_nodes =
2574   {
2575 #define _(s,n) [TCP_SYN_SENT_NEXT_##s] = n,
2576     foreach_tcp_state_next
2577 #undef _
2578   },
2579   .format_trace = format_tcp_rx_trace_short,
2580 };
2581 /* *INDENT-ON* */
2582
2583 VLIB_NODE_FUNCTION_MULTIARCH (tcp4_syn_sent_node, tcp4_syn_sent);
2584
2585 /* *INDENT-OFF* */
2586 VLIB_REGISTER_NODE (tcp6_syn_sent_node) =
2587 {
2588   .function = tcp6_syn_sent_rcv,
2589   .name = "tcp6-syn-sent",
2590   /* Takes a vector of packets. */
2591   .vector_size = sizeof (u32),
2592   .n_errors = TCP_N_ERROR,
2593   .error_strings = tcp_error_strings,
2594   .n_next_nodes = TCP_SYN_SENT_N_NEXT,
2595   .next_nodes =
2596   {
2597 #define _(s,n) [TCP_SYN_SENT_NEXT_##s] = n,
2598     foreach_tcp_state_next
2599 #undef _
2600   },
2601   .format_trace = format_tcp_rx_trace_short,
2602 };
2603 /* *INDENT-ON* */
2604
2605 VLIB_NODE_FUNCTION_MULTIARCH (tcp6_syn_sent_node, tcp6_syn_sent_rcv);
2606
2607 vlib_node_registration_t tcp4_rcv_process_node;
2608 vlib_node_registration_t tcp6_rcv_process_node;
2609
2610 /**
2611  * Handles reception for all states except LISTEN, SYN-SENT and ESTABLISHED
2612  * as per RFC793 p. 64
2613  */
2614 always_inline uword
2615 tcp46_rcv_process_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
2616                           vlib_frame_t * from_frame, int is_ip4)
2617 {
2618   u32 n_left_from, next_index, *from, *to_next, n_fins = 0;
2619   u32 my_thread_index = vm->thread_index, errors = 0;
2620   tcp_worker_ctx_t *wrk = tcp_get_worker (my_thread_index);
2621
2622   from = vlib_frame_vector_args (from_frame);
2623   n_left_from = from_frame->n_vectors;
2624   next_index = node->cached_next_index;
2625
2626   while (n_left_from > 0)
2627     {
2628       u32 n_left_to_next;
2629
2630       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2631
2632       while (n_left_from > 0 && n_left_to_next > 0)
2633         {
2634           u32 bi0;
2635           vlib_buffer_t *b0;
2636           tcp_header_t *tcp0 = 0;
2637           tcp_connection_t *tc0;
2638           u32 next0 = tcp_next_drop (is_ip4), error0 = TCP_ERROR_NONE;
2639           u8 is_fin0;
2640
2641           bi0 = from[0];
2642           to_next[0] = bi0;
2643           from += 1;
2644           to_next += 1;
2645           n_left_from -= 1;
2646           n_left_to_next -= 1;
2647
2648           b0 = vlib_get_buffer (vm, bi0);
2649           tc0 = tcp_connection_get (vnet_buffer (b0)->tcp.connection_index,
2650                                     my_thread_index);
2651           if (PREDICT_FALSE (tc0 == 0))
2652             {
2653               error0 = TCP_ERROR_INVALID_CONNECTION;
2654               goto drop;
2655             }
2656
2657           tcp0 = tcp_buffer_hdr (b0);
2658           is_fin0 = tcp_is_fin (tcp0);
2659
2660           /* SYNs, FINs and data consume sequence numbers */
2661           vnet_buffer (b0)->tcp.seq_end = vnet_buffer (b0)->tcp.seq_number
2662             + tcp_is_syn (tcp0) + is_fin0 + vnet_buffer (b0)->tcp.data_len;
2663
2664           if (CLIB_DEBUG)
2665             {
2666               tcp_connection_t *tmp;
2667               tmp = tcp_lookup_connection (tc0->c_fib_index, b0,
2668                                            my_thread_index, is_ip4);
2669               if (tmp->state != tc0->state)
2670                 {
2671                   clib_warning ("state changed");
2672                   goto drop;
2673                 }
2674             }
2675
2676           /*
2677            * Special treatment for CLOSED
2678            */
2679           if (PREDICT_FALSE (tc0->state == TCP_STATE_CLOSED))
2680             {
2681               error0 = TCP_ERROR_CONNECTION_CLOSED;
2682               goto drop;
2683             }
2684
2685           /*
2686            * For all other states (except LISTEN)
2687            */
2688
2689           /* 1-4: check SEQ, RST, SYN */
2690           if (PREDICT_FALSE (tcp_segment_validate (vm, tc0, b0, tcp0,
2691                                                    &next0, &error0)))
2692             {
2693               tcp_maybe_inc_counter (rcv_process, error0, 1);
2694               goto drop;
2695             }
2696
2697           /* 5: check the ACK field  */
2698           switch (tc0->state)
2699             {
2700             case TCP_STATE_SYN_RCVD:
2701               /*
2702                * If the segment acknowledgment is not acceptable, form a
2703                * reset segment,
2704                *  <SEQ=SEG.ACK><CTL=RST>
2705                * and send it.
2706                */
2707               if (!tcp_rcv_ack_is_acceptable (tc0, b0))
2708                 {
2709                   TCP_DBG ("connection not accepted");
2710                   tcp_send_reset_w_pkt (tc0, b0, is_ip4);
2711                   error0 = TCP_ERROR_ACK_INVALID;
2712                   goto drop;
2713                 }
2714
2715               /* Update rtt and rto */
2716               tcp_update_rtt (tc0, vnet_buffer (b0)->tcp.ack_number);
2717
2718               /* Switch state to ESTABLISHED */
2719               tc0->state = TCP_STATE_ESTABLISHED;
2720               TCP_EVT_DBG (TCP_EVT_STATE_CHANGE, tc0);
2721
2722               /* Initialize session variables */
2723               tc0->snd_una = vnet_buffer (b0)->tcp.ack_number;
2724               tc0->snd_wnd = clib_net_to_host_u16 (tcp0->window)
2725                 << tc0->rcv_opts.wscale;
2726               tc0->snd_wl1 = vnet_buffer (b0)->tcp.seq_number;
2727               tc0->snd_wl2 = vnet_buffer (b0)->tcp.ack_number;
2728
2729               /* Reset SYN-ACK retransmit and SYN_RCV establish timers */
2730               tcp_retransmit_timer_reset (tc0);
2731               tcp_timer_reset (tc0, TCP_TIMER_ESTABLISH);
2732               stream_session_accept_notify (&tc0->connection);
2733               error0 = TCP_ERROR_ACK_OK;
2734               break;
2735             case TCP_STATE_ESTABLISHED:
2736               /* We can get packets in established state here because they
2737                * were enqueued before state change */
2738               if (tcp_rcv_ack (wrk, tc0, b0, tcp0, &next0, &error0))
2739                 {
2740                   tcp_maybe_inc_counter (rcv_process, error0, 1);
2741                   goto drop;
2742                 }
2743
2744               break;
2745             case TCP_STATE_FIN_WAIT_1:
2746               /* In addition to the processing for the ESTABLISHED state, if
2747                * our FIN is now acknowledged then enter FIN-WAIT-2 and
2748                * continue processing in that state. */
2749               if (tcp_rcv_ack (wrk, tc0, b0, tcp0, &next0, &error0))
2750                 {
2751                   tcp_maybe_inc_counter (rcv_process, error0, 1);
2752                   goto drop;
2753                 }
2754
2755               /* Still have to send the FIN */
2756               if (tc0->flags & TCP_CONN_FINPNDG)
2757                 {
2758                   /* TX fifo finally drained */
2759                   if (!session_tx_fifo_max_dequeue (&tc0->connection))
2760                     tcp_send_fin (tc0);
2761                 }
2762               /* If FIN is ACKed */
2763               else if (tc0->snd_una == tc0->snd_una_max)
2764                 {
2765                   tc0->state = TCP_STATE_FIN_WAIT_2;
2766                   TCP_EVT_DBG (TCP_EVT_STATE_CHANGE, tc0);
2767
2768                   /* Stop all retransmit timers because we have nothing more
2769                    * to send. Enable waitclose though because we're willing to
2770                    * wait for peer's FIN but not indefinitely. */
2771                   tcp_connection_timers_reset (tc0);
2772                   tcp_timer_update (tc0, TCP_TIMER_WAITCLOSE, TCP_2MSL_TIME);
2773                 }
2774               break;
2775             case TCP_STATE_FIN_WAIT_2:
2776               /* In addition to the processing for the ESTABLISHED state, if
2777                * the retransmission queue is empty, the user's CLOSE can be
2778                * acknowledged ("ok") but do not delete the TCB. */
2779               if (tcp_rcv_ack (wrk, tc0, b0, tcp0, &next0, &error0))
2780                 {
2781                   tcp_maybe_inc_counter (rcv_process, error0, 1);
2782                   goto drop;
2783                 }
2784               break;
2785             case TCP_STATE_CLOSE_WAIT:
2786               /* Do the same processing as for the ESTABLISHED state. */
2787               if (tcp_rcv_ack (wrk, tc0, b0, tcp0, &next0, &error0))
2788                 {
2789                   tcp_maybe_inc_counter (rcv_process, error0, 1);
2790                   goto drop;
2791                 }
2792               if (tc0->flags & TCP_CONN_FINPNDG)
2793                 {
2794                   /* TX fifo finally drained */
2795                   if (!session_tx_fifo_max_dequeue (&tc0->connection))
2796                     {
2797                       tcp_send_fin (tc0);
2798                       tcp_connection_timers_reset (tc0);
2799                       tc0->state = TCP_STATE_LAST_ACK;
2800                       tcp_timer_update (tc0, TCP_TIMER_WAITCLOSE,
2801                                         TCP_2MSL_TIME);
2802                     }
2803                 }
2804               break;
2805             case TCP_STATE_CLOSING:
2806               /* In addition to the processing for the ESTABLISHED state, if
2807                * the ACK acknowledges our FIN then enter the TIME-WAIT state,
2808                * otherwise ignore the segment. */
2809               if (tcp_rcv_ack (wrk, tc0, b0, tcp0, &next0, &error0))
2810                 {
2811                   tcp_maybe_inc_counter (rcv_process, error0, 1);
2812                   goto drop;
2813                 }
2814
2815               tc0->state = TCP_STATE_TIME_WAIT;
2816               TCP_EVT_DBG (TCP_EVT_STATE_CHANGE, tc0);
2817               tcp_timer_update (tc0, TCP_TIMER_WAITCLOSE, TCP_TIMEWAIT_TIME);
2818               goto drop;
2819
2820               break;
2821             case TCP_STATE_LAST_ACK:
2822               /* The only thing that [should] arrive in this state is an
2823                * acknowledgment of our FIN. If our FIN is now acknowledged,
2824                * delete the TCB, enter the CLOSED state, and return. */
2825
2826               if (!tcp_rcv_ack_is_acceptable (tc0, b0))
2827                 {
2828                   error0 = TCP_ERROR_ACK_INVALID;
2829                   goto drop;
2830                 }
2831               error0 = TCP_ERROR_ACK_OK;
2832               tc0->snd_una = vnet_buffer (b0)->tcp.ack_number;
2833               /* Apparently our ACK for the peer's FIN was lost */
2834               if (is_fin0 && tc0->snd_una != tc0->snd_una_max)
2835                 {
2836                   tcp_send_fin (tc0);
2837                   goto drop;
2838                 }
2839
2840               tc0->state = TCP_STATE_CLOSED;
2841               TCP_EVT_DBG (TCP_EVT_STATE_CHANGE, tc0);
2842
2843               /* Don't free the connection from the data path since
2844                * we can't ensure that we have no packets already enqueued
2845                * to output. Rely instead on the waitclose timer */
2846               tcp_connection_timers_reset (tc0);
2847               tcp_timer_update (tc0, TCP_TIMER_WAITCLOSE, 1);
2848
2849               goto drop;
2850
2851               break;
2852             case TCP_STATE_TIME_WAIT:
2853               /* The only thing that can arrive in this state is a
2854                * retransmission of the remote FIN. Acknowledge it, and restart
2855                * the 2 MSL timeout. */
2856
2857               if (tcp_rcv_ack (wrk, tc0, b0, tcp0, &next0, &error0))
2858                 {
2859                   tcp_maybe_inc_counter (rcv_process, error0, 1);
2860                   goto drop;
2861                 }
2862
2863               tcp_make_ack (tc0, b0);
2864               next0 = tcp_next_output (is_ip4);
2865               tcp_timer_update (tc0, TCP_TIMER_WAITCLOSE, TCP_TIMEWAIT_TIME);
2866               goto drop;
2867
2868               break;
2869             default:
2870               ASSERT (0);
2871             }
2872
2873           /* 6: check the URG bit TODO */
2874
2875           /* 7: process the segment text */
2876           switch (tc0->state)
2877             {
2878             case TCP_STATE_ESTABLISHED:
2879             case TCP_STATE_FIN_WAIT_1:
2880             case TCP_STATE_FIN_WAIT_2:
2881               if (vnet_buffer (b0)->tcp.data_len)
2882                 {
2883                   error0 = tcp_segment_rcv (tc0, b0, &next0);
2884                   tcp_maybe_inc_counter (rcv_process, error0, 1);
2885                 }
2886               else if (is_fin0)
2887                 tc0->rcv_nxt += 1;
2888               break;
2889             case TCP_STATE_CLOSE_WAIT:
2890             case TCP_STATE_CLOSING:
2891             case TCP_STATE_LAST_ACK:
2892             case TCP_STATE_TIME_WAIT:
2893               /* This should not occur, since a FIN has been received from the
2894                * remote side.  Ignore the segment text. */
2895               break;
2896             }
2897
2898           /* 8: check the FIN bit */
2899           if (!is_fin0)
2900             goto drop;
2901
2902           switch (tc0->state)
2903             {
2904             case TCP_STATE_ESTABLISHED:
2905             case TCP_STATE_SYN_RCVD:
2906               /* Send FIN-ACK notify app and enter CLOSE-WAIT */
2907               tcp_connection_timers_reset (tc0);
2908               tcp_make_fin (tc0, b0);
2909               tc0->snd_nxt += 1;
2910               tc0->snd_una_max = tc0->snd_nxt;
2911               tcp_retransmit_timer_set (tc0);
2912               next0 = tcp_next_output (tc0->c_is_ip4);
2913               stream_session_disconnect_notify (&tc0->connection);
2914               tc0->state = TCP_STATE_CLOSE_WAIT;
2915               TCP_EVT_DBG (TCP_EVT_STATE_CHANGE, tc0);
2916               break;
2917             case TCP_STATE_CLOSE_WAIT:
2918             case TCP_STATE_CLOSING:
2919             case TCP_STATE_LAST_ACK:
2920               /* move along .. */
2921               break;
2922             case TCP_STATE_FIN_WAIT_1:
2923               tc0->state = TCP_STATE_CLOSING;
2924               tcp_make_ack (tc0, b0);
2925               next0 = tcp_next_output (is_ip4);
2926               TCP_EVT_DBG (TCP_EVT_STATE_CHANGE, tc0);
2927               /* Wait for ACK but not forever */
2928               tcp_timer_update (tc0, TCP_TIMER_WAITCLOSE, TCP_2MSL_TIME);
2929               break;
2930             case TCP_STATE_FIN_WAIT_2:
2931               /* Got FIN, send ACK! Be more aggressive with resource cleanup */
2932               tc0->state = TCP_STATE_TIME_WAIT;
2933               tcp_connection_timers_reset (tc0);
2934               tcp_timer_update (tc0, TCP_TIMER_WAITCLOSE, TCP_TIMEWAIT_TIME);
2935               tcp_make_ack (tc0, b0);
2936               next0 = tcp_next_output (is_ip4);
2937               TCP_EVT_DBG (TCP_EVT_STATE_CHANGE, tc0);
2938               break;
2939             case TCP_STATE_TIME_WAIT:
2940               /* Remain in the TIME-WAIT state. Restart the time-wait
2941                * timeout.
2942                */
2943               tcp_timer_update (tc0, TCP_TIMER_WAITCLOSE, TCP_TIMEWAIT_TIME);
2944               break;
2945             }
2946           TCP_EVT_DBG (TCP_EVT_FIN_RCVD, tc0);
2947           n_fins += 1;
2948
2949         drop:
2950           b0->error = error0 ? node->errors[error0] : 0;
2951
2952           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2953             {
2954               tcp_rx_trace_t *t0 =
2955                 vlib_add_trace (vm, node, b0, sizeof (*t0));
2956               tcp_set_rx_trace_data (t0, tc0, tcp0, b0, is_ip4);
2957             }
2958
2959           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2960                                            n_left_to_next, bi0, next0);
2961         }
2962
2963       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2964     }
2965
2966   errors = session_manager_flush_enqueue_events (TRANSPORT_PROTO_TCP,
2967                                                  my_thread_index);
2968   tcp_inc_counter (rcv_process, TCP_ERROR_EVENT_FIFO_FULL, errors);
2969   tcp_inc_counter (rcv_process, TCP_ERROR_FIN_RCVD, n_fins);
2970   tcp_handle_postponed_dequeues (wrk);
2971   return from_frame->n_vectors;
2972 }
2973
2974 static uword
2975 tcp4_rcv_process (vlib_main_t * vm, vlib_node_runtime_t * node,
2976                   vlib_frame_t * from_frame)
2977 {
2978   return tcp46_rcv_process_inline (vm, node, from_frame, 1 /* is_ip4 */ );
2979 }
2980
2981 static uword
2982 tcp6_rcv_process (vlib_main_t * vm, vlib_node_runtime_t * node,
2983                   vlib_frame_t * from_frame)
2984 {
2985   return tcp46_rcv_process_inline (vm, node, from_frame, 0 /* is_ip4 */ );
2986 }
2987
2988 /* *INDENT-OFF* */
2989 VLIB_REGISTER_NODE (tcp4_rcv_process_node) =
2990 {
2991   .function = tcp4_rcv_process,
2992   .name = "tcp4-rcv-process",
2993   /* Takes a vector of packets. */
2994   .vector_size = sizeof (u32),
2995   .n_errors = TCP_N_ERROR,
2996   .error_strings = tcp_error_strings,
2997   .n_next_nodes = TCP_RCV_PROCESS_N_NEXT,
2998   .next_nodes =
2999   {
3000 #define _(s,n) [TCP_RCV_PROCESS_NEXT_##s] = n,
3001     foreach_tcp_state_next
3002 #undef _
3003   },
3004   .format_trace = format_tcp_rx_trace_short,
3005 };
3006 /* *INDENT-ON* */
3007
3008 VLIB_NODE_FUNCTION_MULTIARCH (tcp4_rcv_process_node, tcp4_rcv_process);
3009
3010 /* *INDENT-OFF* */
3011 VLIB_REGISTER_NODE (tcp6_rcv_process_node) =
3012 {
3013   .function = tcp6_rcv_process,
3014   .name = "tcp6-rcv-process",
3015   /* Takes a vector of packets. */
3016   .vector_size = sizeof (u32),
3017   .n_errors = TCP_N_ERROR,
3018   .error_strings = tcp_error_strings,
3019   .n_next_nodes = TCP_RCV_PROCESS_N_NEXT,
3020   .next_nodes =
3021   {
3022 #define _(s,n) [TCP_RCV_PROCESS_NEXT_##s] = n,
3023     foreach_tcp_state_next
3024 #undef _
3025   },
3026   .format_trace = format_tcp_rx_trace_short,
3027 };
3028 /* *INDENT-ON* */
3029
3030 VLIB_NODE_FUNCTION_MULTIARCH (tcp6_rcv_process_node, tcp6_rcv_process);
3031
3032 vlib_node_registration_t tcp4_listen_node;
3033 vlib_node_registration_t tcp6_listen_node;
3034
3035 /**
3036  * LISTEN state processing as per RFC 793 p. 65
3037  */
3038 always_inline uword
3039 tcp46_listen_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
3040                      vlib_frame_t * from_frame, int is_ip4)
3041 {
3042   u32 n_left_from, next_index, *from, *to_next, n_syns = 0;
3043   u32 my_thread_index = vm->thread_index;
3044
3045   from = vlib_frame_vector_args (from_frame);
3046   n_left_from = from_frame->n_vectors;
3047
3048   next_index = node->cached_next_index;
3049
3050   while (n_left_from > 0)
3051     {
3052       u32 n_left_to_next;
3053
3054       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
3055
3056       while (n_left_from > 0 && n_left_to_next > 0)
3057         {
3058           u32 bi0;
3059           vlib_buffer_t *b0;
3060           tcp_rx_trace_t *t0;
3061           tcp_header_t *th0 = 0;
3062           tcp_connection_t *lc0;
3063           ip4_header_t *ip40;
3064           ip6_header_t *ip60;
3065           tcp_connection_t *child0;
3066           u32 error0 = TCP_ERROR_NONE, next0 = tcp_next_drop (is_ip4);
3067
3068           bi0 = from[0];
3069           to_next[0] = bi0;
3070           from += 1;
3071           to_next += 1;
3072           n_left_from -= 1;
3073           n_left_to_next -= 1;
3074
3075           b0 = vlib_get_buffer (vm, bi0);
3076           lc0 = tcp_listener_get (vnet_buffer (b0)->tcp.connection_index);
3077
3078           if (is_ip4)
3079             {
3080               ip40 = vlib_buffer_get_current (b0);
3081               th0 = ip4_next_header (ip40);
3082             }
3083           else
3084             {
3085               ip60 = vlib_buffer_get_current (b0);
3086               th0 = ip6_next_header (ip60);
3087             }
3088
3089           /* Create child session. For syn-flood protection use filter */
3090
3091           /* 1. first check for an RST: handled in dispatch */
3092           /* if (tcp_rst (th0))
3093              goto drop; */
3094
3095           /* 2. second check for an ACK: handled in dispatch */
3096           /* if (tcp_ack (th0))
3097              {
3098              tcp_send_reset (b0, is_ip4);
3099              goto drop;
3100              } */
3101
3102           /* 3. check for a SYN (did that already) */
3103
3104           /* Make sure connection wasn't just created */
3105           child0 = tcp_lookup_connection (lc0->c_fib_index, b0,
3106                                           my_thread_index, is_ip4);
3107           if (PREDICT_FALSE (child0->state != TCP_STATE_LISTEN))
3108             {
3109               error0 = TCP_ERROR_CREATE_EXISTS;
3110               goto drop;
3111             }
3112
3113           /* Create child session and send SYN-ACK */
3114           child0 = tcp_connection_new (my_thread_index);
3115           child0->c_lcl_port = th0->dst_port;
3116           child0->c_rmt_port = th0->src_port;
3117           child0->c_is_ip4 = is_ip4;
3118           child0->state = TCP_STATE_SYN_RCVD;
3119           child0->c_fib_index = lc0->c_fib_index;
3120
3121           if (is_ip4)
3122             {
3123               child0->c_lcl_ip4.as_u32 = ip40->dst_address.as_u32;
3124               child0->c_rmt_ip4.as_u32 = ip40->src_address.as_u32;
3125             }
3126           else
3127             {
3128               clib_memcpy (&child0->c_lcl_ip6, &ip60->dst_address,
3129                            sizeof (ip6_address_t));
3130               clib_memcpy (&child0->c_rmt_ip6, &ip60->src_address,
3131                            sizeof (ip6_address_t));
3132             }
3133
3134           if (tcp_options_parse (th0, &child0->rcv_opts))
3135             {
3136               clib_warning ("options parse fail");
3137               goto drop;
3138             }
3139
3140           child0->irs = vnet_buffer (b0)->tcp.seq_number;
3141           child0->rcv_nxt = vnet_buffer (b0)->tcp.seq_number + 1;
3142           child0->rcv_las = child0->rcv_nxt;
3143           child0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
3144
3145           /* RFC1323: TSval timestamps sent on {SYN} and {SYN,ACK}
3146            * segments are used to initialize PAWS. */
3147           if (tcp_opts_tstamp (&child0->rcv_opts))
3148             {
3149               child0->tsval_recent = child0->rcv_opts.tsval;
3150               child0->tsval_recent_age = tcp_time_now ();
3151             }
3152
3153           if (tcp_opts_wscale (&child0->rcv_opts))
3154             child0->snd_wscale = child0->rcv_opts.wscale;
3155
3156           child0->snd_wnd = clib_net_to_host_u16 (th0->window)
3157             << child0->snd_wscale;
3158           child0->snd_wl1 = vnet_buffer (b0)->tcp.seq_number;
3159           child0->snd_wl2 = vnet_buffer (b0)->tcp.ack_number;
3160
3161           tcp_connection_init_vars (child0);
3162           TCP_EVT_DBG (TCP_EVT_SYN_RCVD, child0, 1);
3163
3164           if (stream_session_accept (&child0->connection, lc0->c_s_index,
3165                                      0 /* notify */ ))
3166             {
3167               clib_warning ("session accept fail");
3168               tcp_connection_cleanup (child0);
3169               error0 = TCP_ERROR_CREATE_SESSION_FAIL;
3170               goto drop;
3171             }
3172
3173           /* Reuse buffer to make syn-ack and send */
3174           tcp_make_synack (child0, b0);
3175           next0 = tcp_next_output (is_ip4);
3176           tcp_timer_set (child0, TCP_TIMER_ESTABLISH, TCP_SYN_RCVD_TIME);
3177
3178         drop:
3179           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
3180             {
3181               t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
3182               clib_memcpy (&t0->tcp_header, th0, sizeof (t0->tcp_header));
3183               clib_memcpy (&t0->tcp_connection, lc0,
3184                            sizeof (t0->tcp_connection));
3185             }
3186
3187           n_syns += (error0 == TCP_ERROR_NONE);
3188           b0->error = node->errors[error0];
3189
3190           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
3191                                            n_left_to_next, bi0, next0);
3192         }
3193
3194       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
3195     }
3196
3197   tcp_inc_counter (listen, TCP_ERROR_SYNS_RCVD, n_syns);
3198   return from_frame->n_vectors;
3199 }
3200
3201 static uword
3202 tcp4_listen (vlib_main_t * vm, vlib_node_runtime_t * node,
3203              vlib_frame_t * from_frame)
3204 {
3205   return tcp46_listen_inline (vm, node, from_frame, 1 /* is_ip4 */ );
3206 }
3207
3208 static uword
3209 tcp6_listen (vlib_main_t * vm, vlib_node_runtime_t * node,
3210              vlib_frame_t * from_frame)
3211 {
3212   return tcp46_listen_inline (vm, node, from_frame, 0 /* is_ip4 */ );
3213 }
3214
3215 /* *INDENT-OFF* */
3216 VLIB_REGISTER_NODE (tcp4_listen_node) =
3217 {
3218   .function = tcp4_listen,
3219   .name = "tcp4-listen",
3220   /* Takes a vector of packets. */
3221   .vector_size = sizeof (u32),
3222   .n_errors = TCP_N_ERROR,
3223   .error_strings = tcp_error_strings,
3224   .n_next_nodes = TCP_LISTEN_N_NEXT,
3225   .next_nodes =
3226   {
3227 #define _(s,n) [TCP_LISTEN_NEXT_##s] = n,
3228     foreach_tcp_state_next
3229 #undef _
3230   },
3231   .format_trace = format_tcp_rx_trace_short,
3232 };
3233 /* *INDENT-ON* */
3234
3235 VLIB_NODE_FUNCTION_MULTIARCH (tcp4_listen_node, tcp4_listen);
3236
3237 /* *INDENT-OFF* */
3238 VLIB_REGISTER_NODE (tcp6_listen_node) =
3239 {
3240   .function = tcp6_listen,
3241   .name = "tcp6-listen",
3242   /* Takes a vector of packets. */
3243   .vector_size = sizeof (u32),
3244   .n_errors = TCP_N_ERROR,
3245   .error_strings = tcp_error_strings,
3246   .n_next_nodes = TCP_LISTEN_N_NEXT,
3247   .next_nodes =
3248   {
3249 #define _(s,n) [TCP_LISTEN_NEXT_##s] = n,
3250     foreach_tcp_state_next
3251 #undef _
3252   },
3253   .format_trace = format_tcp_rx_trace_short,
3254 };
3255 /* *INDENT-ON* */
3256
3257 VLIB_NODE_FUNCTION_MULTIARCH (tcp6_listen_node, tcp6_listen);
3258
3259 vlib_node_registration_t tcp4_input_node;
3260 vlib_node_registration_t tcp6_input_node;
3261
3262 typedef enum _tcp_input_next
3263 {
3264   TCP_INPUT_NEXT_DROP,
3265   TCP_INPUT_NEXT_LISTEN,
3266   TCP_INPUT_NEXT_RCV_PROCESS,
3267   TCP_INPUT_NEXT_SYN_SENT,
3268   TCP_INPUT_NEXT_ESTABLISHED,
3269   TCP_INPUT_NEXT_RESET,
3270   TCP_INPUT_NEXT_PUNT,
3271   TCP_INPUT_N_NEXT
3272 } tcp_input_next_t;
3273
3274 #define foreach_tcp4_input_next                 \
3275   _ (DROP, "ip4-drop")                          \
3276   _ (LISTEN, "tcp4-listen")                     \
3277   _ (RCV_PROCESS, "tcp4-rcv-process")           \
3278   _ (SYN_SENT, "tcp4-syn-sent")                 \
3279   _ (ESTABLISHED, "tcp4-established")           \
3280   _ (RESET, "tcp4-reset")                       \
3281   _ (PUNT, "ip4-punt")
3282
3283 #define foreach_tcp6_input_next                 \
3284   _ (DROP, "ip6-drop")                          \
3285   _ (LISTEN, "tcp6-listen")                     \
3286   _ (RCV_PROCESS, "tcp6-rcv-process")           \
3287   _ (SYN_SENT, "tcp6-syn-sent")                 \
3288   _ (ESTABLISHED, "tcp6-established")           \
3289   _ (RESET, "tcp6-reset")                       \
3290   _ (PUNT, "ip6-punt")
3291
3292 #define filter_flags (TCP_FLAG_SYN|TCP_FLAG_ACK|TCP_FLAG_RST|TCP_FLAG_FIN)
3293
3294 static void
3295 tcp_input_trace_frame (vlib_main_t * vm, vlib_node_runtime_t * node,
3296                        vlib_buffer_t ** bs, u32 n_bufs, u8 is_ip4)
3297 {
3298   tcp_connection_t *tc;
3299   tcp_header_t *tcp;
3300   tcp_rx_trace_t *t;
3301   int i;
3302
3303   for (i = 0; i < n_bufs; i++)
3304     {
3305       if (bs[i]->flags & VLIB_BUFFER_IS_TRACED)
3306         {
3307           t = vlib_add_trace (vm, node, bs[i], sizeof (*t));
3308           tc = tcp_connection_get (vnet_buffer (bs[i])->tcp.connection_index,
3309                                    vm->thread_index);
3310           tcp = vlib_buffer_get_current (bs[i]);
3311           tcp_set_rx_trace_data (t, tc, tcp, bs[i], is_ip4);
3312         }
3313     }
3314 }
3315
3316 static void
3317 tcp_input_set_error_next (tcp_main_t * tm, u16 * next, u32 * error, u8 is_ip4)
3318 {
3319   if (*error == TCP_ERROR_FILTERED)
3320     {
3321       *next = TCP_INPUT_NEXT_DROP;
3322     }
3323   else if ((is_ip4 && tm->punt_unknown4) || (!is_ip4 && tm->punt_unknown6))
3324     {
3325       *next = TCP_INPUT_NEXT_PUNT;
3326       *error = TCP_ERROR_PUNT;
3327     }
3328   else
3329     {
3330       *next = TCP_INPUT_NEXT_RESET;
3331       *error = TCP_ERROR_NO_LISTENER;
3332     }
3333 }
3334
3335 static inline tcp_connection_t *
3336 tcp_input_lookup_buffer (vlib_buffer_t * b, u8 thread_index, u32 * error,
3337                          u8 is_ip4)
3338 {
3339   u32 fib_index = vnet_buffer (b)->ip.fib_index;
3340   int n_advance_bytes, n_data_bytes;
3341   transport_connection_t *tc;
3342   tcp_header_t *tcp;
3343   u8 is_filtered = 0;
3344
3345   if (is_ip4)
3346     {
3347       ip4_header_t *ip4 = vlib_buffer_get_current (b);
3348       tcp = ip4_next_header (ip4);
3349       vnet_buffer (b)->tcp.hdr_offset = (u8 *) tcp - (u8 *) ip4;
3350       n_advance_bytes = (ip4_header_bytes (ip4) + tcp_header_bytes (tcp));
3351       n_data_bytes = clib_net_to_host_u16 (ip4->length) - n_advance_bytes;
3352
3353       /* Length check. Checksum computed by ipx_local no need to compute again */
3354       if (PREDICT_FALSE (n_advance_bytes < 0))
3355         {
3356           *error = TCP_ERROR_LENGTH;
3357           return 0;
3358         }
3359
3360       tc = session_lookup_connection_wt4 (fib_index, &ip4->dst_address,
3361                                           &ip4->src_address, tcp->dst_port,
3362                                           tcp->src_port, TRANSPORT_PROTO_TCP,
3363                                           thread_index, &is_filtered);
3364     }
3365   else
3366     {
3367       ip6_header_t *ip6 = vlib_buffer_get_current (b);
3368       tcp = ip6_next_header (ip6);
3369       vnet_buffer (b)->tcp.hdr_offset = (u8 *) tcp - (u8 *) ip6;
3370       n_advance_bytes = tcp_header_bytes (tcp);
3371       n_data_bytes = clib_net_to_host_u16 (ip6->payload_length)
3372         - n_advance_bytes;
3373       n_advance_bytes += sizeof (ip6[0]);
3374
3375       if (PREDICT_FALSE (n_advance_bytes < 0))
3376         {
3377           *error = TCP_ERROR_LENGTH;
3378           return 0;
3379         }
3380
3381       tc = session_lookup_connection_wt6 (fib_index, &ip6->dst_address,
3382                                           &ip6->src_address, tcp->dst_port,
3383                                           tcp->src_port, TRANSPORT_PROTO_TCP,
3384                                           thread_index, &is_filtered);
3385     }
3386
3387   vnet_buffer (b)->tcp.seq_number = clib_net_to_host_u32 (tcp->seq_number);
3388   vnet_buffer (b)->tcp.ack_number = clib_net_to_host_u32 (tcp->ack_number);
3389   vnet_buffer (b)->tcp.data_offset = n_advance_bytes;
3390   vnet_buffer (b)->tcp.data_len = n_data_bytes;
3391   vnet_buffer (b)->tcp.flags = 0;
3392
3393   *error = is_filtered ? TCP_ERROR_FILTERED : *error;
3394
3395   return tcp_get_connection_from_transport (tc);
3396 }
3397
3398 static inline void
3399 tcp_input_dispatch_buffer (tcp_main_t * tm, tcp_connection_t * tc,
3400                            vlib_buffer_t * b, u16 * next, u32 * error)
3401 {
3402   tcp_header_t *tcp;
3403   u8 flags;
3404
3405   tcp = tcp_buffer_hdr (b);
3406   flags = tcp->flags & filter_flags;
3407   *next = tm->dispatch_table[tc->state][flags].next;
3408   *error = tm->dispatch_table[tc->state][flags].error;
3409
3410   if (PREDICT_FALSE (*error == TCP_ERROR_DISPATCH
3411                      || *next == TCP_INPUT_NEXT_RESET))
3412     {
3413       /* Overload tcp flags to store state */
3414       tcp_state_t state = tc->state;
3415       vnet_buffer (b)->tcp.flags = tc->state;
3416
3417       if (*error == TCP_ERROR_DISPATCH)
3418         clib_warning ("disp error state %U flags %U", format_tcp_state,
3419                       state, format_tcp_flags, (int) flags);
3420     }
3421 }
3422
3423 always_inline uword
3424 tcp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
3425                     vlib_frame_t * frame, int is_ip4)
3426 {
3427   u32 n_left_from, *from, thread_index = vm->thread_index;
3428   tcp_main_t *tm = vnet_get_tcp_main ();
3429   vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
3430   u16 nexts[VLIB_FRAME_SIZE], *next;
3431
3432   tcp_set_time_now (tcp_get_worker (thread_index));
3433
3434   from = vlib_frame_vector_args (frame);
3435   n_left_from = frame->n_vectors;
3436   vlib_get_buffers (vm, from, bufs, n_left_from);
3437
3438   b = bufs;
3439   next = nexts;
3440
3441   while (n_left_from >= 4)
3442     {
3443       u32 error0 = TCP_ERROR_NO_LISTENER, error1 = TCP_ERROR_NO_LISTENER;
3444       tcp_connection_t *tc0, *tc1;
3445
3446       {
3447         vlib_prefetch_buffer_header (b[2], STORE);
3448         CLIB_PREFETCH (b[2]->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
3449
3450         vlib_prefetch_buffer_header (b[3], STORE);
3451         CLIB_PREFETCH (b[3]->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
3452       }
3453
3454       next[0] = next[1] = TCP_INPUT_NEXT_DROP;
3455
3456       tc0 = tcp_input_lookup_buffer (b[0], thread_index, &error0, is_ip4);
3457       tc1 = tcp_input_lookup_buffer (b[1], thread_index, &error1, is_ip4);
3458
3459       if (PREDICT_TRUE (!tc0 + !tc1 == 0))
3460         {
3461           ASSERT (tcp_lookup_is_valid (tc0, tcp_buffer_hdr (b[0])));
3462           ASSERT (tcp_lookup_is_valid (tc1, tcp_buffer_hdr (b[1])));
3463
3464           vnet_buffer (b[0])->tcp.connection_index = tc0->c_c_index;
3465           vnet_buffer (b[1])->tcp.connection_index = tc1->c_c_index;
3466
3467           tcp_input_dispatch_buffer (tm, tc0, b[0], &next[0], &error0);
3468           tcp_input_dispatch_buffer (tm, tc1, b[1], &next[1], &error1);
3469         }
3470       else
3471         {
3472           if (PREDICT_TRUE (tc0 != 0))
3473             {
3474               ASSERT (tcp_lookup_is_valid (tc0, tcp_buffer_hdr (b[0])));
3475               vnet_buffer (b[0])->tcp.connection_index = tc0->c_c_index;
3476               tcp_input_dispatch_buffer (tm, tc0, b[0], &next[0], &error0);
3477             }
3478           else
3479             tcp_input_set_error_next (tm, &next[0], &error0, is_ip4);
3480
3481           if (PREDICT_TRUE (tc1 != 0))
3482             {
3483               ASSERT (tcp_lookup_is_valid (tc1, tcp_buffer_hdr (b[1])));
3484               vnet_buffer (b[1])->tcp.connection_index = tc1->c_c_index;
3485               tcp_input_dispatch_buffer (tm, tc1, b[1], &next[1], &error1);
3486             }
3487           else
3488             tcp_input_set_error_next (tm, &next[1], &error1, is_ip4);
3489         }
3490
3491       b += 2;
3492       next += 2;
3493       n_left_from -= 2;
3494     }
3495   while (n_left_from > 0)
3496     {
3497       tcp_connection_t *tc0;
3498       u32 error0 = TCP_ERROR_NO_LISTENER;
3499
3500       if (n_left_from > 1)
3501         {
3502           vlib_prefetch_buffer_header (b[1], STORE);
3503           CLIB_PREFETCH (b[1]->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
3504         }
3505
3506       next[0] = TCP_INPUT_NEXT_DROP;
3507       tc0 = tcp_input_lookup_buffer (b[0], thread_index, &error0, is_ip4);
3508       if (PREDICT_TRUE (tc0 != 0))
3509         {
3510           ASSERT (tcp_lookup_is_valid (tc0, tcp_buffer_hdr (b[0])));
3511           vnet_buffer (b[0])->tcp.connection_index = tc0->c_c_index;
3512           tcp_input_dispatch_buffer (tm, tc0, b[0], &next[0], &error0);
3513         }
3514       else
3515         tcp_input_set_error_next (tm, &next[0], &error0, is_ip4);
3516
3517       b += 1;
3518       next += 1;
3519       n_left_from -= 1;
3520     }
3521
3522   if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
3523     tcp_input_trace_frame (vm, node, bufs, frame->n_vectors, is_ip4);
3524
3525   vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
3526   return frame->n_vectors;
3527 }
3528
3529 static uword
3530 tcp4_input (vlib_main_t * vm, vlib_node_runtime_t * node,
3531             vlib_frame_t * from_frame)
3532 {
3533   return tcp46_input_inline (vm, node, from_frame, 1 /* is_ip4 */ );
3534 }
3535
3536 static uword
3537 tcp6_input (vlib_main_t * vm, vlib_node_runtime_t * node,
3538             vlib_frame_t * from_frame)
3539 {
3540   return tcp46_input_inline (vm, node, from_frame, 0 /* is_ip4 */ );
3541 }
3542
3543 /* *INDENT-OFF* */
3544 VLIB_REGISTER_NODE (tcp4_input_node) =
3545 {
3546   .function = tcp4_input,
3547   .name = "tcp4-input",
3548   /* Takes a vector of packets. */
3549   .vector_size = sizeof (u32),
3550   .n_errors = TCP_N_ERROR,
3551   .error_strings = tcp_error_strings,
3552   .n_next_nodes = TCP_INPUT_N_NEXT,
3553   .next_nodes =
3554   {
3555 #define _(s,n) [TCP_INPUT_NEXT_##s] = n,
3556     foreach_tcp4_input_next
3557 #undef _
3558   },
3559   .format_buffer = format_tcp_header,
3560   .format_trace = format_tcp_rx_trace,
3561 };
3562 /* *INDENT-ON* */
3563
3564 VLIB_NODE_FUNCTION_MULTIARCH (tcp4_input_node, tcp4_input);
3565
3566 /* *INDENT-OFF* */
3567 VLIB_REGISTER_NODE (tcp6_input_node) =
3568 {
3569   .function = tcp6_input,
3570   .name = "tcp6-input",
3571   /* Takes a vector of packets. */
3572   .vector_size = sizeof (u32),
3573   .n_errors = TCP_N_ERROR,
3574   .error_strings = tcp_error_strings,
3575   .n_next_nodes = TCP_INPUT_N_NEXT,
3576   .next_nodes =
3577   {
3578 #define _(s,n) [TCP_INPUT_NEXT_##s] = n,
3579     foreach_tcp6_input_next
3580 #undef _
3581   },
3582   .format_buffer = format_tcp_header,
3583   .format_trace = format_tcp_rx_trace,
3584 };
3585 /* *INDENT-ON* */
3586
3587 VLIB_NODE_FUNCTION_MULTIARCH (tcp6_input_node, tcp6_input);
3588
3589 static void
3590 tcp_dispatch_table_init (tcp_main_t * tm)
3591 {
3592   int i, j;
3593   for (i = 0; i < ARRAY_LEN (tm->dispatch_table); i++)
3594     for (j = 0; j < ARRAY_LEN (tm->dispatch_table[i]); j++)
3595       {
3596         tm->dispatch_table[i][j].next = TCP_INPUT_NEXT_DROP;
3597         tm->dispatch_table[i][j].error = TCP_ERROR_DISPATCH;
3598       }
3599
3600 #define _(t,f,n,e)                                              \
3601 do {                                                            \
3602     tm->dispatch_table[TCP_STATE_##t][f].next = (n);            \
3603     tm->dispatch_table[TCP_STATE_##t][f].error = (e);           \
3604 } while (0)
3605
3606   /* SYNs for new connections -> tcp-listen. */
3607   _(LISTEN, TCP_FLAG_SYN, TCP_INPUT_NEXT_LISTEN, TCP_ERROR_NONE);
3608   _(LISTEN, TCP_FLAG_ACK, TCP_INPUT_NEXT_RESET, TCP_ERROR_NONE);
3609   _(LISTEN, TCP_FLAG_RST, TCP_INPUT_NEXT_DROP, TCP_ERROR_RST_RCVD);
3610   _(LISTEN, TCP_FLAG_FIN | TCP_FLAG_ACK, TCP_INPUT_NEXT_RESET,
3611     TCP_ERROR_NONE);
3612   /* ACK for for a SYN-ACK -> tcp-rcv-process. */
3613   _(SYN_RCVD, TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
3614   _(SYN_RCVD, TCP_FLAG_RST, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
3615   _(SYN_RCVD, TCP_FLAG_RST | TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS,
3616     TCP_ERROR_NONE);
3617   _(SYN_RCVD, TCP_FLAG_SYN, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
3618   _(SYN_RCVD, TCP_FLAG_FIN | TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS,
3619     TCP_ERROR_NONE);
3620   /* SYN-ACK for a SYN */
3621   _(SYN_SENT, TCP_FLAG_SYN | TCP_FLAG_ACK, TCP_INPUT_NEXT_SYN_SENT,
3622     TCP_ERROR_NONE);
3623   _(SYN_SENT, TCP_FLAG_ACK, TCP_INPUT_NEXT_SYN_SENT, TCP_ERROR_NONE);
3624   _(SYN_SENT, TCP_FLAG_RST, TCP_INPUT_NEXT_SYN_SENT, TCP_ERROR_NONE);
3625   _(SYN_SENT, TCP_FLAG_RST | TCP_FLAG_ACK, TCP_INPUT_NEXT_SYN_SENT,
3626     TCP_ERROR_NONE);
3627   /* ACK for for established connection -> tcp-established. */
3628   _(ESTABLISHED, TCP_FLAG_ACK, TCP_INPUT_NEXT_ESTABLISHED, TCP_ERROR_NONE);
3629   /* FIN for for established connection -> tcp-established. */
3630   _(ESTABLISHED, TCP_FLAG_FIN, TCP_INPUT_NEXT_ESTABLISHED, TCP_ERROR_NONE);
3631   _(ESTABLISHED, TCP_FLAG_FIN | TCP_FLAG_ACK, TCP_INPUT_NEXT_ESTABLISHED,
3632     TCP_ERROR_NONE);
3633   _(ESTABLISHED, TCP_FLAG_RST, TCP_INPUT_NEXT_ESTABLISHED, TCP_ERROR_NONE);
3634   _(ESTABLISHED, TCP_FLAG_RST | TCP_FLAG_ACK, TCP_INPUT_NEXT_ESTABLISHED,
3635     TCP_ERROR_NONE);
3636   _(ESTABLISHED, TCP_FLAG_SYN, TCP_INPUT_NEXT_ESTABLISHED, TCP_ERROR_NONE);
3637   _(ESTABLISHED, TCP_FLAG_SYN | TCP_FLAG_ACK, TCP_INPUT_NEXT_ESTABLISHED,
3638     TCP_ERROR_NONE);
3639   /* ACK or FIN-ACK to our FIN */
3640   _(FIN_WAIT_1, TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
3641   _(FIN_WAIT_1, TCP_FLAG_ACK | TCP_FLAG_FIN, TCP_INPUT_NEXT_RCV_PROCESS,
3642     TCP_ERROR_NONE);
3643   /* FIN in reply to our FIN from the other side */
3644   _(FIN_WAIT_1, TCP_FLAG_FIN, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
3645   _(FIN_WAIT_1, TCP_FLAG_RST, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
3646   _(CLOSING, TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
3647   /* FIN confirming that the peer (app) has closed */
3648   _(FIN_WAIT_2, TCP_FLAG_FIN, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
3649   _(FIN_WAIT_2, TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
3650   _(FIN_WAIT_2, TCP_FLAG_FIN | TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS,
3651     TCP_ERROR_NONE);
3652   _(CLOSE_WAIT, TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
3653   _(CLOSE_WAIT, TCP_FLAG_FIN | TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS,
3654     TCP_ERROR_NONE);
3655   _(LAST_ACK, TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
3656   _(LAST_ACK, TCP_FLAG_FIN, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
3657   _(LAST_ACK, TCP_FLAG_FIN | TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS,
3658     TCP_ERROR_NONE);
3659   _(LAST_ACK, TCP_FLAG_RST, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
3660   _(LAST_ACK, TCP_FLAG_SYN, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
3661   _(TIME_WAIT, TCP_FLAG_FIN, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
3662   _(TIME_WAIT, TCP_FLAG_FIN | TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS,
3663     TCP_ERROR_NONE);
3664   _(TIME_WAIT, TCP_FLAG_RST, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
3665   _(TIME_WAIT, TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
3666   _(CLOSED, TCP_FLAG_ACK, TCP_INPUT_NEXT_DROP, TCP_ERROR_CONNECTION_CLOSED);
3667   _(CLOSED, TCP_FLAG_RST, TCP_INPUT_NEXT_DROP, TCP_ERROR_CONNECTION_CLOSED);
3668   _(CLOSED, TCP_FLAG_FIN | TCP_FLAG_ACK, TCP_INPUT_NEXT_DROP,
3669     TCP_ERROR_CONNECTION_CLOSED);
3670 #undef _
3671 }
3672
3673 static clib_error_t *
3674 tcp_input_init (vlib_main_t * vm)
3675 {
3676   clib_error_t *error = 0;
3677   tcp_main_t *tm = vnet_get_tcp_main ();
3678
3679   if ((error = vlib_call_init_function (vm, tcp_init)))
3680     return error;
3681
3682   /* Initialize dispatch table. */
3683   tcp_dispatch_table_init (tm);
3684
3685   return error;
3686 }
3687
3688 VLIB_INIT_FUNCTION (tcp_input_init);
3689
3690 /*
3691  * fd.io coding-style-patch-verification: ON
3692  *
3693  * Local Variables:
3694  * eval: (c-set-style "gnu")
3695  * End:
3696  */