Improvements to tcp rx path and debugging

- Increment rcv_nxt for fin packets
- Call tcp_segment_rcv only if buffer has data
- Parse rcv opts before deleting half-open connection
- Fix initial rcv_wnd
- Improved event logging

Change-Id: I9b83c04f432c4cec832c480b03e534deff02c3b1
Signed-off-by: Florin Coras <fcoras@cisco.com>
This commit is contained in:
Florin Coras
2017-07-18 05:38:03 -04:00
parent 161c59c75c
commit 6534b7aa13
13 changed files with 657 additions and 228 deletions
+73
View File
@@ -443,6 +443,79 @@ dump_thread_0_event_queue (void)
}
}
static u8
session_node_cmp_event (session_fifo_event_t * e, svm_fifo_t * f)
{
stream_session_t *s;
switch (e->event_type)
{
case FIFO_EVENT_APP_RX:
case FIFO_EVENT_APP_TX:
case FIFO_EVENT_BUILTIN_RX:
if (e->fifo == f)
return 1;
break;
case FIFO_EVENT_DISCONNECT:
break;
case FIFO_EVENT_RPC:
s = stream_session_get_from_handle (e->session_handle);
if (!s)
{
clib_warning ("session has event but doesn't exist!");
break;
}
if (s->server_rx_fifo == f || s->server_tx_fifo == f)
return 1;
break;
default:
break;
}
return 0;
}
u8
session_node_lookup_fifo_event (svm_fifo_t * f, session_fifo_event_t * e)
{
session_manager_main_t *smm = vnet_get_session_manager_main ();
unix_shared_memory_queue_t *q;
session_fifo_event_t *pending_event_vector, *evt;
int i, index, found = 0;
i8 *headp;
u8 thread_index;
ASSERT (e);
thread_index = f->master_thread_index;
/*
* Search evt queue
*/
q = smm->vpp_event_queues[thread_index];
index = q->head;
for (i = 0; i < q->cursize; i++)
{
headp = (i8 *) (&q->data[0] + q->elsize * index);
clib_memcpy (e, headp, q->elsize);
found = session_node_cmp_event (e, f);
if (found)
break;
if (++index == q->maxsize)
index = 0;
}
/*
* Search pending events vector
*/
pending_event_vector = smm->pending_event_vector[thread_index];
vec_foreach (evt, pending_event_vector)
{
found = session_node_cmp_event (evt, f);
if (found)
{
clib_memcpy (e, evt, sizeof (*evt));
break;
}
}
return found;
}
static uword
session_queue_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
vlib_frame_t * frame)
+34 -4
View File
@@ -32,6 +32,22 @@ static transport_proto_vft_t *tp_vfts;
session_manager_main_t session_manager_main;
transport_connection_t *
stream_session_lookup_half_open (transport_connection_t * tc)
{
session_manager_main_t *smm = &session_manager_main;
session_kv4_t kv4;
int rv;
if (tc->is_ip4)
{
make_v4_ss_kv_from_tc (&kv4, tc);
rv = clib_bihash_search_inline_16_8 (&smm->v4_half_open_hash, &kv4);
if (rv == 0)
return tp_vfts[tc->proto].get_half_open (kv4.value & 0xFFFFFFFFULL);
}
return 0;
}
/*
* Session lookup key; (src-ip, dst-ip, src-port, dst-port, session-type)
* Value: (owner thread index << 32 | session_index);
@@ -501,7 +517,7 @@ stream_session_create_i (segment_manager_t * sm, transport_connection_t * tc,
tc->s_index = s->session_index;
/* Add to the main lookup table */
value = (((u64) thread_index) << 32) | (u64) s->session_index;
value = stream_session_handle (s);
stream_session_table_add_for_tc (tc, value);
*ret_s = s;
@@ -817,8 +833,18 @@ stream_session_connect_notify (transport_connection_t * tc, u8 sst,
}
/* Notify client */
app->cb_fns.session_connected_callback (app->index, api_context, new_s,
is_fail);
if (app->cb_fns.session_connected_callback (app->index, api_context, new_s,
is_fail))
{
clib_warning ("failed to notify app");
if (!is_fail)
stream_session_disconnect (new_s);
}
else
{
if (!is_fail)
new_s->session_state = SESSION_STATE_READY;
}
/* Cleanup session lookup */
stream_session_half_open_table_del (smm, sst, tc);
@@ -862,15 +888,19 @@ void
stream_session_delete (stream_session_t * s)
{
session_manager_main_t *smm = vnet_get_session_manager_main ();
int rv;
/* Delete from the main lookup table. */
stream_session_table_del (smm, s);
if ((rv = stream_session_table_del (smm, s)))
clib_warning ("hash delete error, rv %d", rv);
/* Cleanup fifo segments */
segment_manager_dealloc_fifos (s->svm_segment_index, s->server_rx_fifo,
s->server_tx_fifo);
pool_put (smm->sessions[s->thread_index], s);
if (CLIB_DEBUG)
memset (s, 0xFA, sizeof (*s));
}
/**
+4
View File
@@ -170,6 +170,8 @@ typedef int
extern session_fifo_rx_fn session_tx_fifo_peek_and_snd;
extern session_fifo_rx_fn session_tx_fifo_dequeue_and_snd;
u8 session_node_lookup_fifo_event (svm_fifo_t * f, session_fifo_event_t * e);
struct _session_manager_main
{
/** Lookup tables for established sessions and listeners */
@@ -289,6 +291,8 @@ transport_connection_t *stream_session_lookup_transport6 (ip6_address_t * lcl,
stream_session_t *stream_session_lookup_listener (ip46_address_t * lcl,
u16 lcl_port, u8 proto);
transport_connection_t
* stream_session_lookup_half_open (transport_connection_t * tc);
void stream_session_table_add_for_tc (transport_connection_t * tc, u64 value);
int stream_session_table_del_for_tc (transport_connection_t * tc);
-7
View File
@@ -184,13 +184,6 @@ send_session_connected_callback (u32 app_index, u32 api_context,
}
vl_msg_api_send_shmem (q, (u8 *) & mp);
/* Remove client if connect failed */
if (!is_fail)
{
s->session_state = SESSION_STATE_READY;
}
return 0;
}
+19 -3
View File
@@ -19,8 +19,24 @@ u8 *
format_stream_session_fifos (u8 * s, va_list * args)
{
stream_session_t *ss = va_arg (*args, stream_session_t *);
int verbose = va_arg (*args, int);
session_fifo_event_t _e, *e = &_e;
u8 found;
s = format (s, " Rx fifo: %U", format_svm_fifo, ss->server_rx_fifo, 1);
if (verbose > 2 && ss->server_rx_fifo->has_event)
{
found = session_node_lookup_fifo_event (ss->server_rx_fifo, e);
s = format (s, " session node event: %s\n",
found ? "found" : "not found");
}
s = format (s, " Tx fifo: %U", format_svm_fifo, ss->server_tx_fifo, 1);
if (verbose > 2 && ss->server_tx_fifo->has_event)
{
found = session_node_lookup_fifo_event (ss->server_tx_fifo, e);
s = format (s, " session node event: %s\n",
found ? "found" : "not found");
}
return s;
}
@@ -55,7 +71,7 @@ format_stream_session (u8 * s, va_list * args)
if (verbose == 1)
s = format (s, "%v", str);
if (verbose > 1)
s = format (s, "%U", format_stream_session_fifos, ss);
s = format (s, "%U", format_stream_session_fifos, ss, verbose);
}
else if (ss->session_state == SESSION_STATE_LISTENING)
{
@@ -75,7 +91,7 @@ format_stream_session (u8 * s, va_list * args)
if (verbose == 1)
s = format (s, "%v", str);
if (verbose > 1)
s = format (s, "%U", format_stream_session_fifos, ss);
s = format (s, "%U", format_stream_session_fifos, ss, verbose);
}
else
{
@@ -248,7 +264,7 @@ show_session_command_fn (vlib_main_t * vm, unformat_input_t * input,
if (one_session)
{
vlib_cli_output (vm, "%U", format_stream_session, s, 2);
vlib_cli_output (vm, "%U", format_stream_session, s, 3);
return 0;
}
+7 -4
View File
@@ -410,9 +410,6 @@ builtin_session_connected_callback (u32 app_index, u32 api_context,
return -1;
}
/* Mark vpp session as connected */
s->session_state = SESSION_STATE_READY;
tm->our_event_queue = session_manager_get_vpp_event_queue (s->thread_index);
tm->vpp_event_queue = session_manager_get_vpp_event_queue (s->thread_index);
@@ -466,6 +463,7 @@ builtin_session_reset_callback (stream_session_t * s)
{
if (s->session_state == SESSION_STATE_READY)
clib_warning ("Reset active connection %U", format_stream_session, s, 2);
stream_session_cleanup (s);
return;
}
@@ -478,6 +476,11 @@ builtin_session_create_callback (stream_session_t * s)
static void
builtin_session_disconnect_callback (stream_session_t * s)
{
tclient_main_t *tm = &tclient_main;
vnet_disconnect_args_t _a, *a = &_a;
a->handle = stream_session_handle (s);
a->app_index = tm->app_index;
vnet_disconnect_session (a);
return;
}
@@ -521,7 +524,7 @@ attach_builtin_test_clients_app (void)
options[SESSION_OPTIONS_ACCEPT_COOKIE] = 0x12345678;
options[SESSION_OPTIONS_SEGMENT_SIZE] = (2ULL << 32);
options[SESSION_OPTIONS_RX_FIFO_SIZE] = tm->fifo_size;
options[SESSION_OPTIONS_TX_FIFO_SIZE] = tm->fifo_size / 2;
options[SESSION_OPTIONS_TX_FIFO_SIZE] = tm->fifo_size;
options[APP_OPTIONS_PRIVATE_SEGMENT_COUNT] = tm->private_segment_count;
options[APP_OPTIONS_PRIVATE_SEGMENT_SIZE] = tm->private_segment_size;
options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] = prealloc_fifos;
+4 -4
View File
@@ -213,15 +213,15 @@ builtin_server_rx_callback (stream_session_t * s)
q = bsm->vpp_queue[thread_index];
if (PREDICT_FALSE (q->cursize == q->maxsize))
clib_warning ("out of event queue space");
else if (unix_shared_memory_queue_add (q, (u8 *) & evt, 0 /* don't wait for mutex */
))
else if (unix_shared_memory_queue_add (q, (u8 *) & evt, 0))
clib_warning ("failed to enqueue self-tap");
bsm->rx_retries[thread_index][s->session_index]++;
if (bsm->rx_retries[thread_index][s->session_index] == 500000)
{
clib_warning ("session stuck: %U", format_stream_session, s, 2);
}
if (bsm->rx_retries[thread_index][s->session_index] < 500001)
bsm->rx_retries[thread_index][s->session_index]++;
}
return 0;
@@ -303,7 +303,7 @@ create_api_loopback (vlib_main_t * vm)
/* Wait for reply */
bsm->node_index = vlib_get_current_process (vm)->node_runtime.node_index;
vlib_process_wait_for_event_or_clock (vm, 1.0);
vlib_process_wait_for_event_or_clock (vm, 2.0);
event_type = vlib_process_get_events (vm, &event_data);
switch (event_type)
{
+50 -9
View File
@@ -163,6 +163,33 @@ tcp_connection_del (tcp_connection_t * tc)
tcp_connection_cleanup (tc);
}
/**
* Cleanup half-open connection
*/
void
tcp_half_open_connection_del (tcp_connection_t * tc)
{
tcp_main_t *tm = vnet_get_tcp_main ();
if (CLIB_DEBUG)
memset (tc, 0xFA, sizeof (*tc));
clib_spinlock_lock (&tm->half_open_lock);
pool_put (tm->half_open_connections, tc);
clib_spinlock_unlock (&tm->half_open_lock);
}
tcp_connection_t *
tcp_connection_new (u8 thread_index)
{
tcp_main_t *tm = vnet_get_tcp_main ();
tcp_connection_t *tc;
pool_get (tm->connections[thread_index], tc);
memset (tc, 0, sizeof (*tc));
tc->c_c_index = tc - tm->connections[thread_index];
tc->c_thread_index = thread_index;
return tc;
}
/** Notify session that connection has been reset.
*
* Switch state to closed and wait for session to call cleanup.
@@ -170,6 +197,7 @@ tcp_connection_del (tcp_connection_t * tc)
void
tcp_connection_reset (tcp_connection_t * tc)
{
TCP_EVT_DBG (TCP_EVT_RST_RCVD, tc);
switch (tc->state)
{
case TCP_STATE_SYN_RCVD:
@@ -178,12 +206,18 @@ tcp_connection_reset (tcp_connection_t * tc)
tcp_connection_cleanup (tc);
break;
case TCP_STATE_SYN_SENT:
/* XXX remove sst from call */
stream_session_connect_notify (&tc->connection, tc->connection.proto,
1 /* fail */ );
tcp_connection_cleanup (tc);
break;
case TCP_STATE_ESTABLISHED:
case TCP_STATE_CLOSE_WAIT:
case TCP_STATE_FIN_WAIT_1:
case TCP_STATE_FIN_WAIT_2:
case TCP_STATE_CLOSING:
tc->state = TCP_STATE_CLOSED;
TCP_EVT_DBG (TCP_EVT_STATE_CHANGE, tc);
/* Make sure all timers are cleared */
tcp_connection_timers_reset (tc);
@@ -227,6 +261,7 @@ tcp_connection_close (tcp_connection_t * tc)
tc->state = TCP_STATE_CLOSED;
else if (tc->state == TCP_STATE_CLOSE_WAIT)
tc->state = TCP_STATE_LAST_ACK;
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
@@ -250,6 +285,7 @@ tcp_session_cleanup (u32 conn_index, u32 thread_index)
/* Wait for the session tx events to clear */
tc->state = TCP_STATE_CLOSED;
TCP_EVT_DBG (TCP_EVT_STATE_CHANGE, tc);
tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, TCP_CLEANUP_TIME);
}
@@ -287,7 +323,7 @@ ip_interface_get_first_ip (u32 sw_if_index, u8 is_ip4)
* Allocate local port and add if successful add entry to local endpoint
* table to mark the pair as used.
*/
u16
int
tcp_allocate_local_port (tcp_main_t * tm, ip46_address_t * ip)
{
transport_endpoint_t *tep;
@@ -484,7 +520,7 @@ tcp_connection_open (ip46_address_t * rmt_addr, u16 rmt_port, u8 is_ip4)
fib_node_index_t fei;
u32 sw_if_index;
ip46_address_t lcl_addr;
u16 lcl_port;
int lcl_port;
/*
* Find the local address and allocate port
@@ -500,12 +536,19 @@ tcp_connection_open (ip46_address_t * rmt_addr, u16 rmt_port, u8 is_ip4)
/* Couldn't find route to destination. Bail out. */
if (fei == FIB_NODE_INDEX_INVALID)
return -1;
{
clib_warning ("no route to destination");
return -1;
}
sw_if_index = fib_entry_get_resolving_interface (fei);
if (sw_if_index == (u32) ~ 0)
return -1;
{
clib_warning ("no resolving interface for %U", format_ip46_address,
rmt_addr, IP46_TYPE_IP4);
return -1;
}
if (is_ip4)
{
@@ -570,11 +613,9 @@ tcp_connection_open (ip46_address_t * rmt_addr, u16 rmt_port, u8 is_ip4)
/* The other connection vars will be initialized after SYN ACK */
tcp_connection_timers_init (tc);
tcp_send_syn (tc);
tc->state = TCP_STATE_SYN_SENT;
TCP_EVT_DBG (TCP_EVT_OPEN, tc);
tc->state = TCP_STATE_SYN_SENT;
tcp_send_syn (tc);
return tc->c_c_index;
}
@@ -1206,7 +1247,7 @@ tcp_main_enable (vlib_main_t * vm)
clib_bihash_init_24_8 (&tm->local_endpoints_table, "local endpoint table",
200000 /* $$$$ config parameter nbuckets */ ,
(64 << 20) /*$$$ config parameter table size */ );
clib_spinlock_init (&tm->half_open_lock);
return error;
}
+7 -5
View File
@@ -33,6 +33,7 @@
#define TCP_DUPACK_THRESHOLD 3
#define TCP_MAX_RX_FIFO_SIZE 4 << 20
#define TCP_MIN_RX_FIFO_SIZE 4 << 10
#define TCP_IW_N_SEGMENTS 10
#define TCP_ALWAYS_ACK 1 /**< On/off delayed acks */
#define TCP_USE_SACKS 1 /**< Disable only for testing */
@@ -371,11 +372,9 @@ typedef struct _tcp_main
/* Per worker-thread timer wheel for connections timers */
tw_timer_wheel_16t_2w_512sl_t *timer_wheels;
// /* Convenience per worker-thread vector of connections to DELACK */
// u32 **delack_connections;
/* Pool of half-open connections on which we've sent a SYN */
tcp_connection_t *half_open_connections;
clib_spinlock_t half_open_lock;
/* Pool of local TCP endpoints */
transport_endpoint_t *local_endpoints;
@@ -455,6 +454,8 @@ tcp_get_connection_from_transport (transport_connection_t * tconn)
void tcp_connection_close (tcp_connection_t * tc);
void tcp_connection_cleanup (tcp_connection_t * tc);
void tcp_connection_del (tcp_connection_t * tc);
void tcp_half_open_connection_del (tcp_connection_t * tc);
tcp_connection_t *tcp_connection_new (u8 thread_index);
void tcp_connection_reset (tcp_connection_t * tc);
u8 *format_tcp_connection_id (u8 * s, va_list * args);
@@ -472,13 +473,15 @@ tcp_listener_get (u32 tli)
always_inline tcp_connection_t *
tcp_half_open_connection_get (u32 conn_index)
{
if (pool_is_free_index (tcp_main.half_open_connections, conn_index))
return 0;
return pool_elt_at_index (tcp_main.half_open_connections, conn_index);
}
void tcp_make_ack (tcp_connection_t * ts, vlib_buffer_t * b);
void tcp_make_fin (tcp_connection_t * tc, vlib_buffer_t * b);
void tcp_make_synack (tcp_connection_t * ts, vlib_buffer_t * b);
void tcp_send_reset (vlib_buffer_t * pkt, u8 is_ip4);
void tcp_send_reset (tcp_connection_t * tc, vlib_buffer_t * pkt, u8 is_ip4);
void tcp_send_syn (tcp_connection_t * tc);
void tcp_send_fin (tcp_connection_t * tc);
void tcp_init_mss (tcp_connection_t * tc);
@@ -658,7 +661,6 @@ tcp_timer_update (tcp_connection_t * tc, u8 timer_id, u32 interval)
tc->c_c_index, timer_id, interval);
}
/* XXX Switch retransmit to faster TW */
always_inline void
tcp_retransmit_timer_set (tcp_connection_t * tc)
{
+230 -106
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+31 -20
View File
@@ -75,12 +75,34 @@ tcp_window_compute_scale (u32 available_space)
}
/**
* TCP's IW as recommended by RFC6928
* Update max segment size we're able to process.
*
* The value is constrained by our interface's MTU and IP options. It is
* also what we advertise to our peer.
*/
void
tcp_update_rcv_mss (tcp_connection_t * tc)
{
/* TODO find our iface MTU */
tc->mss = dummy_mtu;
}
/**
* TCP's initial window
*/
always_inline u32
tcp_initial_wnd_unscaled (tcp_connection_t * tc)
{
return TCP_IW_N_SEGMENTS * tc->mss;
/* RFC 6928 recommends the value lower. However at the time our connections
* are initialized, fifos may not be allocated. Therefore, advertise the
* smallest possible unscaled window size and update once fifos are
* assigned to the session.
*/
/*
tcp_update_rcv_mss (tc);
TCP_IW_N_SEGMENTS * tc->mss;
*/
return TCP_MIN_RX_FIFO_SIZE;
}
/**
@@ -372,19 +394,6 @@ tcp_make_options (tcp_connection_t * tc, tcp_options_t * opts,
}
}
/**
* Update max segment size we're able to process.
*
* The value is constrained by our interface's MTU and IP options. It is
* also what we advertise to our peer.
*/
void
tcp_update_rcv_mss (tcp_connection_t * tc)
{
/* TODO find our iface MTU */
tc->mss = dummy_mtu;
}
/**
* Update snd_mss to reflect the effective segment size that we can send
* by taking into account all TCP options, including SACKs
@@ -576,6 +585,7 @@ tcp_make_synack (tcp_connection_t * tc, vlib_buffer_t * b)
/* Init retransmit timer */
tcp_retransmit_timer_set (tc);
TCP_EVT_DBG (TCP_EVT_SYNACK_SENT, tc);
}
always_inline void
@@ -684,7 +694,7 @@ tcp_make_reset_in_place (vlib_main_t * vm, vlib_buffer_t * b0,
* Send reset without reusing existing buffer
*/
void
tcp_send_reset (vlib_buffer_t * pkt, u8 is_ip4)
tcp_send_reset (tcp_connection_t * tc, vlib_buffer_t * pkt, u8 is_ip4)
{
vlib_buffer_t *b;
u32 bi;
@@ -720,7 +730,7 @@ tcp_send_reset (vlib_buffer_t * pkt, u8 is_ip4)
{
flags = TCP_FLAG_RST;
seq = pkt_th->ack_number;
ack = 0;
ack = (tc && tc->state >= TCP_STATE_SYN_RCVD) ? tc->rcv_nxt : 0;
}
else
{
@@ -754,6 +764,7 @@ tcp_send_reset (vlib_buffer_t * pkt, u8 is_ip4)
}
tcp_enqueue_to_ip_lookup (vm, b, bi, is_ip4);
TCP_EVT_DBG (TCP_EVT_RST_SENT, tc);
}
void
@@ -839,6 +850,7 @@ tcp_send_syn (tcp_connection_t * tc)
tcp_push_ip_hdr (tm, tc, b);
tcp_enqueue_to_ip_lookup (vm, b, bi, tc->c_is_ip4);
TCP_EVT_DBG (TCP_EVT_SYN_SENT, tc);
}
always_inline void
@@ -1148,12 +1160,13 @@ tcp_timer_retransmit_handler_i (u32 index, u8 is_syn)
tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);
vlib_buffer_make_headroom (b, MAX_HDRS_LEN);
tcp_push_hdr_i (tc, b, tc->state, 1);
/* Account for the SYN */
tc->snd_nxt += 1;
tc->rtt_ts = 0;
TCP_EVT_DBG (TCP_EVT_SYN_RXT, tc,
(tc->state == TCP_STATE_SYN_SENT ? 0 : 1));
}
else
{
@@ -1173,8 +1186,6 @@ tcp_timer_retransmit_handler_i (u32 index, u8 is_syn)
{
ASSERT (tc->state == TCP_STATE_SYN_SENT);
TCP_EVT_DBG (TCP_EVT_SYN_RTX, tc);
/* This goes straight to ipx_lookup */
tcp_push_ip_hdr (tm, tc, b);
tcp_enqueue_to_ip_lookup (vm, b, bi, tc->c_is_ip4);
+99
View File
@@ -1550,6 +1550,101 @@ tcp_test_fifo (vlib_main_t * vm, unformat_input_t * input)
return res;
}
static int
tcp_test_lookup (vlib_main_t * vm, unformat_input_t * input)
{
session_manager_main_t *smm = &session_manager_main;
tcp_main_t *tm = &tcp_main;
transport_connection_t _tc1, *tc1 = &_tc1, _tc2, *tc2 = &_tc2, *tconn;
tcp_connection_t *tc;
stream_session_t *s;
u8 cmp = 0;
pool_get (smm->sessions[0], s);
memset (s, 0, sizeof (*s));
s->session_index = s - smm->sessions[0];
pool_get (tm->connections[0], tc);
memset (tc, 0, sizeof (*tc));
tc->connection.c_index = tc - tm->connections[0];
tc->connection.s_index = s->session_index;
s->connection_index = tc->connection.c_index;
tc->connection.lcl_ip.ip4.as_u32 = clib_host_to_net_u32 (0x06000101);
tc->connection.rmt_ip.ip4.as_u32 = clib_host_to_net_u32 (0x06000103);
tc->connection.lcl_port = 35051;
tc->connection.rmt_port = 53764;
tc->connection.proto = 0;
clib_memcpy (tc1, &tc->connection, sizeof (*tc1));
pool_get (session_manager_main.sessions[0], s);
memset (s, 0, sizeof (*s));
s->session_index = s - smm->sessions[0];
pool_get (tm->connections[0], tc);
memset (tc, 0, sizeof (*tc));
tc->connection.c_index = tc - tm->connections[0];
tc->connection.s_index = s->session_index;
s->connection_index = tc->connection.c_index;
tc->connection.lcl_ip.ip4.as_u32 = clib_host_to_net_u32 (0x06000101);
tc->connection.rmt_ip.ip4.as_u32 = clib_host_to_net_u32 (0x06000102);
tc->connection.lcl_port = 38225;
tc->connection.rmt_port = 53764;
tc->connection.proto = 0;
clib_memcpy (tc2, &tc->connection, sizeof (*tc2));
/*
* Confirm that connection lookup works
*/
stream_session_table_add_for_tc (tc1, tc1->s_index);
tconn = stream_session_lookup_transport_wt4 (&tc1->lcl_ip.ip4,
&tc1->rmt_ip.ip4,
tc1->lcl_port, tc1->rmt_port,
tc1->proto, 0);
cmp = (memcmp (&tconn->rmt_ip, &tc1->rmt_ip, sizeof (tc1->rmt_ip)) == 0);
TCP_TEST ((cmp), "rmt ip is identical %d", cmp);
TCP_TEST ((tconn->lcl_port == tc1->lcl_port),
"rmt port is identical %d", tconn->lcl_port == tc1->lcl_port);
/*
* Non-existing connection lookup should not work
*/
tconn = stream_session_lookup_transport_wt4 (&tc2->lcl_ip.ip4,
&tc2->rmt_ip.ip4,
tc2->lcl_port, tc2->rmt_port,
tc2->proto, 0);
TCP_TEST ((tconn == 0), "lookup result should be null");
/*
* Delete and lookup again
*/
stream_session_table_del_for_tc (tc1);
tconn = stream_session_lookup_transport_wt4 (&tc1->lcl_ip.ip4,
&tc1->rmt_ip.ip4,
tc1->lcl_port, tc1->rmt_port,
tc1->proto, 0);
TCP_TEST ((tconn == 0), "lookup result should be null");
tconn = stream_session_lookup_transport_wt4 (&tc2->lcl_ip.ip4,
&tc2->rmt_ip.ip4,
tc2->lcl_port, tc2->rmt_port,
tc2->proto, 0);
TCP_TEST ((tconn == 0), "lookup result should be null");
/*
* Re-add and lookup tc2
*/
stream_session_table_add_for_tc (tc1, tc1->s_index);
tconn = stream_session_lookup_transport_wt4 (&tc2->lcl_ip.ip4,
&tc2->rmt_ip.ip4,
tc2->lcl_port, tc2->rmt_port,
tc2->proto, 0);
TCP_TEST ((tconn == 0), "lookup result should be null");
return 0;
}
static int
tcp_test_session (vlib_main_t * vm, unformat_input_t * input)
{
@@ -1632,6 +1727,10 @@ tcp_test (vlib_main_t * vm,
{
res = tcp_test_session (vm, input);
}
else if (unformat (input, "lookup"))
{
res = tcp_test_lookup (vm, input);
}
else
break;
}