Commit 49a9c3a0 authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Remember forwarded requests, satisfy them later.

parent 167be8b8
...@@ -58,6 +58,8 @@ find_destination(const unsigned char *d, int create, unsigned char seqno) ...@@ -58,6 +58,8 @@ find_destination(const unsigned char *d, int create, unsigned char seqno)
dests[i].seqno = seqno; dests[i].seqno = seqno;
dests[i].metric = INFINITY; dests[i].metric = INFINITY;
dests[i].time = now.tv_sec; dests[i].time = now.tv_sec;
dests[i].requested_seqno = -1;
dests[i].requested_net = NULL;
return &dests[i]; return &dests[i];
} }
...@@ -73,3 +75,47 @@ update_destination(struct destination *dest, ...@@ -73,3 +75,47 @@ update_destination(struct destination *dest,
dest->time = now.tv_sec; dest->time = now.tv_sec;
} }
void
notice_request(struct destination *dest, unsigned char seqno,
struct network *net)
{
if(dest->requested_seqno < 0) {
dest->requested_seqno = seqno;
dest->requested_net = net;
} else {
if(seqno_compare(dest->requested_seqno, seqno) < 0)
dest->requested_seqno = seqno;
if(net == NULL || net != dest->requested_net)
dest->requested_net = NULL;
}
}
int
request_requested(struct destination *dest, unsigned char seqno,
struct network *net)
{
if(dest->requested_seqno < 0)
return 0;
if(seqno_compare(dest->requested_seqno, seqno) < 0)
return 0;
if(net == NULL || net != dest->requested_net)
return 0;
return 1;
}
void
satisfy_request(struct destination *dest, unsigned char seqno,
struct network *net)
{
if(dest->requested_seqno >= 0) {
if(net == NULL || net == dest->requested_net) {
if(seqno_compare(seqno, dest->requested_seqno) >= 0) {
dest->requested_seqno = -1;
dest->requested_net = NULL;
}
}
}
}
...@@ -25,9 +25,17 @@ struct destination { ...@@ -25,9 +25,17 @@ struct destination {
unsigned char seqno; unsigned char seqno;
unsigned short metric; unsigned short metric;
int time; int time;
int requested_seqno;
struct network *requested_net;
}; };
struct destination *find_destination(const unsigned char *d, struct destination *find_destination(const unsigned char *d,
int create, unsigned char seqno); int create, unsigned char seqno);
void update_destination(struct destination *dest, void update_destination(struct destination *dest,
unsigned char seqno, unsigned short metric); unsigned char seqno, unsigned short metric);
void notice_request(struct destination *dest, unsigned char seqno,
struct network *net);
int request_requested(struct destination *dest, unsigned char seqno,
struct network *net);
void satisfy_request(struct destination *dest, unsigned char seqno,
struct network *net);
...@@ -144,14 +144,16 @@ parse_packet(const unsigned char *from, struct network *net, ...@@ -144,14 +144,16 @@ parse_packet(const unsigned char *from, struct network *net,
if(seqno_compare(installed->seqno, if(seqno_compare(installed->seqno,
theirseqno) >= 0) theirseqno) >= 0)
send_update(dest, neigh->network); send_update(dest, neigh->network);
else if(hopcount >= 2) { else if(!request_requested(dest,
theirseqno,
neigh->network)) {
if(hopcount >= 2)
send_unicast_request(installed->nexthop, send_unicast_request(installed->nexthop,
dest, dest,
hopcount - 1, hopcount - 1,
theirseqno); theirseqno);
/* For now, let's hope the new seqno notice_request(dest, theirseqno,
arrives before the update is flushed. */ neigh->network);
send_update(dest, neigh->network);
} }
} }
} }
...@@ -530,6 +532,7 @@ flushupdates(void) ...@@ -530,6 +532,7 @@ flushupdates(void)
accumulate_byte(net, seqno); accumulate_byte(net, seqno);
accumulate_short(net, metric); accumulate_short(net, metric);
accumulate_data(net, buffered_updates[i]->address, 16); accumulate_data(net, buffered_updates[i]->address, 16);
satisfy_request(buffered_updates[i], seqno, net);
} }
} }
schedule_flush_now(net); schedule_flush_now(net);
...@@ -578,6 +581,12 @@ send_update(struct destination *dest, struct network *net) ...@@ -578,6 +581,12 @@ send_update(struct destination *dest, struct network *net)
if(net == NULL) { if(net == NULL) {
for(i = 0; i < numnets; i++) for(i = 0; i < numnets; i++)
send_update(dest, &nets[i]); send_update(dest, &nets[i]);
if(dest != NULL) {
/* This case is not handled by flushupdates. */
struct route *installed = find_installed_route(dest);
satisfy_request(dest, installed ? installed->seqno : dest->seqno,
NULL);
}
return; return;
} }
......
...@@ -428,6 +428,9 @@ send_triggered_update(struct route *route, int oldmetric) ...@@ -428,6 +428,9 @@ send_triggered_update(struct route *route, int oldmetric)
if((route->metric >= INFINITY && oldmetric < INFINITY) || if((route->metric >= INFINITY && oldmetric < INFINITY) ||
(route->metric - oldmetric >= 256 || oldmetric - route->metric >= 256)) (route->metric - oldmetric >= 256 || oldmetric - route->metric >= 256))
send_update(route->dest, NULL); send_update(route->dest, NULL);
else if(route->dest->requested_seqno >= 0 &&
seqno_compare(route->dest->requested_seqno, route->seqno) <= 0)
send_update(route->dest, route->dest->requested_net);
if(oldmetric < INFINITY) { if(oldmetric < INFINITY) {
if(route->metric >= INFINITY) { if(route->metric >= INFINITY) {
......
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