source: test/test-tracetime-parallel.c @ b148e3b

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivendag_formatrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since b148e3b was b148e3b, checked in by Richard Sanger <rsanger@…>, 4 years ago

Updates DPDK to latest release and improves performance

Thanks to Richard Cziva for supplying an intial patch for this.

We now recommend using the latest release of DPDK, ideally 16.04 or newer

To support newer releases

  • Fixes RSS hashing renames
  • Fixes deprecated rte_mempool_count
  • Fixes ETH_LINK_SPEED_X rename
  • Fixes TX minimum memory requirement
  • Fixes dropped vs errored counting in recent versions (for best results use 16.04 or newer)

Tuned to allow DPDK's SSE vector in supporting drivers mode for better performance.
Bumps default internal batch size up to 32 to matches DPDK in SSE vector mode.

  • Property mode set to 100644
File size: 7.4 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007 The University of Waikato, Hamilton, New Zealand.
5 * Authors: Richard Sanger
6 *
7 * All rights reserved.
8 *
9 * This code has been developed by the University of Waikato WAND
10 * research group. For further information please see http://www.wand.net.nz/
11 *
12 * libtrace is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * libtrace is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with libtrace; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25 *
26 * $Id$
27 *
28 */
29
30#ifndef WIN32
31#include <sys/time.h>
32#endif
33#include <stdio.h>
34#include <stdlib.h>
35#include <assert.h>
36#include <sys/types.h>
37#include <signal.h>
38#include <unistd.h>
39#include "libtrace_parallel.h"
40
41static double timeval_to_seconds(struct timeval tv) {
42        return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
43}
44
45static void iferr(libtrace_t *trace,const char *msg)
46{
47        libtrace_err_t err = trace_get_err(trace);
48        if (err.err_num==0)
49                return;
50        printf("Error: %s: %s\n", msg, err.problem);
51        exit(1);
52}
53
54static bool check_range_jitter(double test, double target, double jit) {
55        if ((test <= target + jit) && (test >= target - jit)) {
56                return true;
57        } else {
58                printf("Have:%f Expected:%f (%f-%f)", test, target, target - jit, target + jit);
59                return false;
60        }
61}
62
63
64libtrace_t *trace = NULL;
65int total = 0;
66
67static void signal_handler(int signal)
68{
69        if (signal == SIGALRM) {
70                trace_ppause(trace);
71
72                /* check within 10 seconds we got 9-11 packets */
73                assert(check_range_jitter(10.0, (double) total, 1.0));
74
75                /* Now fullspeed it */
76                trace_set_tracetime(trace, false);
77
78                /* And restart */
79                trace_pstart(trace, NULL, NULL, NULL);
80        }
81}
82
83struct counter {
84        int total;
85        int skipped;
86};
87
88static void *start_report(libtrace_t *trace UNUSED,
89                libtrace_thread_t *t UNUSED, void *global UNUSED) {
90       
91        struct counter *c = (struct counter *)malloc(sizeof(struct counter));
92        c->total = 0;
93        c->skipped = 0;
94        return c;
95
96}
97
98static void stop_report(libtrace_t *trace UNUSED,
99                libtrace_thread_t *t UNUSED, void *global UNUSED, void *tls) {
100
101        struct counter *c = (struct counter *)tls;
102
103        assert(c->skipped <= 20);
104        assert(c->skipped + c->total == 100);
105
106        free(c);
107}
108
109static void report_cb(libtrace_t *trace UNUSED,
110                libtrace_thread_t *sender UNUSED, void *global UNUSED,
111                void *tls, libtrace_result_t *result) {
112
113        struct counter *c = (struct counter *)tls;
114        if (result->type == RESULT_USER)
115                c->total ++;
116        if (result->type == RESULT_USER + 1)
117                c->skipped ++;
118
119        total = c->total;
120
121}
122
123static void *start_process(libtrace_t *trace UNUSED,
124                libtrace_thread_t *t UNUSED, void *global UNUSED) {
125
126        bool *accepting = (bool *)malloc(sizeof(bool));
127        *accepting = true;
128        return accepting;
129
130}
131
132static void stop_process(libtrace_t *trace UNUSED,
133                libtrace_thread_t *t UNUSED, void *global UNUSED, void *tls) {
134        bool *accepting = (bool *)tls;
135        free(accepting);
136}
137
138static void pause_process(libtrace_t *trace UNUSED,
139                libtrace_thread_t *t UNUSED, void *global UNUSED, void *tls) {
140        bool *accepting = (bool *)tls;
141        *accepting = false;
142}
143
144static void resume_process(libtrace_t *trace UNUSED,
145                libtrace_thread_t *t UNUSED, void *global UNUSED, void *tls) {
146        bool *accepting = (bool *)tls;
147        *accepting = true;
148}
149
150static void user_message(libtrace_t *trace UNUSED,
151                libtrace_thread_t *t UNUSED, void *global UNUSED,
152                void *tls UNUSED, int msg UNUSED, libtrace_generic_t ts) {
153
154        struct timeval tv;
155        double time;
156
157        gettimeofday(&tv, NULL);
158        time = timeval_to_seconds(tv);
159
160        assert(check_range_jitter(ts.rdouble, time, 0.01));
161}
162
163static libtrace_packet_t *per_packet(libtrace_t *trace, libtrace_thread_t *t,
164                void *global UNUSED, void *tls, libtrace_packet_t *packet) {
165
166        struct timeval tv;
167        double time;
168        libtrace_message_t message;
169        bool *accepting = (bool *)tls;
170
171        gettimeofday(&tv, NULL);
172        time = timeval_to_seconds(tv);
173
174        if (*accepting) {
175                fprintf(stderr, ".");
176                trace_publish_result(trace, t, (uint64_t)time,
177                                (libtrace_generic_t){.rdouble = time},
178                                RESULT_USER);
179                /* Test that we are not interfering with message delivery */
180                message.code = MESSAGE_USER;
181                message.sender = t;
182                message.data.rdouble = time;
183                trace_message_perpkts(trace, &message);
184        } else {
185                trace_publish_result(trace, t, (uint64_t)time,
186                                (libtrace_generic_t){.rdouble = time},
187                                RESULT_USER+1);
188
189        }
190        return packet;
191
192}
193/**
194 * Test that tracetime playback functions.
195 * Including:
196 * * Delaying packets
197 * * Not blocking messages
198 * * Instantly returning when paused (or stopped)
199 * * Can be switched off/on from a paused state
200 */
201int test_tracetime(const char *tracename) {
202        int error = 0;
203        struct timeval tv;
204        double start, end;
205        libtrace_callback_set_t *processing;
206        libtrace_callback_set_t *reporter;
207
208        gettimeofday(&tv, NULL);
209        start = timeval_to_seconds(tv);
210        printf("Testing delay\n");
211
212        // Create the trace
213        trace = trace_create(tracename);
214        iferr(trace,tracename);
215
216        // Always use 2 threads for simplicity
217        trace_set_perpkt_threads(trace, 2);
218        trace_set_tracetime(trace, true);
219
220        processing = trace_create_callback_set();
221        trace_set_starting_cb(processing, start_process);
222        trace_set_stopping_cb(processing, stop_process);
223        trace_set_pausing_cb(processing, pause_process);
224        trace_set_resuming_cb(processing, resume_process);
225        trace_set_packet_cb(processing, per_packet);
226        trace_set_user_message_cb(processing, user_message);
227
228        reporter = trace_create_callback_set();
229        trace_set_starting_cb(reporter, start_report);
230        trace_set_stopping_cb(reporter, stop_report);
231        trace_set_result_cb(reporter, report_cb);
232
233        trace_set_reporter_thold(trace, 1);
234        trace_set_burst_size(trace, 10);
235
236        // Start it
237        trace_pstart(trace, NULL, processing, reporter);
238        iferr(trace,tracename);
239        fprintf(stderr, "Running in tracetime (Will take about 10 seconds)\t");
240
241        // Timeout after 10 which should be about 10 packets seconds
242        alarm(10);
243
244        /* Wait for all threads to stop */
245        trace_join(trace);
246
247        if (error != 0) {
248                iferr(trace,tracename);
249        }
250        /* The whole test should take about 10 seconds */
251        gettimeofday(&tv, NULL);
252        end = timeval_to_seconds(tv);
253        assert(check_range_jitter(end-start, 10.0, 1.0));
254        trace_destroy(trace);
255        return error;
256}
257
258int main() {
259        int error = 0;
260        const char *tracename;
261
262        signal(SIGALRM, signal_handler);
263
264        tracename = "pcapfile:traces/100_seconds.pcap";
265
266        error = test_tracetime(tracename);
267        fprintf(stderr, "\n");
268        return error;
269}
Note: See TracBrowser for help on using the repository browser.