Ok, could get that problem with the missing entries fixed, the pointer to the interface-list needed to be set to the top of the list after going through the list again. So basically I just added lines 95, 112, 113. So works fine for me now :).
Cheers, Linus
Index: vis.c =================================================================== --- vis.c (revision 1418) +++ vis.c (working copy) @@ -87,7 +87,7 @@ struct vis_info *d1, *d2; d1 = data1; d2 = data2; - return memcmp(d1->packet.vis_orig, d2->packet.vis_orig, ETH_ALEN) == 0; + return compare_orig(d1->packet.vis_orig, d2->packet.vis_orig); }
/* hash function to choose an entry in a hash table of given size */ @@ -326,13 +326,14 @@
while (NULL != (hashit = hash_iterate(orig_hash, hashit))) { orig_node = hashit->bucket->data; - if (orig_node->router != NULL && - memcmp(orig_node->router->addr, - orig_node->orig, ETH_ALEN) == 0 && - orig_node->router->tq_avg > 0) { + if (orig_node->router != NULL + && compare_orig(orig_node->router->addr, orig_node->orig) + && orig_node->batman_if + && orig_node->router->tq_avg > 0) {
/* fill one entry into buffer. */ entry = &entry_array[info->packet.entries]; + memcpy(entry->src, orig_node->batman_if->net_dev->dev_addr, ETH_ALEN); memcpy(entry->dest, orig_node->orig, ETH_ALEN); entry->quality = orig_node->router->tq_avg; info->packet.entries++; @@ -351,6 +352,7 @@ while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) { hna_local_entry = hashit->bucket->data; entry = &entry_array[info->packet.entries]; + memset(entry->src, 0, ETH_ALEN); memcpy(entry->dest, hna_local_entry->addr, ETH_ALEN); entry->quality = 0; /* 0 means HNA */ info->packet.entries++; @@ -556,3 +558,4 @@ queue_delayed_work(bat_event_workqueue, &vis_timer_wq, (atomic_read(&vis_interval)/1000) * HZ); } + Index: vis.h =================================================================== --- vis.h (revision 1418) +++ vis.h (working copy) @@ -33,6 +33,7 @@ } __attribute__((packed));
struct vis_info_entry { + uint8_t src[ETH_ALEN]; uint8_t dest[ETH_ALEN]; uint8_t quality; /* quality = 0 means HNA */ } __attribute__((packed)); Index: packet.h =================================================================== --- packet.h (revision 1418) +++ packet.h (working copy) @@ -26,7 +26,7 @@ #define BAT_VIS 0x05
/* this file is included by batctl which needs these defines */ -#define COMPAT_VERSION 7 +#define COMPAT_VERSION 8 #define DIRECTLINK 0x40 #define VIS_SERVER 0x20
Index: proc.c =================================================================== --- proc.c (revision 1418) +++ proc.c (working copy) @@ -403,17 +403,62 @@ return single_open(file, proc_transt_global_read, NULL); }
+/* insert interface to the list of interfaces of one originator */ + +static void proc_vis_insert_interface(const uint8_t *interface, + struct vis_if_list **if_entry, + bool primary) +{ + /* Did we get an empty list? (then insert imediately) */ + if(*if_entry == NULL) { + *if_entry = kmalloc(sizeof(struct vis_if_list), GFP_KERNEL); + if (*if_entry == NULL) + return; + + (*if_entry)->primary = primary; + (*if_entry)->next = NULL; + memcpy((*if_entry)->addr, interface, ETH_ALEN); + } else { + struct vis_if_list *head_if_entry = *if_entry; + /* Do we already have this interface in our list? */ + while (!compare_orig((*if_entry)->addr, (void *)interface)) { + + /* Or did we reach the end (then append the interface) */ + if ((*if_entry)->next == NULL) { + (*if_entry)->next = kmalloc(sizeof(struct vis_if_list), GFP_KERNEL); + if ((*if_entry)->next == NULL) + return; + + memcpy((*if_entry)->next->addr, interface, ETH_ALEN); + (*if_entry)->next->primary = primary; + (*if_entry)->next->next = NULL; + break; + } + *if_entry = (*if_entry)->next; + } + /* Rewind the list to its head */ + *if_entry = head_if_entry; + } +} +/* read an entry */ + static void proc_vis_read_entry(struct seq_file *seq, struct vis_info_entry *entry, - char *from, + struct vis_if_list **if_entry, + uint8_t *vis_orig, uint8_t current_format, uint8_t first_line) { + char from[40]; char to[40]; int int_part, frac_part;
addr_to_string(to, entry->dest); if (entry->quality == 0) { +#ifndef VIS_SUBCLUSTERS_DISABLED + proc_vis_insert_interface(vis_orig, if_entry, true); +#endif /* VIS_SUBCLUSTERS_DISABLED */ + addr_to_string(from, vis_orig); if (current_format == DOT_DRAW) { seq_printf(seq, "\t"%s" -> "%s" [label="HNA"]\n", from, to); @@ -423,10 +468,17 @@ (first_line ? "" : ",\n"), from, to); } } else { +#ifndef VIS_SUBCLUSTERS_DISABLED + proc_vis_insert_interface(entry->src, if_entry, compare_orig(entry->src, vis_orig)); +#endif /* VIS_SUBCLUSTERS_DISABLED */ + addr_to_string(from, entry->src); + /* kernel has no printf-support for %f? it'd be better to return * this in float. */ + int_part = TQ_MAX_VALUE / entry->quality; frac_part = 1000 * TQ_MAX_VALUE / entry->quality - int_part * 1000; + if (current_format == DOT_DRAW) { seq_printf(seq, "\t"%s" -> "%s" [label="%d.%d"]\n", @@ -439,14 +491,19 @@ } }
+ static int proc_vis_read(struct seq_file *seq, void *offset) { struct hash_it_t *hashit = NULL; struct vis_info *info; struct vis_info_entry *entries; - char from[40]; + struct vis_if_list *if_entries = NULL; int i; uint8_t current_format, first_line = 1; +#ifndef VIS_SUBCLUSTERS_DISABLED + char tmp_addr_str[ETH_STR_LEN]; + struct vis_if_list *tmp_if_next; +#endif /* VIS_SUBCLUSTERS_DISABLED */
current_format = vis_format;
@@ -468,14 +525,37 @@ info = hashit->bucket->data; entries = (struct vis_info_entry *) ((char *)info + sizeof(struct vis_info)); - addr_to_string(from, info->packet.vis_orig);
for (i = 0; i < info->packet.entries; i++) { - proc_vis_read_entry(seq, &entries[i], from, + proc_vis_read_entry(seq, &entries[i], &if_entries, + info->packet.vis_orig, current_format, first_line); if (first_line) first_line = 0; } + +#ifndef VIS_SUBCLUSTERS_DISABLED + /* Generate subgraphs from the collected items */ + if (current_format == DOT_DRAW) { + + addr_to_string(tmp_addr_str, info->packet.vis_orig); + seq_printf(seq, "\tsubgraph "cluster_%s" {\n", tmp_addr_str); + while (if_entries != NULL) { + + addr_to_string(tmp_addr_str, if_entries->addr); + if (if_entries->primary) + seq_printf(seq, "\t\t"%s" [peripheries=2]\n", tmp_addr_str); + else + seq_printf(seq, "\t\t"%s"\n", tmp_addr_str); + + /* ... and empty the list while doing this */ + tmp_if_next = if_entries->next; + kfree(if_entries); + if_entries = tmp_if_next; + } + seq_printf(seq, "\t}\n"); + } +#endif /* VIS_SUBCLUSTERS_DISABLED */ } spin_unlock(&vis_hash_lock);
Index: proc.h =================================================================== --- proc.h (revision 1418) +++ proc.h (working copy) @@ -35,3 +35,13 @@
void cleanup_procfs(void); int setup_procfs(void); + +/* While scanning for vis-entries of a particular vis-originator + * this list collects its interfaces to create a subgraph/cluster + * out of them later + */ +struct vis_if_list { + uint8_t addr[ETH_ALEN]; + bool primary; + struct vis_if_list *next; +}; Index: main.c =================================================================== --- main.c (revision 1418) +++ main.c (working copy) @@ -224,6 +224,8 @@ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); }
+/* returns 1 if they are the same originator */ + int compare_orig(void *data1, void *data2) { return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); Index: main.h =================================================================== --- main.h (revision 1418) +++ main.h (working copy) @@ -25,6 +25,10 @@ #define DRIVER_DEVICE "batman-adv"
#define SOURCE_VERSION "0.2-beta" + + +/* B.A.T.M.A.N. parameters */ + #define TQ_MAX_VALUE 255 #define JITTER 20 #define TTL 50 /* Time To Live of broadcast messages */ @@ -82,6 +86,16 @@ #define LOG_TYPE_BATMAN_NAME "batman" #define LOG_TYPE_ROUTES_NAME "routes"
+/* + * Vis + */ + +/* #define VIS_SUBCLUSTERS_DISABLED */ + +/* + * Kernel headers + */ + #include <linux/mutex.h> /* mutex */ #include <linux/module.h> /* needed by all modules */ #include <linux/netdevice.h> /* netdevice */