Commit dac97fdf authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Merge branch 'rfc6126bis'

parents 6f3b45bb 13f0c503
...@@ -172,7 +172,7 @@ main(int argc, char **argv) ...@@ -172,7 +172,7 @@ main(int argc, char **argv)
while(1) { while(1) {
opt = getopt(argc, argv, opt = getopt(argc, argv,
"m:p:h:H:i:k:A:sruS:d:g:G:lwz:M:t:T:c:C:DL:I:V"); "m:p:h:H:i:k:A:srS:d:g:G:lwz:M:t:T:c:C:DL:I:V");
if(opt < 0) if(opt < 0)
break; break;
...@@ -225,9 +225,6 @@ main(int argc, char **argv) ...@@ -225,9 +225,6 @@ main(int argc, char **argv)
case 'r': case 'r':
random_id = 1; random_id = 1;
break; break;
case 'u':
keep_unfeasible = 1;
break;
case 'S': case 'S':
state_file = optarg; state_file = optarg;
break; break;
...@@ -1116,11 +1113,12 @@ dump_tables(FILE *out) ...@@ -1116,11 +1113,12 @@ dump_tables(FILE *out)
fprintf(out, "My id %s seqno %d\n", format_eui64(myid), myseqno); fprintf(out, "My id %s seqno %d\n", format_eui64(myid), myseqno);
FOR_ALL_NEIGHBOURS(neigh) { FOR_ALL_NEIGHBOURS(neigh) {
fprintf(out, "Neighbour %s dev %s reach %04x rxcost %d txcost %d " fprintf(out, "Neighbour %s dev %s reach %04x ureach %04x "
"rtt %s rttcost %d chan %d%s.\n", "rxcost %d txcost %d rtt %s rttcost %d chan %d%s.\n",
format_address(neigh->address), format_address(neigh->address),
neigh->ifp->name, neigh->ifp->name,
neigh->reach, neigh->hello.reach,
neigh->uhello.reach,
neighbour_rxcost(neigh), neighbour_rxcost(neigh),
neigh->txcost, neigh->txcost,
format_thousands(neigh->rtt), format_thousands(neigh->rtt),
......
...@@ -196,11 +196,6 @@ at least ...@@ -196,11 +196,6 @@ at least
Do not use this option unless you know what you are doing, as it can Do not use this option unless you know what you are doing, as it can
cause persistent route flapping. cause persistent route flapping.
.TP .TP
.BR keep-unfeasible " {" true | false }
This specifies whether to keep unfeasible (useless) routes, and is
equivalent to the command-line option
.BR \-u .
.TP
.BR random-id " {" true | false } .BR random-id " {" true | false }
This specifies whether to use a random router-id, and is This specifies whether to use a random router-id, and is
equivalent to the command-line option equivalent to the command-line option
......
...@@ -755,8 +755,7 @@ parse_option(int c, gnc_t gnc, void *closure, char *token) ...@@ -755,8 +755,7 @@ parse_option(int c, gnc_t gnc, void *closure, char *token)
because they require no special setup or because there is special because they require no special setup or because there is special
case code for them. */ case code for them. */
if(config_finalised) { if(config_finalised) {
if(strcmp(token, "keep-unfeasible") != 0 && if(strcmp(token, "link-detect") != 0 &&
strcmp(token, "link-detect") != 0 &&
strcmp(token, "log-file") != 0 && strcmp(token, "log-file") != 0 &&
strcmp(token, "diversity") != 0 && strcmp(token, "diversity") != 0 &&
strcmp(token, "diversity-factor") != 0 && strcmp(token, "diversity-factor") != 0 &&
...@@ -798,8 +797,7 @@ parse_option(int c, gnc_t gnc, void *closure, char *token) ...@@ -798,8 +797,7 @@ parse_option(int c, gnc_t gnc, void *closure, char *token)
add_import_table(v); add_import_table(v);
else else
abort(); abort();
} else if(strcmp(token, "keep-unfeasible") == 0 || } else if(strcmp(token, "link-detect") == 0 ||
strcmp(token, "link-detect") == 0 ||
strcmp(token, "random-id") == 0 || strcmp(token, "random-id") == 0 ||
strcmp(token, "daemonise") == 0 || strcmp(token, "daemonise") == 0 ||
strcmp(token, "skip-kernel-setup") == 0 || strcmp(token, "skip-kernel-setup") == 0 ||
...@@ -810,9 +808,7 @@ parse_option(int c, gnc_t gnc, void *closure, char *token) ...@@ -810,9 +808,7 @@ parse_option(int c, gnc_t gnc, void *closure, char *token)
if(c < -1) if(c < -1)
goto error; goto error;
b = (b == CONFIG_YES); b = (b == CONFIG_YES);
if(strcmp(token, "keep-unfeasible") == 0) if(strcmp(token, "link-detect") == 0)
keep_unfeasible = b;
else if(strcmp(token, "link-detect") == 0)
link_detect = b; link_detect = b;
else if(strcmp(token, "random-id") == 0) else if(strcmp(token, "random-id") == 0)
random_id = b; random_id = b;
......
...@@ -153,14 +153,16 @@ local_notify_neighbour_1(struct local_socket *s, ...@@ -153,14 +153,16 @@ local_notify_neighbour_1(struct local_socket *s,
rc = snprintf(buf, 512, rc = snprintf(buf, 512,
"%s neighbour %lx address %s " "%s neighbour %lx address %s "
"if %s reach %04x rxcost %d txcost %d%s cost %d\n", "if %s reach %04x ureach %04x "
"rxcost %d txcost %d%s cost %d\n",
local_kind(kind), local_kind(kind),
/* Neighbours never move around in memory , so we can use the /* Neighbours never move around in memory , so we can use the
address as a unique identifier. */ address as a unique identifier. */
(unsigned long int)neigh, (unsigned long int)neigh,
format_address(neigh->address), format_address(neigh->address),
neigh->ifp->name, neigh->ifp->name,
neigh->reach, neigh->hello.reach,
neigh->uhello.reach,
neighbour_rxcost(neigh), neighbour_rxcost(neigh),
neighbour_txcost(neigh), neighbour_txcost(neigh),
rttbuf, rttbuf,
......
...@@ -165,7 +165,10 @@ parse_update_subtlv(struct interface *ifp, int metric, ...@@ -165,7 +165,10 @@ parse_update_subtlv(struct interface *ifp, int metric,
memcpy(channels, a + i + 2, MIN(len, *channels_len_return)); memcpy(channels, a + i + 2, MIN(len, *channels_len_return));
channels_len = MIN(len, *channels_len_return); channels_len = MIN(len, *channels_len_return);
} else { } else {
debugf("Received unknown update sub-TLV %d.\n", type); debugf("Received unknown%s Update sub-TLV %d.\n",
(type & 0x80) != 0 ? " mandatory" : "", type);
if((type & 0x80) != 0)
return -1;
} }
i += len + 2; i += len + 2;
...@@ -210,7 +213,10 @@ parse_hello_subtlv(const unsigned char *a, int alen, ...@@ -210,7 +213,10 @@ parse_hello_subtlv(const unsigned char *a, int alen,
/* But don't break. */ /* But don't break. */
} }
} else { } else {
debugf("Received unknown Hello sub-TLV type %d.\n", type); debugf("Received unknown%s Hello sub-TLV %d.\n",
(type & 0x80) != 0 ? " mandatory" : "", type);
if((type & 0x80) != 0)
return -1;
} }
i += len + 2; i += len + 2;
...@@ -262,7 +268,10 @@ parse_ihu_subtlv(const unsigned char *a, int alen, ...@@ -262,7 +268,10 @@ parse_ihu_subtlv(const unsigned char *a, int alen,
/* But don't break. */ /* But don't break. */
} }
} else { } else {
debugf("Received unknown IHU sub-TLV type %d.\n", type); debugf("Received unknown%s IHU sub-TLV %d.\n",
(type & 0x80) != 0 ? " mandatory" : "", type);
if((type & 0x80) != 0)
return -1;
} }
i += len + 2; i += len + 2;
...@@ -277,6 +286,38 @@ parse_ihu_subtlv(const unsigned char *a, int alen, ...@@ -277,6 +286,38 @@ parse_ihu_subtlv(const unsigned char *a, int alen,
return 1; return 1;
} }
static int
parse_other_subtlv(const unsigned char *a, int alen)
{
int type, len, i = 0;
while(i < alen) {
type = a[0];
if(type == SUBTLV_PAD1) {
i++;
continue;
}
if(i + 1 > alen) {
fprintf(stderr, "Received truncated sub-TLV.\n");
return -1;
}
len = a[i + 1];
if(i + len > alen) {
fprintf(stderr, "Received truncated sub-TLV.\n");
return -1;
}
if((type & 0x80) != 0) {
debugf("Received unknown mandatory sub-TLV %d.\n", type);
return -1;
}
i += len + 2;
}
return 1;
}
static int static int
network_address(int ae, const unsigned char *a, unsigned int len, network_address(int ae, const unsigned char *a, unsigned int len,
unsigned char *a_r) unsigned char *a_r)
...@@ -364,42 +405,53 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -364,42 +405,53 @@ parse_packet(const unsigned char *from, struct interface *ifp,
len, format_address(from), ifp->name); len, format_address(from), ifp->name);
} else if(type == MESSAGE_ACK_REQ) { } else if(type == MESSAGE_ACK_REQ) {
unsigned short nonce, interval; unsigned short nonce, interval;
int rc;
if(len < 6) goto fail; if(len < 6) goto fail;
DO_NTOHS(nonce, message + 4); DO_NTOHS(nonce, message + 4);
DO_NTOHS(interval, message + 6); DO_NTOHS(interval, message + 6);
debugf("Received ack-req (%04X %d) from %s on %s.\n", debugf("Received ack-req (%04X %d) from %s on %s.\n",
nonce, interval, format_address(from), ifp->name); nonce, interval, format_address(from), ifp->name);
rc = parse_other_subtlv(message + 8, len - 6);
if(rc < 0)
goto done;
send_ack(neigh, nonce, interval); send_ack(neigh, nonce, interval);
} else if(type == MESSAGE_ACK) { } else if(type == MESSAGE_ACK) {
int rc;
debugf("Received ack from %s on %s.\n", debugf("Received ack from %s on %s.\n",
format_address(from), ifp->name); format_address(from), ifp->name);
rc = parse_other_subtlv(message + 4, len - 2);
if(rc < 0)
goto done;
/* Nothing right now */ /* Nothing right now */
} else if(type == MESSAGE_HELLO) { } else if(type == MESSAGE_HELLO) {
unsigned short seqno, interval; unsigned short seqno, interval;
int changed, have_timestamp; int unicast, changed, have_timestamp, rc;
unsigned int timestamp; unsigned int timestamp;
if(len < 6) goto fail; if(len < 6) goto fail;
unicast = !!(message[2] & 0x80);
DO_NTOHS(seqno, message + 4); DO_NTOHS(seqno, message + 4);
DO_NTOHS(interval, message + 6); DO_NTOHS(interval, message + 6);
debugf("Received hello %d (%d) from %s on %s.\n", debugf("Received hello %d (%d) from %s on %s.\n",
seqno, interval, seqno, interval,
format_address(from), ifp->name); format_address(from), ifp->name);
changed = update_neighbour(neigh, seqno, interval); /* Sub-TLV handling. */
rc = parse_hello_subtlv(message + 8, len - 6,
&timestamp, &have_timestamp);
if(rc < 0)
goto done;
changed =
update_neighbour(neigh,
unicast ? &neigh->uhello : &neigh->hello,
unicast, seqno, interval);
update_neighbour_metric(neigh, changed); update_neighbour_metric(neigh, changed);
if(interval > 0) if(interval > 0)
/* Multiply by 3/2 to allow hellos to expire. */ /* Multiply by 3/2 to allow hellos to expire. */
schedule_neighbours_check(interval * 15, 0); schedule_neighbours_check(interval * 15, 0);
/* Sub-TLV handling. */ if(have_timestamp) {
if(len > 8) {
int rc;
rc = parse_hello_subtlv(message + 8, len - 6,
&timestamp, &have_timestamp);
if(rc >= 0 && have_timestamp) {
neigh->hello_send_us = timestamp; neigh->hello_send_us = timestamp;
neigh->hello_rtt_receive_time = now; neigh->hello_rtt_receive_time = now;
have_hello_rtt = 1; have_hello_rtt = 1;
} }
}
} else if(type == MESSAGE_IHU) { } else if(type == MESSAGE_IHU) {
unsigned short txcost, interval; unsigned short txcost, interval;
unsigned char address[16]; unsigned char address[16];
...@@ -414,7 +466,13 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -414,7 +466,13 @@ parse_packet(const unsigned char *from, struct interface *ifp,
format_address(from), ifp->name, format_address(from), ifp->name,
format_address(address)); format_address(address));
if(message[2] == 0 || interface_ll_address(ifp, address)) { if(message[2] == 0 || interface_ll_address(ifp, address)) {
int changed = txcost != neigh->txcost; int changed;
rc = parse_ihu_subtlv(message + 8 + rc, len - 6 - rc,
&hello_send_us, &hello_rtt_receive_time,
NULL);
if(rc < 0)
goto done;
changed = txcost != neigh->txcost;
neigh->txcost = txcost; neigh->txcost = txcost;
neigh->ihu_time = now; neigh->ihu_time = now;
neigh->ihu_interval = interval; neigh->ihu_interval = interval;
...@@ -422,13 +480,9 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -422,13 +480,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
if(interval > 0) if(interval > 0)
/* Multiply by 3/2 to allow neighbours to expire. */ /* Multiply by 3/2 to allow neighbours to expire. */
schedule_neighbours_check(interval * 45, 0); schedule_neighbours_check(interval * 45, 0);
/* RTT sub-TLV. */
if(len > 10 + rc)
parse_ihu_subtlv(message + 8 + rc, len - 6 - rc,
&hello_send_us, &hello_rtt_receive_time,
NULL);
} }
} else if(type == MESSAGE_ROUTER_ID) { } else if(type == MESSAGE_ROUTER_ID) {
int rc;
if(len < 10) { if(len < 10) {
have_router_id = 0; have_router_id = 0;
goto fail; goto fail;
...@@ -437,6 +491,9 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -437,6 +491,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
have_router_id = 1; have_router_id = 1;
debugf("Received router-id %s from %s on %s.\n", debugf("Received router-id %s from %s on %s.\n",
format_eui64(router_id), format_address(from), ifp->name); format_eui64(router_id), format_address(from), ifp->name);
rc = parse_other_subtlv(message + 12, len - 10);
if(rc < 0)
goto done;
} else if(type == MESSAGE_NH) { } else if(type == MESSAGE_NH) {
unsigned char nh[16]; unsigned char nh[16];
int rc; int rc;
...@@ -462,6 +519,9 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -462,6 +519,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
memcpy(v6_nh, nh, 16); memcpy(v6_nh, nh, 16);
have_v6_nh = 1; have_v6_nh = 1;
} }
rc = parse_other_subtlv(message + 4 + rc, len - 2 - rc);
if(rc < 0)
goto done;
} else if(type == MESSAGE_UPDATE) { } else if(type == MESSAGE_UPDATE) {
unsigned char prefix[16], src_prefix[16], *nh; unsigned char prefix[16], src_prefix[16], *nh;
unsigned char plen, src_plen; unsigned char plen, src_plen;
...@@ -530,6 +590,9 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -530,6 +590,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
format_address(from), ifp->name); format_address(from), ifp->name);
if(message[2] == 0) { if(message[2] == 0) {
rc = parse_other_subtlv(message + 12, len - 10);
if(rc < 0)
goto done;
if(metric < 0xFFFF) { if(metric < 0xFFFF) {
fprintf(stderr, fprintf(stderr,
"Received wildcard update with finite metric.\n"); "Received wildcard update with finite metric.\n");
...@@ -547,13 +610,16 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -547,13 +610,16 @@ parse_packet(const unsigned char *from, struct interface *ifp,
nh = neigh->address; nh = neigh->address;
} }
rc = parse_update_subtlv(ifp, metric, message + 2 + parsed_len,
len - parsed_len, channels, &channels_len);
if (rc < 0)
goto done;
if(message[2] == 1) { if(message[2] == 1) {
if(!ifp->ipv4) if(!ifp->ipv4)
goto done; goto done;
} }
parse_update_subtlv(ifp, metric, message + 2 + parsed_len,
len - parsed_len, channels, &channels_len);
update_route(router_id, prefix, plen, src_prefix, src_plen, seqno, update_route(router_id, prefix, plen, src_prefix, src_plen, seqno,
metric, interval, neigh, nh, metric, interval, neigh, nh,
channels, channels_len); channels, channels_len);
...@@ -568,6 +634,9 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -568,6 +634,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
debugf("Received request for %s from %s on %s.\n", debugf("Received request for %s from %s on %s.\n",
message[2] == 0 ? "any" : format_prefix(prefix, plen), message[2] == 0 ? "any" : format_prefix(prefix, plen),
format_address(from), ifp->name); format_address(from), ifp->name);
rc = parse_other_subtlv(message + 4 + rc, len - 2 - rc);
if(rc < 0)
goto done;
if(message[2] == 0) { if(message[2] == 0) {
/* If a neighbour is requesting a full route dump from us, /* If a neighbour is requesting a full route dump from us,
we might as well send it an IHU. */ we might as well send it an IHU. */
...@@ -598,6 +667,9 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -598,6 +667,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
rc = network_prefix(message[2], message[3], 0, rc = network_prefix(message[2], message[3], 0,
message + 16, NULL, len - 14, prefix); message + 16, NULL, len - 14, prefix);
if(rc < 0) goto fail; if(rc < 0) goto fail;
rc = parse_other_subtlv(message + 16 + rc, len - 14 - rc);
if(rc < 0)
goto done;
plen = message[3] + (message[2] == 1 ? 96 : 0); plen = message[3] + (message[2] == 1 ? 96 : 0);
if(message[2] == 1) { if(message[2] == 1) {
v4tov6(src_prefix, zeroes); v4tov6(src_prefix, zeroes);
...@@ -663,6 +735,9 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -663,6 +735,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
if(ae == 0) { if(ae == 0) {
debugf("Received invalid Source-Specific wildcard update.\n"); debugf("Received invalid Source-Specific wildcard update.\n");
rc = parse_other_subtlv(message + 12, len - 10);
if(rc < 0)
goto done;
retract_neighbour_routes(neigh); retract_neighbour_routes(neigh);
goto done; goto done;
} else if(ae == 1) { } else if(ae == 1) {
...@@ -675,13 +750,16 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -675,13 +750,16 @@ parse_packet(const unsigned char *from, struct interface *ifp,
nh = neigh->address; nh = neigh->address;
} }
rc = parse_update_subtlv(ifp, metric, message + 2 + parsed_len,
len - parsed_len, channels, &channels_len);
if(rc < 0)
goto done;
if(ae == 1) { if(ae == 1) {
if(!ifp->ipv4) if(!ifp->ipv4)
goto done; goto done;
} }
parse_update_subtlv(ifp, metric, message + 2 + parsed_len,
len - parsed_len, channels, &channels_len);
update_route(router_id, prefix, plen, src_prefix, src_plen, update_route(router_id, prefix, plen, src_prefix, src_plen,
seqno, metric, interval, neigh, nh, seqno, metric, interval, neigh, nh,
channels, channels_len); channels, channels_len);
...@@ -704,6 +782,9 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -704,6 +782,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
if(ae == 1) if(ae == 1)
src_plen += 96; src_plen += 96;
parsed += rc; parsed += rc;
rc = parse_other_subtlv(message + parsed, len - parsed + 2);
if(rc < 0)
goto done;
if(ae == 0) { if(ae == 0) {
debugf("Received request for any source-specific " debugf("Received request for any source-specific "
"from %s on %s.\n", "from %s on %s.\n",
...@@ -741,6 +822,10 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -741,6 +822,10 @@ parse_packet(const unsigned char *from, struct interface *ifp,
rc = network_prefix(ae, src_plen, 0, message + parsed, rc = network_prefix(ae, src_plen, 0, message + parsed,
NULL, len + 2 - parsed, src_prefix); NULL, len + 2 - parsed, src_prefix);
if(rc < 0) goto fail; if(rc < 0) goto fail;
parsed += rc;
rc = parse_other_subtlv(message + parsed, len - parsed + 2);
if(rc < 0)
goto done;
if(ae == 1) if(ae == 1)
src_plen += 96; src_plen += 96;
debugf("Received request (%d) for (%s, %s)" debugf("Received request (%d) for (%s, %s)"
...@@ -1753,7 +1838,7 @@ send_marginal_ihu(struct interface *ifp) ...@@ -1753,7 +1838,7 @@ send_marginal_ihu(struct interface *ifp)
FOR_ALL_NEIGHBOURS(neigh) { FOR_ALL_NEIGHBOURS(neigh) {
if(ifp && neigh->ifp != ifp) if(ifp && neigh->ifp != ifp)
continue; continue;
if(neigh->txcost >= 384 || (neigh->reach & 0xF000) != 0xF000) if(neigh->txcost >= 384 || (neigh->hello.reach & 0xF000) != 0xF000)
send_ihu(neigh, ifp); send_ihu(neigh, ifp);
} }
} }
......
...@@ -90,11 +90,11 @@ find_neighbour(const unsigned char *address, struct interface *ifp) ...@@ -90,11 +90,11 @@ find_neighbour(const unsigned char *address, struct interface *ifp)
return NULL; return NULL;
} }
neigh->hello_seqno = -1; neigh->hello.seqno = neigh->uhello.seqno = -1;
memcpy(neigh->address, address, 16); memcpy(neigh->address, address, 16);
neigh->txcost = INFINITY; neigh->txcost = INFINITY;
neigh->ihu_time = now; neigh->ihu_time = now;
neigh->hello_time = zero; neigh->hello.time = neigh->uhello.time = zero;
neigh->hello_rtt_receive_time = zero; neigh->hello_rtt_receive_time = zero;
neigh->rtt_time = zero; neigh->rtt_time = zero;
neigh->ifp = ifp; neigh->ifp = ifp;
...@@ -108,84 +108,79 @@ find_neighbour(const unsigned char *address, struct interface *ifp) ...@@ -108,84 +108,79 @@ find_neighbour(const unsigned char *address, struct interface *ifp)
/* Recompute a neighbour's rxcost. Return true if anything changed. /* Recompute a neighbour's rxcost. Return true if anything changed.
This does not call local_notify_neighbour, see update_neighbour_metric. */ This does not call local_notify_neighbour, see update_neighbour_metric. */
int int
update_neighbour(struct neighbour *neigh, int hello, int hello_interval) update_neighbour(struct neighbour *neigh, struct hello_history *hist,
int unicast, int hello, int hello_interval)
{ {
int missed_hellos; int missed_hellos;
int rc = 0; int rc = 0;
if(hello < 0) { if(hello < 0) {
if(neigh->hello_interval <= 0) if(hist->interval <= 0)
return rc; return rc;
missed_hellos = missed_hellos =
((int)timeval_minus_msec(&now, &neigh->hello_time) - ((int)timeval_minus_msec(&now, &hist->time) -
neigh->hello_interval * 7) / hist->interval * 7) /
(neigh->hello_interval * 10); (hist->interval * 10);
if(missed_hellos <= 0) if(missed_hellos <= 0)
return rc; return rc;
timeval_add_msec(&neigh->hello_time, &neigh->hello_time, timeval_add_msec(&hist->time, &hist->time,
missed_hellos * neigh->hello_interval * 10); missed_hellos * hist->interval * 10);
} else { } else {
if(neigh->hello_seqno >= 0 && neigh->reach > 0) { if(hist->seqno >= 0 && hist->reach > 0) {
missed_hellos = seqno_minus(hello, neigh->hello_seqno) - 1; missed_hellos = seqno_minus(hello, hist->seqno) - 1;
if(missed_hellos < -8) { if(missed_hellos < -8) {
/* Probably a neighbour that rebooted and lost its seqno. /* Probably a neighbour that rebooted and lost its seqno.
Reboot the universe. */ Reboot the universe. */
neigh->reach = 0; hist->reach = 0;
missed_hellos = 0; missed_hellos = 0;
rc = 1; rc = 1;
} else if(missed_hellos < 0) { } else if(missed_hellos < 0) {
if(hello_interval > neigh->hello_interval) { hist->reach <<= -missed_hellos;
/* This neighbour has increased its hello interval,
and we didn't notice. */
neigh->reach <<= -missed_hellos;
missed_hellos = 0; missed_hellos = 0;
} else {
/* Late hello. Probably due to the link layer buffering
packets during a link outage. Ignore it, but reset
the expected seqno. */
neigh->hello_seqno = hello;
hello = -1;
missed_hellos = 0;
}
rc = 1; rc = 1;
} }
} else { } else {
missed_hellos = 0; missed_hellos = 0;
} }
neigh->hello_time = now; if(hello_interval != 0) {
neigh->hello_interval = hello_interval; hist->time = now;
hist->interval = hello_interval;
}
} }
if(missed_hellos > 0) { if(missed_hellos > 0) {
neigh->reach >>= missed_hellos; hist->reach >>= missed_hellos;
neigh->hello_seqno = seqno_plus(neigh->hello_seqno, missed_hellos); hist->seqno = seqno_plus(hist->seqno, missed_hellos);
missed_hellos = 0; missed_hellos = 0;
rc = 1; rc = 1;
} }
if(hello >= 0) { if(hello >= 0) {
neigh->hello_seqno = hello; hist->seqno = hello;
neigh->reach >>= 1; hist->reach >>= 1;
neigh->reach |= 0x8000; hist->reach |= 0x8000;
if((neigh->reach & 0xFC00) != 0xFC00) if((hist->reach & 0xFC00) != 0xFC00)
rc = 1; rc = 1;
} }
if(unicast)
return rc;
/* Make sure to give neighbours some feedback early after association */ /* Make sure to give neighbours some feedback early after association */
if((neigh->reach & 0xBF00) == 0x8000) { if((hist->reach & 0xBF00) == 0x8000) {
/* A new neighbour */ /* A new neighbour */
send_hello(neigh->ifp); send_hello(neigh->ifp);
} else { } else {
/* Don't send hellos, in order to avoid a positive feedback loop. */ /* Don't send hellos, in order to avoid a positive feedback loop. */
int a = (neigh->reach & 0xC000); int a = (hist->reach & 0xC000);
int b = (neigh->reach & 0x3000); int b = (hist->reach & 0x3000);
if((a == 0xC000 && b == 0) || (a == 0 && b == 0x3000)) { if((a == 0xC000 && b == 0) || (a == 0 && b == 0x3000)) {
/* Reachability is either 1100 or 0011 */ /* Reachability is either 1100 or 0011 */
send_self_update(neigh->ifp); send_self_update(neigh->ifp);
} }
} }
if((neigh->reach & 0xFC00) == 0xC000) { if((hist->reach & 0xFC00) == 0xC000) {
/* This is a newish neighbour, let's request a full route dump. /* This is a newish neighbour, let's request a full route dump.
We ought to avoid this when the network is dense */ We ought to avoid this when the network is dense */
send_unicast_request(neigh, NULL, 0, NULL, 0); send_unicast_request(neigh, NULL, 0, NULL, 0);
...@@ -205,7 +200,7 @@ reset_txcost(struct neighbour *neigh) ...@@ -205,7 +200,7 @@ reset_txcost(struct neighbour *neigh)
return 0; return 0;
/* If we're losing a lot of packets, we probably lost an IHU too */ /* If we're losing a lot of packets, we probably lost an IHU too */
if(delay >= 180000 || (neigh->reach & 0xFFF0) == 0 || if(delay >= 180000 || (neigh->hello.reach & 0xFFF0) == 0 ||
(neigh->ihu_interval > 0 && (neigh->ihu_interval > 0 &&
delay >= neigh->ihu_interval * 10 * 10)) { delay >= neigh->ihu_interval * 10 * 10)) {
neigh->txcost = INFINITY; neigh->txcost = INFINITY;
...@@ -226,18 +221,20 @@ unsigned ...@@ -226,18 +221,20 @@ unsigned
check_neighbours() check_neighbours()
{ {
struct neighbour *neigh; struct neighbour *neigh;
int changed, rc;
unsigned msecs = 50000; unsigned msecs = 50000;
debugf("Checking neighbours.\n"); debugf("Checking neighbours.\n");
neigh = neighs; neigh = neighs;
while(neigh) { while(neigh) {
changed = update_neighbour(neigh, -1, 0); int changed, rc;
changed = update_neighbour(neigh, &neigh->hello, 0, -1, 0);
rc = update_neighbour(neigh, &neigh->uhello, 1, -1, 0);
changed = changed || rc;
if(neigh->reach == 0 || if(neigh->hello.reach == 0 ||
neigh->hello_time.tv_sec > now.tv_sec || /* clock stepped */ neigh->hello.time.tv_sec > now.tv_sec || /* clock stepped */
timeval_minus_msec(&now, &neigh->hello_time) > 300000) { timeval_minus_msec(&now, &neigh->hello.time) > 300000) {
struct neighbour *old = neigh; struct neighbour *old = neigh;
neigh = neigh->next; neigh = neigh->next;
flush_neighbour(old); flush_neighbour(old);
...@@ -249,8 +246,8 @@ check_neighbours() ...@@ -249,8 +246,8 @@ check_neighbours()
update_neighbour_metric(neigh, changed); update_neighbour_metric(neigh, changed);
if(neigh->hello_interval > 0) if(neigh->hello.interval > 0)
msecs = MIN(msecs, neigh->hello_interval * 10); msecs = MIN(msecs, neigh->hello.interval * 10);
if(neigh->ihu_interval > 0) if(neigh->ihu_interval > 0)
msecs = MIN(msecs, neigh->ihu_interval * 10); msecs = MIN(msecs, neigh->ihu_interval * 10);
neigh = neigh->next; neigh = neigh->next;
...@@ -259,15 +256,32 @@ check_neighbours() ...@@ -259,15 +256,32 @@ check_neighbours()
return msecs; return msecs;
} }
/* To lose one hello is a misfortune, to lose two is carelessness. */
static int
two_three(int reach)
{
if((reach & 0xC000) == 0xC000)
return 1;
else if((reach & 0xC000) == 0)
return 0;
else if((reach & 0x2000))
return 1;
else
return 0;
}
unsigned unsigned
neighbour_rxcost(struct neighbour *neigh) neighbour_rxcost(struct neighbour *neigh)
{ {
unsigned delay; unsigned delay, udelay;
unsigned short reach = neigh->reach; unsigned short reach = neigh->hello.reach;
unsigned short ureach = neigh->uhello.reach;
delay = timeval_minus_msec(&now, &neigh->hello_time); delay = timeval_minus_msec(&now, &neigh->hello.time);
udelay = timeval_minus_msec(&now, &neigh->uhello.time);
if((reach & 0xFFF0) == 0 || delay >= 180000) { if(((reach & 0xFFF0) == 0 || delay >= 180000) &&
((ureach & 0xFFF0) == 0 || udelay >= 180000)) {
return INFINITY; return INFINITY;
} else if((neigh->ifp->flags & IF_LQ)) { } else if((neigh->ifp->flags & IF_LQ)) {
int sreach = int sreach =
...@@ -281,12 +295,7 @@ neighbour_rxcost(struct neighbour *neigh) ...@@ -281,12 +295,7 @@ neighbour_rxcost(struct neighbour *neigh)
cost = (cost * (delay - 20000) + 10000) / 20000; cost = (cost * (delay - 20000) + 10000) / 20000;
return MIN(cost, INFINITY); return MIN(cost, INFINITY);
} else { } else {
/* To lose one hello is a misfortune, to lose two is carelessness. */ if(two_three(reach) || two_three(ureach))
if((reach & 0xC000) == 0xC000)
return neigh->ifp->cost;
else if((reach & 0xC000) == 0)
return INFINITY;
else if((reach & 0x2000))
return neigh->ifp->cost; return neigh->ifp->cost;
else else
return INFINITY; return INFINITY;
......
...@@ -20,16 +20,21 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ...@@ -20,16 +20,21 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
*/ */
struct hello_history {
unsigned short reach;
unsigned short interval; /* in centiseconds */
int seqno;
struct timeval time;
};
struct neighbour { struct neighbour {
struct neighbour *next; struct neighbour *next;
/* This is -1 when unknown, so don't make it unsigned */ /* This is -1 when unknown, so don't make it unsigned */
int hello_seqno;
unsigned char address[16]; unsigned char address[16];
unsigned short reach; struct hello_history hello;
struct hello_history uhello; /* for Unicast hellos */
unsigned short txcost; unsigned short txcost;
struct timeval hello_time;
struct timeval ihu_time; struct timeval ihu_time;
unsigned short hello_interval; /* in centiseconds */
unsigned short ihu_interval; /* in centiseconds */ unsigned short ihu_interval; /* in centiseconds */
/* Used for RTT estimation. */ /* Used for RTT estimation. */
/* Absolute time (modulo 2^32) at which the Hello was sent, /* Absolute time (modulo 2^32) at which the Hello was sent,
...@@ -50,7 +55,8 @@ int neighbour_valid(struct neighbour *neigh); ...@@ -50,7 +55,8 @@ int neighbour_valid(struct neighbour *neigh);
void flush_neighbour(struct neighbour *neigh); void flush_neighbour(struct neighbour *neigh);
struct neighbour *find_neighbour(const unsigned char *address, struct neighbour *find_neighbour(const unsigned char *address,
struct interface *ifp); struct interface *ifp);
int update_neighbour(struct neighbour *neigh, int hello, int hello_interval); int update_neighbour(struct neighbour *neigh, struct hello_history *hist,
int unicast, int hello, int hello_interval);
unsigned check_neighbours(void); unsigned check_neighbours(void);
unsigned neighbour_txcost(struct neighbour *neigh); unsigned neighbour_txcost(struct neighbour *neigh);
unsigned neighbour_rxcost(struct neighbour *neigh); unsigned neighbour_rxcost(struct neighbour *neigh);
......
...@@ -47,7 +47,6 @@ int kernel_metric = 0, reflect_kernel_metric = 0; ...@@ -47,7 +47,6 @@ int kernel_metric = 0, reflect_kernel_metric = 0;
int allow_duplicates = -1; int allow_duplicates = -1;
int diversity_kind = DIVERSITY_NONE; int diversity_kind = DIVERSITY_NONE;
int diversity_factor = 256; /* in units of 1/256 */ int diversity_factor = 256; /* in units of 1/256 */
int keep_unfeasible = 0;
static int smoothing_half_life = 0; static int smoothing_half_life = 0;
static int two_to_the_one_over_hl = 0; /* 2^(1/hl) * 0x10000 */ static int two_to_the_one_over_hl = 0; /* 2^(1/hl) * 0x10000 */
...@@ -907,7 +906,7 @@ update_route(const unsigned char *id, ...@@ -907,7 +906,7 @@ update_route(const unsigned char *id,
} }
route->src = retain_source(src); route->src = retain_source(src);
if((feasible || keep_unfeasible) && refmetric < INFINITY) if(refmetric < INFINITY)
route->time = now.tv_sec; route->time = now.tv_sec;
route->seqno = seqno; route->seqno = seqno;
...@@ -953,8 +952,6 @@ update_route(const unsigned char *id, ...@@ -953,8 +952,6 @@ update_route(const unsigned char *id,
return NULL; return NULL;
if(!feasible) { if(!feasible) {
send_unfeasible_request(neigh, 0, seqno, metric, src); send_unfeasible_request(neigh, 0, seqno, metric, src);
if(!keep_unfeasible)
return NULL;
} }
route = calloc(1, sizeof(struct babel_route)); route = calloc(1, sizeof(struct babel_route));
......
...@@ -51,7 +51,6 @@ struct route_stream; ...@@ -51,7 +51,6 @@ struct route_stream;
extern struct babel_route **routes; extern struct babel_route **routes;
extern int kernel_metric, allow_duplicates, reflect_kernel_metric; extern int kernel_metric, allow_duplicates, reflect_kernel_metric;
extern int diversity_kind, diversity_factor; extern int diversity_kind, diversity_factor;
extern int keep_unfeasible;
static inline int static inline int
route_metric(const struct babel_route *route) route_metric(const struct babel_route *route)
......
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