aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Barach <dave@barachs.net>2020-04-15 09:34:43 -0400
committerFlorin Coras <florin.coras@gmail.com>2020-04-15 19:19:29 +0000
commit08eb2bb205f998a75dacd1f3b999ec1a10160b35 (patch)
treec5d83c0db16472322720ba17c626cb74aae635e6
parent4422753b9f7edf7ff391f97a10c1b8a7dbd7dafb (diff)
pg: set vnet buffer flags in pg streams
See .../extras/pg/checksum_offload.pg for a nontrivial example, which deliberately sets bogus ip and udp checksums in the generated packets, then fixes the mess with (software emulated) hardware checksum offload. Validated via "pcap dispatch trace on max 1000 buffer-trace pg-input 100". Packets stuffed into loop1-output have the configured bogus ip and udp checksums. vnet_calc_checksums_inline(...) fixes the checksums, which are correct when packets visit loop1-tx. The packet generator is a dumb robot in this regard. If you ask for a ridiculous flag combination - example: ip4 and ip6 - your mileage may vary. Type: feature Signed-off-by: Dave Barach <dave@barachs.net> Change-Id: I6d9e790f373bcd9e445a89113ca8e4c8f9aa9419
-rw-r--r--extras/pg/checksum_offload.pg26
-rw-r--r--extras/pg/ip6_simple.pg12
-rw-r--r--src/vnet/interface_format.c28
-rw-r--r--src/vnet/interface_funcs.h1
-rw-r--r--src/vnet/pg/cli.c4
-rw-r--r--src/vnet/pg/input.c5
-rw-r--r--src/vnet/pg/pg.h3
7 files changed, 78 insertions, 1 deletions
diff --git a/extras/pg/checksum_offload.pg b/extras/pg/checksum_offload.pg
new file mode 100644
index 00000000000..a2e3205a21e
--- /dev/null
+++ b/extras/pg/checksum_offload.pg
@@ -0,0 +1,26 @@
+set term pag off
+loop cre
+set int ip address loop0 11.22.33.1/24
+set int state loop0 up
+loop cre
+set int ip address loop1 11.22.34.1/24
+set int state loop1 up
+
+set ip neighbor loop1 11.22.34.44 03:00:11:22:34:44
+
+packet-generator new {
+ name s0
+ limit 10000
+ size 128-128
+ interface loop0
+ tx-interface loop1
+ node loop1-output
+ buffer-flags ip4 offload-ip-cksum offload-udp-cksum
+ data { IP4: 1.2.3 -> 4.5.6
+ UDP: 11.22.33.44 -> 11.22.34.44
+ ttl 2 checksum 13
+ UDP: 1234 -> 2345
+ checksum 11
+ incrementing 114
+ }
+}
diff --git a/extras/pg/ip6_simple.pg b/extras/pg/ip6_simple.pg
new file mode 100644
index 00000000000..023bde6837f
--- /dev/null
+++ b/extras/pg/ip6_simple.pg
@@ -0,0 +1,12 @@
+
+packet-generator new {
+ name x
+ limit 5
+ size 128-128
+ interface local0
+ node ip6-lookup
+ data {
+ ICMP: db00::1 -> db00::2
+ incrementing 30
+ }
+}
diff --git a/src/vnet/interface_format.c b/src/vnet/interface_format.c
index 507e2676ccb..8278102c644 100644
--- a/src/vnet/interface_format.c
+++ b/src/vnet/interface_format.c
@@ -671,6 +671,34 @@ vnet_register_format_buffer_opaque2_helper (vnet_buffer_opquae_formatter_t fp)
uword
+unformat_vnet_buffer_flags (unformat_input_t * input, va_list * args)
+{
+ u32 *flagp = va_arg (*args, u32 *);
+ int rv = 0;
+ u32 flags = 0;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ /* Red herring, there is no such buffer flag */
+ if (unformat (input, "avail8"))
+ return 0;
+#define _(bit,enum,str,verbose) \
+ else if (unformat (input, str)) \
+ { \
+ flags |= (1 << LOG2_VLIB_BUFFER_FLAG_USER(bit)); \
+ rv = 1; \
+ }
+ foreach_vnet_buffer_flag
+#undef _
+ else
+ break;
+ }
+ if (rv)
+ *flagp = flags;
+ return rv;
+}
+
+uword
unformat_vnet_hw_interface (unformat_input_t * input, va_list * args)
{
vnet_main_t *vnm = va_arg (*args, vnet_main_t *);
diff --git a/src/vnet/interface_funcs.h b/src/vnet/interface_funcs.h
index f5c66d447de..7d9c098b118 100644
--- a/src/vnet/interface_funcs.h
+++ b/src/vnet/interface_funcs.h
@@ -444,6 +444,7 @@ format_function_t format_vnet_sw_interface_flags;
/* Parses sw/hw interface name -> index. */
unformat_function_t unformat_vnet_sw_interface;
unformat_function_t unformat_vnet_hw_interface;
+unformat_function_t unformat_vnet_buffer_flags;
/* Parses interface flags (up, down, enable, disable, etc.) */
unformat_function_t unformat_vnet_hw_interface_flags;
diff --git a/src/vnet/pg/cli.c b/src/vnet/pg/cli.c
index 9336ca406d7..b3aaddfda2b 100644
--- a/src/vnet/pg/cli.c
+++ b/src/vnet/pg/cli.c
@@ -376,6 +376,10 @@ new_stream (vlib_main_t * vm,
else if (unformat (input, "source pg%u", &s.if_id))
;
+ else if (unformat (input, "buffer-flags %U",
+ unformat_vnet_buffer_flags, &s.buffer_flags))
+ ;
+
else if (unformat (input, "node %U",
unformat_vlib_node, vm, &s.node_index))
;
diff --git a/src/vnet/pg/input.c b/src/vnet/pg/input.c
index bbcd34e763a..8ba3b361894 100644
--- a/src/vnet/pg/input.c
+++ b/src/vnet/pg/input.c
@@ -1106,6 +1106,8 @@ init_buffers_inline (vlib_main_t * vm,
b0 = vlib_get_buffer (vm, bi0);
b1 = vlib_get_buffer (vm, bi1);
+ b0->flags |= s->buffer_flags;
+ b1->flags |= s->buffer_flags;
vnet_buffer (b0)->sw_if_index[VLIB_RX] =
vnet_buffer (b1)->sw_if_index[VLIB_RX] = s->sw_if_index[VLIB_RX];
@@ -1135,6 +1137,7 @@ init_buffers_inline (vlib_main_t * vm,
n_left -= 1;
b0 = vlib_get_buffer (vm, bi0);
+ b0->flags |= s->buffer_flags;
vnet_buffer (b0)->sw_if_index[VLIB_RX] = s->sw_if_index[VLIB_RX];
vnet_buffer (b0)->sw_if_index[VLIB_TX] = s->sw_if_index[VLIB_TX];
@@ -1269,7 +1272,7 @@ pg_stream_fill_replay (pg_main_t * pg, pg_stream_t * s, u32 n_alloc)
clib_memcpy_fast (b->data, d0 + data_offset, bytes_this_chunk);
vnet_buffer (b)->sw_if_index[VLIB_RX] = s->sw_if_index[VLIB_RX];
vnet_buffer (b)->sw_if_index[VLIB_TX] = s->sw_if_index[VLIB_TX];
- b->flags = 0;
+ b->flags = s->buffer_flags;
b->next_buffer = 0;
b->current_data = 0;
b->current_length = bytes_this_chunk;
diff --git a/src/vnet/pg/pg.h b/src/vnet/pg/pg.h
index 55bc75dc282..a6616d9ced7 100644
--- a/src/vnet/pg/pg.h
+++ b/src/vnet/pg/pg.h
@@ -123,6 +123,9 @@ typedef struct pg_stream_t
for max_packet_bytes. */
u32 buffer_bytes;
+ /* Buffer flags to set in each packet e.g. checksum offload flags */
+ u32 buffer_flags;
+
/* Last packet length if packet size edit type is increment. */
u32 last_increment_packet_size;