memset (listener, 0, sizeof (*listener));
listener->c_c_index = listener - tm->listener_pool;
- listener->c_lcl_port = clib_host_to_net_u16 (lcl->port);
+ listener->c_lcl_port = lcl->port;
if (lcl->is_ip4)
{
{
tcp_main_t *tm = vnet_get_tcp_main ();
tcp_connection_t *tc = 0;
+ ASSERT (vlib_get_thread_index () == 0);
pool_get (tm->half_open_connections, tc);
memset (tc, 0, sizeof (*tc));
tc->c_c_index = tc - tm->half_open_connections;
tc->state = TCP_STATE_FIN_WAIT_1;
break;
case TCP_STATE_CLOSE_WAIT:
+ tcp_connection_timers_reset (tc);
tcp_send_fin (tc);
tc->state = TCP_STATE_LAST_ACK;
+ tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, TCP_2MSL_TIME);
break;
case TCP_STATE_FIN_WAIT_1:
+ tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, TCP_2MSL_TIME);
break;
default:
- clib_warning ("state: %u", tc->state);
+ TCP_DBG ("state: %u", tc->state);
}
TCP_EVT_DBG (TCP_EVT_STATE_CHANGE, tc);
/* If in CLOSED and WAITCLOSE timer is not set, delete connection now */
- if (tc->timers[TCP_TIMER_WAITCLOSE] == TCP_TIMER_HANDLE_INVALID
+ if (!tcp_timer_is_active (tc, TCP_TIMER_WAITCLOSE)
&& tc->state == TCP_STATE_CLOSED)
tcp_connection_del (tc);
}
{
tcp_connection_t *tc;
tc = tcp_connection_get (conn_index, thread_index);
+ tcp_connection_timers_reset (tc);
/* Wait for the session tx events to clear */
tc->state = TCP_STATE_CLOSED;
}
#endif /* 0 */
+/**
+ * Initialize connection send variables.
+ */
+void
+tcp_init_snd_vars (tcp_connection_t * tc)
+{
+ u32 time_now;
+
+ /* Set random initial sequence */
+ time_now = tcp_time_now ();
+ tc->iss = random_u32 (&time_now);
+ tc->snd_una = tc->iss;
+ tc->snd_nxt = tc->iss + 1;
+ tc->snd_una_max = tc->snd_nxt;
+}
+
/** Initialize tcp connection variables
*
* Should be called after having received a msg from the peer, i.e., a SYN or
tcp_init_mss (tc);
scoreboard_init (&tc->sack_sb);
tcp_cc_init (tc);
+ if (tc->state == TCP_STATE_SYN_RCVD)
+ tcp_init_snd_vars (tc);
+
// tcp_connection_fib_attach (tc);
}
tc = tcp_half_open_connection_new ();
clib_memcpy (&tc->c_rmt_ip, &rmt->ip, sizeof (ip46_address_t));
clib_memcpy (&tc->c_lcl_ip, &lcl_addr, sizeof (ip46_address_t));
- tc->c_rmt_port = clib_host_to_net_u16 (rmt->port);
+ tc->c_rmt_port = rmt->port;
tc->c_lcl_port = clib_host_to_net_u16 (lcl_port);
tc->c_is_ip4 = rmt->is_ip4;
tc->c_transport_proto = TRANSPORT_PROTO_TCP;
TCP_EVT_DBG (TCP_EVT_OPEN, tc);
tc->state = TCP_STATE_SYN_SENT;
+ tcp_init_snd_vars (tc);
tcp_send_syn (tc);
clib_spinlock_unlock_if_init (&tm->half_open_lock);
return s;
}
+const char *tcp_connection_flags_str[] = {
+#define _(sym, str) str,
+ foreach_tcp_connection_flag
+#undef _
+};
+
+u8 *
+format_tcp_connection_flags (u8 * s, va_list * args)
+{
+ tcp_connection_t *tc = va_arg (*args, tcp_connection_t *);
+ int i, last = -1;
+
+ for (i = 0; i < TCP_CONN_N_FLAG_BITS; i++)
+ if (tc->flags & (1 << i))
+ last = i;
+ for (i = 0; i < last; i++)
+ {
+ if (tc->flags & (1 << i))
+ s = format (s, "%s, ", tcp_connection_flags_str[i]);
+ }
+ if (last >= 0)
+ s = format (s, "%s", tcp_connection_flags_str[last]);
+ return s;
+}
+
const char *tcp_conn_timers[] = {
#define _(sym, str) str,
foreach_tcp_timer
format_tcp_vars (u8 * s, va_list * args)
{
tcp_connection_t *tc = va_arg (*args, tcp_connection_t *);
+ s = format (s, " flags: %U timers: %U\n", format_tcp_connection_flags, tc,
+ format_tcp_timers, tc);
s = format (s, " snd_una %u snd_nxt %u snd_una_max %u",
tc->snd_una - tc->iss, tc->snd_nxt - tc->iss,
tc->snd_una_max - tc->iss);
tc->snd_wnd, tc->rcv_wnd, tc->snd_wl1 - tc->irs,
tc->snd_wl2 - tc->iss);
s = format (s, " flight size %u send space %u rcv_wnd_av %d\n",
- tcp_flight_size (tc), tcp_available_snd_space (tc),
+ tcp_flight_size (tc), tcp_available_output_snd_space (tc),
tcp_rcv_wnd_available (tc));
s = format (s, " cong %U ", format_tcp_congestion_status, tc);
s = format (s, "cwnd %u ssthresh %u rtx_bytes %u bytes_acked %u\n",
{
s = format (s, "%-15U", format_tcp_state, tc->state);
if (verbose > 1)
- s = format (s, " %U\n%U", format_tcp_timers, tc, format_tcp_vars, tc);
+ s = format (s, "\n%U", format_tcp_vars, tc);
}
return s;
/* If not snd_wnd constrained and we can't write at least a segment,
* don't try at all */
if (PREDICT_FALSE (snd_space < tc->snd_mss))
- return 0;
+ return snd_space < tc->cwnd ? 0 : snd_space;
/* round down to mss multiple */
return snd_space - (snd_space % tc->snd_mss);
{
ASSERT (tc->state == TCP_STATE_SYN_SENT);
stream_session_connect_notify (&tc->connection, 1 /* fail */ );
+ TCP_DBG ("establish pop: %U", format_tcp_connection, tc, 2);
}
else
{
/* note: the connection may have already disappeared */
if (PREDICT_FALSE (tc == 0))
return;
-
+ TCP_DBG ("establish pop: %U", format_tcp_connection, tc, 2);
ASSERT (tc->state == TCP_STATE_SYN_RCVD);
+ /* Start cleanup. App wasn't notified yet so use delete notify as
+ * opposed to delete to cleanup session layer state. */
+ stream_session_delete_notify (&tc->connection);
}
tc->timers[TCP_TIMER_ESTABLISH] = TCP_TIMER_HANDLE_INVALID;
tcp_connection_cleanup (tc);
vec_validate (tm->tx_frames[0], num_threads - 1);
vec_validate (tm->tx_frames[1], num_threads - 1);
+ vec_validate (tm->ip_lookup_tx_frames[0], num_threads - 1);
+ vec_validate (tm->ip_lookup_tx_frames[1], num_threads - 1);
tm->bytes_per_buffer = vlib_buffer_free_list_buffer_size
(vm, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
return 0;
}
+void
+tcp_punt_unknown (vlib_main_t * vm, u8 is_ip4, u8 is_add)
+{
+ tcp_main_t *tm = &tcp_main;
+ if (is_ip4)
+ tm->punt_unknown4 = is_add;
+ else
+ tm->punt_unknown6 = is_add;
+}
+
clib_error_t *
tcp_init (vlib_main_t * vm)
{
v6set = 1;
else if (unformat (input, "%U", unformat_ip6_address, &v6start))
{
- memcpy (&v6end, &v6start, sizeof (v4start));
+ memcpy (&v6end, &v6start, sizeof (v6start));
v6set = 1;
}
else if (unformat (input, "fib-table %d", &table_id))
};
/* *INDENT-ON* */
+static clib_error_t *
+show_tcp_punt_fn (vlib_main_t * vm, unformat_input_t * input,
+ vlib_cli_command_t * cmd_arg)
+{
+ tcp_main_t *tm = vnet_get_tcp_main ();
+ if (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ return clib_error_return (0, "unknown input `%U'", format_unformat_error,
+ input);
+ vlib_cli_output (vm, "IPv4 TCP punt: %s",
+ tm->punt_unknown4 ? "enabled" : "disabled");
+ vlib_cli_output (vm, "IPv6 TCP punt: %s",
+ tm->punt_unknown6 ? "enabled" : "disabled");
+ return 0;
+}
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (show_tcp_punt_command, static) =
+{
+ .path = "show tcp punt",
+ .short_help = "show tcp punt",
+ .function = show_tcp_punt_fn,
+};
+/* *INDENT-ON* */
+
/*
* fd.io coding-style-patch-verification: ON
*