This patch introduced the auto-validation function which allows users to compare the batch of packets obtained from different miniflow implementations against the linear miniflow extract and return a hitmask.
The autovaidator function can be triggered at runtime using the following command: $ ovs-appctl dpif-netdev/miniflow-parser-set autovalidator Signed-off-by: Kumar Amber <[email protected]> Co-authored-by: Harry van Haaren <[email protected]> Signed-off-by: Harry van Haaren <[email protected]> --- lib/dpif-netdev-private-extract.c | 79 +++++++++++++++++++++++++++++++ lib/dpif-netdev-private-extract.h | 15 ++++++ 2 files changed, 94 insertions(+) diff --git a/lib/dpif-netdev-private-extract.c b/lib/dpif-netdev-private-extract.c index fcc56ef26..9a53d4985 100644 --- a/lib/dpif-netdev-private-extract.c +++ b/lib/dpif-netdev-private-extract.c @@ -32,6 +32,11 @@ VLOG_DEFINE_THIS_MODULE(dpif_netdev_extract); /* Implementations of available extract options. */ static struct dpif_miniflow_extract_impl mfex_impls[] = { + { + .probe = NULL, + .extract_func = dpif_miniflow_extract_autovalidator, + .name = "autovalidator", + }, { .probe = NULL, .extract_func = NULL, @@ -84,3 +89,77 @@ dpif_miniflow_extract_info_get(struct dpif_miniflow_extract_impl **out_ptr) *out_ptr = mfex_impls; return ARRAY_SIZE(mfex_impls); } + +uint32_t +dpif_miniflow_extract_autovalidator(struct dp_packet_batch *packets, + struct netdev_flow_key *keys, + uint32_t keys_size, odp_port_t in_port, + void *pmd_handle) +{ + const size_t cnt = dp_packet_batch_size(packets); + uint16_t good_l2_5_ofs[cnt]; + uint16_t good_l3_ofs[cnt]; + uint16_t good_l4_ofs[cnt]; + uint16_t good_l2_pad_size[cnt]; + struct dp_packet *packet; + struct dp_netdev_pmd_thread *pmd = pmd_handle; + struct dpif_miniflow_extract_impl *miniflow_funcs; + + int32_t mfunc_count = dpif_miniflow_extract_info_get(&miniflow_funcs); + if (mfunc_count < 0) { + pmd->miniflow_extract_opt = NULL; + VLOG_ERR("failed to get miniflow extract function implementations\n"); + return 0; + } + ovs_assert(keys_size >= cnt); + struct netdev_flow_key test_keys[keys_size]; + + /* Run scalar miniflow_extract to get default result. */ + DP_PACKET_BATCH_FOR_EACH (i, packet, packets) { + pkt_metadata_init(&packet->md, in_port); + miniflow_extract(packet, &keys[i].mf); + /* Store good offsets for comparisons with optimized offsets. */ + good_l2_5_ofs[i] = packet->l2_5_ofs; + good_l3_ofs[i] = packet->l3_ofs; + good_l4_ofs[i] = packet->l4_ofs; + good_l2_pad_size[i] = packet->l2_pad_size; + } + + /* Iterate through each version of miniflow implementations. */ + for (int j = MFEX_IMPL_START_IDX; j < mfunc_count; j++) { + if (!mfex_impls[j].available) { + continue; + } + memset(test_keys, 0, keys_size * sizeof(struct netdev_flow_key)); + /* Call optimized miniflow for each batch of packet. */ + uint32_t hit_mask = mfex_impls[j].extract_func(packets, test_keys, + keys_size, in_port, pmd_handle); + + /* Do a miniflow compare for bits, blocks and offsets for all the + * classified packets in the hitmask marked by set bits. */ + while (hit_mask) { + /* Index for the set bit. */ + uint32_t i = __builtin_ctz(hit_mask); + /* Set the index in hitmask to Zero. */ + hit_mask &= (hit_mask - 1); + if (!miniflow_equal(&keys[i].mf, &test_keys[i].mf) || + (packets->packets[i]->l2_5_ofs != good_l2_5_ofs[i]) || + (packets->packets[i]->l3_ofs != good_l3_ofs[i]) || + (packets->packets[i]->l4_ofs != good_l4_ofs[i]) || + (packets->packets[i]->l2_pad_size != good_l2_pad_size[i])) { + + uint32_t block_size = netdev_flow_key_size( + miniflow_n_values(&keys[i].mf)); + VLOG_ERR("Autovalidation fails for mfex implementation %s" + " hitmask 0x%x index: %d\n", mfex_impls[j].name, + hit_mask, i); + VLOG_ERR("Good scalar Miniflow data hexdump : \n"); + ovs_hex_dump(stdout, &keys[i].mf, block_size, 0, true); + VLOG_ERR("Vector bad Miniflow data hexdump : \n"); + ovs_hex_dump(stdout, &test_keys[i].mf, block_size, 0, true); + } + } + } + /* Always return full hitmask as scalar mfex will always work. */ + return (1ULL << cnt) - 1; +} diff --git a/lib/dpif-netdev-private-extract.h b/lib/dpif-netdev-private-extract.h index b7b0b2be4..455a7b590 100644 --- a/lib/dpif-netdev-private-extract.h +++ b/lib/dpif-netdev-private-extract.h @@ -24,6 +24,11 @@ /* Max size of dpif_miniflow_extract_impl array. */ #define MFEX_IMPLS_MAX_SIZE (16) +/* Skip the autovalidator study and null when iterating all available + * miniflow implementations. + */ +#define MFEX_IMPL_START_IDX (1) + /* Forward declarations. */ struct dp_packet; struct miniflow; @@ -90,5 +95,15 @@ dpif_miniflow_extract_init(void); int32_t dpif_miniflow_extract_info_get(struct dpif_miniflow_extract_impl **out_ptr); +/* Retrieve the hitmask of the batch of pakcets which is obtained by comparing + * different miniflow implementations with linear miniflow extract. + * On error, returns a zero. + * On success, returns the number of packets in the batch compared. + */ +uint32_t +dpif_miniflow_extract_autovalidator(struct dp_packet_batch *batch, + struct netdev_flow_key *keys, + uint32_t keys_size, odp_port_t in_port, + void *pmd_handle); #endif /* DPIF_NETDEV_AVX512_EXTRACT */ -- 2.25.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
