mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-09 12:48:43 +00:00
Dropping obsolete protocol Perf
We have now better methods how to measure overall performance and this obsolete protocol has basically rotten away. If anybody needs its features, feel free to revive it in future.
This commit is contained in:
parent
43d48ff9fe
commit
9a520e364b
@ -309,7 +309,7 @@ if test "$enable_mpls_kernel" != no ; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# temporarily removed "mrt" from all_protocols to speed up 3.0-alpha1 release
|
# temporarily removed "mrt" from all_protocols to speed up 3.0-alpha1 release
|
||||||
all_protocols="aggregator bfd babel bgp l3vpn ospf perf pipe radv rip rpki static"
|
all_protocols="aggregator bfd babel bgp l3vpn ospf pipe radv rip rpki static"
|
||||||
all_protocols=`echo $all_protocols | sed 's/ /,/g'`
|
all_protocols=`echo $all_protocols | sed 's/ /,/g'`
|
||||||
|
|
||||||
if test "$with_protocols" = all ; then
|
if test "$with_protocols" = all ; then
|
||||||
|
@ -4867,55 +4867,6 @@ protocol ospf MyOSPF {
|
|||||||
}
|
}
|
||||||
</code>
|
</code>
|
||||||
|
|
||||||
<sect>Perf
|
|
||||||
<label id="perf">
|
|
||||||
|
|
||||||
<sect1>Introduction
|
|
||||||
<label id="perf-intro">
|
|
||||||
|
|
||||||
<p>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.
|
|
||||||
|
|
||||||
<p>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.
|
|
||||||
|
|
||||||
<p>Export mode of this protocol repeats route refresh from table and measures how long it takes.
|
|
||||||
|
|
||||||
<p>Output data is logged on info level. There is a Perl script <cf>proto/perf/parse.pl</cf>
|
|
||||||
which may be handy to parse the data and draw some plots.
|
|
||||||
|
|
||||||
<p>Implementation of this protocol is experimental. Use with caution and do not keep
|
|
||||||
any instance of Perf in production configs for long time. The config interface is also unstable
|
|
||||||
and may change in future versions without warning.
|
|
||||||
|
|
||||||
<sect1>Configuration
|
|
||||||
<label id="perf-config">
|
|
||||||
|
|
||||||
<p><descrip>
|
|
||||||
<tag><label id="perf-mode">mode import|export</tag>
|
|
||||||
Set perf mode. Default: import
|
|
||||||
|
|
||||||
<tag><label id="perf-repeat">repeat <m/number/</tag>
|
|
||||||
Run this amount of iterations of the benchmark for every amount step. Default: 4
|
|
||||||
|
|
||||||
<tag><label id="perf-from">exp from <m/number/</tag>
|
|
||||||
Begin benchmarking on this exponent for number of generated routes in one step.
|
|
||||||
Default: 10
|
|
||||||
|
|
||||||
<tag><label id="perf-to">exp to <m/number/</tag>
|
|
||||||
Stop benchmarking on this exponent. Default: 20
|
|
||||||
|
|
||||||
<tag><label id="perf-threshold-min">threshold min <m/time/</tag>
|
|
||||||
If a run for the given exponent took less than this time for route import,
|
|
||||||
increase the exponent immediately. Default: 1 ms
|
|
||||||
|
|
||||||
<tag><label id="perf-threshold-max">threshold max <m/time/</tag>
|
|
||||||
If every run for the given exponent took at least this time for route import,
|
|
||||||
stop benchmarking. Default: 500 ms
|
|
||||||
</descrip>
|
|
||||||
|
|
||||||
<sect>Pipe
|
<sect>Pipe
|
||||||
<label id="pipe">
|
<label id="pipe">
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ void protos_dump_all(void);
|
|||||||
|
|
||||||
extern struct protocol
|
extern struct protocol
|
||||||
proto_device, proto_radv, proto_rip, proto_static, proto_mrt,
|
proto_device, proto_radv, proto_rip, proto_static, proto_mrt,
|
||||||
proto_ospf, proto_perf, proto_l3vpn, proto_aggregator,
|
proto_ospf, proto_l3vpn, proto_aggregator,
|
||||||
proto_pipe, proto_bgp, proto_bmp, proto_bfd, proto_babel, proto_rpki;
|
proto_pipe, proto_bgp, proto_bmp, proto_bfd, proto_babel, proto_rpki;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1 +0,0 @@
|
|||||||
S perf.c
|
|
@ -1,6 +0,0 @@
|
|||||||
src := perf.c
|
|
||||||
obj := $(src-o-files)
|
|
||||||
$(all-daemon)
|
|
||||||
$(cf-local)
|
|
||||||
|
|
||||||
tests_objs := $(tests_objs) $(src-o-files)
|
|
@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* BIRD -- Benchmarking Dummy Protocol Configuration
|
|
||||||
*
|
|
||||||
* (c) 2018 Maria Matejka <mq@jmq.cz>
|
|
||||||
*
|
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
CF_HDR
|
|
||||||
|
|
||||||
#include "filter/filter.h"
|
|
||||||
#include "proto/perf/perf.h"
|
|
||||||
|
|
||||||
CF_DEFINES
|
|
||||||
|
|
||||||
#define PERF_CFG ((struct perf_config *) this_proto)
|
|
||||||
|
|
||||||
CF_DECLS
|
|
||||||
|
|
||||||
CF_KEYWORDS(PERF, EXP, FROM, TO, REPEAT, THRESHOLD, MIN, MAX, KEEP, MODE, IMPORT, EXPORT)
|
|
||||||
|
|
||||||
CF_GRAMMAR
|
|
||||||
|
|
||||||
proto: perf_proto '}' ;
|
|
||||||
|
|
||||||
perf_proto_start: proto_start PERF
|
|
||||||
{
|
|
||||||
this_proto = proto_config_new(&proto_perf, $1);
|
|
||||||
PERF_CFG->from = 10;
|
|
||||||
PERF_CFG->to = 20;
|
|
||||||
PERF_CFG->repeat = 4;
|
|
||||||
PERF_CFG->threshold_max = 500 MS_;
|
|
||||||
PERF_CFG->threshold_min = 1 MS_;
|
|
||||||
PERF_CFG->attrs_per_rte = 0;
|
|
||||||
PERF_CFG->keep = 0;
|
|
||||||
PERF_CFG->mode = PERF_MODE_IMPORT;
|
|
||||||
};
|
|
||||||
|
|
||||||
perf_proto:
|
|
||||||
perf_proto_start proto_name '{'
|
|
||||||
| perf_proto perf_proto_item ';'
|
|
||||||
| perf_proto proto_item ';'
|
|
||||||
;
|
|
||||||
|
|
||||||
perf_proto_item:
|
|
||||||
proto_channel { this_proto->net_type = $1->net_type; }
|
|
||||||
| EXP FROM NUM { PERF_CFG->from = $3; }
|
|
||||||
| EXP TO NUM { PERF_CFG->to = $3; }
|
|
||||||
| REPEAT NUM { PERF_CFG->repeat = $2; }
|
|
||||||
| THRESHOLD MIN expr_us { PERF_CFG->threshold_min = $3; }
|
|
||||||
| THRESHOLD MAX expr_us { PERF_CFG->threshold_max = $3; }
|
|
||||||
| ATTRIBUTES NUM { PERF_CFG->attrs_per_rte = $2; }
|
|
||||||
| KEEP bool { PERF_CFG->keep = $2; }
|
|
||||||
| MODE IMPORT { PERF_CFG->mode = PERF_MODE_IMPORT; }
|
|
||||||
| MODE EXPORT { PERF_CFG->mode = PERF_MODE_EXPORT; }
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
CF_CODE
|
|
||||||
|
|
||||||
CF_END
|
|
@ -1,169 +0,0 @@
|
|||||||
#!/usr/bin/perl
|
|
||||||
|
|
||||||
use File::Temp ();
|
|
||||||
|
|
||||||
package row;
|
|
||||||
|
|
||||||
use Moose;
|
|
||||||
|
|
||||||
has 'exp' => ( is => 'ro', 'isa' => 'Num' );
|
|
||||||
has 'gen' => ( is => 'ro', 'isa' => 'Num' );
|
|
||||||
has 'temp' => ( is => 'ro', 'isa' => 'Num' );
|
|
||||||
has 'update' => ( is => 'ro', 'isa' => 'Num' );
|
|
||||||
has 'withdraw' => ( is => 'ro', 'isa' => 'Num' );
|
|
||||||
|
|
||||||
sub reduce {
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
my $N = 1 << $self->exp;
|
|
||||||
return row->new(
|
|
||||||
exp => $self->exp,
|
|
||||||
gen => $self->gen / $N,
|
|
||||||
temp => $self->temp / $N,
|
|
||||||
update => $self->update / $N,
|
|
||||||
withdraw => $self->withdraw / $N
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub dump {
|
|
||||||
my ($self, $fh) = @_;
|
|
||||||
|
|
||||||
print $fh join ",", $self->exp, $self->gen, $self->temp, $self->update, $self->withdraw;
|
|
||||||
print $fh "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
package results;
|
|
||||||
|
|
||||||
use Moose;
|
|
||||||
|
|
||||||
has 'name' => (
|
|
||||||
is => 'ro',
|
|
||||||
isa => 'Str',
|
|
||||||
required => 1,
|
|
||||||
);
|
|
||||||
|
|
||||||
has 'date' => (
|
|
||||||
is => 'ro',
|
|
||||||
isa => 'Str',
|
|
||||||
required => 1,
|
|
||||||
);
|
|
||||||
|
|
||||||
has 'reduced' => (
|
|
||||||
is => 'ro',
|
|
||||||
isa => 'Bool',
|
|
||||||
default => 0,
|
|
||||||
);
|
|
||||||
|
|
||||||
has 'rows' => (
|
|
||||||
is => 'ro',
|
|
||||||
isa => 'ArrayRef[row]',
|
|
||||||
default => sub { [] },
|
|
||||||
);
|
|
||||||
|
|
||||||
has 'stub' => (
|
|
||||||
is => 'ro',
|
|
||||||
isa => 'Str',
|
|
||||||
lazy => 1,
|
|
||||||
builder => '_build_stub',
|
|
||||||
);
|
|
||||||
|
|
||||||
sub _build_stub {
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
my $date = $self->date;
|
|
||||||
my $name = $self->name;
|
|
||||||
|
|
||||||
my $reduced = "-reduced" if $self->reduced;
|
|
||||||
|
|
||||||
my $stub = $date . "-" . $name . $reduced;
|
|
||||||
|
|
||||||
$stub =~ tr/a-zA-Z0-9_-/@/c;
|
|
||||||
return $stub;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub add {
|
|
||||||
my $self = shift;
|
|
||||||
push @{$self->rows}, row->new(@_);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub reduce {
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
return $self if $self->reduced;
|
|
||||||
|
|
||||||
return results->new(
|
|
||||||
name => $self->name,
|
|
||||||
date => $self->date,
|
|
||||||
reduced => 1,
|
|
||||||
rows => [
|
|
||||||
map { $_->reduce } @{$self->rows}
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub dump {
|
|
||||||
my $self = shift;
|
|
||||||
my $fn = $self->stub . ".csv";
|
|
||||||
|
|
||||||
open my $CSV, ">", $fn;
|
|
||||||
map {
|
|
||||||
$_->dump($CSV);
|
|
||||||
} @{$self->rows};
|
|
||||||
|
|
||||||
close $CSV;
|
|
||||||
return $fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub draw {
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
my $csv = $self->dump();
|
|
||||||
my $svg = $self->stub . ".svg";
|
|
||||||
|
|
||||||
my $title = $self->name;
|
|
||||||
$title =~ s/_/ /g;
|
|
||||||
|
|
||||||
open PLOT, "|-", "gnuplot -p";
|
|
||||||
print PLOT "set terminal svg;\n";
|
|
||||||
print PLOT "set output '$svg';\n";
|
|
||||||
print PLOT "set title '$title';\n";
|
|
||||||
print PLOT "set datafile separator ',';\n";
|
|
||||||
print PLOT "set jitter over 0.3 spread 0.3;\n";
|
|
||||||
print PLOT "plot '$csv' using 1:2 title 'gen', '$csv' using 1:3 title 'temp', '$csv' using 1:4 title 'update', '$csv' using 1:5 title 'withdraw';\n";
|
|
||||||
close PLOT;
|
|
||||||
}
|
|
||||||
|
|
||||||
package main;
|
|
||||||
|
|
||||||
my %results;
|
|
||||||
my @done;
|
|
||||||
|
|
||||||
while (<>) {
|
|
||||||
if (m/(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}).*?Perf (.+) starting$/) {
|
|
||||||
my $date = $1;
|
|
||||||
my $name = $2;
|
|
||||||
die "Garbled input data" if exists $results{$name};
|
|
||||||
$results{$name} = results->new(name => $name, date => $date);
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m/Perf (.+) done with exp=(\d+)$/) {
|
|
||||||
my $name = $1;
|
|
||||||
die "Garbled input data" unless exists $results{$name};
|
|
||||||
push @done, $results{$name};
|
|
||||||
delete $results{$name};
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
my ($name, $exp, $gen, $temp, $update, $withdraw) = m/Perf (.+) exp=(\d+) times: gen=(\d+) temp=(\d+) update=(\d+) withdraw=(\d+)$/ or next;
|
|
||||||
|
|
||||||
exists $results{$name} or die "Garbled input data";
|
|
||||||
|
|
||||||
$results{$name}->add(exp => $exp, gen => $gen, temp => $temp, update => $update, withdraw => $withdraw);
|
|
||||||
}
|
|
||||||
|
|
||||||
scalar %results and die "Incomplete input data";
|
|
||||||
|
|
||||||
foreach my $res (@done) {
|
|
||||||
$res->reduce->draw();
|
|
||||||
}
|
|
@ -1,328 +0,0 @@
|
|||||||
/*
|
|
||||||
* BIRD -- Table-to-Table Routing Protocol a.k.a Pipe
|
|
||||||
*
|
|
||||||
* (c) 1999--2000 Martin Mares <mj@ucw.cz>
|
|
||||||
*
|
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DOC: Perf
|
|
||||||
*
|
|
||||||
* Run this protocol to measure route import and export times.
|
|
||||||
* Generates a load of dummy routes and measures time to import.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#undef LOCAL_DEBUG
|
|
||||||
|
|
||||||
#include "nest/bird.h"
|
|
||||||
#include "nest/iface.h"
|
|
||||||
#include "nest/protocol.h"
|
|
||||||
#include "nest/route.h"
|
|
||||||
#include "nest/cli.h"
|
|
||||||
#include "conf/conf.h"
|
|
||||||
#include "filter/filter.h"
|
|
||||||
#include "lib/string.h"
|
|
||||||
|
|
||||||
#include "perf.h"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#define PLOG(msg, ...) log(L_INFO "Perf %s %s " msg, BIRD_VERSION, p->p.name, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
random_data(void *p, uint len)
|
|
||||||
{
|
|
||||||
uint ints = (len + sizeof(int) - 1) / sizeof(int);
|
|
||||||
int *d = alloca(sizeof(uint) * ints);
|
|
||||||
for (uint i=0; i<ints; i++)
|
|
||||||
d[i] = random();
|
|
||||||
|
|
||||||
memcpy(p, d, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ip_addr
|
|
||||||
random_gw(net_addr *prefix)
|
|
||||||
{
|
|
||||||
ASSERT(net_is_ip(prefix));
|
|
||||||
ip_addr px = net_prefix(prefix);
|
|
||||||
ip_addr mask = net_pxmask(prefix);
|
|
||||||
|
|
||||||
ip_addr out;
|
|
||||||
random_data(&out, sizeof(ip_addr));
|
|
||||||
|
|
||||||
if (ipa_is_ip4(px))
|
|
||||||
out = ipa_and(out, ipa_from_ip4(ip4_mkmask(32)));
|
|
||||||
|
|
||||||
return ipa_or(ipa_and(px, mask), ipa_and(out, ipa_not(mask)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static net_addr_ip4
|
|
||||||
random_net_ip4(void)
|
|
||||||
{
|
|
||||||
u32 x; random_data(&x, sizeof(u32));
|
|
||||||
x &= ((1 << 20) - 1);
|
|
||||||
uint pxlen = u32_log2(x) + 5;
|
|
||||||
|
|
||||||
ip4_addr px; random_data(&px, sizeof(ip4_addr));
|
|
||||||
|
|
||||||
net_addr_ip4 out = {
|
|
||||||
.type = NET_IP4,
|
|
||||||
.pxlen = pxlen,
|
|
||||||
.length = sizeof(net_addr_ip4),
|
|
||||||
.prefix = ip4_and(ip4_mkmask(pxlen), px),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!net_validate((net_addr *) &out))
|
|
||||||
return random_net_ip4();
|
|
||||||
|
|
||||||
int c = net_classify((net_addr *) &out);
|
|
||||||
if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
|
|
||||||
return random_net_ip4();
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct perf_random_routes {
|
|
||||||
ea_list *a;
|
|
||||||
net_addr net;
|
|
||||||
};
|
|
||||||
|
|
||||||
//static const uint perf_random_routes_size = sizeof(struct perf_random_routes) + (RTA_MAX_SIZE - sizeof(struct rta));
|
|
||||||
|
|
||||||
static inline s64 timediff(struct timespec *begin, struct timespec *end)
|
|
||||||
{ return (end->tv_sec - begin->tv_sec) * (s64) 1000000000 + end->tv_nsec - begin->tv_nsec; }
|
|
||||||
|
|
||||||
static void
|
|
||||||
perf_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
|
|
||||||
{
|
|
||||||
struct perf_proto *p = (struct perf_proto *) P;
|
|
||||||
|
|
||||||
if (ad->flags & IA_SECONDARY)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (p->ifa && p->ifa == ad && (flags & IF_CHANGE_DOWN)) {
|
|
||||||
p->ifa = NULL;
|
|
||||||
if (ev_active(p->loop))
|
|
||||||
ev_postpone(p->loop);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!p->ifa && (flags & IF_CHANGE_UP)) {
|
|
||||||
p->ifa = ad;
|
|
||||||
ev_schedule(p->loop);
|
|
||||||
PLOG("starting");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
perf_loop(void *data)
|
|
||||||
{
|
|
||||||
struct proto *P = data;
|
|
||||||
struct perf_proto *p = data;
|
|
||||||
|
|
||||||
const uint N = 1U << p->exp;
|
|
||||||
|
|
||||||
if (!p->run) {
|
|
||||||
ASSERT(p->data == NULL);
|
|
||||||
p->data = xmalloc(sizeof(struct perf_random_routes) * N);
|
|
||||||
p->stop = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ip_addr gw = random_gw(&p->ifa->prefix);
|
|
||||||
|
|
||||||
struct timespec ts_begin, ts_generated, ts_update, ts_withdraw;
|
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts_begin);
|
|
||||||
|
|
||||||
for (uint i=0; i<N; i++) {
|
|
||||||
*((net_addr_ip4 *) &(p->data[i].net)) = random_net_ip4();
|
|
||||||
|
|
||||||
if (!p->attrs_per_rte || !(i % p->attrs_per_rte)) {
|
|
||||||
ea_list *ea = NULL;
|
|
||||||
|
|
||||||
ea_set_attr_u32(&ea, &ea_gen_preference, 0, p->p.main_channel->preference);
|
|
||||||
ea_set_attr_u32(&ea, &ea_gen_source, 0, RTS_PERF);
|
|
||||||
|
|
||||||
struct nexthop_adata nhad = {
|
|
||||||
.nh.iface = p->ifa->iface,
|
|
||||||
.nh.gw = gw,
|
|
||||||
.nh.weight = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
ea_set_attr_data(&ea, &ea_gen_nexthop, 0,
|
|
||||||
&nhad.ad.data, sizeof nhad - sizeof nhad.ad);
|
|
||||||
|
|
||||||
p->data[i].a = ea_lookup(ea, 0, EALS_CUSTOM);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
p->data[i].a = ea_ref(p->data[i-1].a);
|
|
||||||
}
|
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts_generated);
|
|
||||||
|
|
||||||
for (uint i=0; i<N; i++)
|
|
||||||
{
|
|
||||||
rte e0 = { .attrs = p->data[i].a, .src = P->main_source, };
|
|
||||||
rte_update(P->main_channel, &(p->data[i].net), &e0, P->main_source);
|
|
||||||
}
|
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts_update);
|
|
||||||
|
|
||||||
if (!p->keep)
|
|
||||||
for (uint i=0; i<N; i++)
|
|
||||||
rte_update(P->main_channel, &(p->data[i].net), NULL, P->main_source);
|
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts_withdraw);
|
|
||||||
|
|
||||||
s64 gentime = timediff(&ts_begin, &ts_generated);
|
|
||||||
s64 updatetime = timediff(&ts_generated, &ts_update);
|
|
||||||
s64 withdrawtime = timediff(&ts_update, &ts_withdraw);
|
|
||||||
|
|
||||||
if (updatetime NS >= p->threshold_min)
|
|
||||||
PLOG("exp=%u times: gen=%ld update=%ld withdraw=%ld",
|
|
||||||
p->exp, gentime, updatetime, withdrawtime);
|
|
||||||
|
|
||||||
if (updatetime NS < p->threshold_max)
|
|
||||||
p->stop = 0;
|
|
||||||
|
|
||||||
if ((updatetime NS < p->threshold_min) || (++p->run == p->repeat)) {
|
|
||||||
xfree(p->data);
|
|
||||||
p->data = NULL;
|
|
||||||
|
|
||||||
if (p->stop || (p->exp == p->to)) {
|
|
||||||
PLOG("done with exp=%u", p->exp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
p->run = 0;
|
|
||||||
p->exp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
RT_LOCKED(P->main_channel->table, tab)
|
|
||||||
rt_schedule_prune(tab);
|
|
||||||
|
|
||||||
ev_schedule(p->loop);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
perf_rt_notify(struct proto *P, struct channel *c UNUSED, const net_addr *net UNUSED, struct rte *new UNUSED, const struct rte *old UNUSED)
|
|
||||||
{
|
|
||||||
struct perf_proto *p = (struct perf_proto *) P;
|
|
||||||
p->exp++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
perf_feed_begin(struct channel *c)
|
|
||||||
{
|
|
||||||
struct perf_proto *p = (struct perf_proto *) c->proto;
|
|
||||||
|
|
||||||
p->run++;
|
|
||||||
p->feed_begin = xmalloc(sizeof(struct timespec));
|
|
||||||
p->exp = 0;
|
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, p->feed_begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
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->feed_begin, &ts_end);
|
|
||||||
|
|
||||||
PLOG("feed n=%lu time=%lu", p->exp, feedtime);
|
|
||||||
|
|
||||||
xfree(p->feed_begin);
|
|
||||||
p->feed_begin = NULL;
|
|
||||||
|
|
||||||
if (p->run < p->repeat)
|
|
||||||
channel_request_feeding_dynamic(c, CFRT_DIRECT);
|
|
||||||
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));
|
|
||||||
|
|
||||||
struct perf_proto *p = (struct perf_proto *) P;
|
|
||||||
|
|
||||||
p->loop = ev_new_init(P->pool, perf_loop, p);
|
|
||||||
|
|
||||||
struct perf_config *cf = (struct perf_config *) CF;
|
|
||||||
|
|
||||||
p->threshold_min = cf->threshold_min;
|
|
||||||
p->threshold_max = cf->threshold_max;
|
|
||||||
p->from = cf->from;
|
|
||||||
p->to = cf->to;
|
|
||||||
p->repeat = cf->repeat;
|
|
||||||
p->keep = cf->keep;
|
|
||||||
p->mode = cf->mode;
|
|
||||||
p->attrs_per_rte = cf->attrs_per_rte;
|
|
||||||
|
|
||||||
switch (p->mode) {
|
|
||||||
case PERF_MODE_IMPORT:
|
|
||||||
P->iface_sub.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
perf_start(struct proto *P)
|
|
||||||
{
|
|
||||||
struct perf_proto *p = (struct perf_proto *) P;
|
|
||||||
|
|
||||||
p->ifa = NULL;
|
|
||||||
p->run = 0;
|
|
||||||
p->exp = p->from;
|
|
||||||
ASSERT(p->data == NULL);
|
|
||||||
|
|
||||||
return PS_UP;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
perf_reconfigure(struct proto *P UNUSED, struct proto_config *CF UNUSED)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
perf_copy_config(struct proto_config *dest UNUSED, struct proto_config *src UNUSED)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
struct protocol proto_perf = {
|
|
||||||
.name = "Perf",
|
|
||||||
.template = "perf%d",
|
|
||||||
.channel_mask = NB_IP,
|
|
||||||
.proto_size = sizeof(struct perf_proto),
|
|
||||||
.config_size = sizeof(struct perf_config),
|
|
||||||
.init = perf_init,
|
|
||||||
.start = perf_start,
|
|
||||||
.reconfigure = perf_reconfigure,
|
|
||||||
.copy_config = perf_copy_config,
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
perf_build(void)
|
|
||||||
{
|
|
||||||
proto_build(&proto_perf);
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* BIRD -- Benchmarking Dummy Protocol
|
|
||||||
*
|
|
||||||
* (c) 2018 Maria Matejka <mq@jmq.cz>
|
|
||||||
*
|
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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;
|
|
||||||
btime threshold_max;
|
|
||||||
uint from;
|
|
||||||
uint to;
|
|
||||||
uint repeat;
|
|
||||||
uint keep;
|
|
||||||
uint attrs_per_rte;
|
|
||||||
enum perf_mode mode;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct perf_proto {
|
|
||||||
struct proto p;
|
|
||||||
struct ifa *ifa;
|
|
||||||
struct perf_random_routes *data;
|
|
||||||
struct timespec *feed_begin;
|
|
||||||
event *loop;
|
|
||||||
btime threshold_min;
|
|
||||||
btime threshold_max;
|
|
||||||
uint from;
|
|
||||||
uint to;
|
|
||||||
uint repeat;
|
|
||||||
uint run;
|
|
||||||
uint exp;
|
|
||||||
uint stop;
|
|
||||||
uint keep;
|
|
||||||
uint attrs_per_rte;
|
|
||||||
enum perf_mode mode;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in New Issue
Block a user