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,
......
This diff is collapsed.
...@@ -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, missed_hellos = 0;
and we didn't notice. */
neigh->reach <<= -missed_hellos;
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