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