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)
while(1) {
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)
break;
......@@ -225,9 +225,6 @@ main(int argc, char **argv)
case 'r':
random_id = 1;
break;
case 'u':
keep_unfeasible = 1;
break;
case 'S':
state_file = optarg;
break;
......@@ -1116,11 +1113,12 @@ dump_tables(FILE *out)
fprintf(out, "My id %s seqno %d\n", format_eui64(myid), myseqno);
FOR_ALL_NEIGHBOURS(neigh) {
fprintf(out, "Neighbour %s dev %s reach %04x rxcost %d txcost %d "
"rtt %s rttcost %d chan %d%s.\n",
fprintf(out, "Neighbour %s dev %s reach %04x ureach %04x "
"rxcost %d txcost %d rtt %s rttcost %d chan %d%s.\n",
format_address(neigh->address),
neigh->ifp->name,
neigh->reach,
neigh->hello.reach,
neigh->uhello.reach,
neighbour_rxcost(neigh),
neigh->txcost,
format_thousands(neigh->rtt),
......
......@@ -196,11 +196,6 @@ at least
Do not use this option unless you know what you are doing, as it can
cause persistent route flapping.
.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 }
This specifies whether to use a random router-id, and is
equivalent to the command-line option
......
......@@ -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
case code for them. */
if(config_finalised) {
if(strcmp(token, "keep-unfeasible") != 0 &&
strcmp(token, "link-detect") != 0 &&
if(strcmp(token, "link-detect") != 0 &&
strcmp(token, "log-file") != 0 &&
strcmp(token, "diversity") != 0 &&
strcmp(token, "diversity-factor") != 0 &&
......@@ -798,8 +797,7 @@ parse_option(int c, gnc_t gnc, void *closure, char *token)
add_import_table(v);
else
abort();
} else if(strcmp(token, "keep-unfeasible") == 0 ||
strcmp(token, "link-detect") == 0 ||
} else if(strcmp(token, "link-detect") == 0 ||
strcmp(token, "random-id") == 0 ||
strcmp(token, "daemonise") == 0 ||
strcmp(token, "skip-kernel-setup") == 0 ||
......@@ -810,9 +808,7 @@ parse_option(int c, gnc_t gnc, void *closure, char *token)
if(c < -1)
goto error;
b = (b == CONFIG_YES);
if(strcmp(token, "keep-unfeasible") == 0)
keep_unfeasible = b;
else if(strcmp(token, "link-detect") == 0)
if(strcmp(token, "link-detect") == 0)
link_detect = b;
else if(strcmp(token, "random-id") == 0)
random_id = b;
......
......@@ -153,14 +153,16 @@ local_notify_neighbour_1(struct local_socket *s,
rc = snprintf(buf, 512,
"%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),
/* Neighbours never move around in memory , so we can use the
address as a unique identifier. */
(unsigned long int)neigh,
format_address(neigh->address),
neigh->ifp->name,
neigh->reach,
neigh->hello.reach,
neigh->uhello.reach,
neighbour_rxcost(neigh),
neighbour_txcost(neigh),
rttbuf,
......
This diff is collapsed.
......@@ -90,11 +90,11 @@ find_neighbour(const unsigned char *address, struct interface *ifp)
return NULL;
}
neigh->hello_seqno = -1;
neigh->hello.seqno = neigh->uhello.seqno = -1;
memcpy(neigh->address, address, 16);
neigh->txcost = INFINITY;
neigh->ihu_time = now;
neigh->hello_time = zero;
neigh->hello.time = neigh->uhello.time = zero;
neigh->hello_rtt_receive_time = zero;
neigh->rtt_time = zero;
neigh->ifp = ifp;
......@@ -108,84 +108,79 @@ find_neighbour(const unsigned char *address, struct interface *ifp)
/* Recompute a neighbour's rxcost. Return true if anything changed.
This does not call local_notify_neighbour, see update_neighbour_metric. */
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 rc = 0;
if(hello < 0) {
if(neigh->hello_interval <= 0)
if(hist->interval <= 0)
return rc;
missed_hellos =
((int)timeval_minus_msec(&now, &neigh->hello_time) -
neigh->hello_interval * 7) /
(neigh->hello_interval * 10);
((int)timeval_minus_msec(&now, &hist->time) -
hist->interval * 7) /
(hist->interval * 10);
if(missed_hellos <= 0)
return rc;
timeval_add_msec(&neigh->hello_time, &neigh->hello_time,
missed_hellos * neigh->hello_interval * 10);
timeval_add_msec(&hist->time, &hist->time,
missed_hellos * hist->interval * 10);
} else {
if(neigh->hello_seqno >= 0 && neigh->reach > 0) {
missed_hellos = seqno_minus(hello, neigh->hello_seqno) - 1;
if(hist->seqno >= 0 && hist->reach > 0) {
missed_hellos = seqno_minus(hello, hist->seqno) - 1;
if(missed_hellos < -8) {
/* Probably a neighbour that rebooted and lost its seqno.
Reboot the universe. */
neigh->reach = 0;
hist->reach = 0;
missed_hellos = 0;
rc = 1;
} else if(missed_hellos < 0) {
if(hello_interval > neigh->hello_interval) {
/* This neighbour has increased its hello interval,
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;
}
hist->reach <<= -missed_hellos;
missed_hellos = 0;
rc = 1;
}
} else {
missed_hellos = 0;
}
neigh->hello_time = now;
neigh->hello_interval = hello_interval;
if(hello_interval != 0) {
hist->time = now;
hist->interval = hello_interval;
}
}
if(missed_hellos > 0) {
neigh->reach >>= missed_hellos;
neigh->hello_seqno = seqno_plus(neigh->hello_seqno, missed_hellos);
hist->reach >>= missed_hellos;
hist->seqno = seqno_plus(hist->seqno, missed_hellos);
missed_hellos = 0;
rc = 1;
}
if(hello >= 0) {
neigh->hello_seqno = hello;
neigh->reach >>= 1;
neigh->reach |= 0x8000;
if((neigh->reach & 0xFC00) != 0xFC00)
hist->seqno = hello;
hist->reach >>= 1;
hist->reach |= 0x8000;
if((hist->reach & 0xFC00) != 0xFC00)
rc = 1;
}
if(unicast)
return rc;
/* Make sure to give neighbours some feedback early after association */
if((neigh->reach & 0xBF00) == 0x8000) {
if((hist->reach & 0xBF00) == 0x8000) {
/* A new neighbour */
send_hello(neigh->ifp);
} else {
/* Don't send hellos, in order to avoid a positive feedback loop. */
int a = (neigh->reach & 0xC000);
int b = (neigh->reach & 0x3000);
int a = (hist->reach & 0xC000);
int b = (hist->reach & 0x3000);
if((a == 0xC000 && b == 0) || (a == 0 && b == 0x3000)) {
/* Reachability is either 1100 or 0011 */
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.
We ought to avoid this when the network is dense */
send_unicast_request(neigh, NULL, 0, NULL, 0);
......@@ -205,7 +200,7 @@ reset_txcost(struct neighbour *neigh)
return 0;
/* 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 &&
delay >= neigh->ihu_interval * 10 * 10)) {
neigh->txcost = INFINITY;
......@@ -226,18 +221,20 @@ unsigned
check_neighbours()
{
struct neighbour *neigh;
int changed, rc;
unsigned msecs = 50000;
debugf("Checking neighbours.\n");
neigh = neighs;
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 ||
neigh->hello_time.tv_sec > now.tv_sec || /* clock stepped */
timeval_minus_msec(&now, &neigh->hello_time) > 300000) {
if(neigh->hello.reach == 0 ||
neigh->hello.time.tv_sec > now.tv_sec || /* clock stepped */
timeval_minus_msec(&now, &neigh->hello.time) > 300000) {
struct neighbour *old = neigh;
neigh = neigh->next;
flush_neighbour(old);
......@@ -249,8 +246,8 @@ check_neighbours()
update_neighbour_metric(neigh, changed);
if(neigh->hello_interval > 0)
msecs = MIN(msecs, neigh->hello_interval * 10);
if(neigh->hello.interval > 0)
msecs = MIN(msecs, neigh->hello.interval * 10);
if(neigh->ihu_interval > 0)
msecs = MIN(msecs, neigh->ihu_interval * 10);
neigh = neigh->next;
......@@ -259,15 +256,32 @@ check_neighbours()
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
neighbour_rxcost(struct neighbour *neigh)
{
unsigned delay;
unsigned short reach = neigh->reach;
unsigned delay, udelay;
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;
} else if((neigh->ifp->flags & IF_LQ)) {
int sreach =
......@@ -281,12 +295,7 @@ neighbour_rxcost(struct neighbour *neigh)
cost = (cost * (delay - 20000) + 10000) / 20000;
return MIN(cost, INFINITY);
} else {
/* To lose one hello is a misfortune, to lose two is carelessness. */
if((reach & 0xC000) == 0xC000)
return neigh->ifp->cost;
else if((reach & 0xC000) == 0)
return INFINITY;
else if((reach & 0x2000))
if(two_three(reach) || two_three(ureach))
return neigh->ifp->cost;
else
return INFINITY;
......
......@@ -20,16 +20,21 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
struct hello_history {
unsigned short reach;
unsigned short interval; /* in centiseconds */
int seqno;
struct timeval time;
};
struct neighbour {
struct neighbour *next;
/* This is -1 when unknown, so don't make it unsigned */
int hello_seqno;
unsigned char address[16];
unsigned short reach;
struct hello_history hello;
struct hello_history uhello; /* for Unicast hellos */
unsigned short txcost;
struct timeval hello_time;
struct timeval ihu_time;
unsigned short hello_interval; /* in centiseconds */
unsigned short ihu_interval; /* in centiseconds */
/* Used for RTT estimation. */
/* Absolute time (modulo 2^32) at which the Hello was sent,
......@@ -50,7 +55,8 @@ int neighbour_valid(struct neighbour *neigh);
void flush_neighbour(struct neighbour *neigh);
struct neighbour *find_neighbour(const unsigned char *address,
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 neighbour_txcost(struct neighbour *neigh);
unsigned neighbour_rxcost(struct neighbour *neigh);
......
......@@ -47,7 +47,6 @@ int kernel_metric = 0, reflect_kernel_metric = 0;
int allow_duplicates = -1;
int diversity_kind = DIVERSITY_NONE;
int diversity_factor = 256; /* in units of 1/256 */
int keep_unfeasible = 0;
static int smoothing_half_life = 0;
static int two_to_the_one_over_hl = 0; /* 2^(1/hl) * 0x10000 */
......@@ -907,7 +906,7 @@ update_route(const unsigned char *id,
}
route->src = retain_source(src);
if((feasible || keep_unfeasible) && refmetric < INFINITY)
if(refmetric < INFINITY)
route->time = now.tv_sec;
route->seqno = seqno;
......@@ -953,8 +952,6 @@ update_route(const unsigned char *id,
return NULL;
if(!feasible) {
send_unfeasible_request(neigh, 0, seqno, metric, src);
if(!keep_unfeasible)
return NULL;
}
route = calloc(1, sizeof(struct babel_route));
......
......@@ -51,7 +51,6 @@ struct route_stream;
extern struct babel_route **routes;
extern int kernel_metric, allow_duplicates, reflect_kernel_metric;
extern int diversity_kind, diversity_factor;
extern int keep_unfeasible;
static inline int
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