Debug CLI to magically create / delete a TCP session
The session ends up in established state, and is hand-crafted to look
like it was created by the builtin_server.
This will come in handy for injecting packets into tcp46-established,
along with ancillary debug CLI to adjust connection parameters.
Immediate applications include screwball window cases, out of order
segments, paws checking, and so on and so forth.
Debug CLI script:
loop create
set int ip address loop0 6.0.1.1/8
set int state loop0 up
set ip arp loop0 6.0.1.2 feed.face.babe
test tcp server
test tcp session
packet-generator new {
name tcp
limit 1
node ip4-input
size 100-100
interface loop0
no-recycle
data {
TCP: 6.0.1.2 -> 6.0.1.1
TCP: 11234 -> 1234
ACK window 2000
seqnum 0
acknum 0
incrementing 100
}
}
Change-Id: I866c2159376064b7d14f70531022c1fe949258c2
Signed-off-by: Dave Barach <dave@barachs.net>
diff --git a/src/vnet/tcp/tcp_test.c b/src/vnet/tcp/tcp_test.c
index 0146154..d65ce1b 100644
--- a/src/vnet/tcp/tcp_test.c
+++ b/src/vnet/tcp/tcp_test.c
@@ -895,6 +895,68 @@
return res;
}
+static int
+tcp_test_session (vlib_main_t * vm, unformat_input_t * input)
+{
+ int rv = 0;
+ tcp_connection_t *tc0;
+ u8 sst = SESSION_TYPE_IP4_TCP;
+ ip4_address_t local, remote;
+ u16 local_port, remote_port;
+ tcp_main_t *tm = vnet_get_tcp_main ();
+ int is_add = 1;
+
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "del"))
+ is_add = 0;
+ else if (unformat (input, "add"))
+ is_add = 1;
+ else
+ break;
+ }
+
+ if (is_add)
+ {
+ local.as_u32 = clib_host_to_net_u32 (0x06000101);
+ remote.as_u32 = clib_host_to_net_u32 (0x06000102);
+ local_port = clib_host_to_net_u16 (1234);
+ remote_port = clib_host_to_net_u16 (11234);
+
+ pool_get (tm->connections[0], tc0);
+ memset (tc0, 0, sizeof (*tc0));
+
+ tc0->state = TCP_STATE_ESTABLISHED;
+ tc0->rcv_las = 1;
+ tc0->c_c_index = tc0 - tm->connections[0];
+ tc0->c_lcl_port = local_port;
+ tc0->c_rmt_port = remote_port;
+ tc0->c_is_ip4 = 1;
+ tc0->c_thread_index = 0;
+ tc0->c_lcl_ip4.as_u32 = local.as_u32;
+ tc0->c_rmt_ip4.as_u32 = remote.as_u32;
+ tc0->opt.mss = 1450;
+ tcp_connection_init_vars (tc0);
+
+ TCP_EVT_DBG (TCP_EVT_OPEN, tc0);
+
+ if (stream_session_accept (&tc0->connection, 0 /* listener index */ ,
+ sst, 0 /* notify */ ))
+ clib_warning ("stream_session_accept failed");
+
+ stream_session_accept_notify (&tc0->connection);
+ }
+ else
+ {
+ tc0 = tcp_connection_get (0 /* connection index */ , 0 /* thread */ );
+ tc0->state = TCP_STATE_CLOSED;
+ stream_session_disconnect_notify (&tc0->connection);
+ }
+
+ return rv;
+}
+
static clib_error_t *
tcp_test (vlib_main_t * vm,
unformat_input_t * input, vlib_cli_command_t * cmd_arg)
@@ -911,11 +973,12 @@
{
res = tcp_test_fifo (vm, input);
}
- else
+ else if (unformat (input, "session"))
{
- return clib_error_return (0, "unknown input `%U'",
- format_unformat_error, input);
+ res = tcp_test_session (vm, input);
}
+ else
+ break;
}
if (res)