Author: marek
Date: 2009-10-25 00:13:51 +0000 (Sun, 25 Oct 2009)
New Revision: 1456
Modified:
trunk/batctl/Makefile
trunk/batctl/bisect.c
trunk/batctl/bisect.h
Log:
[batctl] add recursive check for routing loops
Modified: trunk/batctl/Makefile
===================================================================
--- trunk/batctl/Makefile 2009-10-25 00:13:47 UTC (rev 1455)
+++ trunk/batctl/Makefile 2009-10-25 00:13:51 UTC (rev 1456)
@@ -26,7 +26,7 @@
endif
CC = gcc
-CFLAGS += -pedantic -Wall -W -O1 -g3 -std=gnu99
+CFLAGS += -pedantic -Wall -W -g3 -std=gnu99
EXTRA_CFLAGS = -DREVISION_VERSION=$(REVISION_VERSION)
LDFLAGS +=
Modified: trunk/batctl/bisect.c
===================================================================
--- trunk/batctl/bisect.c 2009-10-25 00:13:47 UTC (rev 1455)
+++ trunk/batctl/bisect.c 2009-10-25 00:13:51 UTC (rev 1456)
@@ -87,24 +87,91 @@
}
strncpy(bat_node->name, name, NAME_LEN);
- INIT_LIST_HEAD_FIRST(bat_node->event_list);
+ INIT_LIST_HEAD_FIRST(bat_node->orig_event_list);
INIT_LIST_HEAD_FIRST(bat_node->rt_table_list);
memset(bat_node->loop_magic, 0, sizeof(bat_node->loop_magic));
+ memset(bat_node->loop_magic2, 0, sizeof(bat_node->loop_magic2));
hash_add(node_hash, bat_node);
out:
return bat_node;
}
+static struct orig_event *orig_event_new(struct bat_node *bat_node, struct bat_node *orig_node)
+{
+ struct orig_event *orig_event;
+
+ orig_event = malloc(sizeof(struct orig_event));
+ if (!orig_event) {
+ fprintf(stderr, "Could not allocate memory for orig event structure (out of mem?) - skipping");
+ return NULL;
+ }
+
+ INIT_LIST_HEAD(&orig_event->list);
+ INIT_LIST_HEAD_FIRST(orig_event->event_list);
+ INIT_LIST_HEAD_FIRST(orig_event->rt_hist_list);
+ orig_event->orig_node = orig_node;
+ list_add_tail(&orig_event->list, &bat_node->orig_event_list);
+
+ return orig_event;
+}
+
+static struct orig_event *orig_event_get_by_name(struct bat_node *bat_node, char *orig)
+{
+ struct bat_node *orig_node;
+ struct orig_event *orig_event;
+
+ if (!bat_node)
+ return NULL;
+
+ list_for_each_entry(orig_event, &bat_node->orig_event_list, list) {
+ if (compare_name(orig_event->orig_node->name, orig))
+ return orig_event;
+ }
+
+ orig_node = node_get(orig);
+ if (!orig_node)
+ return NULL;
+
+ return orig_event_new(bat_node, orig_node);
+}
+
+static struct orig_event *orig_event_get_by_ptr(struct bat_node *bat_node, struct bat_node *orig_node)
+{
+ struct orig_event *orig_event;
+
+ if (!bat_node)
+ return NULL;
+
+ list_for_each_entry(orig_event, &bat_node->orig_event_list, list) {
+ if (orig_event->orig_node == orig_node)
+ return orig_event;
+ }
+
+ return orig_event_new(bat_node, orig_node);
+}
+
static void node_free(void *data)
{
+ struct orig_event *orig_event, *orig_event_tmp;
struct seqno_event *seqno_event, *seqno_event_tmp;
struct rt_table *rt_table, *rt_table_tmp;
+ struct rt_hist *rt_hist, *rt_hist_tmp;
struct bat_node *bat_node = (struct bat_node *)data;
- list_for_each_entry_safe(seqno_event, seqno_event_tmp, &bat_node->event_list, list) {
- list_del((struct list_head *)&bat_node->event_list, &seqno_event->list, &bat_node->event_list);
- free(seqno_event);
+ list_for_each_entry_safe(orig_event, orig_event_tmp, &bat_node->orig_event_list, list) {
+ list_for_each_entry_safe(seqno_event, seqno_event_tmp, &orig_event->event_list, list) {
+ list_del((struct list_head *)&orig_event->event_list, &seqno_event->list, &orig_event->event_list);
+ free(seqno_event);
+ }
+
+ list_for_each_entry_safe(rt_hist, rt_hist_tmp, &orig_event->rt_hist_list, list) {
+ list_del((struct list_head *)&orig_event->rt_hist_list, &rt_hist->list, &orig_event->rt_hist_list);
+ free(rt_hist);
+ }
+
+ list_del((struct list_head *)&bat_node->orig_event_list, &orig_event->list, &bat_node->orig_event_list);
+ free(orig_event);
}
list_for_each_entry_safe(rt_table, rt_table_tmp, &bat_node->rt_table_list, list) {
@@ -120,8 +187,10 @@
static int routing_table_new(char *orig, char *next_hop, char *old_next_hop, char rt_flag)
{
struct bat_node *next_hop_node;
+ struct orig_event *orig_event;
struct seqno_event *seqno_event;
struct rt_table *rt_table, *prev_rt_table = NULL;
+ struct rt_hist *rt_hist;
int i, j;
if (!curr_bat_node) {
@@ -148,19 +217,46 @@
if ((rt_flag != RT_FLAG_DELETE) && (!next_hop_node))
goto err;
+ orig_event = orig_event_get_by_name(curr_bat_node, orig);
+ if (!orig_event)
+ goto err;
+
+ if (list_empty(&orig_event->event_list)) {
+ fprintf(stderr, "Routing table change without any preceeding OGM of that originator - skipping");
+ goto err;
+ }
+
+ if (!compare_name(((struct seqno_event *)(orig_event->event_list.prev))->orig->name, orig)) {
+ fprintf(stderr, "Routing table change does not match with last received OGM - skipping");
+ goto err;
+ }
+
rt_table = malloc(sizeof(struct rt_table));
if (!rt_table) {
fprintf(stderr, "Could not allocate memory for routing table (out of mem?) - skipping");
goto err;
}
+ rt_hist = malloc(sizeof(struct rt_hist));
+ if (!rt_hist) {
+ fprintf(stderr, "Could not allocate memory for routing history (out of mem?) - skipping");
+ goto table_free;
+ }
+
INIT_LIST_HEAD(&rt_table->list);
+ rt_table->num_entries = 1;
+ INIT_LIST_HEAD(&rt_hist->list);
+ rt_hist->prev_rt_hist = NULL;
+ rt_hist->next_hop = next_hop_node;
+ rt_hist->flags = rt_flag;
+
+ if (!(list_empty(&orig_event->rt_hist_list)))
+ rt_hist->prev_rt_hist = (struct rt_hist *)(orig_event->rt_hist_list.prev);
+
if (!(list_empty(&curr_bat_node->rt_table_list)))
prev_rt_table = (struct rt_table *)(curr_bat_node->rt_table_list.prev);
- rt_table->num_entries = 1;
-
switch (rt_flag) {
case RT_FLAG_ADD:
if (prev_rt_table)
@@ -193,9 +289,9 @@
if (rt_table->num_entries != prev_rt_table->num_entries) {
fprintf(stderr,
- "Found a delete entry of orig '%s' but no previous existing record - skipping",
+ "Found a delete entry of orig '%s' but no existing record - skipping",
orig);
- goto table_free;
+ goto rt_hist_free;
}
/**
@@ -205,29 +301,29 @@
seqno_event = malloc(sizeof(struct seqno_event));
if (!seqno_event) {
fprintf(stderr, "Could not allocate memory for delete seqno event (out of mem?) - skipping");
- goto table_free;
+ goto rt_hist_free;
}
INIT_LIST_HEAD(&seqno_event->list);
- seqno_event->orig = NULL;
+ seqno_event->orig = node_get(orig);
seqno_event->neigh = NULL;
seqno_event->prev_sender = NULL;
seqno_event->seqno = -1;
seqno_event->tq = -1;
seqno_event->ttl = -1;
- seqno_event->rt_table = NULL;
- list_add_tail(&seqno_event->list, &curr_bat_node->event_list);
+ seqno_event->rt_hist = NULL;
+ list_add_tail(&seqno_event->list, &orig_event->event_list);
}
break;
default:
fprintf(stderr, "Unknown rt_flag received: %i - skipping", rt_flag);
- goto table_free;
+ goto rt_hist_free;
}
rt_table->entries = malloc(sizeof(struct rt_entry) * rt_table->num_entries);
if (!rt_table->entries) {
fprintf(stderr, "Could not allocate memory for routing table entries (out of mem?) - skipping");
- goto table_free;
+ goto rt_hist_free;
}
if (prev_rt_table) {
@@ -246,7 +342,9 @@
*/
j++;
- memcpy((char *)&rt_table->entries[j], (char *)&prev_rt_table->entries[i], sizeof(struct rt_entry));
+ memcpy((char *)&rt_table->entries[j],
+ (char *)&prev_rt_table->entries[i],
+ sizeof(struct rt_entry));
if (compare_name(orig, rt_table->entries[j].orig)) {
if (rt_flag != RT_FLAG_DELETE)
@@ -266,11 +364,17 @@
rt_table->entries[i - 1].flags = rt_flag;
}
+ rt_table->rt_hist = rt_hist;
+ rt_hist->seqno_event = (struct seqno_event *)(orig_event->event_list.prev);
+ rt_hist->seqno_event->rt_hist = rt_hist;
+ rt_hist->rt_table = rt_table;
list_add_tail(&rt_table->list, &curr_bat_node->rt_table_list);
- ((struct seqno_event *)(curr_bat_node->event_list.prev))->rt_table = rt_table;
+ list_add_tail(&rt_hist->list, &orig_event->rt_hist_list);
return 1;
+rt_hist_free:
+ free(rt_hist);
table_free:
free(rt_table);
err:
@@ -280,6 +384,7 @@
static int seqno_event_new(char *iface_addr, char *orig, char *prev_sender, char *neigh, int seqno, int tq, int ttl)
{
struct bat_node *orig_node, *neigh_node, *prev_sender_node;
+ struct orig_event *orig_event;
struct seqno_event *seqno_event;
if (!iface_addr) {
@@ -328,6 +433,10 @@
if (!prev_sender_node)
goto err;
+ orig_event = orig_event_get_by_ptr(curr_bat_node, orig_node);
+ if (!orig_event)
+ goto err;
+
seqno_event = malloc(sizeof(struct seqno_event));
if (!seqno_event) {
fprintf(stderr, "Could not allocate memory for seqno event (out of mem?) - skipping");
@@ -341,8 +450,8 @@
seqno_event->seqno = seqno;
seqno_event->tq = tq;
seqno_event->ttl = ttl;
- seqno_event->rt_table = NULL;
- list_add_tail(&seqno_event->list, &curr_bat_node->event_list);
+ seqno_event->rt_hist = NULL;
+ list_add_tail(&seqno_event->list, &orig_event->event_list);
return 1;
@@ -464,8 +573,8 @@
}
}
-// printf("route (line %i): orig: '%s', neigh: '%s', prev_sender: '%s'\n",
-// line_count, orig, neigh, prev_sender);
+// printf("route (file: %s, line %i): orig: '%s', neigh: '%s', prev_sender: '%s'\n",
+// file_path, line_count, orig, neigh, prev_sender);
if (((rt_flag == RT_FLAG_ADD) && (!neigh)) ||
((rt_flag == RT_FLAG_UPDATE) && (!prev_sender)) ||
@@ -485,102 +594,203 @@
// printf("File '%s' parsed (lines: %i)\n", file_path, line_count);
fclose(fd);
+ curr_bat_node = NULL;
return 1;
}
-static int validate_path(struct bat_node *bat_node, struct seqno_event *seqno_event,
- struct rt_entry *rt_entry, int seqno_count, int read_opt)
+static struct rt_hist *get_rt_hist_by_seqno(struct orig_event *orig_event, int seqno)
{
- struct bat_node *next_hop_node;
- struct seqno_event *seqno_event_tmp;
- struct rt_table *rt_table_tmp;
- struct rt_entry *rt_entry_tmp = rt_entry;
+ struct seqno_event *seqno_event;
+ struct rt_hist *rt_hist = NULL;
+
+ list_for_each_entry(seqno_event, &orig_event->event_list, list) {
+ if (seqno_event->seqno > seqno)
+
+ break;
+ if (seqno_event->rt_hist)
+ rt_hist = seqno_event->rt_hist;
+ }
+
+ return rt_hist;
+}
+
+static struct rt_hist *get_rt_hist_by_node_seqno(struct bat_node *bat_node, struct bat_node *orig_node, int seqno)
+{
+ struct orig_event *orig_event;
+ struct rt_hist *rt_hist;
+
+ orig_event = orig_event_get_by_ptr(bat_node, orig_node);
+ if (!orig_event)
+ return NULL;
+
+ rt_hist = get_rt_hist_by_seqno(orig_event, seqno);
+ return rt_hist;
+}
+
+static int print_rt_path_at_seqno(struct bat_node *src_node, struct bat_node *dst_node,
+ struct bat_node *next_hop, int seqno, int seqno_rand, int read_opt)
+{
+ struct bat_node *next_hop_tmp;
+ struct orig_event *orig_event;
+ struct rt_hist *rt_hist;
char curr_loop_magic[LOOP_MAGIC_LEN];
- int i;
- snprintf(curr_loop_magic, LOOP_MAGIC_LEN, "%s%s%i%i",
- bat_node->name, rt_entry->orig,
- seqno_event->seqno, seqno_count);
+ memset(curr_loop_magic, 0, LOOP_MAGIC_LEN);
+ snprintf(curr_loop_magic, LOOP_MAGIC_LEN, "%s%s%i%i", src_node->name,
+ dst_node->name, seqno, seqno_rand);
- printf("Path towards %s (seqno %i):",
- get_name_by_macstr(rt_entry->orig, read_opt),
- seqno_event->seqno);
+ printf("Path towards %s (seqno %i ",
+ get_name_by_macstr(dst_node->name, read_opt), seqno);
+ printf("via neigh %s):", get_name_by_macstr(next_hop->name, read_opt));
+
+ next_hop_tmp = next_hop;
+
while (1) {
- next_hop_node = rt_entry_tmp->next_hop;
+ printf(" -> %s%s",
+ get_name_by_macstr(next_hop_tmp->name, read_opt),
+ (dst_node == next_hop_tmp ? "." : ""));
- printf(" -> %s",
- get_name_by_macstr(next_hop_node->name, read_opt));
+ /* destination reached */
+ if (dst_node == next_hop_tmp)
+ break;
+ orig_event = orig_event_get_by_ptr(next_hop_tmp, dst_node);
+ if (!orig_event)
+ goto out;
+
/* no more data - path seems[tm] fine */
- if (list_empty(&next_hop_node->event_list))
+ if (list_empty(&orig_event->event_list))
goto out;
/* same here */
- if (list_empty(&next_hop_node->rt_table_list))
+ if (list_empty(&orig_event->rt_hist_list))
continue;
- rt_table_tmp = NULL;
- rt_entry_tmp = NULL;
-
/* we are running in a loop */
- if (memcmp(curr_loop_magic, next_hop_node->loop_magic, LOOP_MAGIC_LEN) == 0) {
+ if (memcmp(curr_loop_magic, next_hop_tmp->loop_magic, LOOP_MAGIC_LEN) == 0) {
printf(" aborted due to loop!");
goto out;
}
- memcpy(next_hop_node->loop_magic, curr_loop_magic, sizeof(next_hop_node->loop_magic));
+ memcpy(next_hop_tmp->loop_magic, curr_loop_magic, sizeof(next_hop_tmp->loop_magic));
- list_for_each_entry(seqno_event_tmp, &next_hop_node->event_list, list) {
- if (seqno_event_tmp->rt_table)
- rt_table_tmp = seqno_event_tmp->rt_table;
+ rt_hist = get_rt_hist_by_seqno(orig_event, seqno);
- if ((seqno_event_tmp->seqno == seqno_event->seqno) &&
- (seqno_event_tmp->orig == seqno_event->orig))
- break;
- }
+ /* no more routing data - what can we do ? */
+ if (!rt_hist)
+ break;
- /* no routing data so far - what can we do ? */
- if (!rt_table_tmp)
- goto out;
+ next_hop_tmp = rt_hist->next_hop;
+ }
- /* search the following next hop */
- for (i = 0; i < rt_table_tmp->num_entries; i++) {
- if (compare_name(rt_table_tmp->entries[i].orig, rt_entry->orig)) {
- rt_entry_tmp = (struct rt_entry *)&rt_table_tmp->entries[i];
- break;
- }
+out:
+ printf("\n");
+ return 1;
+}
+
+static int find_rt_table_change(struct bat_node *src_node, struct bat_node *dst_node,
+ struct bat_node *curr_node, int seqno_min, int seqno_max,
+ int seqno_rand, int read_opt)
+{
+ struct orig_event *orig_event;
+ struct rt_hist *rt_hist, *rt_hist_tmp;
+ char curr_loop_magic[LOOP_MAGIC_LEN];
+ int res;
+
+ /* recursion ends here */
+ if (curr_node == dst_node) {
+ rt_hist = get_rt_hist_by_node_seqno(src_node, dst_node, seqno_max);
+
+ if (rt_hist)
+ print_rt_path_at_seqno(src_node, dst_node, rt_hist->next_hop,
+ seqno_max, seqno_rand, read_opt);
+ return 0;
+ }
+
+ memset(curr_loop_magic, 0, LOOP_MAGIC_LEN);
+ snprintf(curr_loop_magic, LOOP_MAGIC_LEN, "%s%s%i%i",
+ src_node->name, dst_node->name,
+ seqno_min, seqno_rand);
+
+ /* we are running in a loop */
+ if (memcmp(curr_loop_magic, curr_node->loop_magic2, LOOP_MAGIC_LEN) == 0) {
+ rt_hist = get_rt_hist_by_node_seqno(src_node, dst_node, seqno_max);
+
+ if (rt_hist)
+ print_rt_path_at_seqno(src_node, dst_node, rt_hist->next_hop,
+ seqno_max, seqno_rand, read_opt);
+ goto out;
+ }
+
+ memcpy(curr_node->loop_magic2, curr_loop_magic, sizeof(curr_node->loop_magic));
+
+ orig_event = orig_event_get_by_ptr(curr_node, dst_node);
+ if (!orig_event)
+ goto out;
+
+ list_for_each_entry(rt_hist, &orig_event->rt_hist_list, list) {
+ /* special seqno that indicates an originator timeout */
+ if (rt_hist->seqno_event->seqno == -1) {
+ printf("Woot - originator timeout ??\n");
+ continue;
}
- /* no routing entry of orig ?? */
- if (!rt_entry_tmp)
- goto out;
+ if ((seqno_min != -1) && (rt_hist->seqno_event->seqno < seqno_min))
+ continue;
- if (compare_name(rt_entry->orig, rt_entry_tmp->next_hop->name)) {
- printf(" -> %s.",
- get_name_by_macstr(rt_entry_tmp->next_hop->name, read_opt));
- break;
- }
+ if ((seqno_max != -1) && (rt_hist->seqno_event->seqno >= seqno_max))
+ continue;
+
+ /* printf("validate route after change (seqno %i) of next hop: %s\n",
+ rt_hist->seqno_event->seqno,
+ get_name_by_macstr(rt_hist->next_hop->name, read_opt));*/
+
+ res = find_rt_table_change(src_node, dst_node, rt_hist->next_hop,
+ seqno_min, rt_hist->seqno_event->seqno,
+ seqno_rand, read_opt);
+
+ /* find_rt_table_change() did not run into a loop and printed the path */
+ if (res == 0)
+ continue;
+
+ /**
+ * retrieve routing table towards dst at that point and
+ * print the routing path
+ **/
+ rt_hist_tmp = get_rt_hist_by_node_seqno(src_node, dst_node, rt_hist->seqno_event->seqno);
+
+ if (!rt_hist_tmp)
+ continue;
+
+ print_rt_path_at_seqno(src_node, dst_node, rt_hist_tmp->next_hop,
+ rt_hist->seqno_event->seqno, seqno_rand, read_opt);
}
+ rt_hist = get_rt_hist_by_seqno(orig_event, seqno_max - 1);
+
+ if (rt_hist)
+ return find_rt_table_change(src_node, dst_node, rt_hist->next_hop,
+ seqno_min, seqno_max, seqno_rand, read_opt);
+
out:
- printf("\n");
- return 1;
+ return -1;
}
static void loop_detection(char *loop_orig, int seqno_min, int seqno_max, int read_opt)
{
struct bat_node *bat_node;
- struct seqno_event *seqno_event;
+ struct orig_event *orig_event;
struct hash_it_t *hashit = NULL;
- int i, last_seqno = -1, seqno_count = 0;
+ struct rt_hist *rt_hist, *prev_rt_hist;
+ int last_seqno = -1, seqno_count = 0;
char check_orig[NAME_LEN];
printf("\nAnalyzing routing tables ");
/* if no option was given loop_orig is empty */
memset(check_orig, 0, NAME_LEN);
- if (memcmp(loop_orig, check_orig, NAME_LEN))
+ if (!compare_name(loop_orig, check_orig))
printf("of originator: %s ",
get_name_by_macstr(loop_orig, read_opt));
@@ -594,60 +804,89 @@
while (NULL != (hashit = hash_iterate(node_hash, hashit))) {
bat_node = hashit->bucket->data;
- if (memcmp(loop_orig, check_orig, NAME_LEN) &&
- memcmp(loop_orig, bat_node->name, NAME_LEN) != 0)
+ if (!compare_name(loop_orig, check_orig) &&
+ !compare_name(loop_orig, bat_node->name))
continue;
- /* we might have no log file from this node */
- if (list_empty(&bat_node->event_list)) {
- fprintf(stderr, "\nNo seqno data from node '%s' - skipping\n",
- get_name_by_macstr(bat_node->name, read_opt));
- continue;
- }
-
- /* or routing tables */
- if (list_empty(&bat_node->rt_table_list)) {
- fprintf(stderr, "\nNo routing tables from node '%s' - skipping\n",
- get_name_by_macstr(bat_node->name, read_opt));
- continue;
- }
-
printf("\nChecking host: %s\n",
get_name_by_macstr(bat_node->name, read_opt));
- list_for_each_entry(seqno_event, &bat_node->event_list, list) {
- /**
- * this received packet did not trigger a routing
- * table change and is considered harmless
- */
- if (!seqno_event->rt_table)
+ list_for_each_entry(orig_event, &bat_node->orig_event_list, list) {
+ if (bat_node == orig_event->orig_node)
continue;
- if ((seqno_min != -1) && (seqno_event->seqno < seqno_min))
+ /* we might have no log file from this node */
+ if (list_empty(&orig_event->event_list)) {
+ fprintf(stderr, "No seqno data of originator '%s' - skipping\n",
+ get_name_by_macstr(orig_event->orig_node->name, read_opt));
continue;
+ }
- if ((seqno_max != -1) && (seqno_event->seqno > seqno_max))
+ /* or routing tables */
+ if (list_empty(&orig_event->rt_hist_list)) {
+ fprintf(stderr, "No routing history of originator '%s' - skipping\n",
+ get_name_by_macstr(orig_event->orig_node->name, read_opt));
continue;
+ }
- /* special seqno that indicates an originator timeout */
- if (seqno_event->seqno == -1)
- continue;
+ list_for_each_entry(rt_hist, &orig_event->rt_hist_list, list) {
+ /* special seqno that indicates an originator timeout */
+ if (rt_hist->seqno_event->seqno == -1)
+ continue;
- /**
- * sometime we change the routing table more than once
- * with the same seqno
- */
- if (last_seqno == seqno_event->seqno)
- seqno_count++;
- else
- seqno_count = 0;
+ if ((seqno_min != -1) && (rt_hist->seqno_event->seqno < seqno_min))
+ continue;
- last_seqno = seqno_event->seqno;
+ if ((seqno_max != -1) && (rt_hist->seqno_event->seqno > seqno_max))
+ continue;
- for (i = 0; i < seqno_event->rt_table->num_entries; i++) {
- validate_path(bat_node, seqno_event,
- (struct rt_entry *)&seqno_event->rt_table->entries[i],
- seqno_count, read_opt);
+ /**
+ * sometime we change the routing table more than once
+ * with the same seqno
+ */
+ if (last_seqno == rt_hist->seqno_event->seqno)
+ seqno_count++;
+ else
+ seqno_count = 0;
+
+ last_seqno = rt_hist->seqno_event->seqno;
+
+ if (rt_hist->flags == RT_FLAG_DELETE) {
+ printf("Path towards %s deleted (originator timeout)\n",
+ get_name_by_macstr(rt_hist->seqno_event->orig->name, read_opt));
+ continue;
+ }
+
+ prev_rt_hist = rt_hist->prev_rt_hist;
+
+ if ((prev_rt_hist) &&
+ (rt_hist->seqno_event->seqno != prev_rt_hist->seqno_event->seqno)) {
+ if (rt_hist->seqno_event->seqno < prev_rt_hist->seqno_event->seqno) {
+ fprintf(stderr,
+ "Smaller seqno (%i) than previously received seqno (%i) of orig %s triggered routing table change - skipping recursive check\n",
+ rt_hist->seqno_event->seqno, prev_rt_hist->seqno_event->seqno,
+ get_name_by_macstr(rt_hist->seqno_event->orig->name, read_opt));
+ goto validate_path;
+ }
+
+ /*printf("\n=> checking orig %s in seqno range of: %i - %i ",
+ get_name_by_macstr(rt_hist->seqno_event->orig->name, read_opt),
+ prev_rt_hist->seqno_event->seqno + 1,
+ rt_hist->seqno_event->seqno);
+
+ printf("(prev nexthop: %s)\n",
+ get_name_by_macstr(prev_rt_hist->next_hop->name, read_opt));*/
+
+ find_rt_table_change(bat_node, rt_hist->seqno_event->orig, prev_rt_hist->next_hop,
+ prev_rt_hist->seqno_event->seqno + 1, rt_hist->seqno_event->seqno,
+ seqno_count, read_opt);
+
+ continue;
+ }
+
+validate_path:
+ print_rt_path_at_seqno(bat_node, rt_hist->seqno_event->orig, rt_hist->next_hop,
+ rt_hist->seqno_event->seqno, seqno_count, read_opt);
}
}
}
@@ -677,9 +916,9 @@
for (i = 0; i < seqno_trace_neigh->num_neighbors; i++) {
snprintf(new_head, sizeof(new_head), "%s%s",
- (strlen(head) > 1 ? head : num_sisters == 0 ? " " : head),
- (strlen(head) == 1 ? " " :
- num_sisters == 0 ? " " : "| "));
+ (strlen(head) > 1 ? head : num_sisters == 0 ? " " : head),
+ (strlen(head) == 1 ? " " :
+ num_sisters == 0 ? " " : "| "));
seqno_trace_print_neigh(seqno_trace_neigh->seqno_trace_neigh[i], seqno_trace_neigh->seqno_event,
seqno_trace_neigh->num_neighbors - i - 1, new_head, read_opt);
@@ -941,6 +1180,7 @@
static void trace_seqnos(char *trace_orig, int seqno_min, int seqno_max, int read_opt)
{
struct bat_node *bat_node;
+ struct orig_event *orig_event;
struct seqno_event *seqno_event;
struct hash_it_t *hashit = NULL;
struct list_head_first trace_list;
@@ -952,28 +1192,31 @@
while (NULL != (hashit = hash_iterate(node_hash, hashit))) {
bat_node = hashit->bucket->data;
- /* we might have no log file from this node */
- if (list_empty(&bat_node->event_list))
- continue;
+ list_for_each_entry(orig_event, &bat_node->orig_event_list, list) {
- list_for_each_entry(seqno_event, &bat_node->event_list, list) {
- /* special seqno that indicates an originator timeout */
- if (seqno_event->seqno == -1)
+ /* we might have no log file from this node */
+ if (list_empty(&orig_event->event_list))
continue;
- if (!compare_name(trace_orig, seqno_event->orig->name))
- continue;
+ list_for_each_entry(seqno_event, &orig_event->event_list, list) {
+ /* special seqno that indicates an originator timeout */
+ if (seqno_event->seqno == -1)
+ continue;
- if ((seqno_min != -1) && (seqno_event->seqno < seqno_min))
- continue;
+ if (!compare_name(trace_orig, seqno_event->orig->name))
+ continue;
- if ((seqno_max != -1) && (seqno_event->seqno > seqno_max))
- continue;
+ if ((seqno_min != -1) && (seqno_event->seqno < seqno_min))
+ continue;
- res = seqno_trace_add(&trace_list, bat_node, seqno_event);
+ if ((seqno_max != -1) && (seqno_event->seqno > seqno_max))
+ continue;
- if (res < 1)
- goto out;
+ res = seqno_trace_add(&trace_list, bat_node, seqno_event);
+
+ if (res < 1)
+ goto out;
+ }
}
}
@@ -991,6 +1234,7 @@
static void print_rt_tables(char *rt_orig, int seqno_min, int seqno_max, int read_opt)
{
struct bat_node *bat_node;
+ struct rt_table *rt_table;
struct seqno_event *seqno_event;
int i;
@@ -1009,16 +1253,11 @@
goto out;
/* we might have no log file from this node */
- if (list_empty(&bat_node->event_list))
- goto out;
-
- /* or routing tables */
if (list_empty(&bat_node->rt_table_list))
goto out;
- list_for_each_entry(seqno_event, &bat_node->event_list, list) {
- if (!seqno_event->rt_table)
- continue;
+ list_for_each_entry(rt_table, &bat_node->rt_table_list, list) {
+ seqno_event = rt_table->rt_hist->seqno_event;
if ((seqno_min != -1) && (seqno_event->seqno < seqno_min))
continue;
@@ -1026,7 +1265,7 @@
if ((seqno_max != -1) && (seqno_event->seqno > seqno_max))
continue;
- if (seqno_event->orig) {
+ if (seqno_event->seqno > -1) {
printf("rt change triggered by OGM from: %s (tq: %i, ttl: %i, seqno %i",
get_name_by_macstr(seqno_event->orig->name, read_opt),
seqno_event->tq, seqno_event->ttl, seqno_event->seqno);
@@ -1038,14 +1277,14 @@
printf("rt change triggered by originator timeout: \n");
}
- for (i = 0; i < seqno_event->rt_table->num_entries; i++) {
+ for (i = 0; i < rt_table->num_entries; i++) {
printf("%s %s via next hop",
- (seqno_event->rt_table->entries[i].flags ? " *" : " "),
- get_name_by_macstr(seqno_event->rt_table->entries[i].orig, read_opt));
+ (rt_table->entries[i].flags ? " *" : " "),
+ get_name_by_macstr(rt_table->entries[i].orig, read_opt));
printf(" %s",
- get_name_by_macstr(seqno_event->rt_table->entries[i].next_hop->name, read_opt));
+ get_name_by_macstr(rt_table->entries[i].next_hop->name, read_opt));
- switch (seqno_event->rt_table->entries[i].flags) {
+ switch (rt_table->entries[i].flags) {
case RT_FLAG_ADD:
printf(" (route added)\n");
break;
Modified: trunk/batctl/bisect.h
===================================================================
--- trunk/batctl/bisect.h 2009-10-25 00:13:47 UTC (rev 1455)
+++ trunk/batctl/bisect.h 2009-10-25 00:13:51 UTC (rev 1456)
@@ -29,19 +29,39 @@
int bisect(int argc, char **argv);
+
+
struct bat_node {
char name[NAME_LEN];
- struct list_head_first event_list;
+ struct list_head_first orig_event_list;
struct list_head_first rt_table_list;
char loop_magic[LOOP_MAGIC_LEN];
+ char loop_magic2[LOOP_MAGIC_LEN];
};
+struct orig_event {
+ struct list_head list;
+ struct bat_node *orig_node;
+ struct list_head_first event_list;
+ struct list_head_first rt_hist_list;
+};
+
struct rt_table {
struct list_head list;
int num_entries;
struct rt_entry *entries;
+ struct rt_hist *rt_hist;
};
+struct rt_hist {
+ struct list_head list;
+ struct rt_table *rt_table;
+ struct rt_hist *prev_rt_hist;
+ struct seqno_event *seqno_event;
+ struct bat_node *next_hop;
+ char flags;
+};
+
struct rt_entry {
char orig[NAME_LEN];
struct bat_node *next_hop;
@@ -56,7 +76,7 @@
int seqno;
int tq;
int ttl;
- struct rt_table *rt_table;
+ struct rt_hist *rt_hist;
};
struct seqno_trace_neigh {