This test is reusing the benchmark infrastructure, but it has some
pre-defined parameters, so it's easier to run in the test suite.

The benchmark code is adjusted to start another thread that does
prefix updates continuously in a loop and the lookup threads are
updated to be able to enter quiescent state periodically, so the
reconfiguration can proceed.

This test is a reproducer for the crashes fixed in the previous
commit.

Signed-off-by: Ilya Maximets <i.maxim...@ovn.org>
---
 tests/classifier.at     |  5 +++
 tests/test-classifier.c | 98 ++++++++++++++++++++++++++++++++++++++---
 2 files changed, 97 insertions(+), 6 deletions(-)

diff --git a/tests/classifier.at b/tests/classifier.at
index dfadf5e5a..bfa1b119c 100644
--- a/tests/classifier.at
+++ b/tests/classifier.at
@@ -17,6 +17,11 @@ m4_foreach(
    AT_CHECK([ovstest test-classifier m4_bpatsubst(testname, [versioned], 
[--versioned])], [0], [], [])
    AT_CLEANUP])])
 
+AT_BANNER([flow classifier stress tests])
+AT_SETUP([flow classifier - prefixes reconfiguration stress test])
+AT_CHECK([ovstest test-classifier stress-prefixes], [0], [stdout])
+AT_CLEANUP
+
 AT_BANNER([miniflow unit tests])
 m4_foreach(
   [testname],
diff --git a/tests/test-classifier.c b/tests/test-classifier.c
index 7f6ba50ee..6ac276d2e 100644
--- a/tests/test-classifier.c
+++ b/tests/test-classifier.c
@@ -37,6 +37,7 @@
 #include "command-line.h"
 #include "fatal-signal.h"
 #include "flow.h"
+#include "openvswitch/vlog.h"
 #include "ovstest.h"
 #include "ovs-atomic.h"
 #include "ovs-thread.h"
@@ -757,11 +758,22 @@ shuffle_u32s(uint32_t *p, size_t n)
         *q = tmp;
     }
 }
+
+static void
+shuffle_fields(enum mf_field_id *p, size_t n)
+{
+    for (; n > 1; n--, p++) {
+        enum mf_field_id *q = &p[random_range(n)];
+        enum mf_field_id tmp = *p;
+        *p = *q;
+        *q = tmp;
+    }
+}
 
 /* Classifier tests. */
 
-static enum mf_field_id trie_fields[2] = {
-    MFF_IPV4_DST, MFF_IPV4_SRC
+static enum mf_field_id trie_fields[4] = {
+    MFF_IPV4_DST, MFF_IPV4_SRC, MFF_IPV6_DST, MFF_IPV6_SRC,
 };
 
 static void
@@ -1286,7 +1298,7 @@ static int n_tables;            /* Number of subtables. */
 static int n_threads;           /* Number of threads to search and mutate. */
 static int n_lookups;           /* Number of lookups each thread performs. */
 
-static void benchmark(bool use_wc);
+static void benchmark(bool use_wc, bool stress_prefixes);
 
 static int
 elapsed(const struct timeval *start)
@@ -1337,9 +1349,29 @@ run_benchmarks(struct ovs_cmdl_context *ctx)
            n_rules, n_priorities, n_tables, n_threads, n_lookups);
 
     puts("\nWithout wildcards: \n");
-    benchmark(false);
+    benchmark(false, false);
     puts("\nWith wildcards: \n");
-    benchmark(true);
+    benchmark(true, false);
+}
+
+static void
+run_prefix_stress(struct ovs_cmdl_context *ctx OVS_UNUSED)
+{
+    vlog_set_levels(NULL, VLF_ANY_DESTINATION, VLL_OFF);
+    vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
+
+    n_rules = 10000;
+    n_priorities = 2;
+    n_tables = 30;
+    n_threads = 2;
+    n_lookups = 2000000;
+
+    printf("\nStress testing prefixes with:\n"
+           "%d rules with %d priorities in %d tables, "
+           "%d threads doing %d lookups each\n",
+           n_rules, n_priorities, n_tables, n_threads, n_lookups);
+
+    benchmark(true, true);
 }
 
 struct cls_aux {
@@ -1347,6 +1379,7 @@ struct cls_aux {
     size_t n_lookup_flows;
     struct flow *lookup_flows;
     bool use_wc;
+    bool quiesce;
     atomic_int hits;
     atomic_int misses;
 };
@@ -1382,15 +1415,47 @@ lookup_classifier(void *aux_)
         } else {
             misses++;
         }
