Commit ec7519a4 authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Use streams for iterating over routes.

parent 5b1869b9
......@@ -990,9 +990,8 @@ init_signals(void)
}
static void
dump_route_callback(struct babel_route *route, void *closure)
dump_route(FILE *out, struct babel_route *route)
{
FILE *out = (FILE*)closure;
const unsigned char *nexthop =
memcmp(route->nexthop, route->neigh->address, 16) == 0 ?
NULL : route->nexthop;
......@@ -1046,6 +1045,7 @@ static void
dump_tables(FILE *out)
{
struct neighbour *neigh;
struct route_stream *routes;
fprintf(out, "\n");
......@@ -1065,7 +1065,15 @@ dump_tables(FILE *out)
if_up(neigh->ifp) ? "" : " (down)");
}
for_all_xroutes(dump_xroute_callback, out);
for_all_routes(dump_route_callback, out);
routes = route_stream(0);
if(routes) {
while(1) {
struct babel_route *route = route_stream_next(routes);
if(route == NULL) break;
dump_route(out, route);
}
route_stream_done(routes);
}
fflush(out);
}
......
......@@ -259,18 +259,13 @@ local_notify_xroute_callback(struct xroute *xroute, void *closure)
local_notify_xroute_1(*(int*)closure, xroute, LOCAL_ADD);
}
static void
local_notify_route_callback(struct babel_route *route, void *closure)
{
local_notify_route_1(*(int*)closure, route, LOCAL_ADD);
}
void
local_notify_all_1(int s)
{
int rc;
struct neighbour *neigh;
const char *header = "BABEL 0.0\n";
struct route_stream *routes;
rc = write_timeout(s, header, strlen(header));
if(rc < 0)
......@@ -281,7 +276,16 @@ local_notify_all_1(int s)
local_notify_neighbour_1(s, neigh, LOCAL_ADD);
}
for_all_xroutes(local_notify_xroute_callback, &s);
for_all_routes(local_notify_route_callback, &s);
routes = route_stream(0);
if(routes) {
while(1) {
struct babel_route *route = route_stream_next(routes);
if(route == NULL)
break;
local_notify_route_1(s, route, LOCAL_ADD);
}
route_stream_done(routes);
}
rc = write_timeout(s, "done\n", 5);
if(rc < 0)
goto fail;
......
......@@ -1278,13 +1278,6 @@ buffer_update(struct interface *ifp,
ifp->num_buffered_updates++;
}
static void
buffer_update_callback(struct babel_route *route, void *closure)
{
buffer_update((struct interface*)closure,
route->src->prefix, route->src->plen);
}
void
send_update(struct interface *ifp, int urgent,
const unsigned char *prefix, unsigned char plen)
......@@ -1313,9 +1306,21 @@ send_update(struct interface *ifp, int urgent,
ifp->name, format_prefix(prefix, plen));
buffer_update(ifp, prefix, plen);
} else {
struct route_stream *routes;
send_self_update(ifp);
debugf("Sending update to %s for any.\n", ifp->name);
for_all_installed_routes(buffer_update_callback, ifp);
routes = route_stream(1);
if(routes) {
while(1) {
struct babel_route *route = route_stream_next(routes);
if(route == NULL)
break;
buffer_update(ifp, route->src->prefix, route->src->plen);
}
route_stream_done(routes);
} else {
fprintf(stderr, "Couldn't allocate route stream.\n");
}
set_timeout(&ifp->update_timeout, ifp->update_interval);
ifp->last_update_time = now.tv_sec;
}
......
......@@ -316,30 +316,58 @@ flush_interface_routes(struct interface *ifp, int v4only)
}
}
/* Iterate a function over all routes. */
void
for_all_routes(void (*f)(struct babel_route*, void*), void *closure)
struct route_stream {
int installed;
int index;
struct babel_route *next;
};
struct route_stream *
route_stream(int installed)
{
int i, n = route_slots;
struct route_stream *stream;
for(i = 0; i < n; i++) {
struct babel_route *r = routes[i];
while(r) {
(*f)(r, closure);
r = r->next;
stream = malloc(sizeof(struct route_stream));
if(stream == NULL)
return NULL;
stream->installed = installed;
stream->index = installed ? 0 : -1;
stream->next = NULL;
return stream;
}
struct babel_route *
route_stream_next(struct route_stream *stream)
{
if(stream->installed) {
while(stream->index < route_slots && !routes[stream->index]->installed)
stream->index++;
if(stream->index < route_slots)
return routes[stream->index++];
else
return NULL;
} else {
struct babel_route *next;
if(!stream->next) {
stream->index++;
if(stream->index >= route_slots)
return NULL;
stream->next = routes[stream->index];
}
next = stream->next;
stream->next = next->next;
return next;
}
}
void
for_all_installed_routes(void (*f)(struct babel_route*, void*), void *closure)
route_stream_done(struct route_stream *stream)
{
int i, n = route_slots;
for(i = 0; i < n; i++) {
if(routes[i]->installed)
(*f)(routes[i], closure);
}
free(stream);
}
static int
......
......@@ -44,6 +44,8 @@ struct babel_route {
struct babel_route *next;
};
struct route_stream;
extern struct babel_route **routes;
extern int kernel_metric, allow_duplicates;
extern int diversity_kind, diversity_factor;
......@@ -76,8 +78,9 @@ void flush_route(struct babel_route *route);
void flush_all_routes(void);
void flush_neighbour_routes(struct neighbour *neigh);
void flush_interface_routes(struct interface *ifp, int v4only);
void for_all_routes(void (*f)(struct babel_route*, void*), void *closure);
void for_all_installed_routes(void (*f)(struct babel_route*, void*), void *closure);
struct route_stream *route_stream(int installed);
struct babel_route *route_stream_next(struct route_stream *stream);
void route_stream_done(struct route_stream *stream);
void install_route(struct babel_route *route);
void uninstall_route(struct babel_route *route);
void switch_route(struct babel_route *old, struct babel_route *new);
......
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