tcp_connection_t tcp_connection;
} tcp_tx_trace_t;
-#ifndef CLIB_MARCH_VARIANT
-u16 dummy_mtu = 1460;
-#endif /* CLIB_MARCH_VARIANT */
-
static u8 *
format_tcp_tx_trace (u8 * s, va_list * args)
{
tcp_update_rcv_mss (tcp_connection_t * tc)
{
/* TODO find our iface MTU */
- tc->mss = dummy_mtu - sizeof (tcp_header_t);
+ tc->mss = tcp_main.default_mtu - sizeof (tcp_header_t);
}
/**
return clib_min (tc->rcv_wnd, TCP_WND_MAX);
}
-static void
+static inline void
tcp_update_rcv_wnd (tcp_connection_t * tc)
{
+ u32 available_space, wnd;
i32 observed_wnd;
- u32 available_space, max_fifo, wnd;
+
+ ASSERT (tc->rcv_opts.mss < transport_rx_fifo_size (&tc->connection));
/*
* Figure out how much space we have available
*/
available_space = transport_max_rx_enqueue (&tc->connection);
- max_fifo = transport_rx_fifo_size (&tc->connection);
-
- ASSERT (tc->rcv_opts.mss < max_fifo);
- if (available_space < tc->rcv_opts.mss && available_space < max_fifo >> 3)
+ if (PREDICT_FALSE (available_space < tc->rcv_opts.mss))
available_space = 0;
/*
* to compute the new window
*/
observed_wnd = (i32) tc->rcv_wnd - (tc->rcv_nxt - tc->rcv_las);
- if (observed_wnd < 0)
- observed_wnd = 0;
/* Bad. Thou shalt not shrink */
- if (available_space < observed_wnd)
+ if (PREDICT_FALSE ((i32) available_space < observed_wnd))
{
- wnd = observed_wnd;
+ wnd = clib_max (observed_wnd, 0);
TCP_EVT_DBG (TCP_EVT_RCV_WND_SHRUNK, tc, observed_wnd, available_space);
}
else
return tcp_initial_window_to_advertise (tc);
tcp_update_rcv_wnd (tc);
-
- if (tc->rcv_wnd == 0)
- {
- tc->flags |= TCP_CONN_SENT_RCV_WND0;
- }
- else
- {
- tc->flags &= ~TCP_CONN_SENT_RCV_WND0;
- }
-
return tc->rcv_wnd >> tc->rcv_wscale;
}
u8 len = 0;
opts->flags |= TCP_OPTS_FLAG_MSS;
- opts->mss = dummy_mtu; /*XXX discover that */
+ opts->mss = tcp_main.default_mtu; /*XXX discover that */
len += TCP_OPTION_LEN_MSS;
opts->flags |= TCP_OPTS_FLAG_WSCALE;
tcp_make_fin (tcp_connection_t * tc, vlib_buffer_t * b)
{
tcp_make_ack_i (tc, b, TCP_STATE_ESTABLISHED, TCP_FLAG_FIN | TCP_FLAG_ACK);
-
- /* Reset flags, make sure ack is sent */
- vnet_buffer (b)->tcp.flags &= ~TCP_BUF_FLAG_DUPACK;
}
/**
tcp_push_hdr_i (tc, b, tc->snd_nxt, /* compute opts */ 0, /* burst */ 1,
/* update_snd_nxt */ 1);
tc->snd_una_max = seq_max (tc->snd_nxt, tc->snd_una_max);
- ASSERT (seq_leq (tc->snd_una_max, tc->snd_una + tc->snd_wnd));
tcp_validate_txf_size (tc, tc->snd_una_max - tc->snd_una);
/* If not tracking an ACK, start tracking */
if (tc->rtt_ts == 0 && !tcp_in_cong_recovery (tc))
tcp_update_rto (tc);
}
+ /* Peer is dead or network connectivity is lost. Close connection.
+ * RFC 1122 section 4.2.3.5 recommends a value of at least 100s. For
+ * a min rto of 0.2s we need to retry about 8 times. */
+ if (tc->rto_boff >= TCP_RTO_BOFF_MAX)
+ {
+ tcp_send_reset (tc);
+ tcp_connection_set_state (tc, TCP_STATE_CLOSED);
+ session_transport_closing_notify (&tc->connection);
+ tcp_connection_timers_reset (tc);
+ tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, TCP_CLOSEWAIT_TIME);
+ return;
+ }
+
/* Increment RTO backoff (also equal to number of retries) and go back
* to first un-acked byte */
tc->rto_boff += 1;
ASSERT (tcp_in_fastrecovery (tc));
TCP_EVT_DBG (TCP_EVT_CC_EVT, tc, 0);
+ snd_space = tcp_available_cc_snd_space (tc);
+
if (!tcp_fastrecovery_first (tc))
goto send_unsent;
/* RFC 6582: [If a partial ack], retransmit the first unacknowledged
* segment. */
- snd_space = tc->sack_sb.last_bytes_delivered;
while (snd_space > 0 && n_segs < burst_size)
{
n_written = tcp_prepare_retransmit_segment (wrk, tc, offset,
send_unsent:
/* RFC 6582: Send a new segment if permitted by the new value of cwnd. */
- snd_space = tcp_available_cc_snd_space (tc);
if (snd_space < tc->snd_mss || tc->snd_mss == 0)
goto done;
return;
}
+ /* If next_index is not drop use it */
+ *next0 = tc0->out_next_index ? tc0->out_next_index : *next0;
+
vnet_buffer (b0)->sw_if_index[VLIB_TX] = tc0->c_fib_index;
vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;