Commit b8e832cb authored by Matthieu Boutier's avatar Matthieu Boutier Committed by Juliusz Chroboczek

Change data structures and related functions to hold source prefixes.

parent 46ac5f94
......@@ -714,7 +714,7 @@ main(int argc, char **argv)
if(timeval_compare(&now, &ifp->hello_timeout) >= 0)
send_hello(ifp);
if(timeval_compare(&now, &ifp->update_timeout) >= 0)
send_update(ifp, 0, NULL, 0);
send_update(ifp, 0, NULL, 0, NULL, 0);
if(timeval_compare(&now, &ifp->update_flush_timeout) >= 0)
flushupdates(ifp);
}
......
......@@ -938,6 +938,7 @@ do_filter(struct filter *f, const unsigned char *id,
int
input_filter(const unsigned char *id,
const unsigned char *prefix, unsigned short plen,
const unsigned char *src_prefix, unsigned short src_plen,
const unsigned char *neigh, unsigned int ifindex)
{
int res;
......@@ -948,8 +949,10 @@ input_filter(const unsigned char *id,
}
int
output_filter(const unsigned char *id, const unsigned char *prefix,
unsigned short plen, unsigned int ifindex)
output_filter(const unsigned char *id,
const unsigned char *prefix, unsigned short plen,
const unsigned char *src_prefix, unsigned short src_plen,
unsigned int ifindex)
{
int res;
res = do_filter(output_filters, id, prefix, plen, NULL, ifindex, 0);
......@@ -960,6 +963,7 @@ output_filter(const unsigned char *id, const unsigned char *prefix,
int
redistribute_filter(const unsigned char *prefix, unsigned short plen,
const unsigned char *src_prefix, unsigned short src_plen,
unsigned int ifindex, int proto)
{
int res;
......
......@@ -42,9 +42,13 @@ void renumber_filters(void);
int input_filter(const unsigned char *id,
const unsigned char *prefix, unsigned short plen,
const unsigned char *src_prefix, unsigned short src_plen,
const unsigned char *neigh, unsigned int ifindex);
int output_filter(const unsigned char *id, const unsigned char *prefix,
unsigned short plen, unsigned int ifindex);
int output_filter(const unsigned char *id,
const unsigned char *prefix, unsigned short plen,
const unsigned char *src_prefix, unsigned short src_plen,
unsigned int ifindex);
int redistribute_filter(const unsigned char *prefix, unsigned short plen,
const unsigned char *src_prefix, unsigned short src_plen,
unsigned int ifindex, int proto);
int finalise_config(void);
......@@ -380,7 +380,7 @@ interface_up(struct interface *ifp, int up)
set_timeout(&ifp->update_timeout, ifp->update_interval);
send_hello(ifp);
if(rc > 0)
send_update(ifp, 0, NULL, 0);
send_update(ifp, 0, NULL, 0, NULL, 0);
send_request(ifp, NULL, 0);
} else {
flush_interface_routes(ifp, 0);
......@@ -467,7 +467,7 @@ check_interfaces(void)
rc = check_interface_ipv4(ifp);
if(rc > 0) {
send_request(ifp, NULL, 0);
send_update(ifp, 0, NULL, 0);
send_update(ifp, 0, NULL, 0, NULL, 0);
}
}
}
......
......@@ -541,7 +541,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
len - parsed_len, channels);
}
update_route(router_id, prefix, plen, seqno, metric, interval,
update_route(router_id, prefix, plen, NULL, 0, seqno, metric, interval,
neigh, nh,
channels, channels_len(channels));
} else if(type == MESSAGE_REQUEST) {
......@@ -565,9 +565,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
shortly after we sent a full update. */
if(neigh->ifp->last_update_time <
now.tv_sec - MAX(neigh->ifp->hello_interval / 100, 1))
send_update(neigh->ifp, 0, NULL, 0);
send_update(neigh->ifp, 0, NULL, 0, zeroes, 0);
} else {
send_update(neigh->ifp, 0, prefix, plen);
send_update(neigh->ifp, 0, prefix, plen, zeroes, 0);
}
} else if(type == MESSAGE_MH_REQUEST) {
unsigned char prefix[16], plen;
......@@ -1002,7 +1002,8 @@ really_send_update(struct interface *ifp,
if(!if_up(ifp))
return;
add_metric = output_filter(id, prefix, plen, ifp->ifindex);
add_metric = output_filter(id, prefix, plen, zeroes,
0, ifp->ifindex);
if(add_metric >= INFINITY)
return;
......@@ -1146,7 +1147,7 @@ flushupdates(struct interface *ifp)
with the same router-id together, with IPv6 going out before IPv4. */
for(i = 0; i < n; i++) {
route = find_installed_route(b[i].prefix, b[i].plen);
route = find_installed_route(b[i].prefix, b[i].plen, zeroes, 0);
if(route)
memcpy(b[i].id, route->src->id, 8);
else
......@@ -1166,8 +1167,10 @@ flushupdates(struct interface *ifp)
continue;
}
xroute = find_xroute(b[i].prefix, b[i].plen);
route = find_installed_route(b[i].prefix, b[i].plen);
xroute = find_xroute(b[i].prefix, b[i].plen,
zeroes, 0);
route = find_installed_route(b[i].prefix, b[i].plen,
zeroes, 0);
if(xroute && (!route || xroute->metric <= kernel_metric)) {
really_send_update(ifp, myid,
......@@ -1191,6 +1194,8 @@ flushupdates(struct interface *ifp)
if(metric < INFINITY)
satisfy_request(route->src->prefix, route->src->plen,
route->src->src_prefix,
route->src->src_plen,
seqno, route->src->id, ifp);
if((ifp->flags & IF_SPLIT_HORIZON) &&
......@@ -1284,20 +1289,21 @@ buffer_update(struct interface *ifp,
void
send_update(struct interface *ifp, int urgent,
const unsigned char *prefix, unsigned char plen)
const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen)
{
if(ifp == NULL) {
struct interface *ifp_aux;
struct babel_route *route;
FOR_ALL_INTERFACES(ifp_aux)
send_update(ifp_aux, urgent, prefix, plen);
send_update(ifp_aux, urgent, prefix, plen, src_prefix, src_plen);
if(prefix) {
/* Since flushupdates only deals with non-wildcard interfaces, we
need to do this now. */
route = find_installed_route(prefix, plen);
route = find_installed_route(prefix, plen, src_prefix, src_plen);
if(route && route_metric(route) < INFINITY)
satisfy_request(prefix, plen, route->src->seqno, route->src->id,
NULL);
satisfy_request(prefix, plen, src_prefix, src_plen,
route->src->seqno, route->src->id, NULL);
}
return;
}
......@@ -1333,12 +1339,14 @@ send_update(struct interface *ifp, int urgent,
void
send_update_resend(struct interface *ifp,
const unsigned char *prefix, unsigned char plen)
const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen)
{
assert(prefix != NULL);
send_update(ifp, 1, prefix, plen);
record_resend(RESEND_UPDATE, prefix, plen, 0, NULL, NULL, resend_delay);
send_update(ifp, 1, prefix, plen, src_prefix, src_plen);
record_resend(RESEND_UPDATE, prefix, plen, src_prefix, src_plen,
0, NULL, NULL, resend_delay);
}
void
......@@ -1394,7 +1402,8 @@ send_self_update(struct interface *ifp)
while(1) {
struct xroute *xroute = xroute_stream_next(xroutes);
if(xroute == NULL) break;
send_update(ifp, 0, xroute->prefix, xroute->plen);
send_update(ifp, 0, xroute->prefix, xroute->plen,
xroute->src_prefix, xroute->src_plen);
}
xroute_stream_done(xroutes);
} else {
......@@ -1678,7 +1687,7 @@ send_request_resend(struct neighbour *neigh,
else
send_multihop_request(NULL, prefix, plen, seqno, id, 127);
record_resend(RESEND_REQUEST, prefix, plen, seqno, id,
record_resend(RESEND_REQUEST, prefix, plen, zeroes, 0, seqno, id,
neigh ? neigh->ifp : NULL, resend_delay);
}
......@@ -1691,8 +1700,8 @@ handle_request(struct neighbour *neigh, const unsigned char *prefix,
struct babel_route *route;
struct neighbour *successor = NULL;
xroute = find_xroute(prefix, plen);
route = find_installed_route(prefix, plen);
xroute = find_xroute(prefix, plen, zeroes, 0);
route = find_installed_route(prefix, plen, zeroes, 0);
if(xroute && (!route || xroute->metric <= kernel_metric)) {
if(hop_count > 0 && memcmp(id, myid, 8) == 0) {
......@@ -1704,14 +1713,16 @@ handle_request(struct neighbour *neigh, const unsigned char *prefix,
update_myseqno();
}
}
send_update(neigh->ifp, 1, prefix, plen);
send_update(neigh->ifp, 1, prefix, plen,
xroute->src_prefix, xroute->src_plen);
return;
}
if(route &&
(memcmp(id, route->src->id, 8) != 0 ||
seqno_compare(seqno, route->seqno) <= 0)) {
send_update(neigh->ifp, 1, prefix, plen);
send_update(neigh->ifp, 1, prefix, plen,
route->src->src_prefix, route->src->src_plen);
return;
}
......@@ -1736,7 +1747,8 @@ handle_request(struct neighbour *neigh, const unsigned char *prefix,
find a different neighbour to forward the request to. */
struct babel_route *other_route;
other_route = find_best_route(prefix, plen, 0, neigh);
other_route = find_best_route(prefix, plen, zeroes, 0,
0, neigh);
if(other_route && route_metric(other_route) < INFINITY)
successor = other_route->neigh;
}
......@@ -1747,6 +1759,6 @@ handle_request(struct neighbour *neigh, const unsigned char *prefix,
send_unicast_multihop_request(successor, prefix, plen, seqno, id,
hop_count - 1);
record_resend(RESEND_REQUEST, prefix, plen, seqno, id,
record_resend(RESEND_REQUEST, prefix, plen, zeroes, 0, seqno, id,
neigh->ifp, 0);
}
......@@ -67,9 +67,12 @@ void send_hello_noupdate(struct interface *ifp, unsigned interval);
void send_hello(struct interface *ifp);
void flush_unicast(int dofree);
void send_update(struct interface *ifp, int urgent,
const unsigned char *prefix, unsigned char plen);
const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen);
void send_update_resend(struct interface *ifp,
const unsigned char *prefix, unsigned char plen);
const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix,
unsigned char src_plen);
void send_wildcard_retraction(struct interface *ifp);
void update_myseqno(void);
void send_self_update(struct interface *ifp);
......
......@@ -75,6 +75,7 @@ find_resend(int kind, const unsigned char *prefix, unsigned char plen,
struct resend *
find_request(const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen,
struct resend **previous_return)
{
return find_resend(RESEND_REQUEST, prefix, plen, previous_return);
......@@ -82,6 +83,7 @@ find_request(const unsigned char *prefix, unsigned char plen,
int
record_resend(int kind, const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen,
unsigned short seqno, const unsigned char *id,
struct interface *ifp, int delay)
{
......@@ -89,9 +91,11 @@ record_resend(int kind, const unsigned char *prefix, unsigned char plen,
unsigned int ifindex = ifp ? ifp->ifindex : 0;
if((kind == RESEND_REQUEST &&
input_filter(NULL, prefix, plen, NULL, ifindex) >= INFINITY) ||
input_filter(NULL, prefix, plen, NULL, 0, NULL, ifindex) >=
INFINITY) ||
(kind == RESEND_UPDATE &&
output_filter(NULL, prefix, plen, ifindex) >= INFINITY))
output_filter(NULL, prefix, plen, src_prefix, src_plen, ifindex) >=
INFINITY))
return 0;
if(delay >= 0xFFFF)
......@@ -161,7 +165,7 @@ unsatisfied_request(const unsigned char *prefix, unsigned char plen,
{
struct resend *request;
request = find_request(prefix, plen, NULL);
request = find_request(prefix, plen, zeroes, 0, NULL);
if(request == NULL || resend_expired(request))
return 0;
......@@ -180,7 +184,7 @@ request_redundant(struct interface *ifp,
{
struct resend *request;
request = find_request(prefix, plen, NULL);
request = find_request(prefix, plen, zeroes, 0, NULL);
if(request == NULL || resend_expired(request))
return 0;
......@@ -205,12 +209,13 @@ request_redundant(struct interface *ifp,
int
satisfy_request(const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen,
unsigned short seqno, const unsigned char *id,
struct interface *ifp)
{
struct resend *request, *previous;
request = find_request(prefix, plen, &previous);
request = find_request(prefix, plen, zeroes, 0, &previous);
if(request == NULL)
return 0;
......@@ -297,7 +302,8 @@ do_resend()
break;
case RESEND_UPDATE:
send_update(resend->ifp, 1,
resend->prefix, resend->plen);
resend->prefix, resend->plen,
zeroes, 0);
break;
default: abort();
}
......
......@@ -42,9 +42,11 @@ struct resend {
extern struct timeval resend_time;
struct resend *find_request(const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen,
struct resend **previous_return);
void flush_resends(struct neighbour *neigh);
int record_resend(int kind, const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen,
unsigned short seqno, const unsigned char *id,
struct interface *ifp, int delay);
int unsatisfied_request(const unsigned char *prefix, unsigned char plen,
......@@ -53,6 +55,7 @@ int request_redundant(struct interface *ifp,
const unsigned char *prefix, unsigned char plen,
unsigned short seqno, const unsigned char *id);
int satisfy_request(const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen,
unsigned short seqno, const unsigned char *id,
struct interface *ifp);
......
......@@ -57,6 +57,7 @@ static int two_to_the_one_over_hl = 0; /* 2^(1/hl) * 0x10000 */
static int
route_compare(const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen,
struct babel_route *route)
{
int i = memcmp(prefix, route->src->prefix, 16);
......@@ -65,9 +66,22 @@ route_compare(const unsigned char *prefix, unsigned char plen,
if(plen < route->src->plen)
return -1;
else if(plen > route->src->plen)
if(plen > route->src->plen)
return 1;
else
if(src_plen == 0) {
if(route->src->src_plen > 0)
return -1;
} else {
i = memcmp(src_prefix, route->src->src_prefix, 16);
if(i != 0)
return i;
if(src_plen < route->src->src_plen)
return -1;
if(src_plen > route->src->src_plen)
return 1;
}
return 0;
}
......@@ -76,6 +90,7 @@ route_compare(const unsigned char *prefix, unsigned char plen,
static int
find_route_slot(const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen,
int *new_return)
{
int p, m, g, c;
......@@ -90,7 +105,7 @@ find_route_slot(const unsigned char *prefix, unsigned char plen,
do {
m = (p + g) / 2;
c = route_compare(prefix, plen, routes[m]);
c = route_compare(prefix, plen, src_prefix, src_plen, routes[m]);
if(c == 0)
return m;
else if(c < 0)
......@@ -107,10 +122,11 @@ find_route_slot(const unsigned char *prefix, unsigned char plen,
struct babel_route *
find_route(const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen,
struct neighbour *neigh, const unsigned char *nexthop)
{
struct babel_route *route;
int i = find_route_slot(prefix, plen, NULL);
int i = find_route_slot(prefix, plen, src_prefix, src_plen, NULL);
if(i < 0)
return NULL;
......@@ -127,9 +143,10 @@ find_route(const unsigned char *prefix, unsigned char plen,
}
struct babel_route *
find_installed_route(const unsigned char *prefix, unsigned char plen)
find_installed_route(const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen)
{
int i = find_route_slot(prefix, plen, NULL);
int i = find_route_slot(prefix, plen, src_prefix, src_plen, NULL);
if(i >= 0 && routes[i]->installed)
return routes[i];
......@@ -173,7 +190,8 @@ insert_route(struct babel_route *route)
assert(!route->installed);
i = find_route_slot(route->src->prefix, route->src->plen, &n);
i = find_route_slot(route->src->prefix, route->src->plen,
route->src->src_prefix, route->src->src_plen, &n);
if(i < 0) {
if(route_slots >= max_route_slots)
......@@ -214,7 +232,8 @@ flush_route(struct babel_route *route)
lost = 1;
}
i = find_route_slot(route->src->prefix, route->src->plen, NULL);
i = find_route_slot(route->src->prefix, route->src->plen,
route->src->src_prefix, route->src->src_plen, NULL);
assert(i >= 0 && i < route_slots);
local_notify_route(route, LOCAL_FLUSH);
......@@ -406,7 +425,8 @@ install_route(struct babel_route *route)
fprintf(stderr, "WARNING: installing unfeasible route "
"(this shouldn't happen).");
i = find_route_slot(route->src->prefix, route->src->plen, NULL);
i = find_route_slot(route->src->prefix, route->src->plen,
route->src->src_prefix, route->src->src_plen, NULL);
assert(i >= 0 && i < route_slots);
if(routes[i] != route && routes[i]->installed) {
......@@ -416,7 +436,7 @@ install_route(struct babel_route *route)
}
rc = kernel_route(ROUTE_ADD, route->src->prefix, route->src->plen,
zeroes, 0,
route->src->src_prefix, route->src->src_plen,
route->nexthop,
route->neigh->ifp->ifindex,
metric_to_kernel(route_metric(route)), NULL, 0, 0);
......@@ -441,7 +461,7 @@ uninstall_route(struct babel_route *route)
return;
rc = kernel_route(ROUTE_FLUSH, route->src->prefix, route->src->plen,
zeroes, 0,
route->src->src_prefix, route->src->src_plen,
route->nexthop,
route->neigh->ifp->ifindex,
metric_to_kernel(route_metric(route)), NULL, 0, 0);
......@@ -474,11 +494,14 @@ switch_routes(struct babel_route *old, struct babel_route *new)
"(this shouldn't happen).");
rc = kernel_route(ROUTE_MODIFY, old->src->prefix, old->src->plen,
zeroes, 0,
old->src->src_prefix, old->src->src_plen,
old->nexthop, old->neigh->ifp->ifindex,
metric_to_kernel(route_metric(old)),
new->nexthop, new->neigh->ifp->ifindex,
metric_to_kernel(route_metric(new)));
/* XXX : should the source-ip be subject to changes ? */
assert(memcmp(old->src->src_prefix, new->src->src_prefix, 16) == 0
&& old->src->src_plen == new->src->src_plen);
if(rc < 0) {
perror("kernel_route(MODIFY)");
return;
......@@ -487,6 +510,8 @@ switch_routes(struct babel_route *old, struct babel_route *new)
old->installed = 0;
new->installed = 1;
move_installed_route(new, find_route_slot(new->src->prefix, new->src->plen,
new->src->src_prefix,
new->src->src_plen,
NULL));
local_notify_route(old, LOCAL_CHANGE);
local_notify_route(new, LOCAL_CHANGE);
......@@ -505,7 +530,7 @@ change_route_metric(struct babel_route *route,
if(route->installed && old != new) {
int rc;
rc = kernel_route(ROUTE_MODIFY, route->src->prefix, route->src->plen,
zeroes, 0,
route->src->src_prefix, route->src->src_plen,
route->nexthop, route->neigh->ifp->ifindex,
old,
route->nexthop, route->neigh->ifp->ifindex,
......@@ -694,11 +719,12 @@ route_acceptable(struct babel_route *route, int feasible,
that's probably overkill. */
struct babel_route *
find_best_route(const unsigned char *prefix, unsigned char plen, int feasible,
struct neighbour *exclude)
find_best_route(const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen,
int feasible, struct neighbour *exclude)
{
struct babel_route *route, *r;
int i = find_route_slot(prefix, plen, NULL);
int i = find_route_slot(prefix, plen, src_prefix, src_plen, NULL);
if(i < 0)
return NULL;
......@@ -738,6 +764,8 @@ update_route_metric(struct babel_route *route)
struct neighbour *neigh = route->neigh;
int add_metric = input_filter(route->src->id,
route->src->prefix, route->src->plen,
route->src->src_prefix,
route->src->src_plen,
neigh->address,
neigh->ifp->ifindex);
change_route_metric(route, route->refmetric,
......@@ -789,6 +817,7 @@ update_interface_metric(struct interface *ifp)
struct babel_route *
update_route(const unsigned char *id,
const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen,
unsigned short seqno, unsigned short refmetric,
unsigned short interval,
struct neighbour *neigh, const unsigned char *nexthop,
......@@ -810,17 +839,18 @@ update_route(const unsigned char *id,
}
add_metric = input_filter(id, prefix, plen,
src_prefix, src_plen,
neigh->address, neigh->ifp->ifindex);
if(add_metric >= INFINITY)
return NULL;
route = find_route(prefix, plen, neigh, nexthop);
route = find_route(prefix, plen, src_prefix, src_plen, neigh, nexthop);
if(route && memcmp(route->src->id, id, 8) == 0)
/* Avoid scanning the source table. */
src = route->src;
else
src = find_source(id, prefix, plen, 1, seqno);
src = find_source(id, prefix, plen, src_prefix, src_plen, 1, seqno);
if(src == NULL)
return NULL;
......@@ -929,7 +959,9 @@ send_unfeasible_request(struct neighbour *neigh, int force,
unsigned short seqno, unsigned short metric,
struct source *src)
{
struct babel_route *route = find_installed_route(src->prefix, src->plen);
struct babel_route *route = find_installed_route(src->prefix, src->plen,
src->src_prefix,
src->src_plen);
if(seqno_minus(src->seqno, seqno) > 100) {
/* Probably a source that lost its seqno. Let it time-out. */
......@@ -962,11 +994,14 @@ consider_route(struct babel_route *route)
if(!route_feasible(route))
return;
xroute = find_xroute(route->src->prefix, route->src->plen);
xroute = find_xroute(route->src->prefix, route->src->plen,
route->src->src_prefix, route->src->src_plen);
if(xroute && (allow_duplicates < 0 || xroute->metric >= allow_duplicates))
return;
installed = find_installed_route(route->src->prefix, route->src->plen);
installed = find_installed_route(route->src->prefix, route->src->plen,
route->src->src_prefix,
route->src->src_plen);
if(installed == NULL)
goto install;
......@@ -988,7 +1023,8 @@ consider_route(struct babel_route *route)
if(installed && route->installed)
send_triggered_update(route, installed->src, route_metric(installed));
else
send_update(NULL, 1, route->src->prefix, route->src->plen);
send_update(NULL, 1, route->src->prefix, route->src->plen,
route->src->src_prefix, route->src->src_plen);
return;
}
......@@ -1054,9 +1090,11 @@ send_triggered_update(struct babel_route *route, struct source *oldsrc,
urgent = 0;
if(urgent >= 2)
send_update_resend(NULL, route->src->prefix, route->src->plen);
send_update_resend(NULL, route->src->prefix, route->src->plen,
route->src->src_prefix, route->src->src_plen);
else
send_update(NULL, urgent, route->src->prefix, route->src->plen);
send_update(NULL, urgent, route->src->prefix, route->src->plen,
route->src->src_prefix, route->src->src_plen);
if(oldmetric < INFINITY) {
if(newmetric >= oldmetric + 512) {
......@@ -1081,7 +1119,9 @@ route_changed(struct babel_route *route,
struct babel_route *better_route;
/* Do this unconditionally -- microoptimisation is not worth it. */
better_route =
find_best_route(route->src->prefix, route->src->plen, 1, NULL);
find_best_route(route->src->prefix, route->src->plen,
route->src->src_prefix, route->src->src_plen,
1, NULL);
if(better_route && route_metric(better_route) < route_metric(route))
consider_route(better_route);
}
......@@ -1101,12 +1141,14 @@ void
route_lost(struct source *src, unsigned oldmetric)
{
struct babel_route *new_route;
new_route = find_best_route(src->prefix, src->plen, 1, NULL);
new_route = find_best_route(src->prefix, src->plen,
src->src_prefix, src->src_plen, 1, NULL);
if(new_route) {
consider_route(new_route);
} else if(oldmetric < INFINITY) {
/* Avoid creating a blackhole. */
send_update_resend(NULL, src->prefix, src->plen);
send_update_resend(NULL, src->prefix, src->plen,
src->src_prefix, src->src_plen);
/* If the route was usable enough, try to get an alternate one.
If it was not, we could be dealing with oscillations around
the value of INFINITY. */
......
......@@ -70,9 +70,15 @@ route_metric_noninterfering(const struct babel_route *route)
}
struct babel_route *find_route(const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen,
struct neighbour *neigh, const unsigned char *nexthop);
struct babel_route *find_installed_route(const unsigned char *prefix,
unsigned char plen);
unsigned char plen, const unsigned char *src_prefix,
unsigned char src_plen);
struct babel_route *find_min_iroute(const unsigned char *dst_prefix,
unsigned char dst_plen,
const unsigned char *src_prefix, unsigned char src_plen,
int is_min_dst, int is_min_src, int exclusive_min);
int installed_routes_estimate(void);
void flush_route(struct babel_route *route);
void flush_all_routes(void);
......@@ -93,6 +99,8 @@ void change_smoothing_half_life(int half_life);
int route_smoothed_metric(struct babel_route *route);
struct babel_route *find_best_route(const unsigned char *prefix,
unsigned char plen,
const unsigned char *src_prefix,
unsigned char src_plen,
int feasible, struct neighbour *exclude);
struct babel_route *install_best_route(const unsigned char prefix[16],
unsigned char plen);
......@@ -101,6 +109,8 @@ void update_interface_metric(struct interface *ifp);
void update_route_metric(struct babel_route *route);
struct babel_route *update_route(const unsigned char *id,
const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix,
unsigned char src_plen,
unsigned short seqno, unsigned short refmetric,
unsigned short interval, struct neighbour *neigh,
const unsigned char *nexthop,
......
......@@ -35,7 +35,9 @@ THE SOFTWARE.
struct source *srcs = NULL;
struct source*
find_source(const unsigned char *id, const unsigned char *p, unsigned char plen,
find_source(const unsigned char *id,
const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen,
int create, unsigned short seqno)
{
struct source *src;
......@@ -49,7 +51,11 @@ find_source(const unsigned char *id, const unsigned char *p, unsigned char plen,
continue;
if(src->plen != plen)
continue;
if(memcmp(src->prefix, p, 16) == 0)
if(src->src_plen != src_plen)
continue;
if(memcmp(src->prefix, prefix, 16) != 0)
continue;
if(memcmp(src->src_prefix, src_prefix, 16) == 0)
return src;
}
......@@ -63,8 +69,10 @@ find_source(const unsigned char *id, const unsigned char *p, unsigned char plen,
}
memcpy(src->id, id, 8);
memcpy(src->prefix, p, 16);
memcpy(src->prefix, prefix, 16);
src->plen = plen;
memcpy(src->src_prefix, src_prefix, 16);
src->src_plen = src_plen;
src->seqno = seqno;
src->metric = INFINITY;
src->time = now.tv_sec;
......
......@@ -27,6 +27,8 @@ struct source {
unsigned char id[8];
unsigned char prefix[16];
unsigned char plen;
unsigned char src_prefix[16];
unsigned char src_plen;
unsigned short seqno;
unsigned short metric;
unsigned short route_count;
......@@ -34,8 +36,10 @@ struct source {
};
struct source *find_source(const unsigned char *id,
const unsigned char *p,
const unsigned char *prefix,
unsigned char plen,
const unsigned char *src_prefix,
unsigned char src_plen,
int create, unsigned short seqno);
struct source *retain_source(struct source *src);
void release_source(struct source *src);
......
......@@ -111,6 +111,7 @@ int linklocal(const unsigned char *address) ATTRIBUTE ((pure));
int v4mapped(const unsigned char *address) ATTRIBUTE ((pure));
void v4tov6(unsigned char *dst, const unsigned char *src);
int daemonise(void);
int set_src_prefix(unsigned char *src_addr, unsigned char *src_plen);
enum prefix_status {
PST_DISJOINT = 1 << 0,
......
......@@ -43,12 +43,15 @@ static struct xroute *xroutes;
static int numxroutes = 0, maxxroutes = 0;
struct xroute *
find_xroute(const unsigned char *prefix, unsigned char plen)
find_xroute(const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen)
{
int i;
for(i = 0; i < numxroutes; i++) {
if(xroutes[i].plen == plen &&
memcmp(xroutes[i].prefix, prefix, 16) == 0)
memcmp(xroutes[i].prefix, prefix, 16) == 0 &&
xroutes[i].src_plen == src_plen &&
memcmp(xroutes[i].src_prefix, src_prefix, 16) == 0)
return &xroutes[i];
}
return NULL;
......@@ -86,9 +89,10 @@ flush_xroute(struct xroute *xroute)
int
add_xroute(unsigned char prefix[16], unsigned char plen,
unsigned char src_prefix[16], unsigned char src_plen,
unsigned short metric, unsigned int ifindex, int proto)
{
struct xroute *xroute = find_xroute(prefix, plen);
struct xroute *xroute = find_xroute(prefix, plen, src_prefix, src_plen);
if(xroute) {
if(xroute->metric <= metric)
return 0;
......@@ -111,6 +115,8 @@ add_xroute(unsigned char prefix[16], unsigned char plen,
memcpy(xroutes[numxroutes].prefix, prefix, 16);
xroutes[numxroutes].plen = plen;
memcpy(xroutes[numxroutes].src_prefix, src_prefix, 16);
xroutes[numxroutes].src_plen = src_plen;
xroutes[numxroutes].metric = metric;
xroutes[numxroutes].ifindex = ifindex;
xroutes[numxroutes].proto = proto;
......@@ -200,6 +206,7 @@ check_xroutes(int send_updates)
while(i < numxroutes) {
export = 0;
metric = redistribute_filter(xroutes[i].prefix, xroutes[i].plen,
xroutes[i].src_prefix, xroutes[i].src_plen,
xroutes[i].ifindex, xroutes[i].proto);
if(metric < INFINITY && metric == xroutes[i].metric) {
for(j = 0; j < numroutes; j++) {
......@@ -215,17 +222,20 @@ check_xroutes(int send_updates)
if(!export) {
unsigned char prefix[16], plen;
unsigned char src_prefix[16], src_plen;
struct babel_route *route;
memcpy(prefix, xroutes[i].prefix, 16);
plen = xroutes[i].plen;
memcpy(src_prefix, xroutes[i].src_prefix, 16);
src_plen = xroutes[i].src_plen;
flush_xroute(&xroutes[i]);
route = find_best_route(prefix, plen, 1, NULL);
route = find_best_route(prefix, plen, src_prefix, src_plen, 1,NULL);
if(route)
install_route(route);
/* send_update_resend only records the prefix, so the update
will only be sent after we perform all of the changes. */
if(send_updates)
send_update_resend(NULL, prefix, plen);
send_update_resend(NULL, prefix, plen, src_prefix, src_plen);
change = 1;
} else {
i++;
......@@ -238,13 +248,17 @@ check_xroutes(int send_updates)
if(martian_prefix(routes[i].prefix, routes[i].plen))
continue;
metric = redistribute_filter(routes[i].prefix, routes[i].plen,
routes[i].src_prefix, routes[i].src_plen,
routes[i].ifindex, routes[i].proto);
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);
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)
......@@ -252,7 +266,8 @@ check_xroutes(int send_updates)
}
change = 1;
if(send_updates)
send_update(NULL, 0, routes[i].prefix, routes[i].plen);
send_update(NULL, 0, routes[i].prefix, routes[i].plen,
routes[i].src_prefix, routes[i].src_plen);
}
}
}
......
......@@ -23,6 +23,8 @@ THE SOFTWARE.
struct xroute {
unsigned char prefix[16];
unsigned char plen;
unsigned char src_prefix[16];
unsigned char src_plen;
unsigned short metric;
unsigned int ifindex;
int proto;
......@@ -30,9 +32,11 @@ struct xroute {
struct xroute_stream;
struct xroute *find_xroute(const unsigned char *prefix, unsigned char plen);
struct xroute *find_xroute(const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen);
void flush_xroute(struct xroute *xroute);
int add_xroute(unsigned char prefix[16], unsigned char plen,
unsigned char src_prefix[16], unsigned char src_plen,
unsigned short metric, unsigned int ifindex, int proto);
int xroutes_estimate(void);
struct xroute_stream *xroute_stream();
......
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