{
ASSERT (timestamp_leq (tc->tsval_recent, tc->rcv_opts.tsval));
tc->tsval_recent = tc->rcv_opts.tsval;
- tc->tsval_recent_age = tcp_time_now_w_thread (tc->c_thread_index);
+ tc->tsval_recent_age = tcp_time_tstamp (tc->c_thread_index);
}
}
/* If it just so happens that a segment updates tsval_recent for a
* segment over 24 days old, invalidate tsval_recent. */
if (timestamp_lt (tc0->tsval_recent_age + TCP_PAWS_IDLE,
- tcp_time_now_w_thread (tc0->c_thread_index)))
+ tcp_time_tstamp (tc0->c_thread_index)))
{
tc0->tsval_recent = tc0->rcv_opts.tsval;
clib_warning ("paws failed: 24-day old segment");
session_tx_fifo_dequeue_drop (&tc->connection, tc->burst_acked);
tcp_validate_txf_size (tc, tc->snd_nxt - tc->snd_una);
- if (PREDICT_FALSE (tc->flags & TCP_CONN_PSH_PENDING))
- {
- if (seq_leq (tc->psh_seq, tc->snd_una))
- tc->flags &= ~TCP_CONN_PSH_PENDING;
- }
-
if (tcp_is_descheduled (tc))
tcp_reschedule (tc);
ASSERT (n_data_bytes);
tc->data_segs_in += 1;
+ /* Make sure we don't consume trailing bytes */
+ if (PREDICT_FALSE (b->current_length > n_data_bytes))
+ b->current_length = n_data_bytes;
+
/* Handle out-of-order data */
if (PREDICT_FALSE (vnet_buffer (b)->tcp.seq_number != tc->rcv_nxt))
{
return;
hw_if = vnet_get_sup_hw_interface (vnm, sw_if_idx);
- if (hw_if->flags & VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO)
+ if (hw_if->caps & VNET_HW_INTERFACE_CAP_SUPPORTS_TCP_GSO)
tc->cfg_flags |= TCP_CFG_F_TSO;
}
goto drop;
}
- /* Half-open completed recently but the connection was't removed
- * yet by the owning thread */
+ /* Half-open completed or cancelled recently but the connection
+ * was't removed yet by the owning thread */
if (PREDICT_FALSE (tc0->flags & TCP_CONN_HALF_OPEN_DONE))
{
- /* Make sure the connection actually exists */
- ASSERT (tcp_lookup_connection (tc0->c_fib_index, b0,
- my_thread_index, is_ip4));
error0 = TCP_ERROR_SPURIOUS_SYN_ACK;
goto drop;
}
if (tcp_opts_tstamp (&new_tc0->rcv_opts))
{
new_tc0->tsval_recent = new_tc0->rcv_opts.tsval;
- new_tc0->tsval_recent_age = tcp_time_now ();
+ new_tc0->tsval_recent_age = tcp_time_tstamp (my_thread_index);
}
if (tcp_opts_wscale (&new_tc0->rcv_opts))
goto cleanup_ho;
}
+ transport_fifos_init_ooo (&new_tc0->connection);
new_tc0->tx_fifo_size =
transport_tx_fifo_size (&new_tc0->connection);
/* Update rtt with the syn-ack sample */
goto cleanup_ho;
}
+ transport_fifos_init_ooo (&new_tc0->connection);
new_tc0->tx_fifo_size =
transport_tx_fifo_size (&new_tc0->connection);
new_tc0->rtt_ts = 0;
case TCP_STATE_FIN_WAIT_2:
if (vnet_buffer (b0)->tcp.data_len)
error0 = tcp_segment_rcv (wrk, tc0, b0);
+ /* Don't accept out of order fins lower */
+ if (vnet_buffer (b0)->tcp.seq_end != tc0->rcv_nxt)
+ goto drop;
break;
case TCP_STATE_CLOSE_WAIT:
case TCP_STATE_CLOSING:
b = vlib_get_buffer (vm, bi);
- lc = tcp_listener_get (vnet_buffer (b)->tcp.connection_index);
- if (PREDICT_FALSE (lc == 0))
+ /* Flags initialized with connection state after lookup */
+ if (vnet_buffer (b)->tcp.flags == TCP_STATE_LISTEN)
+ {
+ lc = tcp_listener_get (vnet_buffer (b)->tcp.connection_index);
+ }
+ else
{
tcp_connection_t *tc;
tc = tcp_connection_get (vnet_buffer (b)->tcp.connection_index,
thread_index);
if (tc->state != TCP_STATE_TIME_WAIT)
{
+ lc = 0;
error = TCP_ERROR_CREATE_EXISTS;
goto done;
}
goto done;
}
+ transport_fifos_init_ooo (&child->connection);
child->tx_fifo_size = transport_tx_fifo_size (&child->connection);
tcp_send_synack (child);
error = tm->dispatch_table[tc->state][flags].error;
tc->segs_in += 1;
+ /* Track connection state when packet was received. It helps
+ * @ref tcp46_listen_inline detect port reuse */
+ vnet_buffer (b)->tcp.flags = tc->state;
+
if (PREDICT_FALSE (error != TCP_ERROR_NONE))
{
b->error = error_node->errors[error];
vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
u16 nexts[VLIB_FRAME_SIZE], *next;
- tcp_set_time_now (tcp_get_worker (thread_index));
+ tcp_update_time_now (tcp_get_worker (thread_index));
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
/* *INDENT-ON* */
#ifndef CLIB_MARCH_VARIANT
+void
+tcp_check_gso (tcp_connection_t *tc)
+{
+ tcp_check_tx_offload (tc, tc->c_is_ip4);
+}
+
static void
tcp_dispatch_table_init (tcp_main_t * tm)
{