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,
......
......@@ -165,7 +165,10 @@ parse_update_subtlv(struct interface *ifp, int metric,
memcpy(channels, a + i + 2, MIN(len, *channels_len_return));
channels_len = MIN(len, *channels_len_return);
} 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;
......@@ -210,7 +213,10 @@ parse_hello_subtlv(const unsigned char *a, int alen,
/* But don't break. */
}
} 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;
......@@ -262,7 +268,10 @@ parse_ihu_subtlv(const unsigned char *a, int alen,
/* But don't break. */
}
} 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;
......@@ -277,6 +286,38 @@ parse_ihu_subtlv(const unsigned char *a, int alen,
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
network_address(int ae, const unsigned char *a, unsigned int len,
unsigned char *a_r)
......@@ -364,42 +405,53 @@ parse_packet(const unsigned char *from, struct interface *ifp,
len, format_address(from), ifp->name);
} else if(type == MESSAGE_ACK_REQ) {
unsigned short nonce, interval;
int rc;
if(len < 6) goto fail;
DO_NTOHS(nonce, message + 4);
DO_NTOHS(interval, message + 6);
debugf("Received ack-req (%04X %d) from %s on %s.\n",
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);
} else if(type == MESSAGE_ACK) {
int rc;
debugf("Received ack from %s on %s.\n",
format_address(from), ifp->name);
rc = parse_other_subtlv(message + 4, len - 2);
if(rc < 0)
goto done;
/* Nothing right now */
} else if(type == MESSAGE_HELLO) {
unsigned short seqno, interval;
int changed, have_timestamp;
int unicast, changed, have_timestamp, rc;
unsigned int timestamp;
if(len < 6) goto fail;
unicast = !!(message[2] & 0x80);
DO_NTOHS(seqno, message + 4);
DO_NTOHS(interval, message + 6);
debugf("Received hello %d (%d) from %s on %s.\n",
seqno, interval,
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);
if(interval > 0)
/* Multiply by 3/2 to allow hellos to expire. */
schedule_neighbours_check(interval * 15, 0);
/* Sub-TLV handling. */
if(len > 8) {
int rc;
rc = parse_hello_subtlv(message + 8, len - 6,
&timestamp, &have_timestamp);
if(rc >= 0 && have_timestamp) {
if(have_timestamp) {
neigh->hello_send_us = timestamp;
neigh->hello_rtt_receive_time = now;
have_hello_rtt = 1;
}
}
} else if(type == MESSAGE_IHU) {
unsigned short txcost, interval;
unsigned char address[16];
......@@ -414,7 +466,13 @@ parse_packet(const unsigned char *from, struct interface *ifp,
format_address(from), ifp->name,
format_address(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->ihu_time = now;
neigh->ihu_interval = interval;
......@@ -422,13 +480,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
if(interval > 0)
/* Multiply by 3/2 to allow neighbours to expire. */
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) {
int rc;
if(len < 10) {
have_router_id = 0;
goto fail;
......@@ -437,6 +491,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
have_router_id = 1;
debugf("Received router-id %s from %s on %s.\n",
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) {
unsigned char nh[16];
int rc;
......@@ -462,6 +519,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
memcpy(v6_nh, nh, 16);
have_v6_nh = 1;
}
rc = parse_other_subtlv(message + 4 + rc, len - 2 - rc);
if(rc < 0)
goto done;
} else if(type == MESSAGE_UPDATE) {
unsigned char prefix[16], src_prefix[16], *nh;
unsigned char plen, src_plen;
......@@ -530,6 +590,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
format_address(from), ifp->name);
if(message[2] == 0) {
rc = parse_other_subtlv(message + 12, len - 10);
if(rc < 0)
goto done;
if(metric < 0xFFFF) {
fprintf(stderr,
"Received wildcard update with finite metric.\n");
......@@ -547,13 +610,16 @@ parse_packet(const unsigned char *from, struct interface *ifp,
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(!ifp->ipv4)
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,
metric, interval, neigh, nh,
channels, channels_len);
......@@ -568,6 +634,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
debugf("Received request for %s from %s on %s.\n",
message[2] == 0 ? "any" : format_prefix(prefix, plen),
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 a neighbour is requesting a full route dump from us,
we might as well send it an IHU. */
......@@ -598,6 +667,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
rc = network_prefix(message[2], message[3], 0,
message + 16, NULL, len - 14, prefix);
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);
if(message[2] == 1) {
v4tov6(src_prefix, zeroes);
......@@ -663,6 +735,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
if(ae == 0) {
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);
goto done;
} else if(ae == 1) {
......@@ -675,13 +750,16 @@ parse_packet(const unsigned char *from, struct interface *ifp,
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(!ifp->ipv4)
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, metric, interval, neigh, nh,
channels, channels_len);
......@@ -704,6 +782,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
if(ae == 1)
src_plen += 96;
parsed += rc;
rc = parse_other_subtlv(message + parsed, len - parsed + 2);
if(rc < 0)
goto done;
if(ae == 0) {
debugf("Received request for any source-specific "
"from %s on %s.\n",
......@@ -741,6 +822,10 @@ parse_packet(const unsigned char *from, struct interface *ifp,
rc = network_prefix(ae, src_plen, 0, message + parsed,
NULL, len + 2 - parsed, src_prefix);
if(rc < 0) goto fail;
parsed += rc;
rc = parse_other_subtlv(message + parsed, len - parsed + 2);
if(rc < 0)
goto done;
if(ae == 1)
src_plen += 96;
debugf("Received request (%d) for (%s, %s)"
......@@ -1753,7 +1838,7 @@ send_marginal_ihu(struct interface *ifp)
FOR_ALL_NEIGHBOURS(neigh) {
if(ifp && neigh->ifp != ifp)
continue;
if(neigh->txcost >= 384 || (neigh->reach & 0xF000) != 0xF000)
if(neigh->txcost >= 384 || (neigh->hello.reach & 0xF000) != 0xF000)
send_ihu(neigh, ifp);
}
}
......
......@@ -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;
hist->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;
}
} 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