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
This commit is contained in:
Dave Barach
2020-04-15 09:34:43 -04:00
committed by Florin Coras
parent 4422753b9f
commit 08eb2bb205
7 changed files with 78 additions and 1 deletions

View File

@ -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
}
}

12
extras/pg/ip6_simple.pg Normal file
View File

@ -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
}
}

View File

@ -670,6 +670,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)
{

View File

@ -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;

View File

@ -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))
;

View File

@ -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;

View File

@ -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;