diff --git a/nest/rt-fib.c b/nest/rt-fib.c index 48091d43..a8800b65 100644 --- a/nest/rt-fib.c +++ b/nest/rt-fib.c @@ -58,11 +58,52 @@ #include "nest/route.h" #include "lib/string.h" +/* + * The FIB rehash values are maintaining FIB count between N/5 and 2N. What + * does it mean? + * + * +------------+--------+---------+-----------+----------+-----------+ + * | Table size | Memory | Min cnt | net + rte | Max cnt | net + rte | + * +------------+--------+---------+-----------+----------+-----------+ + * | 1k | 8k | 0 | 0 | 2k | 192 k | + * | 2k | 16k | 409 | 38.3k | 4k | 384 k | + * | 4k | 32k | 819 | 76.8k | 8k | 768 k | + * | 8k | 64k | 1.6k | 153.6k | 16k | 1.5M | + * | 16k | 128k | 3.2k | 307.1k | 32k | 3 M | + * | 32k | 256k | 6.4k | 614.3k | 64k | 6 M | + * | 64k | 512k | 12.8k | 1.2M | 128k | 12 M | + * | 128k | 1024k | 25.6k | 2.4M | 256k | 24 M | + * | 256k | 2M | 51.2k | 4.8M | 512k | 48 M | + * | 512k | 4M | 102.4k | 9.6M | 1M | 96 M | + * | 1M | 8M | 204.8k | 19.2M | 2M | 192 M | + * | 2M | 16M | 409.6k | 38.4M | 4M | 384 M | + * | 4M | 32M | 819.2k | 76.8M | 8M | 768 M | + * | 8M | 64M | 1.6M | 153.6M | infinity | infinity | + * +------------+--------+---------+-----------+----------+-----------+ + * + * Table size shows how many slots are in FIB table. + * Memory shows how much memory is eaten by FIB table. + * Min cnt minimal number of nets in table of given size + * Max cnt maximal number of nets in table of given size + * net + rte memory eaten by 1 net and one route in it for min cnt and max cnt + * + * Example: If we have 750,000 network entries in a table: + * * the table size may be 512k if we have never had more + * * the table size may be 1M or 2M if we at least happened to have more + * * 256k is too small, 8M is too big + * + * When growing, rehash is done on demand so we do it on every power of 2. + * When shrinking, rehash is done on delete which is done (in global tables) + * in a scheduled event. Rehashing down 2 steps. + * + */ + + #define HASH_DEF_ORDER 10 -#define HASH_HI_MARK *4 -#define HASH_HI_STEP 2 +#define HASH_HI_MARK * 2 +#define HASH_HI_STEP 1 #define HASH_HI_MAX 24 -#define HASH_LO_MARK /5 +#define HASH_LO_MARK / 5 #define HASH_LO_STEP 2 #define HASH_LO_MIN 10 diff --git a/nest/rt-table.c b/nest/rt-table.c index 194eadf8..a1900532 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -405,8 +405,6 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int si rt = rt0; *rt_free = NULL; - rte_make_tmp_attrs(&rt, pool); - v = p->preexport ? p->preexport(p, &rt, pool) : 0; if (v < 0) { @@ -425,6 +423,8 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int si goto accept; } + rte_make_tmp_attrs(&rt, pool); + v = filter && ((filter == FILTER_REJECT) || (f_run(filter, &rt, pool, (silent ? FF_SILENT : 0)) > F_ACCEPT)); @@ -1368,7 +1368,10 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) rte_update_lock(); if (new) { - nn = net_get(c->table, n); + /* Create a temporary table node */ + nn = alloca(sizeof(net) + n->length); + memset(nn, 0, sizeof(net) + n->length); + net_copy(nn->n.addr, n); new->net = nn; new->sender = c; @@ -1419,6 +1422,10 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) if (!rta_is_cached(new->attrs)) /* Need to copy attributes */ new->attrs = rta_lookup(new->attrs); new->flags |= REF_COW; + + /* Use the actual struct network, not the dummy one */ + nn = net_get(c->table, n); + new->net = nn; } else { @@ -1433,16 +1440,21 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) } recalc: + /* And recalculate the best route */ rte_hide_dummy_routes(nn, &dummy); rte_recalculate(c, nn, new, src); rte_unhide_dummy_routes(nn, &dummy); + rte_update_unlock(); return; drop: rte_free(new); new = NULL; - goto recalc; + if (nn = net_find(c->table, n)) + goto recalc; + + rte_update_unlock(); } /* Independent call to rte_announce(), used from next hop @@ -1499,12 +1511,14 @@ rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter) rte_update_lock(); /* Rest is stripped down export_filter() */ - rte_make_tmp_attrs(&rt, rte_update_pool); int v = p->preexport ? p->preexport(p, &rt, rte_update_pool) : 0; if (v == RIC_PROCESS) + { + rte_make_tmp_attrs(&rt, rte_update_pool); v = (f_run(filter, &rt, rte_update_pool, FF_SILENT) <= F_ACCEPT); + } - /* Discard temporary rte */ + /* Discard temporary rte */ if (rt != n->routes) rte_free(rt); diff --git a/proto/perf/config.Y b/proto/perf/config.Y index 617b2233..60a96c11 100644 --- a/proto/perf/config.Y +++ b/proto/perf/config.Y @@ -38,6 +38,7 @@ perf_proto_start: proto_start PERF perf_proto: perf_proto_start proto_name '{' | perf_proto perf_proto_item ';' + | perf_proto proto_item ';' ; perf_proto_item: diff --git a/proto/perf/perf.c b/proto/perf/perf.c index 6741f7cb..8412254a 100644 --- a/proto/perf/perf.c +++ b/proto/perf/perf.c @@ -29,7 +29,7 @@ #include #include -#define PLOG(msg, ...) log(L_INFO "Perf %s " msg, p->p.name, ##__VA_ARGS__) +#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) @@ -206,6 +206,7 @@ perf_loop(void *data) p->exp++; } + rt_schedule_prune(P->main_channel->table); ev_schedule(p->loop); }