Commit febf623a authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Implement proper redistribution of routes.

Xroutes are now generated dynamically as needed.
parent 70a28d7c
...@@ -24,6 +24,7 @@ THE SOFTWARE. ...@@ -24,6 +24,7 @@ THE SOFTWARE.
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <assert.h>
#include "babel.h" #include "babel.h"
#include "kernel.h" #include "kernel.h"
...@@ -32,73 +33,119 @@ THE SOFTWARE. ...@@ -32,73 +33,119 @@ THE SOFTWARE.
#include "route.h" #include "route.h"
#include "xroute.h" #include "xroute.h"
#include "util.h" #include "util.h"
#include "filter.h"
struct xroute xroutes[MAXXROUTES]; struct xroute xroutes[MAXXROUTES];
int numxroutes = 0; int numxroutes = 0;
struct xroute * struct xroute *
find_exported_xroute(const unsigned char *prefix, unsigned char plen) find_xroute(const unsigned char *prefix, unsigned char plen)
{ {
int i; int i;
for(i = 0; i < numxroutes; i++) { for(i = 0; i < numxroutes; i++) {
if(xroutes[i].exported) { if(xroutes[i].plen == plen &&
if(xroutes[i].plen == plen && memcmp(xroutes[i].prefix, prefix, 16) == 0)
memcmp(xroutes[i].prefix, prefix, 16) == 0) return &xroutes[i];
return &xroutes[i];
}
} }
return NULL; return NULL;
} }
void
flush_xroute(struct xroute *xroute)
{
int n;
n = xroute - xroutes;
assert(n >= 0 && n < numxroutes);
if(n != numxroutes - 1)
memcpy(xroutes + n, xroutes + numxroutes - 1, sizeof(struct xroute));
numxroutes--;
VALGRIND_MAKE_MEM_UNDEFINED(xroutes + numxroutes, sizeof(struct xroute));
}
int int
check_xroutes() add_xroute(unsigned char prefix[16], unsigned char plen,
unsigned short metric, unsigned int ifindex, int proto)
{ {
int i, j, n, change; struct xroute *xroute = find_xroute(prefix, plen);
struct kernel_route routes[120]; if(xroute) {
if(xroute->metric <= metric)
return 0;
if(xroute->forced)
return 0;
xroute->metric = metric;
return 1;
}
debugf("\nChecking kernel routes.\n"); if(numxroutes >= MAXXROUTES)
return -1;
n = -1; memcpy(xroutes[numxroutes].prefix, prefix, 16);
for(i = 0; i < numxroutes; i++) xroutes[numxroutes].plen = plen;
if(xroutes[i].exported < 2) xroutes[numxroutes].forced = 0;
n = MAX(n, xroutes[i].plen); xroutes[numxroutes].metric = metric;
xroutes[numxroutes].ifindex = ifindex;
xroutes[numxroutes].proto = proto;
numxroutes++;
return 1;
}
if(n < 0) int
return 0; check_xroutes()
{
int i, j, n, metric, export, change = 0, rc;
struct kernel_route routes[240];
n = kernel_routes(n, routes, 120); debugf("\nChecking kernel routes.\n");
n = kernel_routes(routes, 240);
if(n < 0) if(n < 0)
return -1; return -1;
change = 0; i = 0;
for(i = 0; i < numxroutes; i++) { while(i < numxroutes) {
int export; if(xroutes[i].forced) {
if(xroutes[i].exported == 2) i++;
continue; continue;
}
export = 0; export = 0;
for(j = 0; j < n; j++) { metric = redistribute_filter(xroutes[i].prefix, xroutes[i].plen,
if(xroutes[i].plen == routes[j].plen && xroutes[i].ifindex, xroutes[i].proto);
memcmp(xroutes[i].prefix, routes[j].prefix, 16) == 0) { if((metric < INFINITY && metric == xroutes[i].metric) ||
export = 1; metric == METRIC_INHERIT) {
break; for(j = 0; j < n; j++) {
if(xroutes[i].plen == routes[j].plen &&
memcmp(xroutes[i].prefix, routes[j].prefix, 16) == 0 &&
xroutes[i].ifindex == routes[j].ifindex &&
xroutes[i].proto == routes[j].proto) {
if(metric < INFINITY ||
(metric == METRIC_INHERIT &&
xroutes[i].metric == routes[j].metric)) {
export = 1;
break;
}
}
} }
} }
if(xroutes[i].exported != export) { if(!export) {
xroutes[i].exported = export; flush_xroute(&xroutes[i]);
if(export) {
struct route *route;
route = find_installed_route(xroutes[i].prefix,
xroutes[i].plen);
if(route)
uninstall_route(route);
} else {
struct route *route;
route = find_best_route(xroutes[i].prefix, xroutes[i].plen);
if(route)
install_route(route);
}
send_update(NULL, 1, xroutes[i].prefix, xroutes[i].plen);
change = 1; change = 1;
} else {
i++;
}
}
for(i = 0; i < n; i++) {
metric = redistribute_filter(routes[i].prefix, routes[i].plen,
routes[i].ifindex, routes[i].proto);
if(metric == METRIC_INHERIT)
metric = routes[i].metric;
if(metric < INFINITY) {
rc = add_xroute(routes[i].prefix, routes[i].plen,
metric, routes[i].ifindex, routes[i].proto);
if(rc)
change = 1;
} }
} }
return change; return change;
......
...@@ -25,13 +25,14 @@ int check_xroutes(void); ...@@ -25,13 +25,14 @@ int check_xroutes(void);
struct xroute { struct xroute {
unsigned char prefix[16]; unsigned char prefix[16];
unsigned char plen; unsigned char plen;
char exported; char forced;
unsigned short metric; unsigned short metric;
unsigned int ifindex;
int proto;
}; };
extern struct xroute xroutes[MAXXROUTES]; extern struct xroute xroutes[MAXXROUTES];
extern int numxroutes; extern int numxroutes;
struct xroute *find_exported_xroute(const unsigned char *prefix, struct xroute *find_xroute(const unsigned char *prefix, unsigned char plen);
unsigned char plen);
int check_xroutes(void); int check_xroutes(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