As pointed out by Joe the following commit breaks the Mac OS X build
(but not the FreeBSD one), because pthread_barrier is not available
there.
The following incremental appears to fix it:
diff --git a/tests/test-conntrack.c b/tests/test-conntrack.c
index e2224e8..37c7277 100644
--- a/tests/test-conntrack.c
+++ b/tests/test-conntrack.c
@@ -75,7 +75,7 @@ struct thread_aux {
static struct conntrack ct;
static unsigned long n_threads, n_pkts, batch_size;
static bool change_conn = false;
-static pthread_barrier_t barrier;
+static struct ovs_barrier barrier;
static void *
ct_thread_main(void *aux_)
@@ -85,11 +85,11 @@ ct_thread_main(void *aux_)
size_t i;
pkt_batch = prepare_packets(batch_size, change_conn, aux->tid);
- pthread_barrier_wait(&barrier);
+ ovs_barrier_block(&barrier);
for (i = 0; i < n_pkts; i += batch_size) {
conntrack_execute(&ct, pkt_batch, true, 0, NULL, NULL, NULL);
}
- pthread_barrier_wait(&barrier);
+ ovs_barrier_block(&barrier);
destroy_packets(pkt_batch);
return NULL;
@@ -120,7 +120,7 @@ test_benchmark(struct ovs_cmdl_context *ctx)
}
threads = xcalloc(n_threads, sizeof *threads);
- pthread_barrier_init(&barrier, NULL, n_threads + 1);
+ ovs_barrier_init(&barrier, n_threads + 1);
conntrack_init(&ct);
/* Create threads */
@@ -130,11 +130,11 @@ test_benchmark(struct ovs_cmdl_context *ctx)
&threads[i]);
}
/* Starts the work inside the threads */
- pthread_barrier_wait(&barrier);
+ ovs_barrier_block(&barrier);
start = time_msec();
/* Wait for the threads to finish the work */
- pthread_barrier_wait(&barrier);
+ ovs_barrier_block(&barrier);
printf("conntrack: %5lld ms\n", time_msec() - start);
for (i = 0; i < n_threads; i++) {
@@ -142,7 +142,7 @@ test_benchmark(struct ovs_cmdl_context *ctx)
}
conntrack_destroy(&ct);
- pthread_barrier_destroy(&barrier);
+ ovs_barrier_destroy(&barrier);
free(threads);
}
On 10/06/2016 15:47, "Daniele Di Proietto" <[email protected]> wrote:
>This introduces a very limited but simple benchmark for
>conntrack_execute(). It just sends repeatedly the same batch of packets
>through the connection tracker and returns the time spent to process
>them.
>
>While this is not a realistic benchmark, it has proven useful during
>development to evaluate different batching and locking strategies.
>
>E.g. the line:
>
>`./test/ovstest test-conntrack benchmark 1 14880000 32`
>
>starts 1 thread that will send 14880000 packets to the connection
>tracker, 32 at a time. It will print the time taken to process them.
>
>Signed-off-by: Daniele Di Proietto <[email protected]>
>Acked-by: Flavio Leitner <[email protected]>
>---
> tests/automake.mk | 1 +
> tests/test-conntrack.c | 172 +++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 173 insertions(+)
> create mode 100644 tests/test-conntrack.c
>
>diff --git a/tests/automake.mk b/tests/automake.mk
>index 777f6db..c3dcb6b 100644
>--- a/tests/automake.mk
>+++ b/tests/automake.mk
>@@ -323,6 +323,7 @@ tests_ovstest_SOURCES = \
> tests/test-classifier.c \
> tests/test-ccmap.c \
> tests/test-cmap.c \
>+ tests/test-conntrack.c \
> tests/test-csum.c \
> tests/test-flows.c \
> tests/test-hash.c \
>diff --git a/tests/test-conntrack.c b/tests/test-conntrack.c
>new file mode 100644
>index 0000000..e2224e8
>--- /dev/null
>+++ b/tests/test-conntrack.c
>@@ -0,0 +1,172 @@
>+/*
>+ * Copyright (c) 2015 Nicira, 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 "conntrack.h"
>+
>+#include "dp-packet.h"
>+#include "fatal-signal.h"
>+#include "flow.h"
>+#include "netdev.h"
>+#include "ovs-thread.h"
>+#include "ovstest.h"
>+#include "timeval.h"
>+
>+static const char payload[] = "50540000000a50540000000908004500001c0000000000"
>+ "11a4cd0a0101010a0101020001000200080000";
>+
>+static struct dp_packet_batch *
>+prepare_packets(size_t n, bool change, unsigned tid)
>+{
>+ struct dp_packet_batch *pkt_batch = xzalloc(sizeof *pkt_batch);
>+ struct flow flow;
>+ size_t i;
>+
>+ ovs_assert(n <= ARRAY_SIZE(pkt_batch->packets));
>+
>+ dp_packet_batch_init(pkt_batch);
>+ pkt_batch->count = n;
>+
>+ for (i = 0; i < n; i++) {
>+ struct udp_header *udp;
>+ struct dp_packet *pkt = dp_packet_new(sizeof payload/2);
>+
>+ dp_packet_put_hex(pkt, payload, NULL);
>+ flow_extract(pkt, &flow);
>+
>+ udp = dp_packet_l4(pkt);
>+ udp->udp_src = htons(ntohs(udp->udp_src) + tid);
>+
>+ if (change) {
>+ udp->udp_dst = htons(ntohs(udp->udp_dst) + i);
>+ }
>+
>+ pkt_batch->packets[i] = pkt;
>+ }
>+
>+ return pkt_batch;
>+}
>+
>+static void
>+destroy_packets(struct dp_packet_batch *pkt_batch)
>+{
>+ dp_packet_delete_batch(pkt_batch, true);
>+ free(pkt_batch);
>+}
>+
>+struct thread_aux {
>+ pthread_t thread;
>+ unsigned tid;
>+};
>+
>+static struct conntrack ct;
>+static unsigned long n_threads, n_pkts, batch_size;
>+static bool change_conn = false;
>+static pthread_barrier_t barrier;
>+
>+static void *
>+ct_thread_main(void *aux_)
>+{
>+ struct thread_aux *aux = aux_;
>+ struct dp_packet_batch *pkt_batch;
>+ size_t i;
>+
>+ pkt_batch = prepare_packets(batch_size, change_conn, aux->tid);
>+ pthread_barrier_wait(&barrier);
>+ for (i = 0; i < n_pkts; i += batch_size) {
>+ conntrack_execute(&ct, pkt_batch, true, 0, NULL, NULL, NULL);
>+ }
>+ pthread_barrier_wait(&barrier);
>+ destroy_packets(pkt_batch);
>+
>+ return NULL;
>+}
>+
>+static void
>+test_benchmark(struct ovs_cmdl_context *ctx)
>+{
>+ struct thread_aux *threads;
>+ long long start;
>+ unsigned i;
>+
>+ fatal_signal_init();
>+
>+ /* Parse arguments */
>+ n_threads = strtoul(ctx->argv[1], NULL, 0);
>+ if (!n_threads) {
>+ ovs_fatal(0, "n_threads must be at least one");
>+ }
>+ n_pkts = strtoul(ctx->argv[2], NULL, 0);
>+ batch_size = strtoul(ctx->argv[3], NULL, 0);
>+ if (batch_size == 0 || batch_size > NETDEV_MAX_BURST) {
>+ ovs_fatal(0, "batch_size must be between 1 and NETDEV_MAX_BURST(%u)",
>+ NETDEV_MAX_BURST);
>+ }
>+ if (ctx->argc > 4) {
>+ change_conn = strtoul(ctx->argv[4], NULL, 0);
>+ }
>+
>+ threads = xcalloc(n_threads, sizeof *threads);
>+ pthread_barrier_init(&barrier, NULL, n_threads + 1);
>+ conntrack_init(&ct);
>+
>+ /* Create threads */
>+ for (i = 0; i < n_threads; i++) {
>+ threads[i].tid = i;
>+ threads[i].thread = ovs_thread_create("ct_thread", ct_thread_main,
>+ &threads[i]);
>+ }
>+ /* Starts the work inside the threads */
>+ pthread_barrier_wait(&barrier);
>+ start = time_msec();
>+
>+ /* Wait for the threads to finish the work */
>+ pthread_barrier_wait(&barrier);
>+ printf("conntrack: %5lld ms\n", time_msec() - start);
>+
>+ for (i = 0; i < n_threads; i++) {
>+ xpthread_join(threads[i].thread, NULL);
>+ }
>+
>+ conntrack_destroy(&ct);
>+ pthread_barrier_destroy(&barrier);
>+ free(threads);
>+}
>+?
>+static const struct ovs_cmdl_command commands[] = {
>+ /* Connection tracker tests. */
>+ /* Starts 'n_threads' threads. Each thread will send 'n_pkts' packets to
>+ * the connection tracker, 'batch_size' per call. If 'change_connection'
>+ * is '1', each packet in a batch will have a different source and
>+ * destination port */
>+ {"benchmark", "n_threads n_pkts batch_size [change_connection]", 3, 4,
>+ test_benchmark},
>+
>+ {NULL, NULL, 0, 0, NULL},
>+};
>+
>+static void
>+test_conntrack_main(int argc, char *argv[])
>+{
>+ struct ovs_cmdl_context ctx = {
>+ .argc = argc - 1,
>+ .argv = argv + 1,
>+ };
>+ set_program_name(argv[0]);
>+ ovs_cmdl_run_command(&ctx, commands);
>+}
>+
>+OVSTEST_REGISTER("test-conntrack", test_conntrack_main);
>--
>2.8.1
>
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev