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