diff --git a/doc/bird.sgml b/doc/bird.sgml
index 0d8d6b15..2926c556 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -3758,21 +3758,27 @@ protocol ospf MyOSPF {
The Perf protocol is a generator of fake routes together with a time measurement
framework. Its purpose is to check BIRD performance and to benchmark filters.
-
This protocol runs in several steps. In each step, it generates 2^x routes,
+
Import mode of this protocol runs in several steps. In each step, it generates 2^x routes,
imports them into the appropriate table and withdraws them. The exponent x is configurable.
It runs the benchmark several times for the same x, then it increases x by one
until it gets too high, then it stops.
+
Export mode of this protocol repeats route refresh from table and measures how long it takes.
+
Output data is logged on info level. There is a Perl script proto/perf/parse.pl
which may be handy to parse the data and draw some plots.
Implementation of this protocol is experimental. Use with caution and do not keep
-any instance of Perf in production configs.
+any instance of Perf in production configs for long time. The config interface is also unstable
+and may change in future versions without warning.
Configuration
+ mode import|export
+ Set perf mode. Default: import
+
repeat
Run this amount of iterations of the benchmark for every amount step. Default: 4
diff --git a/proto/perf/config.Y b/proto/perf/config.Y
index 52f509a6..617b2233 100644
--- a/proto/perf/config.Y
+++ b/proto/perf/config.Y
@@ -17,7 +17,7 @@ CF_DEFINES
CF_DECLS
-CF_KEYWORDS(PERF, EXP, FROM, TO, REPEAT, THRESHOLD, MIN, MAX, KEEP)
+CF_KEYWORDS(PERF, EXP, FROM, TO, REPEAT, THRESHOLD, MIN, MAX, KEEP, MODE, IMPORT, EXPORT)
CF_GRAMMAR
@@ -32,6 +32,7 @@ perf_proto_start: proto_start PERF
PERF_CFG->threshold_max = 500 MS_;
PERF_CFG->threshold_min = 1 MS_;
PERF_CFG->keep = 0;
+ PERF_CFG->mode = PERF_MODE_IMPORT;
};
perf_proto:
@@ -47,6 +48,8 @@ perf_proto_item:
| THRESHOLD MIN expr_us { PERF_CFG->threshold_min = $3; }
| THRESHOLD MAX expr_us { PERF_CFG->threshold_max = $3; }
| KEEP bool { PERF_CFG->keep = $2; }
+ | MODE IMPORT { PERF_CFG->mode = PERF_MODE_IMPORT; }
+ | MODE EXPORT { PERF_CFG->mode = PERF_MODE_EXPORT; }
;
diff --git a/proto/perf/perf.c b/proto/perf/perf.c
index 733eeb88..97fd8340 100644
--- a/proto/perf/perf.c
+++ b/proto/perf/perf.c
@@ -209,13 +209,49 @@ perf_loop(void *data)
ev_schedule(p->loop);
}
+static void
+perf_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net UNUSED, struct rte *new UNUSED, struct rte *old UNUSED)
+{
+ struct perf_proto *p = (struct perf_proto *) P;
+ p->exp++;
+ return;
+}
+
+static void
+perf_feed_begin(struct channel *c, int initial UNUSED)
+{
+ struct perf_proto *p = (struct perf_proto *) c->proto;
+
+ p->run++;
+ p->data = xmalloc(sizeof(struct timespec));
+ p->exp = 0;
+
+ clock_gettime(CLOCK_MONOTONIC, p->data);
+}
+
+static void
+perf_feed_end(struct channel *c)
+{
+ struct perf_proto *p = (struct perf_proto *) c->proto;
+ struct timespec ts_end;
+ clock_gettime(CLOCK_MONOTONIC, &ts_end);
+
+ s64 feedtime = timediff(p->data, &ts_end);
+
+ PLOG("feed n=%lu time=%lu", p->exp, feedtime);
+
+ if (p->run < p->repeat)
+ channel_request_feeding(c);
+ else
+ PLOG("feed done");
+}
+
static struct proto *
perf_init(struct proto_config *CF)
{
struct proto *P = proto_new(CF);
P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF));
- P->ifa_notify = perf_ifa_notify;
struct perf_proto *p = (struct perf_proto *) P;
@@ -229,6 +265,18 @@ perf_init(struct proto_config *CF)
p->to = cf->to;
p->repeat = cf->repeat;
p->keep = cf->keep;
+ p->mode = cf->mode;
+
+ switch (p->mode) {
+ case PERF_MODE_IMPORT:
+ P->ifa_notify = perf_ifa_notify;
+ break;
+ case PERF_MODE_EXPORT:
+ P->rt_notify = perf_rt_notify;
+ P->feed_begin = perf_feed_begin;
+ P->feed_end = perf_feed_end;
+ break;
+ }
return P;
}
diff --git a/proto/perf/perf.h b/proto/perf/perf.h
index f31becdd..301c6110 100644
--- a/proto/perf/perf.h
+++ b/proto/perf/perf.h
@@ -9,6 +9,11 @@
#ifndef _BIRD_PERF_H_
#define _BIRD_PERF_H_
+enum perf_mode {
+ PERF_MODE_IMPORT,
+ PERF_MODE_EXPORT,
+};
+
struct perf_config {
struct proto_config p;
btime threshold_min;
@@ -17,6 +22,7 @@ struct perf_config {
uint to;
uint repeat;
uint keep;
+ enum perf_mode mode;
};
struct perf_proto {
@@ -33,6 +39,7 @@ struct perf_proto {
uint exp;
uint stop;
uint keep;
+ enum perf_mode mode;
};
#endif