Commit a726ccd5 authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Sort list of imported routes before generating xroutes.

This allows walking the two lists in parallel.
parent d49b3651
...@@ -33,6 +33,7 @@ THE SOFTWARE. ...@@ -33,6 +33,7 @@ THE SOFTWARE.
#include "interface.h" #include "interface.h"
#include "neighbour.h" #include "neighbour.h"
#include "message.h" #include "message.h"
#include "source.h"
#include "route.h" #include "route.h"
#include "xroute.h" #include "xroute.h"
#include "util.h" #include "util.h"
...@@ -122,13 +123,8 @@ add_xroute(unsigned char prefix[16], unsigned char plen, ...@@ -122,13 +123,8 @@ add_xroute(unsigned char prefix[16], unsigned char plen,
int n = -1; int n = -1;
int i = find_xroute_slot(prefix, plen, src_prefix, src_plen, &n); int i = find_xroute_slot(prefix, plen, src_prefix, src_plen, &n);
if(i >= 0) { if(i >= 0)
if(xroutes[i].metric <= metric) return -1;
return 0;
xroutes[i].metric = metric;
local_notify_xroute(&xroutes[i], LOCAL_CHANGE);
return 1;
}
if(numxroutes >= maxxroutes) { if(numxroutes >= maxxroutes) {
struct xroute *new_xroutes; struct xroute *new_xroutes;
...@@ -308,10 +304,39 @@ kernel_addresses(int ifindex, int ll, struct kernel_route *routes, ...@@ -308,10 +304,39 @@ kernel_addresses(int ifindex, int ll, struct kernel_route *routes,
return found; return found;
} }
/* This must coincide with the ordering defined by xroute_compare above. */
static int
kernel_route_compare(const void *v1, const void *v2)
{
const struct kernel_route *route1 = (struct kernel_route*)v1;
const struct kernel_route *route2 = (struct kernel_route*)v2;
int rc;
if(route1->plen < route2->plen)
return -1;
if(route1->plen > route2->plen)
return 1;
rc = memcmp(route1->prefix, route2->prefix, 16);
if(rc != 0)
return rc;
if(route1->src_plen < route2->src_plen)
return -1;
if(route1->src_plen > route2->src_plen)
return 1;
rc = memcmp(route1->src_prefix, route2->src_prefix, 16);
if(rc != 0)
return rc;
return 0;
}
int int
check_xroutes(int send_updates) check_xroutes(int send_updates)
{ {
int i, j, metric, export, change = 0, rc; int i, j, change = 0, rc;
struct kernel_route *routes; struct kernel_route *routes;
struct filter_result filter_result; struct filter_result filter_result;
int numroutes, numaddresses; int numroutes, numaddresses;
...@@ -350,39 +375,58 @@ check_xroutes(int send_updates) ...@@ -350,39 +375,58 @@ check_xroutes(int send_updates)
/* Apply filter to kernel routes (e.g. change the source prefix). */ /* Apply filter to kernel routes (e.g. change the source prefix). */
for(i = numaddresses; i < numroutes; i++) { for(i = numaddresses; i < numroutes; i++) {
redistribute_filter(routes[i].prefix, routes[i].plen, routes[i].metric = redistribute_filter(routes[i].prefix, routes[i].plen,
routes[i].src_prefix, routes[i].src_plen, routes[i].src_prefix,
routes[i].ifindex, routes[i].proto, routes[i].src_plen,
&filter_result); routes[i].ifindex,
if(filter_result.src_prefix) { routes[i].proto,
&filter_result);
if(filter_result.src_prefix != NULL) {
memcpy(routes[i].src_prefix, filter_result.src_prefix, 16); memcpy(routes[i].src_prefix, filter_result.src_prefix, 16);
routes[i].src_plen = filter_result.src_plen; routes[i].src_plen = filter_result.src_plen;
} }
} }
/* Check for any routes that need to be flushed */ qsort(routes, numroutes, sizeof(struct kernel_route), kernel_route_compare);
i = 0; i = 0;
while(i < numxroutes) { j = 0;
export = 0; while(i < numroutes || j < numxroutes) {
metric = redistribute_filter(xroutes[i].prefix, xroutes[i].plen, if(i >= numroutes)
xroutes[i].src_prefix, xroutes[i].src_plen, rc = +1;
xroutes[i].ifindex, xroutes[i].proto, else if(j >= numxroutes)
NULL); rc = -1;
if(metric < INFINITY && metric == xroutes[i].metric) { else
for(j = 0; j < numroutes; j++) { rc = xroute_compare(routes[i].prefix, routes[i].plen,
if(xroutes[i].plen == routes[j].plen && routes[i].src_prefix, routes[i].src_plen,
memcmp(xroutes[i].prefix, routes[j].prefix, 16) == 0 && &xroutes[j]);
xroutes[i].ifindex == routes[j].ifindex && if(rc < 0) {
xroutes[i].proto == routes[j].proto) { /* Add route i. */
export = 1; if(!martian_prefix(routes[i].prefix, routes[i].plen) &&
break; routes[i].metric < INFINITY) {
rc = add_xroute(routes[i].prefix, routes[i].plen,
routes[i].src_prefix, routes[i].src_plen,
routes[i].metric, routes[i].ifindex,
routes[i].proto);
if(rc > 0) {
struct babel_route *route;
route = find_installed_route(routes[i].prefix,
routes[i].plen,
routes[i].src_prefix,
routes[i].src_plen);
if(route) {
if(allow_duplicates < 0 ||
routes[i].metric < allow_duplicates)
uninstall_route(route);
}
if(send_updates)
send_update(NULL, 0, routes[i].prefix, routes[i].plen,
routes[i].src_prefix, routes[i].src_plen);
j++;
} }
} }
} i++;
} else if(rc > 0) {
if(!export) { /* Flush xroute j. */
unsigned char prefix[16], plen; unsigned char prefix[16], plen;
unsigned char src_prefix[16], src_plen; unsigned char src_prefix[16], src_plen;
struct babel_route *route; struct babel_route *route;
...@@ -390,47 +434,32 @@ check_xroutes(int send_updates) ...@@ -390,47 +434,32 @@ check_xroutes(int send_updates)
plen = xroutes[i].plen; plen = xroutes[i].plen;
memcpy(src_prefix, xroutes[i].src_prefix, 16); memcpy(src_prefix, xroutes[i].src_prefix, 16);
src_plen = xroutes[i].src_plen; src_plen = xroutes[i].src_plen;
flush_xroute(&xroutes[i]); flush_xroute(&xroutes[j]);
route = find_best_route(prefix, plen, src_prefix, src_plen, 1,NULL); route = find_best_route(prefix, plen, src_prefix, src_plen,
if(route) 1, NULL);
if(route != NULL) {
install_route(route); install_route(route);
/* send_update_resend only records the prefix, so the update send_update(NULL, 0, prefix, plen, src_prefix, src_plen);
will only be sent after we perform all of the changes. */ } else {
if(send_updates)
send_update_resend(NULL, prefix, plen, src_prefix, src_plen); send_update_resend(NULL, prefix, plen, src_prefix, src_plen);
change = 1; }
} else { } else {
i++; /* It fits */
} if(routes[i].metric >= INFINITY) {
} flush_xroute(&xroutes[j]);
} else if(routes[i].metric != xroutes[j].metric ||
/* Add any new routes */ routes[i].proto != xroutes[j].proto) {
xroutes[j].metric = routes[i].metric;
for(i = 0; i < numroutes; i++) { xroutes[j].proto = routes[i].proto;
if(martian_prefix(routes[i].prefix, routes[i].plen)) local_notify_xroute(&xroutes[j], LOCAL_CHANGE);
continue;
metric = redistribute_filter(routes[i].prefix, routes[i].plen,
routes[i].src_prefix, routes[i].src_plen,
routes[i].ifindex, routes[i].proto, NULL);
if(metric < INFINITY) {
rc = add_xroute(routes[i].prefix, routes[i].plen,
routes[i].src_prefix, routes[i].src_plen,
metric, routes[i].ifindex, routes[i].proto);
if(rc > 0) {
struct babel_route *route;
route = find_installed_route(routes[i].prefix, routes[i].plen,
routes[i].src_prefix,
routes[i].src_plen);
if(route) {
if(allow_duplicates < 0 ||
routes[i].metric < allow_duplicates)
uninstall_route(route);
}
change = 1;
if(send_updates) if(send_updates)
send_update(NULL, 0, routes[i].prefix, routes[i].plen, send_update(NULL, 0, xroutes[j].prefix, xroutes[j].plen,
routes[i].src_prefix, routes[i].src_plen); xroutes[j].src_prefix, xroutes[j].src_plen);
j++;
} else {
j++;
} }
i++;
} }
} }
......
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