* 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;
* Setup retransmit and establish timers before requesting buffer
* such that we can return if we've ran out.
*/
- tcp_timer_set (tc, TCP_TIMER_ESTABLISH, TCP_ESTABLISH_TIME);
+ tcp_timer_set (tc, TCP_TIMER_ESTABLISH_AO, TCP_ESTABLISH_TIME);
tcp_timer_update (tc, TCP_TIMER_RETRANSMIT_SYN,
tc->rto * TCP_TO_TIMER_TICK);
{
/* Out of buffers so program fin retransmit ASAP */
tcp_timer_update (tc, TCP_TIMER_RETRANSMIT, 1);
- goto post_enqueue;
+ if (fin_snt)
+ tc->snd_nxt = tc->snd_una_max;
+ return;
}
tcp_retransmit_timer_force_update (tc);
tcp_enqueue_to_output_now (wrk, b, bi, tc->c_is_ip4);
TCP_EVT_DBG (TCP_EVT_FIN_SENT, tc);
-post_enqueue:
if (!fin_snt)
{
tc->flags |= TCP_CONN_FINSNT;
{
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
{
tc = tcp_connection_get (index, thread_index);
/* Note: the connection may have been closed and pool_put */
- if (PREDICT_FALSE (tc == 0 || tc->state < TCP_STATE_SYN_RCVD))
+ if (PREDICT_FALSE (tc == 0 || tc->state == TCP_STATE_SYN_SENT))
return;
tc->timers[TCP_TIMER_RETRANSMIT] = TCP_TIMER_HANDLE_INVALID;
+ /* Wait-close and retransmit could pop at the same time */
+ if (tc->state == TCP_STATE_CLOSED)
+ return;
}
if (tc->state >= TCP_STATE_ESTABLISHED)
/* Send one segment. Note that n_bytes may be zero due to buffer
* shortfall */
n_bytes = tcp_prepare_retransmit_segment (wrk, tc, 0, tc->snd_mss, &b);
-
- if (n_bytes == 0)
+ if (!n_bytes)
{
tcp_retransmit_timer_force_update (tc);
return;
if (tc->flags & TCP_CONN_HALF_OPEN_DONE)
{
if (tcp_half_open_connection_cleanup (tc))
- {
- clib_warning ("could not remove half-open connection");
- ASSERT (0);
- }
+ TCP_DBG ("could not remove half-open connection");
return;
}