Commit df7c427d authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Add reference counting to the source table.

This avoids the quadratic behaviour of expire_sources.
parent 5a3400fc
......@@ -237,13 +237,17 @@ flush_route(struct route *route)
if(lost)
route_lost(src, oldmetric);
release_source(src);
}
void
flush_all_routes()
{
int i;
/* Start from the end, to avoid shifting the table. */
int i = route_slots - 1;
i = route_slots - 1;
while(i >= 0) {
while(i < route_slots) {
/* Uninstall first, to avoid calling route_lost. */
......@@ -253,6 +257,8 @@ flush_all_routes()
}
i--;
}
check_sources_released();
}
void
......@@ -326,24 +332,6 @@ for_all_installed_routes(void (*f)(struct route*, void*), void *closure)
}
}
/* Find any route with a given source. This should go when we fix our
data structures. */
struct route *
find_route_with_source(struct source *src)
{
int i;
for(i = 0; i < route_slots; i++) {
struct route *r = routes[i];
while(r) {
if(r->src == src)
return r;
r = r->next;
}
}
return NULL;
}
static int
metric_to_kernel(int metric)
{
......@@ -723,7 +711,7 @@ update_route(const unsigned char *a, const unsigned char *p, unsigned char plen,
}
}
route->src = src;
route->src = retain_source(src);
if((feasible || keep_unfeasible) && refmetric < INFINITY)
route->time = now.tv_sec;
route->seqno = seqno;
......@@ -738,6 +726,7 @@ update_route(const unsigned char *a, const unsigned char *p, unsigned char plen,
if(!feasible)
send_unfeasible_request(neigh, route->installed && route_old(route),
seqno, metric, src);
release_source(oldsrc);
} else {
struct route *new_route;
......@@ -756,7 +745,7 @@ update_route(const unsigned char *a, const unsigned char *p, unsigned char plen,
return NULL;
}
route->src = src;
route->src = retain_source(src);
route->refmetric = refmetric;
route->cost = neighbour_cost(neigh);
route->add_metric = add_metric;
......
......@@ -75,7 +75,6 @@ void flush_neighbour_routes(struct neighbour *neigh);
void flush_interface_routes(struct interface *ifp, int v4only);
void for_all_routes(void (*f)(struct route*, void*), void *closure);
void for_all_installed_routes(void (*f)(struct route*, void*), void *closure);
struct route *find_route_with_source(struct source *src);
void install_route(struct route *route);
void uninstall_route(struct route *route);
void switch_route(struct route *old, struct route *new);
......
......@@ -24,6 +24,7 @@ THE SOFTWARE.
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <assert.h>
#include "babeld.h"
#include "util.h"
......@@ -67,17 +68,32 @@ find_source(const unsigned char *id, const unsigned char *p, unsigned char plen,
src->seqno = seqno;
src->metric = INFINITY;
src->time = now.tv_sec;
src->route_count = 0;
src->next = srcs;
srcs = src;
return src;
}
struct source *
retain_source(struct source *src)
{
assert(src->route_count < 0xffff);
src->route_count++;
return src;
}
void
release_source(struct source *src)
{
assert(src->route_count > 0);
src->route_count--;
}
int
flush_source(struct source *src)
{
/* This is absolutely horrible -- it makes expire_sources quadratic.
But it's not called very often. */
if(find_route_with_source(src))
if(src->route_count > 0)
/* The source is in use by a route. */
return 0;
if(srcs == src) {
......@@ -128,3 +144,17 @@ expire_sources()
src = src->next;
}
}
void
check_sources_released(void)
{
struct source *src;
for(src = srcs; src; src = src->next) {
if(src->route_count != 0)
fprintf(stderr, "Warning: source %s %s has refcount %d.\n",
format_eui64(src->id),
format_prefix(src->prefix, src->plen),
(int)src->route_count);
}
}
......@@ -29,6 +29,7 @@ struct source {
unsigned char plen;
unsigned short seqno;
unsigned short metric;
unsigned short route_count;
time_t time;
};
......@@ -36,7 +37,10 @@ struct source *find_source(const unsigned char *id,
const unsigned char *p,
unsigned char plen,
int create, unsigned short seqno);
struct source *retain_source(struct source *src);
void release_source(struct source *src);
int flush_source(struct source *src);
void update_source(struct source *src,
unsigned short seqno, unsigned short metric);
void expire_sources(void);
void check_sources_released(void);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment