* scale to be computed in the same way */
max_fifo = tm->max_rx_fifo ? tm->max_rx_fifo : TCP_MAX_RX_FIFO_SIZE;
- tc->rcv_wscale = tcp_window_compute_scale (max_fifo);
+ /* Compute rcv wscale only if peer advertised support for it */
+ if (tc->state != TCP_STATE_SYN_RCVD || tcp_opts_wscale (&tc->rcv_opts))
+ tc->rcv_wscale = tcp_window_compute_scale (max_fifo);
+
tc->rcv_wnd = tcp_initial_wnd_unscaled (tc);
return clib_min (tc->rcv_wnd, TCP_WND_MAX);
switch (state)
{
case TCP_STATE_ESTABLISHED:
+ case TCP_STATE_CLOSE_WAIT:
case TCP_STATE_FIN_WAIT_1:
+ case TCP_STATE_LAST_ACK:
+ case TCP_STATE_CLOSING:
+ case TCP_STATE_FIN_WAIT_2:
+ case TCP_STATE_TIME_WAIT:
case TCP_STATE_CLOSED:
- case TCP_STATE_CLOSE_WAIT:
return tcp_make_established_options (tc, opts);
case TCP_STATE_SYN_RCVD:
return tcp_make_synack_options (tc, opts);
if (tc->snd_mss < 45)
{
- clib_warning ("snd mss is 0");
/* Assume that at least the min default mss works */
tc->snd_mss = default_min_mss;
tc->rcv_opts.mss = default_min_mss;
if (PREDICT_FALSE (tcp_get_free_buffer_index (wrk, &bi)))
return;
+ tc->rtt_ts = tcp_time_now_us (tc->c_thread_index);
b = vlib_get_buffer (vm, bi);
tcp_make_synack (tc, b);
tcp_enqueue_to_output (wrk, b, bi, tc->c_is_ip4);
{
case TCP_STATE_ESTABLISHED:
case TCP_STATE_CLOSE_WAIT:
+ case TCP_STATE_TIME_WAIT:
+ case TCP_STATE_FIN_WAIT_2:
return TCP_FLAG_ACK;
case TCP_STATE_SYN_RCVD:
return TCP_FLAG_SYN | TCP_FLAG_ACK;
return TCP_FLAG_SYN;
case TCP_STATE_LAST_ACK:
case TCP_STATE_FIN_WAIT_1:
+ case TCP_STATE_CLOSING:
if (tc->snd_nxt + 1 < tc->snd_una_max)
return TCP_FLAG_ACK;
else
advertise_wnd = tcp_window_to_advertise (tc, next_state);
flags = tcp_make_state_flags (tc, next_state);
-
+ if (PREDICT_FALSE (tc->flags & TCP_CONN_PSH_PENDING))
+ {
+ if (seq_geq (tc->psh_seq, tc->snd_nxt)
+ && seq_lt (tc->psh_seq, tc->snd_nxt + data_len))
+ flags |= TCP_FLAG_PSH;
+ }
th = vlib_buffer_push_tcp (b, tc->c_lcl_port, tc->c_rmt_port, tc->snd_nxt,
tc->rcv_nxt, tcp_hdr_opts_len, flags,
advertise_wnd);
{
tc = tcp_half_open_connection_get (index);
/* Note: the connection may have transitioned to ESTABLISHED... */
- if (PREDICT_FALSE (tc == 0))
+ if (PREDICT_FALSE (tc == 0 || tc->state != TCP_STATE_SYN_SENT))
return;
tc->timers[TCP_TIMER_RETRANSMIT_SYN] = TCP_TIMER_HANDLE_INVALID;
}
{
tc = tcp_connection_get (index, thread_index);
/* Note: the connection may have been closed and pool_put */
- if (PREDICT_FALSE (tc == 0))
+ if (PREDICT_FALSE (tc == 0 || tc->state < TCP_STATE_SYN_RCVD))
return;
tc->timers[TCP_TIMER_RETRANSMIT] = TCP_TIMER_HANDLE_INVALID;
}
/* Takes a vector of packets. */
.vector_size = sizeof (u32),
.n_errors = TCP_N_ERROR,
+ .protocol_hint = VLIB_NODE_PROTO_HINT_TCP,
.error_strings = tcp_error_strings,
.n_next_nodes = TCP_OUTPUT_N_NEXT,
.next_nodes = {
/* Takes a vector of packets. */
.vector_size = sizeof (u32),
.n_errors = TCP_N_ERROR,
+ .protocol_hint = VLIB_NODE_PROTO_HINT_TCP,
.error_strings = tcp_error_strings,
.n_next_nodes = TCP_OUTPUT_N_NEXT,
.next_nodes = {