Commit ebd21fcf authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Make route->channels carry an explicit length.

This allows 0 to appear within a channel list, which is consistent with
draft-chroboczek-babel-diversity-routing-01.
parent 77a68bb9
...@@ -1059,23 +1059,19 @@ dump_route(FILE *out, struct babel_route *route) ...@@ -1059,23 +1059,19 @@ dump_route(FILE *out, struct babel_route *route)
NULL : route->nexthop; NULL : route->nexthop;
char channels[100]; char channels[100];
if(route->channels[0] == 0) if(route->channels_len == 0) {
channels[0] = '\0'; channels[0] = '\0';
else { } else {
int k, j = 0; int k, j = 0;
snprintf(channels, 100, " chan ("); snprintf(channels, 100, " chan (");
j = strlen(channels); j = strlen(channels);
for(k = 0; k < DIVERSITY_HOPS; k++) { for(k = 0; k < route->channels_len; k++) {
if(route->channels[k] == 0)
break;
if(k > 0) if(k > 0)
channels[j++] = ','; channels[j++] = ',';
snprintf(channels + j, 100 - j, "%u", (unsigned)route->channels[k]); snprintf(channels + j, 100 - j, "%u", (unsigned)route->channels[k]);
j = strlen(channels); j = strlen(channels);
} }
snprintf(channels + j, 100 - j, ")"); snprintf(channels + j, 100 - j, ")");
if(k == 0)
channels[0] = '\0';
} }
fprintf(out, "%s from %s metric %d (%d) refmetric %d id %s " fprintf(out, "%s from %s metric %d (%d) refmetric %d id %s "
......
...@@ -57,6 +57,8 @@ struct timeval unicast_flush_timeout = {0, 0}; ...@@ -57,6 +57,8 @@ struct timeval unicast_flush_timeout = {0, 0};
static const unsigned char v4prefix[16] = static const unsigned char v4prefix[16] =
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }; {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
#define MAX_CHANNEL_HOPS 20
/* Parse a network prefix, encoded in the somewhat baroque compressed /* Parse a network prefix, encoded in the somewhat baroque compressed
representation used by Babel. Return the number of bytes parsed. */ representation used by Babel. Return the number of bytes parsed. */
static int static int
...@@ -122,21 +124,22 @@ network_prefix(int ae, int plen, unsigned int omitted, ...@@ -122,21 +124,22 @@ network_prefix(int ae, int plen, unsigned int omitted,
static void static void
parse_update_subtlv(struct interface *ifp, int metric, parse_update_subtlv(struct interface *ifp, int metric,
const unsigned char *a, int alen, const unsigned char *a, int alen,
unsigned char *channels) unsigned char *channels, int *channels_len_return)
{ {
int type, len, i = 0; int type, len, i = 0;
int channels_len;
if((ifp->flags & IF_FARAWAY)) { /* This will be overwritten if there's a DIVERSITY_HOPS sub-TLV. */
channels[0] = 0; if(*channels_len_return < 1 || (ifp->flags & IF_FARAWAY)) {
channels_len = 0;
} else { } else {
/* This will be overwritten if there's a DIVERSITY_HOPS sub-TLV. */
if(metric < 256) { if(metric < 256) {
/* Assume non-interfering (wired) link. */ /* Assume non-interfering (wired) link. */
channels[0] = 0; channels_len = 0;
} else { } else {
/* Assume interfering. */ /* Assume interfering. */
channels[0] = IF_CHANNEL_INTERFERING; channels[0] = IF_CHANNEL_INTERFERING;
channels[1] = 0; channels_len = 1;
} }
} }
...@@ -160,27 +163,15 @@ parse_update_subtlv(struct interface *ifp, int metric, ...@@ -160,27 +163,15 @@ parse_update_subtlv(struct interface *ifp, int metric,
if(type == SUBTLV_PADN) { if(type == SUBTLV_PADN) {
/* Nothing. */ /* Nothing. */
} else if(type == SUBTLV_DIVERSITY) { } else if(type == SUBTLV_DIVERSITY) {
if(!(ifp->flags & IF_FARAWAY)) { memcpy(channels, a + i + 2, MIN(len, *channels_len_return));
if(len > DIVERSITY_HOPS) { channels_len = MIN(len, *channels_len_return);
fprintf(stderr,
"Received overlong channel information (%d > %d).\n",
len, DIVERSITY_HOPS);
len = DIVERSITY_HOPS;
}
if(memchr(a + i + 2, 0, len) != NULL) {
/* 0 is reserved. */
fprintf(stderr, "Channel information contains 0!");
return;
}
memset(channels, 0, DIVERSITY_HOPS);
memcpy(channels, a + i + 2, len);
}
} else { } else {
debugf("Received unknown update sub-TLV %d.\n", type); debugf("Received unknown update sub-TLV %d.\n", type);
} }
i += len + 2; i += len + 2;
} }
*channels_len_return = channels_len;
} }
static int static int
...@@ -277,13 +268,6 @@ network_address(int ae, const unsigned char *a, unsigned int len, ...@@ -277,13 +268,6 @@ network_address(int ae, const unsigned char *a, unsigned int len,
return network_prefix(ae, -1, 0, a, NULL, len, a_r); return network_prefix(ae, -1, 0, a, NULL, len, a_r);
} }
static int
channels_len(unsigned char *channels)
{
unsigned char *p = memchr(channels, 0, DIVERSITY_HOPS);
return p ? (p - channels) : DIVERSITY_HOPS;
}
void void
parse_packet(const unsigned char *from, struct interface *ifp, parse_packet(const unsigned char *from, struct interface *ifp,
const unsigned char *packet, int packetlen) const unsigned char *packet, int packetlen)
...@@ -461,7 +445,8 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -461,7 +445,8 @@ parse_packet(const unsigned char *from, struct interface *ifp,
} else if(type == MESSAGE_UPDATE) { } else if(type == MESSAGE_UPDATE) {
unsigned char prefix[16], *nh; unsigned char prefix[16], *nh;
unsigned char plen; unsigned char plen;
unsigned char channels[DIVERSITY_HOPS]; unsigned char channels[MAX_CHANNEL_HOPS];
int channels_len = MAX_CHANNEL_HOPS;
unsigned short interval, seqno, metric; unsigned short interval, seqno, metric;
int rc, parsed_len; int rc, parsed_len;
if(len < 10) { if(len < 10) {
...@@ -541,10 +526,10 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -541,10 +526,10 @@ parse_packet(const unsigned char *from, struct interface *ifp,
} }
parse_update_subtlv(ifp, metric, message + 2 + parsed_len, parse_update_subtlv(ifp, metric, message + 2 + parsed_len,
len - parsed_len, channels); len - parsed_len, channels, &channels_len);
update_route(router_id, prefix, plen, zeroes, 0, seqno, update_route(router_id, prefix, plen, zeroes, 0, seqno,
metric, interval, neigh, nh, metric, interval, neigh, nh,
channels, channels_len(channels)); channels, channels_len);
} else if(type == MESSAGE_REQUEST) { } else if(type == MESSAGE_REQUEST) {
unsigned char prefix[16], plen; unsigned char prefix[16], plen;
int rc; int rc;
...@@ -590,7 +575,8 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -590,7 +575,8 @@ parse_packet(const unsigned char *from, struct interface *ifp,
} else if(type == MESSAGE_UPDATE_SRC_SPECIFIC) { } else if(type == MESSAGE_UPDATE_SRC_SPECIFIC) {
unsigned char prefix[16], src_prefix[16], *nh; unsigned char prefix[16], src_prefix[16], *nh;
unsigned char ae, plen, src_plen, omitted; unsigned char ae, plen, src_plen, omitted;
unsigned char channels[DIVERSITY_HOPS]; unsigned char channels[MAX_CHANNEL_HOPS];
int channels_len = MAX_CHANNEL_HOPS;
unsigned short interval, seqno, metric; unsigned short interval, seqno, metric;
const unsigned char *src_prefix_beginning = NULL; const unsigned char *src_prefix_beginning = NULL;
int rc, parsed_len = 0; int rc, parsed_len = 0;
...@@ -654,11 +640,10 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -654,11 +640,10 @@ parse_packet(const unsigned char *from, struct interface *ifp,
} }
parse_update_subtlv(ifp, metric, message + 2 + parsed_len, parse_update_subtlv(ifp, metric, message + 2 + parsed_len,
len - parsed_len, channels); 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, channels_len);
} else if(type == MESSAGE_REQUEST_SRC_SPECIFIC) { } else if(type == MESSAGE_REQUEST_SRC_SPECIFIC) {
unsigned char prefix[16], plen, ae, src_prefix[16], src_plen; unsigned char prefix[16], plen, ae, src_prefix[16], src_plen;
int rc, parsed = 5; int rc, parsed = 5;
...@@ -1361,7 +1346,7 @@ flushupdates(struct interface *ifp) ...@@ -1361,7 +1346,7 @@ flushupdates(struct interface *ifp)
last_src_prefix = xroute->src_prefix; last_src_prefix = xroute->src_prefix;
last_src_plen = xroute->src_plen; last_src_plen = xroute->src_plen;
} else if(route) { } else if(route) {
unsigned char channels[DIVERSITY_HOPS]; unsigned char channels[MAX_CHANNEL_HOPS];
int chlen; int chlen;
struct interface *route_ifp = route->neigh->ifp; struct interface *route_ifp = route->neigh->ifp;
unsigned short metric; unsigned short metric;
...@@ -1384,7 +1369,9 @@ flushupdates(struct interface *ifp) ...@@ -1384,7 +1369,9 @@ flushupdates(struct interface *ifp)
continue; continue;
if(route_ifp->channel == IF_CHANNEL_NONINTERFERING) { if(route_ifp->channel == IF_CHANNEL_NONINTERFERING) {
memcpy(channels, route->channels, DIVERSITY_HOPS); memcpy(channels, route->channels,
MIN(route->channels_len, MAX_CHANNEL_HOPS));
chlen = MIN(route->channels_len, MAX_CHANNEL_HOPS);
} else { } else {
if(route_ifp->channel == IF_CHANNEL_UNKNOWN) if(route_ifp->channel == IF_CHANNEL_UNKNOWN)
channels[0] = IF_CHANNEL_INTERFERING; channels[0] = IF_CHANNEL_INTERFERING;
...@@ -1393,10 +1380,11 @@ flushupdates(struct interface *ifp) ...@@ -1393,10 +1380,11 @@ flushupdates(struct interface *ifp)
route_ifp->channel <= 255); route_ifp->channel <= 255);
channels[0] = route_ifp->channel; channels[0] = route_ifp->channel;
} }
memcpy(channels + 1, route->channels, DIVERSITY_HOPS - 1); memcpy(channels + 1, route->channels,
MIN(route->channels_len, MAX_CHANNEL_HOPS - 1));
chlen = 1 + MIN(route->channels_len, MAX_CHANNEL_HOPS - 1);
} }
chlen = channels_len(channels);
really_send_update(ifp, route->src->id, really_send_update(ifp, route->src->id,
route->src->prefix, route->src->plen, route->src->prefix, route->src->plen,
route->src->src_prefix, route->src->src_plen, route->src->src_prefix, route->src->src_plen,
......
...@@ -242,6 +242,13 @@ insert_route(struct babel_route *route) ...@@ -242,6 +242,13 @@ insert_route(struct babel_route *route)
return route; return route;
} }
static void
destroy_route(struct babel_route *route)
{
free(route->channels);
free(route);
}
void void
flush_route(struct babel_route *route) flush_route(struct babel_route *route)
{ {
...@@ -267,7 +274,7 @@ flush_route(struct babel_route *route) ...@@ -267,7 +274,7 @@ flush_route(struct babel_route *route)
if(route == routes[i]) { if(route == routes[i]) {
routes[i] = route->next; routes[i] = route->next;
route->next = NULL; route->next = NULL;
free(route); destroy_route(route);
if(routes[i] == NULL) { if(routes[i] == NULL) {
if(i < route_slots - 1) if(i < route_slots - 1)
...@@ -288,7 +295,7 @@ flush_route(struct babel_route *route) ...@@ -288,7 +295,7 @@ flush_route(struct babel_route *route)
r = r->next; r = r->next;
r->next = route->next; r->next = route->next;
route->next = NULL; route->next = NULL;
free(route); destroy_route(route);
} }
if(lost) if(lost)
...@@ -620,10 +627,9 @@ route_interferes(struct babel_route *route, struct interface *ifp) ...@@ -620,10 +627,9 @@ route_interferes(struct babel_route *route, struct interface *ifp)
return 1; return 1;
if(diversity_kind == DIVERSITY_CHANNEL) { if(diversity_kind == DIVERSITY_CHANNEL) {
int i; int i;
for(i = 0; i < DIVERSITY_HOPS; i++) { for(i = 0; i < route->channels_len; i++) {
if(route->channels[i] == 0) if(route->channels[i] != 0 &&
break; channels_interfere(ifp->channel, route->channels[i]))
if(channels_interfere(ifp->channel, route->channels[i]))
return 1; return 1;
} }
} }
...@@ -910,10 +916,24 @@ update_route(const unsigned char *id, ...@@ -910,10 +916,24 @@ update_route(const unsigned char *id,
route->time = now.tv_sec; route->time = now.tv_sec;
route->seqno = seqno; route->seqno = seqno;
memset(&route->channels, 0, sizeof(route->channels)); if(channels_len == 0) {
if(channels_len > 0) free(route->channels);
memcpy(&route->channels, channels, route->channels_len = 0;
MIN(channels_len, DIVERSITY_HOPS)); } else {
if(channels_len != route->channels_len) {
unsigned char *new_channels =
realloc(route->channels, channels_len);
if(new_channels == NULL) {
perror("malloc(channels)");
/* Truncate the data. */
channels_len = MIN(channels_len, route->channels_len);
} else {
route->channels = new_channels;
}
}
memcpy(route->channels, channels, channels_len);
route->channels_len = channels_len;
}
change_route_metric(route, change_route_metric(route,
refmetric, neighbour_cost(neigh), add_metric); refmetric, neighbour_cost(neigh), add_metric);
...@@ -956,14 +976,19 @@ update_route(const unsigned char *id, ...@@ -956,14 +976,19 @@ update_route(const unsigned char *id,
route->hold_time = hold_time; route->hold_time = hold_time;
route->smoothed_metric = MAX(route_metric(route), INFINITY / 2); route->smoothed_metric = MAX(route_metric(route), INFINITY / 2);
route->smoothed_metric_time = now.tv_sec; route->smoothed_metric_time = now.tv_sec;
if(channels_len > 0) if(channels_len > 0) {
memcpy(&route->channels, channels, route->channels = malloc(channels_len);
MIN(channels_len, DIVERSITY_HOPS)); if(route->channels == NULL) {
perror("malloc(channels)");
} else {
memcpy(route->channels, channels, channels_len);
}
}
route->next = NULL; route->next = NULL;
new_route = insert_route(route); new_route = insert_route(route);
if(new_route == NULL) { if(new_route == NULL) {
fprintf(stderr, "Couldn't insert route.\n"); fprintf(stderr, "Couldn't insert route.\n");
free(route); destroy_route(route);
return NULL; return NULL;
} }
local_notify_route(route, LOCAL_ADD); local_notify_route(route, LOCAL_ADD);
......
...@@ -25,8 +25,6 @@ THE SOFTWARE. ...@@ -25,8 +25,6 @@ THE SOFTWARE.
#define DIVERSITY_CHANNEL_1 2 #define DIVERSITY_CHANNEL_1 2
#define DIVERSITY_CHANNEL 3 #define DIVERSITY_CHANNEL 3
#define DIVERSITY_HOPS 8
struct babel_route { struct babel_route {
struct source *src; struct source *src;
unsigned short refmetric; unsigned short refmetric;
...@@ -40,7 +38,8 @@ struct babel_route { ...@@ -40,7 +38,8 @@ struct babel_route {
unsigned short smoothed_metric; /* for route selection */ unsigned short smoothed_metric; /* for route selection */
time_t smoothed_metric_time; time_t smoothed_metric_time;
short installed; short installed;
unsigned char channels[DIVERSITY_HOPS]; short channels_len;
unsigned char *channels;
struct babel_route *next; struct babel_route *next;
}; };
......
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