Signed-off-by: Dumitru Ceara <dce...@redhat.com> --- controller/test-lflow-cache.c | 224 +++++++++++++++++++++++++++++++++++ controller/test-ofctrl-seqno.c | 18 --- tests/automake.mk | 8 + tests/ovn-lflow-cache.at | 257 ++++++++++++++++++++++++++++++++++++++++ tests/ovn.at | 68 +++++++++++ tests/test-utils.c | 49 ++++++++ tests/test-utils.h | 26 ++++ tests/testsuite.at | 1 8 files changed, 633 insertions(+), 18 deletions(-) create mode 100644 controller/test-lflow-cache.c create mode 100644 tests/ovn-lflow-cache.at create mode 100644 tests/test-utils.c create mode 100644 tests/test-utils.h
diff --git a/controller/test-lflow-cache.c b/controller/test-lflow-cache.c new file mode 100644 index 0000000..d6e962e --- /dev/null +++ b/controller/test-lflow-cache.c @@ -0,0 +1,224 @@ +/* Copyright (c) 2021, Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <config.h> + +#include "ovn/expr.h" +#include "ovn-sb-idl.h" +#include "tests/ovstest.h" +#include "tests/test-utils.h" +#include "util.h" + +#include "lflow-cache.h" + +static void +test_lflow_cache_add__(struct lflow_cache *lc, const char *op_type, + const struct sbrec_logical_flow *lflow, + unsigned int conj_id_ofs, + struct expr *e) +{ + printf("ADD %s:\n", op_type); + printf(" conj-id-ofs: %u\n", conj_id_ofs); + + if (!strcmp(op_type, "conj-id")) { + lflow_cache_add_conj_id(lc, lflow, conj_id_ofs); + } else if (!strcmp(op_type, "expr")) { + lflow_cache_add_expr(lc, lflow, conj_id_ofs, expr_clone(e)); + } else if (!strcmp(op_type, "matches")) { + struct hmap *matches = xmalloc(sizeof *matches); + ovs_assert(expr_to_matches(e, NULL, NULL, matches) == 0); + ovs_assert(hmap_count(matches) == 1); + lflow_cache_add_matches(lc, lflow, matches); + } else { + OVS_NOT_REACHED(); + } +} + +static void +test_lflow_cache_lookup__(struct lflow_cache *lc, + const struct sbrec_logical_flow *lflow) +{ + struct lflow_cache_value *lcv = lflow_cache_get(lc, lflow); + + printf("LOOKUP:\n"); + if (!lcv) { + printf(" not found\n"); + return; + } + + printf(" conj_id_ofs: %"PRIu32"\n", lcv->conj_id_ofs); + switch (lcv->type) { + case LCACHE_T_CONJ_ID: + printf(" type: conj-id\n"); + break; + case LCACHE_T_EXPR: + printf(" type: expr\n"); + break; + case LCACHE_T_MATCHES: + printf(" type: matches\n"); + break; + case LCACHE_T_NONE: + OVS_NOT_REACHED(); + break; + } +} + +static void +test_lflow_cache_delete__(struct lflow_cache *lc, + const struct sbrec_logical_flow *lflow) +{ + printf("DELETE\n"); + lflow_cache_delete(lc, lflow); +} + +static void +test_lflow_cache_stats__(struct lflow_cache *lc) +{ + struct lflow_cache_stats *lcs = lflow_cache_get_stats(lc); + + if (!lcs) { + return; + } + printf("Enabled: %s\n", lflow_cache_is_enabled(lc) ? "true" : "false"); + for (size_t i = 0; i < LCACHE_T_MAX; i++) { + printf(" %s: %"PRIuSIZE"\n", lflow_cache_type_names[i], + lcs->n_entries[i]); + } + free(lcs); +} + +static void +test_lflow_cache_operations(struct ovs_cmdl_context *ctx) +{ + struct lflow_cache *lc = lflow_cache_create(); + struct expr *e = expr_create_boolean(true); + bool enabled = !strcmp(ctx->argv[1], "true"); + unsigned int shift = 2; + unsigned int n_ops; + + lflow_cache_enable(lc, enabled); + test_lflow_cache_stats__(lc); + + if (!test_read_uint_value(ctx, shift++, "n_ops", &n_ops)) { + goto done; + } + + for (unsigned int i = 0; i < n_ops; i++) { + const char *op = test_read_value(ctx, shift++, "op"); + + if (!op) { + goto done; + } + + struct sbrec_logical_flow lflow; + uuid_generate(&lflow.header_.uuid); + + if (!strcmp(op, "add")) { + const char *op_type = test_read_value(ctx, shift++, "op_type"); + if (!op_type) { + goto done; + } + + unsigned int conj_id_ofs; + if (!test_read_uint_value(ctx, shift++, "conj-id-ofs", + &conj_id_ofs)) { + goto done; + } + + test_lflow_cache_add__(lc, op_type, &lflow, conj_id_ofs, e); + test_lflow_cache_lookup__(lc, &lflow); + } else if (!strcmp(op, "add-del")) { + const char *op_type = test_read_value(ctx, shift++, "op_type"); + if (!op_type) { + goto done; + } + + unsigned int conj_id_ofs; + if (!test_read_uint_value(ctx, shift++, "conj-id-ofs", + &conj_id_ofs)) { + goto done; + } + + test_lflow_cache_add__(lc, op_type, &lflow, conj_id_ofs, e); + test_lflow_cache_lookup__(lc, &lflow); + test_lflow_cache_delete__(lc, &lflow); + test_lflow_cache_lookup__(lc, &lflow); + } else if (!strcmp(op, "enable")) { + printf("ENABLE\n"); + lflow_cache_enable(lc, true); + } else if (!strcmp(op, "disable")) { + printf("DISABLE\n"); + lflow_cache_enable(lc, false); + } else if (!strcmp(op, "flush")) { + printf("FLUSH\n"); + lflow_cache_flush(lc); + } else { + OVS_NOT_REACHED(); + } + test_lflow_cache_stats__(lc); + } +done: + lflow_cache_destroy(lc); + expr_destroy(e); +} + +static void +test_lflow_cache_negative(struct ovs_cmdl_context *ctx OVS_UNUSED) +{ + lflow_cache_flush(NULL); + lflow_cache_destroy(NULL); + lflow_cache_enable(NULL, true); + ovs_assert(!lflow_cache_is_enabled(NULL)); + ovs_assert(!lflow_cache_get_stats(NULL)); + + struct lflow_cache *lcs[] = { + NULL, + lflow_cache_create(), + }; + + for (size_t i = 0; i < ARRAY_SIZE(lcs); i++) { + struct expr *e = expr_create_boolean(true); + struct hmap *matches = xmalloc(sizeof *matches); + + ovs_assert(expr_to_matches(e, NULL, NULL, matches) == 0); + ovs_assert(hmap_count(matches) == 1); + + lflow_cache_add_conj_id(lcs[i], NULL, 0); + lflow_cache_add_expr(lcs[i], NULL, 0, NULL); + lflow_cache_add_expr(lcs[i], NULL, 0, e); + lflow_cache_add_matches(lcs[i], NULL, NULL); + lflow_cache_add_matches(lcs[i], NULL, matches); + lflow_cache_destroy(lcs[i]); + } +} + +static void +test_lflow_cache_main(int argc, char *argv[]) +{ + set_program_name(argv[0]); + static const struct ovs_cmdl_command commands[] = { + {"lflow_cache_operations", NULL, 3, INT_MAX, + test_lflow_cache_operations, OVS_RO}, + {"lflow_cache_negative", NULL, 0, 0, + test_lflow_cache_negative, OVS_RO}, + {NULL, NULL, 0, 0, NULL, OVS_RO}, + }; + struct ovs_cmdl_context ctx; + ctx.argc = argc - 1; + ctx.argv = argv + 1; + ovs_cmdl_run_command(&ctx, commands); +} + +OVSTEST_REGISTER("test-lflow-cache", test_lflow_cache_main); diff --git a/controller/test-ofctrl-seqno.c b/controller/test-ofctrl-seqno.c index fce88d4..b96da9d 100644 --- a/controller/test-ofctrl-seqno.c +++ b/controller/test-ofctrl-seqno.c @@ -16,6 +16,7 @@ #include <config.h> #include "tests/ovstest.h" +#include "tests/test-utils.h" #include "sort.h" #include "util.h" @@ -27,23 +28,6 @@ test_init(void) ofctrl_seqno_init(); } -static bool -test_read_uint_value(struct ovs_cmdl_context *ctx, unsigned int index, - const char *descr, unsigned int *result) -{ - if (index >= ctx->argc) { - fprintf(stderr, "Missing %s argument\n", descr); - return false; - } - - const char *arg = ctx->argv[index]; - if (!str_to_uint(arg, 10, result)) { - fprintf(stderr, "Invalid %s: %s\n", descr, arg); - return false; - } - return true; -} - static int test_seqno_compare(size_t a, size_t b, void *values_) { diff --git a/tests/automake.mk b/tests/automake.mk index 282d1b1..df6d0a2 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -33,7 +33,8 @@ TESTSUITE_AT = \ tests/ovn-macros.at \ tests/ovn-performance.at \ tests/ovn-ofctrl-seqno.at \ - tests/ovn-ipam.at + tests/ovn-ipam.at \ + tests/ovn-lflow-cache.at SYSTEM_KMOD_TESTSUITE_AT = \ tests/system-common-macros.at \ @@ -207,8 +208,13 @@ noinst_PROGRAMS += tests/ovstest tests_ovstest_SOURCES = \ tests/ovstest.c \ tests/ovstest.h \ + tests/test-utils.c \ + tests/test-utils.h \ tests/test-ovn.c \ + controller/test-lflow-cache.c \ controller/test-ofctrl-seqno.c \ + controller/lflow-cache.c \ + controller/lflow-cache.h \ controller/ofctrl-seqno.c \ controller/ofctrl-seqno.h \ northd/test-ipam.c \ diff --git a/tests/ovn-lflow-cache.at b/tests/ovn-lflow-cache.at new file mode 100644 index 0000000..f7e8959 --- /dev/null +++ b/tests/ovn-lflow-cache.at @@ -0,0 +1,257 @@ +# +# Unit tests for the controller/lflow-cache.c module. +# +AT_BANNER([OVN unit tests - lflow-cache]) + +AT_SETUP([ovn -- unit test -- lflow-cache single add/lookup]) +AT_CHECK( + [ovstest test-lflow-cache lflow_cache_operations \ + true 3 \ + add conj-id 1 \ + add expr 2 \ + add matches 3], + [0], [dnl +Enabled: true + cache-conj-id: 0 + cache-expr: 0 + cache-matches: 0 +ADD conj-id: + conj-id-ofs: 1 +LOOKUP: + conj_id_ofs: 1 + type: conj-id +Enabled: true + cache-conj-id: 1 + cache-expr: 0 + cache-matches: 0 +ADD expr: + conj-id-ofs: 2 +LOOKUP: + conj_id_ofs: 2 + type: expr +Enabled: true + cache-conj-id: 1 + cache-expr: 1 + cache-matches: 0 +ADD matches: + conj-id-ofs: 3 +LOOKUP: + conj_id_ofs: 0 + type: matches +Enabled: true + cache-conj-id: 1 + cache-expr: 1 + cache-matches: 1 +]) +AT_CLEANUP + +AT_SETUP([ovn -- unit test -- lflow-cache single add/lookup/del]) +AT_CHECK( + [ovstest test-lflow-cache lflow_cache_operations \ + true 3 \ + add-del conj-id 1 \ + add-del expr 2 \ + add-del matches 3], + [0], [dnl +Enabled: true + cache-conj-id: 0 + cache-expr: 0 + cache-matches: 0 +ADD conj-id: + conj-id-ofs: 1 +LOOKUP: + conj_id_ofs: 1 + type: conj-id +DELETE +LOOKUP: + not found +Enabled: true + cache-conj-id: 0 + cache-expr: 0 + cache-matches: 0 +ADD expr: + conj-id-ofs: 2 +LOOKUP: + conj_id_ofs: 2 + type: expr +DELETE +LOOKUP: + not found +Enabled: true + cache-conj-id: 0 + cache-expr: 0 + cache-matches: 0 +ADD matches: + conj-id-ofs: 3 +LOOKUP: + conj_id_ofs: 0 + type: matches +DELETE +LOOKUP: + not found +Enabled: true + cache-conj-id: 0 + cache-expr: 0 + cache-matches: 0 +]) +AT_CLEANUP + +AT_SETUP([ovn -- unit test -- lflow-cache disabled single add/lookup/del]) +AT_CHECK( + [ovstest test-lflow-cache lflow_cache_operations \ + false 3 \ + add conj-id 1 \ + add expr 2 \ + add matches 3], + [0], [dnl +Enabled: false + cache-conj-id: 0 + cache-expr: 0 + cache-matches: 0 +ADD conj-id: + conj-id-ofs: 1 +LOOKUP: + not found +Enabled: false + cache-conj-id: 0 + cache-expr: 0 + cache-matches: 0 +ADD expr: + conj-id-ofs: 2 +LOOKUP: + not found +Enabled: false + cache-conj-id: 0 + cache-expr: 0 + cache-matches: 0 +ADD matches: + conj-id-ofs: 3 +LOOKUP: + not found +Enabled: false + cache-conj-id: 0 + cache-expr: 0 + cache-matches: 0 +]) +AT_CLEANUP + +AT_SETUP([ovn -- unit test -- lflow-cache disable/enable/flush]) +AT_CHECK( + [ovstest test-lflow-cache lflow_cache_operations \ + true 12 \ + add conj-id 1 \ + add expr 2 \ + add matches 3 \ + disable \ + add conj-id 4 \ + add expr 5 \ + add matches 6 \ + enable \ + add conj-id 7 \ + add expr 8 \ + add matches 9 \ + flush], + [0], [dnl +Enabled: true + cache-conj-id: 0 + cache-expr: 0 + cache-matches: 0 +ADD conj-id: + conj-id-ofs: 1 +LOOKUP: + conj_id_ofs: 1 + type: conj-id +Enabled: true + cache-conj-id: 1 + cache-expr: 0 + cache-matches: 0 +ADD expr: + conj-id-ofs: 2 +LOOKUP: + conj_id_ofs: 2 + type: expr +Enabled: true + cache-conj-id: 1 + cache-expr: 1 + cache-matches: 0 +ADD matches: + conj-id-ofs: 3 +LOOKUP: + conj_id_ofs: 0 + type: matches +Enabled: true + cache-conj-id: 1 + cache-expr: 1 + cache-matches: 1 +DISABLE +Enabled: false + cache-conj-id: 0 + cache-expr: 0 + cache-matches: 0 +ADD conj-id: + conj-id-ofs: 4 +LOOKUP: + not found +Enabled: false + cache-conj-id: 0 + cache-expr: 0 + cache-matches: 0 +ADD expr: + conj-id-ofs: 5 +LOOKUP: + not found +Enabled: false + cache-conj-id: 0 + cache-expr: 0 + cache-matches: 0 +ADD matches: + conj-id-ofs: 6 +LOOKUP: + not found +Enabled: false + cache-conj-id: 0 + cache-expr: 0 + cache-matches: 0 +ENABLE +Enabled: true + cache-conj-id: 0 + cache-expr: 0 + cache-matches: 0 +ADD conj-id: + conj-id-ofs: 7 +LOOKUP: + conj_id_ofs: 7 + type: conj-id +Enabled: true + cache-conj-id: 1 + cache-expr: 0 + cache-matches: 0 +ADD expr: + conj-id-ofs: 8 +LOOKUP: + conj_id_ofs: 8 + type: expr +Enabled: true + cache-conj-id: 1 + cache-expr: 1 + cache-matches: 0 +ADD matches: + conj-id-ofs: 9 +LOOKUP: + conj_id_ofs: 0 + type: matches +Enabled: true + cache-conj-id: 1 + cache-expr: 1 + cache-matches: 1 +FLUSH +Enabled: true + cache-conj-id: 0 + cache-expr: 0 + cache-matches: 0 +]) +AT_CLEANUP + +AT_SETUP([ovn -- unit test -- lflow-cache negative tests]) +AT_CHECK([ovstest test-lflow-cache lflow_cache_negative], [0], []) +AT_CLEANUP diff --git a/tests/ovn.at b/tests/ovn.at index 4a75acc..0e114cf 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -22235,6 +22235,74 @@ OVN_CLEANUP([hv1]) AT_CLEANUP +AT_SETUP([ovn -- lflow cache operations]) +ovn_start +net_add n1 +sim_add hv1 + +as hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 + +as hv1 +ovs-vsctl -- add-port br-int hv1-vif1 \ + -- set interface hv1-vif1 external-ids:iface-id=lsp1 \ + -- add-port br-int hv1-vif2 \ + -- set interface hv1-vif2 external-ids:iface-id=lsp2 + +ovn-nbctl ls-add ls1 \ + -- lsp-add ls1 lsp1 \ + -- lsp-add ls1 lsp2 \ + -- pg-add pg1 lsp1 lsp2 \ + -- create Address_Set name=as1 addresses=\"10.0.0.1\",\"10.0.0.2\" +check ovn-nbctl --wait=hv sync +wait_for_ports_up lsp1 lsp2 + +get_cache_count () { + local cache_name=$1 + as hv1 ovn-appctl -t ovn-controller lflow-cache/show-stats | grep ${cache_name} | awk '{ print $3 }' +} + +AS_BOX([Check matches caching]) +conj_id_cnt=$(get_cache_count cache-conj-id) +expr_cnt=$(get_cache_count cache-expr) +matches_cnt=$(get_cache_count cache-matches) + +check ovn-nbctl acl-add ls1 from-lport 1 '1' drop +check ovn-nbctl --wait=hv sync + +AT_CHECK([test "$conj_id_cnt" = "$(get_cache_count cache-conj-id)"], [0], []) +AT_CHECK([test "$expr_cnt" = "$(get_cache_count cache-expr)"], [0], []) +AT_CHECK([test "$(($matches_cnt + 1))" = "$(get_cache_count cache-matches)"], [0], []) + +AS_BOX([Check expr caching for is_chassis_resident() matches]) +conj_id_cnt=$(get_cache_count cache-conj-id) +expr_cnt=$(get_cache_count cache-expr) +matches_cnt=$(get_cache_count cache-matches) + +check ovn-nbctl acl-add ls1 from-lport 1 'is_chassis_resident("lsp1")' drop +check ovn-nbctl --wait=hv sync + +AT_CHECK([test "$conj_id_cnt" = "$(get_cache_count cache-conj-id)"], [0], []) +AT_CHECK([test "$(($expr_cnt + 1))" = "$(get_cache_count cache-expr)"], [0], []) +AT_CHECK([test "$matches_cnt" = "$(get_cache_count cache-matches)"], [0], []) + +AS_BOX([Check conj-id caching for conjunctive port group/address set matches]) +conj_id_cnt=$(get_cache_count cache-conj-id) +expr_cnt=$(get_cache_count cache-expr) +matches_cnt=$(get_cache_count cache-matches) + +check ovn-nbctl acl-add ls1 from-lport 1 'inport == @pg1 && outport == @pg1 && is_chassis_resident("lsp1")' drop +check ovn-nbctl acl-add ls1 from-lport 1 'ip4.src == $as1 && ip4.dst == $as1 && is_chassis_resident("lsp1")' drop +check ovn-nbctl --wait=hv sync + +AT_CHECK([test "$(($conj_id_cnt + 2))" = "$(get_cache_count cache-conj-id)"], [0], []) +AT_CHECK([test "$expr_cnt" = "$(get_cache_count cache-expr)"], [0], []) +AT_CHECK([test "$matches_cnt" = "$(get_cache_count cache-matches)"], [0], []) + +OVN_CLEANUP([hv1]) +AT_CLEANUP + AT_SETUP([ovn -- Delete Port_Binding and OVS port Incremental Processing]) ovn_start diff --git a/tests/test-utils.c b/tests/test-utils.c new file mode 100644 index 0000000..6a3b198 --- /dev/null +++ b/tests/test-utils.c @@ -0,0 +1,49 @@ +/* Copyright (c) 2021, Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <config.h> + +#include "test-utils.h" + +#include "util.h" + +bool +test_read_uint_value(struct ovs_cmdl_context *ctx, unsigned int index, + const char *descr, unsigned int *result) +{ + if (index >= ctx->argc) { + fprintf(stderr, "Missing %s argument\n", descr); + return false; + } + + const char *arg = ctx->argv[index]; + if (!str_to_uint(arg, 10, result)) { + fprintf(stderr, "Invalid %s: %s\n", descr, arg); + return false; + } + return true; +} + +const char * +test_read_value(struct ovs_cmdl_context *ctx, unsigned int index, + const char *descr) +{ + if (index >= ctx->argc) { + fprintf(stderr, "Missing %s argument\n", descr); + return NULL; + } + + return ctx->argv[index]; +} diff --git a/tests/test-utils.h b/tests/test-utils.h new file mode 100644 index 0000000..721032f --- /dev/null +++ b/tests/test-utils.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2021, Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TEST_UTILS_H +#define TEST_UTILS_H 1 + +#include "ovstest.h" + +bool test_read_uint_value(struct ovs_cmdl_context *ctx, unsigned int index, + const char *descr, unsigned int *result); +const char *test_read_value(struct ovs_cmdl_context *ctx, unsigned int index, + const char *descr); + +#endif /* tests/test-utils.h */ diff --git a/tests/testsuite.at b/tests/testsuite.at index 6253d11..35908ad 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -27,6 +27,7 @@ m4_include([tests/ovn.at]) m4_include([tests/ovn-performance.at]) m4_include([tests/ovn-northd.at]) m4_include([tests/ovn-nbctl.at]) +m4_include([tests/ovn-lflow-cache.at]) m4_include([tests/ovn-ofctrl-seqno.at]) m4_include([tests/ovn-sbctl.at]) m4_include([tests/ovn-ic-nbctl.at]) _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev