)
func init() {
- RegisterVethTests(EchoBuiltinTest, EchoBuiltinBandwidthTest, EchoBuiltinEchobytesTest, EchoBuiltinRoundtripTest)
+ RegisterVethTests(EchoBuiltinTest, EchoBuiltinBandwidthTest, EchoBuiltinEchobytesTest, EchoBuiltinRoundtripTest, EchoBuiltinTestbytesTest)
RegisterSoloVethTests(TcpWithLossTest)
RegisterVeth6Tests(TcpWithLoss6Test)
}
s.AssertNotContains(o, "test echo clients: failed: timeout with 1 sessions")
}
+func EchoBuiltinTestbytesTest(s *VethsSuite) {
+ serverVpp := s.Containers.ServerVpp.VppInstance
+
+ serverVpp.Vppctl("test echo server " +
+ " uri udp://" + s.Interfaces.Server.Ip4AddressString() + "/" + s.Ports.Port1)
+
+ clientVpp := s.Containers.ClientVpp.VppInstance
+
+ // Add loss of packets with Network Delay Simulator
+ clientVpp.Vppctl("set nsim poll-main-thread delay 0.1 ms bandwidth 10 mbps packet-size 1460 packets-per-drop 125")
+ clientVpp.Vppctl("nsim output-feature enable-disable host-" + s.Interfaces.Client.Name())
+
+ o := clientVpp.Vppctl("test echo client echo-bytes test-bytes verbose bytes 32k test-timeout 1 uri" +
+ " udp://" + s.Interfaces.Server.Ip4AddressString() + "/" + s.Ports.Port1)
+ s.Log(o)
+ s.AssertNotContains(o, "failed")
+ s.AssertContains(o, " bytes out of 32768 sent (32768 target)")
+}
+
func TcpWithLossTest(s *VethsSuite) {
serverVpp := s.Containers.ServerVpp.VppInstance
send_data_chunk (ec_main_t *ecm, ec_session_t *es)
{
u8 *test_data = ecm->connect_test_data;
- int test_buf_len, test_buf_offset, rv;
+ int test_buf_len, rv;
u64 bytes_to_send;
- u32 bytes_this_chunk;
+ u32 bytes_this_chunk, test_buf_offset;
svm_fifo_t *f = es->tx_fifo;
test_buf_len = vec_len (test_data);
bytes_this_chunk = clib_min (bytes_this_chunk, max_enqueue);
if (!ecm->throughput)
bytes_this_chunk = clib_min (bytes_this_chunk, 1460);
- rv =
- app_send_dgram ((app_session_t *) es, test_data + test_buf_offset,
- bytes_this_chunk, 0);
+ if (ecm->cfg.test_bytes)
+ {
+ /* Include buffer offset info to also be able to verify
+ * out-of-order packets */
+ svm_fifo_seg_t data_segs[3] = {
+ { NULL, 0 },
+ { (u8 *) &test_buf_offset, sizeof (u32) },
+ { test_data + test_buf_offset, bytes_this_chunk }
+ };
+ rv = app_send_dgram_segs ((app_session_t *) es, data_segs, 2,
+ bytes_this_chunk + sizeof (u32), 0);
+ if (rv)
+ rv -= sizeof (u32);
+ }
+ else
+ rv = app_send_dgram ((app_session_t *) es,
+ test_data + test_buf_offset, bytes_this_chunk,
+ 0);
}
}
svm_fifo_t *rx_fifo = es->rx_fifo;
session_dgram_pre_hdr_t ph;
int n_read, i;
+ u8 *rx_buf_start = wrk->rx_buf;
+ u32 test_buf_offset = es->bytes_received;
if (ecm->cfg.test_bytes)
{
n_read =
app_recv ((app_session_t *) es, wrk->rx_buf, vec_len (wrk->rx_buf));
+ if (ecm->transport_proto != TRANSPORT_PROTO_TCP)
+ {
+ test_buf_offset = *(u32 *) wrk->rx_buf;
+ rx_buf_start = wrk->rx_buf + sizeof (u32);
+ n_read -= sizeof (u32);
+ }
}
else
{
{
for (i = 0; i < n_read; i++)
{
- if (wrk->rx_buf[i] != ((es->bytes_received + i) & 0xff))
+ if (rx_buf_start[i] != ((test_buf_offset + i) & 0xff))
{
ec_err ("read %d error at byte %lld, 0x%x not 0x%x", n_read,
- es->bytes_received + i, wrk->rx_buf[i],
- ((es->bytes_received + i) & 0xff));
+ test_buf_offset + i, rx_buf_start[i],
+ ((test_buf_offset + i) & 0xff));
ecm->test_failed = 1;
}
}
es->vpp_session_index = s->session_index;
es->bytes_paced_target = ~0;
es->bytes_paced_current = ~0;
+ if (ecm->transport_proto != TRANSPORT_PROTO_TCP && ecm->cfg.test_bytes)
+ vec_validate (es->test_send_buffer,
+ ecm->max_chunk_bytes + sizeof (int) + 1);
s->opaque = es->session_index;
vec_add1 (wrk->conn_indices, es->session_index);
ec_session_disconnect_callback (session_t *s)
{
ec_main_t *ecm = &ec_main;
+ ec_worker_t *wrk;
+ ec_session_t *es;
vnet_disconnect_args_t _a = { 0 }, *a = &_a;
+ wrk = ec_worker_get (s->thread_index);
+ es = ec_session_get (wrk, s->opaque);
+ vec_free (es->test_send_buffer);
+
if (session_handle (s) == ecm->ctrl_session_handle)
{
ec_dbg ("ctrl session disconnect");
ec_session_disconnect (session_t *s)
{
ec_main_t *ecm = &ec_main;
+ ec_worker_t *wrk;
+ ec_session_t *es;
vnet_disconnect_args_t _a = { 0 }, *a = &_a;
+
+ wrk = ec_worker_get (s->thread_index);
+ es = ec_session_get (wrk, s->opaque);
+ vec_free (es->test_send_buffer);
+
a->handle = session_handle (s);
a->app_index = ecm->app_index;
vnet_disconnect_session (a);
int rv, timed_run_conflict = 0, tput_conflict = 0, had_config = 1;
u64 total_bytes;
f64 delta;
+ ec_worker_t *wrk;
+ ec_session_t *sess;
if (ecm->test_client_attached)
return clib_error_return (0, "failed: already running!");
case ~0:
ec_cli ("Timeout at %.6f with %d sessions still active...",
vlib_time_now (ecm->vlib_main), ecm->ready_connections);
- error = clib_error_return (0, "failed: timeout with %d sessions",
- ecm->ready_connections);
+ if (ecm->transport_proto == TRANSPORT_PROTO_UDP)
+ {
+ u64 received_bytes = 0;
+ u64 sent_bytes = 0;
+ vec_foreach (wrk, ecm->wrk)
+ pool_foreach (sess, wrk->sessions)
+ {
+ received_bytes += sess->bytes_received;
+ sent_bytes += sess->bytes_sent;
+ }
+ ec_cli ("Received %llu bytes out of %llu sent (%llu target)",
+ received_bytes, sent_bytes,
+ ecm->bytes_to_send * ecm->n_clients);
+ }
+ else
+ error = clib_error_return (0, "failed: timeout with %d sessions",
+ ecm->ready_connections);
goto stop_test;
case EC_CLI_TEST_DONE:
}
static void
-es_test_bytes (es_worker_t *wrk, es_session_t *es, int actual_transfer)
+es_test_bytes (u8 *rx_buf, int actual_transfer, u32 offset)
{
int i;
for (i = 0; i < actual_transfer; i++)
{
- if (wrk->rx_buf[i] != ((es->byte_index + i) & 0xff))
+ if (rx_buf[i] != ((offset + i) & 0xff))
{
- es_err ("at %lld expected %d got %d", es->byte_index + i,
- (es->byte_index + i) & 0xff, wrk->rx_buf[i]);
+ es_err ("at %lld expected %d got %d", offset + i,
+ (offset + i) & 0xff, rx_buf[i]);
}
}
- es->byte_index += actual_transfer;
}
int
vec_validate (wrk->rx_buf, max_transfer);
actual_transfer = app_recv ((app_session_t *) es, wrk->rx_buf, max_transfer);
+ if (!actual_transfer)
+ return 0;
ASSERT (actual_transfer == max_transfer);
if (esm->cfg.test_bytes)
{
- es_test_bytes (wrk, es, actual_transfer);
+ if (esm->transport_proto == TRANSPORT_PROTO_TCP)
+ {
+ es_test_bytes (wrk->rx_buf, actual_transfer, es->byte_index);
+ es->byte_index += actual_transfer;
+ }
+ else
+ es_test_bytes ((wrk->rx_buf + sizeof (u32)),
+ actual_transfer - sizeof (u32), *(u32 *) wrk->rx_buf);
}
/*