if (mrtt > 0 && mrtt < TCP_RTT_MAX)
tcp_estimate_rtt (tc, mrtt);
+ tcp_update_rto (tc);
}
/**
{
u32 thread_index = vm->thread_index, errors = 0, *first_buffer;
tcp_worker_ctx_t *wrk = tcp_get_worker (thread_index);
- u32 n_left_from, *from;
+ u32 n_left_from, *from, max_dequeue;
from = first_buffer = vlib_frame_vector_args (from_frame);
n_left_from = from_frame->n_vectors;
}
/* Make sure the ack is exactly right */
- if (tc0->rcv_nxt != vnet_buffer (b0)->tcp.seq_number || is_fin0)
+ if (tc0->rcv_nxt != vnet_buffer (b0)->tcp.seq_number || is_fin0
+ || vnet_buffer (b0)->tcp.data_len)
{
tcp_connection_reset (tc0);
error0 = TCP_ERROR_SEGMENT_INVALID;
if (tc0->flags & TCP_CONN_FINPNDG)
{
/* TX fifo finally drained */
- if (!session_tx_fifo_max_dequeue (&tc0->connection))
+ max_dequeue = session_tx_fifo_max_dequeue (&tc0->connection);
+ if (max_dequeue <= tc0->burst_acked)
tcp_send_fin (tc0);
}
/* If FIN is ACKed */
tcp_send_fin (tc0);
tcp_connection_timers_reset (tc0);
tc0->state = TCP_STATE_LAST_ACK;
+ TCP_EVT_DBG (TCP_EVT_STATE_CHANGE, tc0);
tcp_timer_update (tc0, TCP_TIMER_WAITCLOSE, TCP_2MSL_TIME);
}
}
switch (tc0->state)
{
case TCP_STATE_ESTABLISHED:
+ tcp_rcv_fin (wrk, tc0, b0, &error0);
+ break;
case TCP_STATE_SYN_RCVD:
- /* Send FIN-ACK notify app and enter CLOSE-WAIT */
+ /* Send FIN-ACK, enter LAST-ACK and because the app was not
+ * notified yet, set a cleanup timer instead of relying on
+ * disconnect notify and the implicit close call. */
tcp_connection_timers_reset (tc0);
+ tc0->rcv_nxt += 1;
tcp_send_fin (tc0);
- stream_session_disconnect_notify (&tc0->connection);
- tc0->state = TCP_STATE_CLOSE_WAIT;
- tcp_timer_update (tc0, TCP_TIMER_WAITCLOSE, TCP_CLOSEWAIT_TIME);
+ tc0->state = TCP_STATE_LAST_ACK;
TCP_EVT_DBG (TCP_EVT_STATE_CHANGE, tc0);
+ tcp_timer_set (tc0, TCP_TIMER_WAITCLOSE, TCP_2MSL_TIME);
break;
case TCP_STATE_CLOSE_WAIT:
case TCP_STATE_CLOSING:
} while (0)
/* RFC 793: In LISTEN if RST drop and if ACK return RST */
+ _(LISTEN, 0, TCP_INPUT_NEXT_DROP, TCP_ERROR_SEGMENT_INVALID);
_(LISTEN, TCP_FLAG_ACK, TCP_INPUT_NEXT_RESET, TCP_ERROR_ACK_INVALID);
_(LISTEN, TCP_FLAG_RST, TCP_INPUT_NEXT_DROP, TCP_ERROR_INVALID_CONNECTION);
_(LISTEN, TCP_FLAG_SYN, TCP_INPUT_NEXT_LISTEN, TCP_ERROR_NONE);
TCP_ERROR_NONE);
/* FIN in reply to our FIN from the other side */
_(FIN_WAIT_1, TCP_FLAG_FIN, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
+ _(FIN_WAIT_1, TCP_FLAG_SYN, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
_(FIN_WAIT_1, TCP_FLAG_RST, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
_(FIN_WAIT_1, TCP_FLAG_RST | TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS,
TCP_ERROR_NONE);
_(CLOSING, TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
+ _(CLOSING, TCP_FLAG_SYN, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
+ _(CLOSING, TCP_FLAG_RST, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
+ _(CLOSING, TCP_FLAG_RST | TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS,
+ TCP_ERROR_NONE);
/* FIN confirming that the peer (app) has closed */
_(FIN_WAIT_2, TCP_FLAG_FIN, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
_(FIN_WAIT_2, TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);