+        if (aux->quiesce) {
+            ovsrcu_quiesce();
+        }
     }
     atomic_add(&aux->hits, hits, &old_hits);
     atomic_add(&aux->misses, misses, &old_misses);
     return NULL;
 }
 
+struct prefix_aux {
+    struct classifier *cls;
+    atomic_bool running;
+    size_t n_updates;
+};
+
+static void *
+update_prefixes(void *aux_)
+{
+    struct prefix_aux *aux = aux_;
+    size_t n, n_updates = 0;
+    bool running = true;
+
+    random_set_seed(1);
+
+    while (running) {
+        n_updates++;
+
+        shuffle_fields(trie_fields, ARRAY_SIZE(trie_fields));
+        n = random_range(ARRAY_SIZE(trie_fields) + 1);
+        classifier_set_prefix_fields(aux->cls, trie_fields, n);
+        verify_tries(aux->cls);
+
+        atomic_read_relaxed(&aux->running, &running);
+    }
+    aux->n_updates = n_updates;
+    return NULL;
+}
+
 /* Benchmark classification. */
 static void
-benchmark(bool use_wc)
+benchmark(bool use_wc, bool stress_prefixes)
 {
     struct classifier cls;
     ovs_version_t version = OVS_VERSION_MIN;
@@ -1421,6 +1486,7 @@ benchmark(bool use_wc)
 
     /* Create lookup flows. */
     aux.use_wc = use_wc;
+    aux.quiesce = stress_prefixes;
     aux.cls = &cls;
     aux.n_lookup_flows = 2 * N_FLOW_VALUES;
     aux.lookup_flows = xzalloc(aux.n_lookup_flows * sizeof *aux.lookup_flows);
@@ -1465,6 +1531,18 @@ benchmark(bool use_wc)
         }
     }
 
+    pthread_t prefix_thread;
+    struct prefix_aux paux;
+
+    if (stress_prefixes) {
+        paux.cls = &cls;
+        paux.n_updates = 0;
+        atomic_init(&paux.running, true);
+
+        prefix_thread = ovs_thread_create("prefixes", update_prefixes, &paux);
+        ovsrcu_quiesce_start();
+    }
+
     /* Lookup. */
     xgettimeofday(&start);
     threads = xmalloc(n_threads * sizeof *threads);
@@ -1479,6 +1557,13 @@ benchmark(bool use_wc)
 
     free(threads);
 
+    if (stress_prefixes) {
+        atomic_store_relaxed(&paux.running, false);
+        xpthread_join(prefix_thread, NULL);
+        printf("Prefixes updated %"PRIuSIZE" times.\n", paux.n_updates);
+        ovsrcu_quiesce_end();
+    }
+
     int hits, misses;
     atomic_read(&aux.hits, &hits);
     atomic_read(&aux.misses, &misses);
@@ -1852,6 +1937,7 @@ static const struct ovs_cmdl_command commands[] = {
     {"many-rules-in-two-tables", NULL, 0, 0, test_many_rules_in_two_tables, 
OVS_RO },
     {"many-rules-in-five-tables", NULL, 0, 0, test_many_rules_in_five_tables, 
OVS_RO },
     {"benchmark", NULL, 0, 5, run_benchmarks, OVS_RO },
+    {"stress-prefixes", NULL, 0, 0, run_prefix_stress, OVS_RO },
 
     /* Miniflow and minimask tests. */
     {"miniflow", NULL, 0, 0, test_miniflow, OVS_RO },
-- 
2.49.0

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to