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