aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/nsim
diff options
context:
space:
mode:
authorDave Barach <dave@barachs.net>2018-12-06 10:20:14 -0500
committerFlorin Coras <florin.coras@gmail.com>2018-12-06 18:28:47 +0000
commit10c5ff143a86d15e78cb1f8625eb0ab8bf72b6ce (patch)
tree00afabf7ca2ccd4042b2315b38fa6fb1bf5902c2 /src/plugins/nsim
parent995ff06fb73a2d1ac8472977cf3089d763f17d33 (diff)
nsim: add packet loss simulation, docs
Change-Id: Ic9747541aad8148ebf7d520b525b99c4cc3961f3 Signed-off-by: Dave Barach <dave@barachs.net>
Diffstat (limited to 'src/plugins/nsim')
-rw-r--r--src/plugins/nsim/node.c23
-rw-r--r--src/plugins/nsim/nsim.api3
-rw-r--r--src/plugins/nsim/nsim.c38
-rw-r--r--src/plugins/nsim/nsim.h3
-rw-r--r--src/plugins/nsim/nsim_input.c13
-rw-r--r--src/plugins/nsim/nsim_test.c7
6 files changed, 79 insertions, 8 deletions
diff --git a/src/plugins/nsim/node.c b/src/plugins/nsim/node.c
index d6413778bf3..25112abe299 100644
--- a/src/plugins/nsim/node.c
+++ b/src/plugins/nsim/node.c
@@ -25,6 +25,7 @@ typedef struct
f64 expires;
u32 tx_sw_if_index;
int is_drop;
+ int is_lost;
} nsim_trace_t;
#ifndef CLIB_MARCH_VARIANT
@@ -38,7 +39,8 @@ format_nsim_trace (u8 * s, va_list * args)
nsim_trace_t *t = va_arg (*args, nsim_trace_t *);
if (t->is_drop)
- s = format (s, "NSIM: ring drop");
+ s = format (s, "NSIM: dropped, %s", t->is_lost ?
+ "simulated network loss" : "no space in ring");
else
s = format (s, "NSIM: tx time %.6f sw_if_index %d",
t->expires, t->tx_sw_if_index);
@@ -51,7 +53,8 @@ vlib_node_registration_t nsim_node;
#define foreach_nsim_error \
_(BUFFERED, "Packets buffered") \
-_(DROPPED, "Packets dropped due to lack of space")
+_(DROPPED, "Packets dropped due to lack of space") \
+_(LOSS, "Network loss simulation drop packets")
typedef enum
{
@@ -90,6 +93,7 @@ nsim_inline (vlib_main_t * vm,
int is_drop0;
u32 no_error = node->errors[NSIM_ERROR_BUFFERED];
u32 no_buffer_error = node->errors[NSIM_ERROR_DROPPED];
+ u32 loss_error = node->errors[NSIM_ERROR_LOSS];
nsim_wheel_entry_t *ep = 0;
ASSERT (wp);
@@ -109,6 +113,19 @@ nsim_inline (vlib_main_t * vm,
is_drop0 = 0;
if (PREDICT_TRUE (wp->cursize < wp->wheel_size))
{
+ if (PREDICT_FALSE (nsm->drop_fraction != 0.0))
+ {
+ /* Get a random number on the closed interval [0,1] */
+ f64 rnd = random_f64 (&nsm->seed);
+ /* Drop the pkt? */
+ if (rnd <= nsm->drop_fraction)
+ {
+ b[0]->error = loss_error;
+ is_drop0 = 1;
+ goto do_trace;
+ }
+ }
+
ep = wp->entries + wp->tail;
wp->tail++;
if (wp->tail == wp->wheel_size)
@@ -130,6 +147,7 @@ nsim_inline (vlib_main_t * vm,
is_drop0 = 1;
}
+ do_trace:
if (is_trace)
{
if (b[0]->flags & VLIB_BUFFER_IS_TRACED)
@@ -137,6 +155,7 @@ nsim_inline (vlib_main_t * vm,
nsim_trace_t *t = vlib_add_trace (vm, node, b[0], sizeof (*t));
t->expires = expires;
t->is_drop = is_drop0;
+ t->is_lost = b[0]->error == loss_error;
t->tx_sw_if_index = (is_drop0 == 0) ? ep->tx_sw_if_index : 0;
}
}
diff --git a/src/plugins/nsim/nsim.api b/src/plugins/nsim/nsim.api
index 89174268aee..7bb84bafacd 100644
--- a/src/plugins/nsim/nsim.api
+++ b/src/plugins/nsim/nsim.api
@@ -3,7 +3,7 @@
* @brief VPP control-plane API messages for the network delay simulator
*/
-option version = "1.0.0";
+option version = "1.1.0";
/** \brief enable / disable the network delay simulation cross-connect
@param client_index - opaque cookie to identify the sender
@@ -47,4 +47,5 @@ autoreply define nsim_configure
u32 delay_in_usec;
u32 average_packet_size;
u64 bandwidth_in_bits_per_second;
+ u32 packets_per_drop;
};
diff --git a/src/plugins/nsim/nsim.c b/src/plugins/nsim/nsim.c
index ec79070b2e7..ce3396c5845 100644
--- a/src/plugins/nsim/nsim.c
+++ b/src/plugins/nsim/nsim.c
@@ -118,7 +118,8 @@ nsim_enable_disable (nsim_main_t * nsm, u32 sw_if_index0,
}
static int
-nsim_configure (nsim_main_t * nsm, f64 bandwidth, f64 delay, f64 packet_size)
+nsim_configure (nsim_main_t * nsm, f64 bandwidth, f64 delay, f64 packet_size,
+ f64 drop_fraction)
{
u64 total_buffer_size_in_bytes, per_worker_buffer_size;
u64 wheel_slots_per_worker;
@@ -148,6 +149,7 @@ nsim_configure (nsim_main_t * nsm, f64 bandwidth, f64 delay, f64 packet_size)
}
nsm->delay = delay;
+ nsm->drop_fraction = drop_fraction;
/* delay in seconds, bandwidth in bits/sec */
total_buffer_size_in_bytes = (u32) ((delay * bandwidth) / 8.0) + 0.5;
@@ -318,14 +320,21 @@ vl_api_nsim_configure_t_handler (vl_api_nsim_configure_t * mp)
{
vl_api_nsim_configure_reply_t *rmp;
nsim_main_t *nsm = &nsim_main;
- f64 delay, bandwidth, packet_size;
+ f64 delay, bandwidth, packet_size, drop_fraction;
+ u32 packets_per_drop;
int rv;
delay = ((f64) (ntohl (mp->delay_in_usec))) * 1e-6;
bandwidth = (f64) (clib_net_to_host_u64 (mp->bandwidth_in_bits_per_second));
packet_size = (f64) (ntohl (mp->average_packet_size));
- rv = nsim_configure (nsm, bandwidth, delay, packet_size);
+ packets_per_drop = ntohl (mp->packets_per_drop);
+ if (packets_per_drop > 0)
+ drop_fraction = 1.0 / (f64) (packets_per_drop);
+ else
+ drop_fraction = 0.0;
+
+ rv = nsim_configure (nsm, bandwidth, delay, packet_size, drop_fraction);
REPLY_MACRO (VL_API_NSIM_CONFIGURE_REPLY);
}
@@ -447,6 +456,8 @@ set_nsim_command_fn (vlib_main_t * vm,
nsim_main_t *nsm = &nsim_main;
f64 delay, bandwidth;
f64 packet_size = 1500.0;
+ f64 drop_fraction = 0.0;
+ u32 packets_per_drop;
u32 num_workers = vlib_num_workers ();
int rv;
@@ -459,11 +470,22 @@ set_nsim_command_fn (vlib_main_t * vm,
;
else if (unformat (input, "packet-size %f", &packet_size))
;
+ else if (unformat (input, "packets-per-drop %d", &packets_per_drop))
+ {
+ if (packets_per_drop > 0)
+ drop_fraction = 1.0 / ((f64) packets_per_drop);
+ }
+ else if (unformat (input, "drop-fraction %f", &drop_fraction))
+ {
+ if (drop_fraction < 0.0 || drop_fraction > 1.0)
+ return clib_error_return
+ (0, "drop fraction must be between zero and 1");
+ }
else
break;
}
- rv = nsim_configure (nsm, bandwidth, delay, packet_size);
+ rv = nsim_configure (nsm, bandwidth, delay, packet_size, drop_fraction);
switch (rv)
{
@@ -485,6 +507,10 @@ set_nsim_command_fn (vlib_main_t * vm,
vlib_cli_output (vm, "Configured link delay %.2f ms, %.2f ms round-trip",
nsm->delay * 1e3, 2.0 * nsm->delay * 1e3);
+ if (nsm->drop_fraction > 0.0)
+ vlib_cli_output (vm, "... simulating a network drop fraction of %.5f",
+ nsm->drop_fraction);
+
if (num_workers)
vlib_cli_output (vm, "Sim uses %llu bytes per thread, %llu bytes total",
@@ -548,6 +574,10 @@ show_nsim_command_fn (vlib_main_t * vm,
"...inserting link delay of %.2f ms, %.2f ms round-trip",
nsm->delay * 1e3, 2.0 * nsm->delay * 1e3);
+ if (nsm->drop_fraction > 0.0)
+ vlib_cli_output (vm, "... simulating a network drop fraction of %.5f",
+ nsm->drop_fraction);
+
if (verbose)
{
diff --git a/src/plugins/nsim/nsim.h b/src/plugins/nsim/nsim.h
index d0b5ed32fee..c5264ecb244 100644
--- a/src/plugins/nsim/nsim.h
+++ b/src/plugins/nsim/nsim.h
@@ -54,6 +54,8 @@ typedef struct
/* Two interfaces, cross-connected with delay */
u32 sw_if_index0, sw_if_index1;
u32 output_next_index0, output_next_index1;
+ /* Random seed for loss-rate simulation */
+ u32 seed;
/* Per-thread buffer / scheduler wheels */
nsim_wheel_t **wheel_by_thread;
@@ -63,6 +65,7 @@ typedef struct
f64 delay;
f64 bandwidth;
f64 packet_size;
+ f64 drop_fraction;
u64 mmap_size;
diff --git a/src/plugins/nsim/nsim_input.c b/src/plugins/nsim/nsim_input.c
index 66bd8d10954..2e328a58bf3 100644
--- a/src/plugins/nsim/nsim_input.c
+++ b/src/plugins/nsim/nsim_input.c
@@ -76,6 +76,7 @@ nsim_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
u32 my_thread_index = vm->thread_index;
u32 *my_buffer_cache = nsm->buffer_indices_by_thread[my_thread_index];
nsim_wheel_t *wp = nsm->wheel_by_thread[my_thread_index];
+ u32 n_trace = vlib_get_trace_count (vm, node);
f64 now = vlib_time_now (vm);
uword n_rx_packets = 0;
vlib_buffer_t *b0;
@@ -153,6 +154,18 @@ nsim_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
b0->current_data = 0;
b0->current_length = ep->current_length;
+ VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
+
+ if (PREDICT_FALSE (n_trace))
+ {
+ nsim_tx_trace_t *t0;
+ vlib_trace_buffer (vm, node, next_index, b0,
+ 0 /* follow_chain */ );
+ t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
+ t0->expired = ep->tx_time;
+ t0->tx_sw_if_index = ep->tx_sw_if_index;
+ }
+
/* Copy data from the ring */
clib_memcpy_fast (b0->data, ep->data, ep->current_length);
b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
diff --git a/src/plugins/nsim/nsim_test.c b/src/plugins/nsim/nsim_test.c
index 0e2a26af55b..7123703fd42 100644
--- a/src/plugins/nsim/nsim_test.c
+++ b/src/plugins/nsim/nsim_test.c
@@ -182,6 +182,7 @@ api_nsim_configure (vat_main_t * vam)
f64 delay = 0.0, bandwidth = 0.0;
f64 packet_size = 1500.0;
u32 num_workers = vlib_num_workers ();
+ u32 packets_per_drop = 0;
int ret;
while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
@@ -192,6 +193,8 @@ api_nsim_configure (vat_main_t * vam)
;
else if (unformat (i, "packet-size %f", &packet_size))
;
+ else if (unformat (i, "packets-per-drop %u", &packets_per_drop))
+ ;
else
break;
}
@@ -211,6 +214,7 @@ api_nsim_configure (vat_main_t * vam)
mp->bandwidth_in_bits_per_second = (u64) (bandwidth);
mp->bandwidth_in_bits_per_second =
clib_host_to_net_u64 (mp->bandwidth_in_bits_per_second);
+ mp->packets_per_drop = ntohl (packets_per_drop);
/* send it... */
S (mp);
@@ -227,7 +231,8 @@ api_nsim_configure (vat_main_t * vam)
#define foreach_vpe_api_msg \
_(nsim_enable_disable, \
"[<intfc0> | sw_if_index <swif0>] [<intfc1> | sw_if_index <swif1>] [disable]") \
-_(nsim_configure, "delay <time> bandwidth <bw> [packet-size <nn>]")
+_(nsim_configure, "delay <time> bandwidth <bw> [packet-size <nn>]" \
+"[packets-per-drop <nnnn>]")
static void
nsim_api_hookup (vat_main_t * vam)